suite('p5.RendererGL', function() {
  var myp5;

  if (!window.Modernizr.webgl) {
    return;
  }

  setup(function() {
    myp5 = new p5(function(p) {
      p.setup = function() {};
      p.draw = function() {};
    });
  });

  teardown(function() {
    myp5.remove();
  });

  suite('createCanvas(w, h, WEBGL)', function() {
    test('creates a p5.RendererGL renderer', function() {
      myp5.createCanvas(100, 100, myp5.WEBGL);
      assert.instanceOf(myp5._renderer, p5.RendererGL);
    });
  });

  suite('default stroke shader', function() {
    test('check activate and deactivating fill and stroke', function(done) {
      myp5.noStroke();
      assert(
        !myp5._renderer._doStroke,
        'stroke shader still active after noStroke()'
      );
      assert.isTrue(
        myp5._renderer._doFill,
        'fill shader deactivated by noStroke()'
      );
      myp5.stroke(0);
      myp5.noFill();
      assert(
        myp5._renderer._doStroke,
        'stroke shader not active after stroke()'
      );
      assert.isTrue(
        !myp5._renderer._doFill,
        'fill shader still active after noFill()'
      );
      done();
    });
  });

  suite('push() and pop() work in WEBGL Mode', function() {
    test('push/pop and translation works as expected in WEBGL Mode', function(done) {
      myp5.createCanvas(100, 100, myp5.WEBGL);
      var modelView = myp5._renderer.uMVMatrix.copy();
      myp5.push();
      myp5.rotateX(Math.random(0, 100));
      myp5.translate(20, 100, 5);
      assert.notEqual(modelView.mat4, myp5._renderer.uMVMatrix.mat4);
      myp5.pop();
      assert.deepEqual(modelView.mat4, myp5._renderer.uMVMatrix.mat4);
      done();
    });

    test('push/pop and directionalLight() works', function(done) {
      myp5.createCanvas(100, 100, myp5.WEBGL);
      myp5.directionalLight(255, 0, 0, 0, 0, 0);
      var dirDiffuseColors =
        myp5._renderer.directionalLightDiffuseColors.slice();
      var dirSpecularColors =
        myp5._renderer.directionalLightSpecularColors.slice();
      var dirLightDirections =
        myp5._renderer.directionalLightDirections.slice();
      myp5.push();
      myp5.directionalLight(0, 0, 255, 0, 10, 5);
      assert.notEqual(
        dirDiffuseColors,
        myp5._renderer.directionalLightDiffuseColors
      );
      assert.notEqual(
        dirSpecularColors,
        myp5._renderer.directionalLightSpecularColors
      );
      assert.notEqual(
        dirLightDirections,
        myp5._renderer.directionalLightDirections
      );
      myp5.pop();
      assert.deepEqual(
        dirDiffuseColors,
        myp5._renderer.directionalLightDiffuseColors
      );
      assert.deepEqual(
        dirSpecularColors,
        myp5._renderer.directionalLightSpecularColors
      );
      assert.deepEqual(
        dirLightDirections,
        myp5._renderer.directionalLightDirections
      );
      done();
    });

    test('push/pop and ambientLight() works', function(done) {
      myp5.createCanvas(100, 100, myp5.WEBGL);
      myp5.ambientLight(100, 0, 100);
      myp5.ambientLight(0, 0, 200);
      var ambColors = myp5._renderer.ambientLightColors.slice();
      myp5.push();
      myp5.ambientLight(0, 0, 0);
      assert.notEqual(ambColors, myp5._renderer.ambientLightColors);
      myp5.pop();
      assert.deepEqual(ambColors, myp5._renderer.ambientLightColors);
      done();
    });

    test('push/pop and pointLight() works', function(done) {
      myp5.createCanvas(100, 100, myp5.WEBGL);
      myp5.pointLight(255, 0, 0, 0, 0, 0);
      var pointDiffuseColors = myp5._renderer.pointLightDiffuseColors.slice();
      var pointSpecularColors = myp5._renderer.pointLightSpecularColors.slice();
      var pointLocs = myp5._renderer.pointLightPositions.slice();
      myp5.push();
      myp5.pointLight(0, 0, 255, 0, 10, 5);
      assert.notEqual(
        pointDiffuseColors,
        myp5._renderer.pointLightDiffuseColors
      );
      assert.notEqual(
        pointSpecularColors,
        myp5._renderer.pointLightSpecularColors
      );
      assert.notEqual(pointLocs, myp5._renderer.pointLightPositions);
      myp5.pop();
      assert.deepEqual(
        pointDiffuseColors,
        myp5._renderer.pointLightDiffuseColors
      );
      assert.deepEqual(
        pointSpecularColors,
        myp5._renderer.pointLightSpecularColors
      );
      assert.deepEqual(pointLocs, myp5._renderer.pointLightPositions);
      done();
    });

    test('push/pop and specularColor() works', function(done) {
      myp5.createCanvas(100, 100, myp5.WEBGL);
      myp5.specularColor(255, 0, 0);
      var specularColors = myp5._renderer.specularColors.slice();
      myp5.push();
      myp5.specularColor(0, 0, 255);
      assert.notEqual(specularColors, myp5._renderer.specularColors);
      myp5.pop();
      assert.deepEqual(specularColors, myp5._renderer.specularColors);
      done();
    });

    test('push/pop and spotLight() works', function(done) {
      myp5.createCanvas(100, 100, myp5.WEBGL);
      myp5.spotLight(255, 0, 255, 1, 2, 3, 0, 1, 0, Math.PI / 4, 7);
      let spotLightDiffuseColors =
        myp5._renderer.spotLightDiffuseColors.slice();
      let spotLightSpecularColors =
        myp5._renderer.spotLightSpecularColors.slice();
      let spotLightPositions = myp5._renderer.spotLightPositions.slice();
      let spotLightDirections = myp5._renderer.spotLightDirections.slice();
      let spotLightAngle = myp5._renderer.spotLightAngle.slice();
      let spotLightConc = myp5._renderer.spotLightConc.slice();
      myp5.push();
      myp5.spotLight(255, 0, 0, 2, 2, 3, 1, 0, 0, Math.PI / 3, 8);
      assert.notEqual(
        spotLightDiffuseColors,
        myp5._renderer.spotLightDiffuseColors
      );
      assert.notEqual(
        spotLightSpecularColors,
        myp5._renderer.spotLightSpecularColors
      );
      assert.notEqual(spotLightPositions, myp5._renderer.spotLightPositions);
      assert.notEqual(spotLightDirections, myp5._renderer.spotLightDirections);
      assert.notEqual(spotLightAngle, myp5._renderer.spotLightAngle);
      assert.notEqual(spotLightConc, myp5._renderer.spotLightConc);
      myp5.pop();
      assert.deepEqual(
        spotLightDiffuseColors,
        myp5._renderer.spotLightDiffuseColors
      );
      assert.deepEqual(
        spotLightSpecularColors,
        myp5._renderer.spotLightSpecularColors
      );
      assert.deepEqual(spotLightPositions, myp5._renderer.spotLightPositions);
      assert.deepEqual(spotLightDirections, myp5._renderer.spotLightDirections);
      assert.deepEqual(spotLightAngle, myp5._renderer.spotLightAngle);
      assert.deepEqual(spotLightConc, myp5._renderer.spotLightConc);
      done();
    });

    test('push/pop and noLights() works', function(done) {
      myp5.createCanvas(100, 100, myp5.WEBGL);
      myp5.ambientLight(0, 0, 200);
      var ambColors = myp5._renderer.ambientLightColors.slice();
      myp5.push();
      myp5.ambientLight(0, 200, 0);
      var ambPopColors = myp5._renderer.ambientLightColors.slice();
      myp5.noLights();
      assert.notEqual(ambColors, myp5._renderer.ambientLightColors);
      assert.notEqual(ambPopColors, myp5._renderer.ambientLightColors);
      myp5.pop();
      assert.deepEqual(ambColors, myp5._renderer.ambientLightColors);
      done();
    });

    test('push/pop and texture() works', function(done) {
      myp5.createCanvas(100, 100, myp5.WEBGL);
      var tex1 = myp5.createGraphics(1, 1);
      myp5.texture(tex1);
      assert.equal(tex1, myp5._renderer._tex);
      myp5.push();
      var tex2 = myp5.createGraphics(2, 2);
      myp5.texture(tex2);
      assert.equal(tex2, myp5._renderer._tex);
      assert.notEqual(tex1, myp5._renderer._tex);
      myp5.pop();
      assert.equal(tex1, myp5._renderer._tex);
      done();
    });

    test('push/pop and shader() works with fill', function(done) {
      myp5.createCanvas(100, 100, myp5.WEBGL);
      var fillShader1 = myp5._renderer._getLightShader();
      var fillShader2 = myp5._renderer._getColorShader();
      myp5.shader(fillShader1);
      assert.equal(fillShader1, myp5._renderer.userFillShader);
      myp5.push();
      myp5.shader(fillShader2);
      assert.equal(fillShader2, myp5._renderer.userFillShader);
      assert.notEqual(fillShader1, myp5._renderer.userFillShader);
      myp5.pop();
      assert.equal(fillShader1, myp5._renderer.userFillShader);
      done();
    });

    test('push/pop builds/unbuilds stack properly', function(done) {
      myp5.createCanvas(100, 100, myp5.WEBGL);
      var col1 = myp5.color(255, 0, 0);
      var col2 = myp5.color(0, 255, 0);
      for (var i = 0; i < 10; i++) {
        myp5.push();
        if (i % 2 === 0) {
          myp5.fill(col1);
        } else {
          myp5.fill(col2);
        }
      }
      for (var j = i; j > 0; j--) {
        if (j % 2 === 0) {
          assert.deepEqual(col2._array, myp5._renderer.curFillColor);
        } else {
          assert.deepEqual(col1._array, myp5._renderer.curFillColor);
        }
        myp5.pop();
      }
      assert.isTrue(myp5._styles.length === 0);
      done();
    });
  });

  suite('loadpixels()', function() {
    test('loadPixels color check', function(done) {
      myp5.createCanvas(100, 100, myp5.WEBGL);
      myp5.background(0, 100, 0);
      myp5.loadPixels();
      var pixels = myp5.pixels;
      assert.deepEqual(pixels[1], 100);
      assert.deepEqual(pixels[3], 255);
      done();
    });

    test('get() singlePixel color and size, with loadPixels', function(done) {
      myp5.createCanvas(100, 100, myp5.WEBGL);
      myp5.background(100, 115, 100);
      myp5.loadPixels();
      var img = myp5.get(0, 0);
      assert.isTrue(img[1] === 115);
      assert.isTrue(img.length === 4);
      done();
    });
  });

  suite('get()', function() {
    var img;
    test('get() size check', function(done) {
      myp5.createCanvas(100, 100, myp5.WEBGL);
      img = myp5.get();
      assert.deepEqual(img.width, myp5.width);
      done();
    });

    test('get() can create p5.Image', function(done) {
      myp5.createCanvas(100, 100, myp5.WEBGL);
      assert.isTrue(img instanceof p5.Image);
      done();
    });

    test('get() singlePixel color and size', function(done) {
      myp5.createCanvas(100, 100, myp5.WEBGL);
      myp5.background(100, 115, 100);
      img = myp5.get(0, 0);
      assert.isTrue(img[1] === 115);
      assert.isTrue(img.length === 4);
      myp5.loadPixels();
      img = myp5.get(0, 0);
      assert.isTrue(img[1] === 115);
      assert.isTrue(img.length === 4);
      done();
    });
  });

  suite('GL Renderer clear()', function() {
    var pg;
    var pixel;
    test('webgl graphics background draws into webgl canvas', function(done) {
      myp5.createCanvas(50, 50, myp5.WEBGL);
      myp5.background(0, 255, 255, 255);
      pg = myp5.createGraphics(25, 50, myp5.WEBGL);
      pg.background(0);
      myp5.image(pg, -myp5.width / 2, -myp5.height / 2);
      pixel = myp5.get(0, 0);
      assert.deepEqual(pixel, [0, 0, 0, 255]);
      done();
    });

    test('transparent GL graphics with GL canvas', function(done) {
      myp5.createCanvas(50, 50, myp5.WEBGL);
      pg = myp5.createGraphics(25, 50, myp5.WEBGL);
      myp5.background(0, 255, 255);
      pg.clear();
      myp5.image(pg, -myp5.width / 2, -myp5.height / 2);
      pixel = myp5.get(0, 0);
      assert.deepEqual(pixel, [0, 255, 255, 255]);
      done();
    });

    test('clear color with rgba arguments', function(done) {
      myp5.createCanvas(50, 50, myp5.WEBGL);
      myp5.clear(1, 0, 0, 1);
      pixel = myp5.get(0, 0);
      assert.deepEqual(pixel, [255, 0, 0, 255]);
      pg = myp5.createGraphics(50, 50, myp5.WEBGL);
      pg.clear(1, 0, 0, 1);
      pixel = pg.get(0, 0);
      assert.deepEqual(pixel, [255, 0, 0, 255]);
      done();
    });

    test('semi-transparent GL graphics with GL canvas', function(done) {
      myp5.createCanvas(50, 50, myp5.WEBGL);
      pg = myp5.createGraphics(25, 50, myp5.WEBGL);
      myp5.background(0, 255, 255);
      pg.background(100, 100, 100, 100);
      myp5.image(pg, -myp5.width / 2, -myp5.height / 2);
      pixel = myp5.get(0, 0);
      assert.deepEqual(pixel, [39, 194, 194, 255]);
      done();
    });

    test('webgl graphics background draws into 2D canvas', function(done) {
      myp5.createCanvas(50, 50);
      myp5.background(0, 255, 255, 255);
      pg = myp5.createGraphics(25, 50, myp5.WEBGL);
      pg.background(0);
      myp5.image(pg, 0, 0);
      pixel = myp5.get(0, 0);
      assert.deepEqual(pixel, [0, 0, 0, 255]);
      done();
    });

    test('transparent GL graphics with 2D canvas', function(done) {
      myp5.createCanvas(50, 50);
      pg = myp5.createGraphics(25, 50, myp5.WEBGL);
      myp5.background(0, 255, 255);
      pg.clear();
      myp5.image(pg, 0, 0);
      pixel = myp5.get(0, 0);
      assert.deepEqual(pixel, [0, 255, 255, 255]);
      done();
    });

    test('semi-transparent GL graphics with 2D canvas', function(done) {
      myp5.createCanvas(50, 50);
      pg = myp5.createGraphics(25, 50, myp5.WEBGL);
      myp5.background(0, 255, 255);
      pg.background(100, 100, 100, 100);
      myp5.image(pg, 0, 0);
      pixel = myp5.get(0, 0);
      assert.deepEqual(pixel, [39, 194, 194, 255]);
      done();
    });
  });

  suite('background()', function() {
    function assertAllPixelsAreColor(target, r, g, b, a) {
      target.loadPixels();
      const expectedPixels = [];
      for (let i = 0; i < target.width * target.height; i++) {
        expectedPixels.push(r, g, b, a);
      }
      assert.deepEqual([ ...target.pixels ], expectedPixels);
    }

    function testDepthGetsCleared(target) {
      target.pixelDensity(1);
      target.noStroke();
      target.fill(255, 0, 0);
      target.plane(target.width, target.height);
      assertAllPixelsAreColor(target, 255, 0, 0, 255);

      target.background(255);
      target.push();
      target.translate(0, 0, -10); // Move farther away
      target.fill(0, 0, 255);
      // expanded to fill the screen
      target.plane(target.width * 4, target.height * 4);
      target.pop();
      // The farther-away plane should not be occluded because we cleared
      // the screen with background()
      assertAllPixelsAreColor(target, 0, 0, 255, 255);
    }

    test('background() resets the depth buffer of the main canvas', function() {
      myp5.createCanvas(10, 10, myp5.WEBGL);
      testDepthGetsCleared(myp5);
    });

    test('background() resets the depth buffer of p5.Graphics', function() {
      const graphics = myp5.createGraphics(10, 10, myp5.WEBGL);
      testDepthGetsCleared(graphics);
    });
  });

  suite('blendMode()', function() {
    var testBlend = function(mode, intended) {
      myp5.blendMode(mode);
      assert.deepEqual(intended, myp5._renderer.curBlendMode);
    };

    test('blendMode sets _curBlendMode correctly', function(done) {
      myp5.createCanvas(100<response clipped><NOTE>Due to the max output limit, only part of the full response has been shown to you.</NOTE>eginShape(myp5.TESS);
      myp5.noFill();
      renderer.stroke(255, 255, 255);
      renderer.vertex(-10, -10, 0, 0);
      renderer.stroke(255, 0, 0);
      renderer.vertex(10, -10, 1, 0);
      renderer.stroke(0, 255, 0);
      renderer.vertex(10, 10, 1, 1);
      renderer.stroke(0, 0, 255);
      renderer.vertex(-10, 10, 0, 1);
      renderer.endShape(myp5.CLOSE);

      // Vertex colors are not run through tessy
      assert.deepEqual(renderer.immediateMode.geometry.vertexStrokeColors, [
        1, 1, 1, 1,
        1, 0, 0, 1,
        0, 1, 0, 1,
        0, 0, 1, 1
      ]);

      done();
    });

    test('TESS interpolates vertex data at intersections', function(done) {
      var renderer = myp5.createCanvas(10, 10, myp5.WEBGL);

      // Hourglass shape:
      //
      // 1     3
      // o     o
      // | \ / |
      // | / \ |
      // o     o
      // 4     2
      //
      // Tessy will add a vertex in the middle
      myp5.textureMode(myp5.NORMAL);
      renderer.beginShape(myp5.TESS);
      renderer.fill(255, 255, 255);
      renderer.normal(-1, -1, 1);
      renderer.vertex(-10, -10, 0, 0);
      renderer.fill(0, 255, 0);
      renderer.normal(1, 1, 1);
      renderer.vertex(10, 10, 1, 1);
      renderer.fill(255, 0, 0);
      renderer.normal(1, -1, 1);
      renderer.vertex(10, -10, 1, 0);
      renderer.fill(0, 0, 255);
      renderer.normal(-1, 1, 1);
      renderer.vertex(-10, 10, 0, 1);
      renderer.endShape(myp5.CLOSE);

      assert.equal(renderer.immediateMode.geometry.vertices.length, 6);
      assert.deepEqual(
        renderer.immediateMode.geometry.vertices[0].array(),
        [0, 0, 0]
      );
      assert.deepEqual(
        renderer.immediateMode.geometry.vertices[1].array(),
        [-10, 10, 0]
      );
      assert.deepEqual(
        renderer.immediateMode.geometry.vertices[2].array(),
        [-10, -10, 0]
      );
      assert.deepEqual(
        renderer.immediateMode.geometry.vertices[3].array(),
        [10, 10, 0]
      );
      assert.deepEqual(
        renderer.immediateMode.geometry.vertices[4].array(),
        [0, 0, 0]
      );
      assert.deepEqual(
        renderer.immediateMode.geometry.vertices[5].array(),
        [10, -10, 0]
      );

      assert.equal(renderer.immediateMode.geometry.vertexNormals.length, 6);
      assert.deepEqual(
        renderer.immediateMode.geometry.vertexNormals[0].array(),
        [0, 0, 1]
      );
      assert.deepEqual(
        renderer.immediateMode.geometry.vertexNormals[1].array(),
        [-1, 1, 1]
      );
      assert.deepEqual(
        renderer.immediateMode.geometry.vertexNormals[2].array(),
        [-1, -1, 1]
      );
      assert.deepEqual(
        renderer.immediateMode.geometry.vertexNormals[3].array(),
        [1, 1, 1]
      );
      assert.deepEqual(
        renderer.immediateMode.geometry.vertexNormals[4].array(),
        [0, 0, 1]
      );
      assert.deepEqual(
        renderer.immediateMode.geometry.vertexNormals[5].array(),
        [1, -1, 1]
      );

      assert.deepEqual(renderer.immediateMode.geometry.vertexColors, [
        0.5, 0.5, 0.5, 1,
        0, 0, 1, 1,
        1, 1, 1, 1,
        0, 1, 0, 1,
        0.5, 0.5, 0.5, 1,
        1, 0, 0, 1
      ]);

      assert.deepEqual(renderer.immediateMode.geometry.uvs, [
        0.5, 0.5,
        0, 1,
        0, 0,
        1, 1,
        0.5, 0.5,
        1, 0
      ]);

      done();
    });

    test('TESS handles vertex data perpendicular to the camera', function(done) {
      var renderer = myp5.createCanvas(10, 10, myp5.WEBGL);

      myp5.textureMode(myp5.NORMAL);
      renderer.beginShape(myp5.TESS);
      renderer.vertex(-10, 0, -10);
      renderer.vertex(10, 0, -10);
      renderer.vertex(10, 0, 10);
      renderer.vertex(-10, 0, 10);
      renderer.endShape(myp5.CLOSE);

      assert.equal(renderer.immediateMode.geometry.vertices.length, 6);
      assert.deepEqual(
        renderer.immediateMode.geometry.vertices[0].array(),
        [10, 0, 10]
      );
      assert.deepEqual(
        renderer.immediateMode.geometry.vertices[1].array(),
        [-10, 0, -10]
      );
      assert.deepEqual(
        renderer.immediateMode.geometry.vertices[2].array(),
        [10, 0, -10]
      );
      assert.deepEqual(
        renderer.immediateMode.geometry.vertices[3].array(),
        [-10, 0, -10]
      );
      assert.deepEqual(
        renderer.immediateMode.geometry.vertices[4].array(),
        [10, 0, 10]
      );
      assert.deepEqual(
        renderer.immediateMode.geometry.vertices[5].array(),
        [-10, 0, 10]
      );

      done();
    });
  });

  suite('color interpolation', function() {
    test('strokes should interpolate colors between vertices', function(done) {
      const renderer = myp5.createCanvas(512, 4, myp5.WEBGL);

      // far left color: (242, 236, 40)
      // far right color: (42, 36, 240)
      // expected middle color: (142, 136, 140)

      renderer.strokeWeight(4);
      renderer.beginShape();
      renderer.stroke(242, 236, 40);
      renderer.vertex(-256, 0);
      renderer.stroke(42, 36, 240);
      renderer.vertex(256, 0);
      renderer.endShape();

      assert.deepEqual(myp5.get(0, 2), [242, 236, 40, 255]);
      assert.deepEqual(myp5.get(256, 2), [142, 136, 140, 255]);
      assert.deepEqual(myp5.get(511, 2), [42, 36, 240, 255]);

      done();
    });

    test('bezierVertex() should interpolate curFillColor', function(done) {
      const renderer = myp5.createCanvas(256, 256, myp5.WEBGL);

      // start color: (255, 255, 255)
      // end color: (255, 0, 0)
      // Intermediate values are expected to be approximately half the value.

      renderer.beginShape();
      renderer.fill(255);
      renderer.vertex(-128, -128);
      renderer.fill(255, 0, 0);
      renderer.bezierVertex(128, -128, 128, 128, -128, 128);
      renderer.endShape();

      assert.deepEqual(myp5.get(128, 128), [255, 129, 129, 255]);

      done();
    });

    test('bezierVertex() should interpolate curStrokeColor', function(done) {
      const renderer = myp5.createCanvas(256, 256, myp5.WEBGL);

      // start color: (255, 255, 255)
      // end color: (255, 0, 0)
      // Intermediate values are expected to be approximately half the value.

      renderer.strokeWeight(5);
      renderer.beginShape();
      myp5.noFill();
      renderer.stroke(255);
      renderer.vertex(-128, -128);
      renderer.stroke(255, 0, 0);
      renderer.bezierVertex(128, -128, 128, 128, -128, 128);
      renderer.endShape();

      assert.deepEqual(myp5.get(190, 128), [255, 128, 128, 255]);

      done();
    });

    test('quadraticVertex() should interpolate curFillColor', function(done) {
      const renderer = myp5.createCanvas(256, 256, myp5.WEBGL);

      // start color: (255, 255, 255)
      // end color: (255, 0, 0)
      // Intermediate values are expected to be approximately half the value.

      renderer.beginShape();
      renderer.fill(255);
      renderer.vertex(-128, -128);
      renderer.fill(255, 0, 0);
      renderer.quadraticVertex(256, 0, -128, 128);
      renderer.endShape();

      assert.deepEqual(myp5.get(128, 128), [255, 128, 128, 255]);

      done();
    });

    test('quadraticVertex() should interpolate curStrokeColor', function(done) {
      const renderer = myp5.createCanvas(256, 256, myp5.WEBGL);

      // start color: (255, 255, 255)
      // end color: (255, 0, 0)
      // Intermediate values are expected to be approximately half the value.

      renderer.strokeWeight(5);
      renderer.beginShape();
      myp5.noFill();
      renderer.stroke(255);
      renderer.vertex(-128, -128);
      renderer.stroke(255, 0, 0);
      renderer.quadraticVertex(256, 0, -128, 128);
      renderer.endShape();

      assert.deepEqual(myp5.get(190, 128), [255, 128, 128, 255]);

      done();
    });

    test('geometry without stroke colors use curStrokeColor', function(done) {
      const renderer = myp5.createCanvas(256, 256, myp5.WEBGL);
      myp5.background(255);
      myp5.fill(255);
      myp5.stroke(0);
      myp5.strokeWeight(4);
      myp5.rectMode(myp5.CENTER);
      myp5.rect(0, 0, myp5.width, myp5.height);

      assert.equal(renderer._useLineColor, false);
      assert.deepEqual(myp5.get(128, 0), [0, 0, 0, 255]);
      done();
    });

    test('geometry with stroke colors use their colors', function(done) {
      const renderer = myp5.createCanvas(256, 256, myp5.WEBGL);
      const myGeom = new p5.Geometry(1, 1, function() {
        this.gid = 'strokeColorTest';
        this.vertices.push(myp5.createVector(-128, -128));
        this.vertices.push(myp5.createVector(-128, 128));
        this.vertices.push(myp5.createVector(128, 128));
        this.vertices.push(myp5.createVector(128, -128));
        this.faces.push([0, 1, 2]);
        this.faces.push([0, 2, 3]);
        this.edges.push([0, 1]);
        this.edges.push([1, 2]);
        this.edges.push([2, 3]);
        this.edges.push([3, 0]);
        this.vertexStrokeColors.push(
          0, 0, 0, 1,
          1, 0, 0, 1,
          0, 0, 1, 1,
          0, 1, 0, 1
        );
        this._edgesToVertices();
      });
      myp5.background(255);
      myp5.fill(255);
      myp5.strokeWeight(4);
      myp5.stroke(0);
      myp5.model(myGeom);

      assert.equal(renderer._useLineColor, true);
      assert.deepEqual(myp5.get(128, 0), [127, 0, 128, 255]);
      done();
    });

    test('immediate mode uses stroke colors', function(done) {
      const renderer = myp5.createCanvas(256, 256, myp5.WEBGL);
      myp5.background(255);
      myp5.fill(255);
      myp5.strokeWeight(4);
      myp5.beginShape();
      myp5.stroke(0);
      myp5.vertex(-128, -128);
      myp5.stroke(255, 0, 0);
      myp5.vertex(-128, 128);
      myp5.stroke(0, 0, 255);
      myp5.vertex(128, 128);
      myp5.stroke(0, 255, 0);
      myp5.vertex(128, -128);
      myp5.endShape(myp5.CLOSE);

      assert.equal(renderer._useLineColor, true);
      assert.deepEqual(myp5.get(128, 0), [127, 0, 128, 255]);
      done();
    });
  });

  suite('interpolation of vertex colors', function(){
    test('immediate mode uses vertex colors (noLight)', function(done) {
      const renderer = myp5.createCanvas(256, 256, myp5.WEBGL);

      // upper color: (200, 0, 0, 255);
      // lower color: (0, 0, 200, 255);
      // expected center color: (100, 0, 100, 255);

      myp5.beginShape();
      myp5.fill(200, 0, 0);
      myp5.vertex(-128, -128);
      myp5.fill(200, 0, 0);
      myp5.vertex(128, -128);
      myp5.fill(0, 0, 200);
      myp5.vertex(128, 128);
      myp5.fill(0, 0, 200);
      myp5.vertex(-128, 128);
      myp5.endShape(myp5.CLOSE);

      assert.equal(renderer._useVertexColor, true);
      assert.deepEqual(myp5.get(128, 128), [100, 0, 100, 255]);
      done();
    });

    test('immediate mode uses vertex colors (light)', function(done) {
      const renderer = myp5.createCanvas(256, 256, myp5.WEBGL);

      myp5.directionalLight(255, 255, 255, 0, 0, -1);
      // diffuseFactor:0.73
      // so, expected color is (73, 0, 73, 255).

      myp5.beginShape();
      myp5.fill(200, 0, 0);
      myp5.vertex(-128, -128);
      myp5.fill(200, 0, 0);
      myp5.vertex(128, -128);
      myp5.fill(0, 0, 200);
      myp5.vertex(128, 128);
      myp5.fill(0, 0, 200);
      myp5.vertex(-128, 128);
      myp5.endShape(myp5.CLOSE);

      assert.equal(renderer._useVertexColor, true);
      assert.deepEqual(myp5.get(128, 128), [73, 0, 73, 255]);
      done();
    });

    test('geom without vertex colors use curFillCol (noLight)', function(done) {
      const renderer = myp5.createCanvas(256, 256, myp5.WEBGL);

      // expected center color is curFillColor.

      myp5.fill(200, 0, 200);
      myp5.rectMode(myp5.CENTER);
      myp5.rect(0, 0, myp5.width, myp5.height);

      assert.equal(renderer._useVertexColor, false);
      assert.deepEqual(myp5.get(128, 128), [200, 0, 200, 255]);
      done();
    });

    test('geom without vertex colors use curFillCol (light)', function(done) {
      const renderer = myp5.createCanvas(256, 256, myp5.WEBGL);

      myp5.directionalLight(255, 255, 255, 0, 0, -1);
      // diffuseFactor:0.73
      // so, expected color is (146, 0, 146, 255).

      myp5.fill(200, 0, 200);
      myp5.rectMode(myp5.CENTER);
      myp5.rect(0, 0, myp5.width, myp5.height);

      assert.equal(renderer._useVertexColor, false);
      assert.deepEqual(myp5.get(128, 128), [146, 0, 146, 255]);
      done();
    });

    test('geom with vertex colors use their color (noLight)', function(done) {
      const renderer = myp5.createCanvas(256, 256, myp5.WEBGL);

      // upper color: (200, 0, 0, 255);
      // lower color: (0, 0, 200, 255);
      // expected center color: (100, 0, 100, 255);

      const myGeom = new p5.Geometry(1, 1, function() {
        this.gid = 'vertexColorTestWithNoLights';
        this.vertices.push(myp5.createVector(-128, -128));
        this.vertices.push(myp5.createVector(128, -128));
        this.vertices.push(myp5.createVector(128, 128));
        this.vertices.push(myp5.createVector(-128, 128));
        this.faces.push([0, 1, 2]);
        this.faces.push([0, 2, 3]);
        this.vertexColors.push(
          200/255, 0, 0, 1,
          200/255, 0, 0, 1,
          0, 0, 200/255, 1,
          0, 0, 200/255, 1
        );
        this.computeNormals();
      });

      myp5.noStroke();
      myp5.model(myGeom);

      assert.equal(renderer._useVertexColor, true);
      assert.deepEqual(myp5.get(128, 128), [100, 0, 100, 255]);
      done();
    });

    test('geom with vertex colors use their color (light)', function(done) {
      const renderer = myp5.createCanvas(256, 256, myp5.WEBGL);

      const myGeom = new p5.Geometry(1, 1, function() {
        this.gid = 'vertexColorTestWithLighs';
        this.vertices.push(myp5.createVector(-128, -128));
        this.vertices.push(myp5.createVector(128, -128));
        this.vertices.push(myp5.createVector(128, 128));
        this.vertices.push(myp5.createVector(-128, 128));
        this.faces.push([0, 1, 2]);
        this.faces.push([0, 2, 3]);
        this.vertexColors.push(
          200/255, 0, 0, 1,
          200/255, 0, 0, 1,
          0, 0, 200/255, 1,
          0, 0, 200/255, 1
        );
        this.computeNormals();
      });

      myp5.directionalLight(255, 255, 255, 0, 0, -1);
      // diffuseFactor:0.73
      // so, expected color is (73, 0, 73, 255).
      myp5.noStroke();
      myp5.model(myGeom);

      assert.equal(renderer._useVertexColor, true);
      assert.deepEqual(myp5.get(128, 128), [73, 0, 73, 255]);
      done();
    });
  });

  suite('setAttributes', function() {
    test('It leaves a reference to the correct canvas', function(done) {
      const renderer = myp5.createCanvas(10, 10, myp5.WEBGL);
      assert.equal(myp5.canvas, renderer.canvas);

      myp5.setAttributes({ alpha: true });
      assert.equal(myp5.canvas, renderer.canvas);
      done();
    });
  });
});
[The command completed with exit code 0.]
[Current working directory: /workspace]
[Python interpreter: /usr/bin/python]
[Command finished with exit code 0]