suite('Caching', function() {
  // this.timeout(5000);
  // CACHING SHAPE

  test('cache simple rectangle', function() {
    var stage = addStage();

    var layer = new Konva.Layer();

    var rect = new Konva.Rect({
      x: 100,
      y: 50,
      width: 100,
      height: 50,
      fill: 'green',
      draggable: true
    });
    rect.cache();

    layer.add(rect);
    stage.add(layer);

    var canvas = createCanvas();
    var context = canvas.getContext('2d');
    context.beginPath();
    context.rect(100, 50, 100, 50);
    context.closePath();
    context.fillStyle = 'green';
    context.fill();

    compareLayerAndCanvas(layer, canvas, 10);
    cloneAndCompareLayer(layer);
  });

  test('cache simple rectangle with transform', function() {
    var stage = addStage();

    var layer = new Konva.Layer();

    var rect = new Konva.Rect({
      x: 100,
      y: 50,
      width: 100,
      height: 50,
      rotation: 45,
      scaleY: 2,
      fill: 'green'
    });
    rect.cache();

    layer.add(rect);
    stage.add(layer);

    var canvas = createCanvas();
    var context = canvas.getContext('2d');
    context.translate(100, 50);
    context.rotate(Math.PI / 4);
    context.beginPath();
    context.rect(0, 0, 100, 100);
    context.closePath();
    context.fillStyle = 'green';
    context.fill();

    compareLayerAndCanvas(layer, canvas, 200);
    cloneAndCompareLayer(layer, 150);
  });

  test('cache rectangle with fill and stroke', function() {
    var stage = addStage();

    var layer = new Konva.Layer();

    var rect = new Konva.Rect({
      x: 100,
      y: 50,
      width: 100,
      height: 50,
      fill: 'green',
      stroke: 'black',
      strokeWidth: 20
    });
    rect.cache();

    layer.add(rect);
    stage.add(layer);

    var canvas = createCanvas();
    var context = canvas.getContext('2d');
    context.beginPath();
    context.rect(100, 50, 100, 50);
    context.closePath();
    context.fillStyle = 'green';
    context.fill();
    context.lineWidth = 20;
    context.stroke();
    compareLayerAndCanvas(layer, canvas, 50);
    cloneAndCompareLayer(layer, 50);
  });

  test('cache rectangle with fill and opacity', function() {
    var stage = addStage();

    var layer = new Konva.Layer();

    var rect = new Konva.Rect({
      x: 100,
      y: 50,
      width: 100,
      height: 50,
      fill: 'green',
      opacity: 0.5
    });
    rect.cache();
    rect.opacity(0.3);

    layer.add(rect);
    stage.add(layer);

    var canvas = createCanvas();
    var context = canvas.getContext('2d');
    context.globalAlpha = 0.3;
    context.beginPath();
    context.rect(100, 50, 100, 50);
    context.closePath();
    context.fillStyle = 'green';
    context.fill();
    compareLayerAndCanvas(layer, canvas, 5);
  });

  test('cache rectangle with fill, stroke opacity', function() {
    var stage = addStage();

    var layer = new Konva.Layer();

    var rect = new Konva.Rect({
      x: 100,
      y: 50,
      width: 100,
      height: 50,
      fill: 'green',
      opacity: 0.5,
      stroke: 'black',
      strokeWidth: 10
    });
    rect.cache();
    rect.opacity(0.3);

    layer.add(rect);
    stage.add(layer);

    cloneAndCompareLayer(layer, 100);
  });

  // skip, because opacity rendering of cached shape is different
  // nothing we can do here
  test.skip('cache rectangle with fill, shadow and opacity', function() {
    var stage = addStage();

    var layer = new Konva.Layer();

    var rect = new Konva.Rect({
      x: 10,
      y: 10,
      width: 100,
      height: 50,
      fill: 'green',
      opacity: 0.5,
      shadowBlur: 10,
      shadowColor: 'black',
      draggable: true
    });
    // rect.cache();
    // rect.opacity(0.3);

    layer.add(rect.clone({ y: 50, x: 50, shadowEnabled: false }));
    layer.add(rect);
    stage.add(layer);

    cloneAndCompareLayer(layer, 10);
  });

  test('cache rectangle with fill and simple shadow', function() {
    Konva.pixelRatio = 1;
    var stage = addStage();

    var layer = new Konva.Layer();

    var rect = new Konva.Rect({
      x: 100,
      y: 50,
      width: 100,
      height: 50,
      fill: 'green',
      shadowColor: 'black',
      shadowBlur: 10,
      draggable: true
    });
    rect.cache();

    layer.add(rect);
    stage.add(layer);

    var canvas = createCanvas();
    var context = canvas.getContext('2d');
    context.beginPath();
    context.rect(100, 50, 100, 50);
    context.closePath();
    context.fillStyle = 'green';
    context.shadowColor = 'black';
    context.shadowBlur = 10;
    context.fill();

    showCanvas(rect._getCanvasCache().scene._canvas);
    showCanvas(rect._getCanvasCache().hit._canvas);
    showHit(layer);
    compareLayerAndCanvas(layer, canvas, 10);
    Konva.pixelRatio = undefined;
  });

  test('cache rectangle with fill and shadow with offset', function() {
    var stage = addStage();

    var layer = new Konva.Layer();

    var rect = new Konva.Rect({
      x: 100,
      y: 50,
      width: 50,
      height: 25,
      fill: 'green',
      shadowOffsetX: 10,
      shadowOffsetY: 10,
      shadowColor: 'black',
      shadowBlur: 10
    });
    rect.cache();

    layer.add(rect);
    stage.add(layer);

    var canvas = createCanvas();
    var context = canvas.getContext('2d');

    context.translate(100, 50);
    context.beginPath();
    context.rect(0, 0, 50, 25);
    context.closePath();
    context.fillStyle = 'green';
    context.shadowColor = 'black';
    context.shadowBlur = 10 * canvas.ratio;
    context.shadowOffsetX = 10 * canvas.ratio;
    context.shadowOffsetY = 10 * canvas.ratio;
    context.fill();
    compareLayerAndCanvas(layer, canvas, 50);
  });

  test('cache rectangle with fill and shadow with negative offset', function() {
    var stage = addStage();

    var layer = new Konva.Layer();

    var rect = new Konva.Rect({
      x: 100,
      y: 50,
      width: 50,
      height: 25,
      fill: 'green',
      shadowOffsetX: -10,
      shadowOffsetY: -10,
      shadowColor: 'black',
      shadowBlur: 10
    });
    rect.cache();

    layer.add(rect);
    stage.add(layer);

    var canvas = createCanvas();
    var context = canvas.getContext('2d');

    context.translate(100, 50);
    context.beginPath();
    context.rect(0, 0, 50, 25);
    context.closePath();
    context.fillStyle = 'green';
    context.shadowColor = 'black';
    context.shadowBlur = 10 * canvas.ratio;
    context.shadowOffsetX = -10 * canvas.ratio;
    context.shadowOffsetY = -10 * canvas.ratio;
    context.fill();
    compareLayerAndCanvas(layer, canvas, 50);
  });

  test('cache rectangle with fill and shadow and some transform', function() {
    var stage = addStage();

    var layer = new Konva.Layer();

    var rect = new Konva.Rect({
      x: 100,
      y: 50,
      width: 50,
      height: 25,
      fill: 'green',
      shadowOffsetX: -10,
      shadowOffsetY: -10,
      shadowColor: 'black',
      shadowBlur: 10,
      offsetX: 50,
      offsetY: 25
    });
    rect.cache();

    layer.add(rect);
    stage.add(layer);

    var canvas = createCanvas();
    var context = canvas.getContext('2d');

    context.translate(50, 25);
    context.beginPath();
    context.rect(0, 0, 50, 25);
    context.closePath();
    context.fillStyle = 'green';
    context.shadowColor = 'black';
    context.shadowBlur = 10 * canvas.ratio;
    context.shadowOffsetX = -10 * canvas.ratio;
    context.shadowOffsetY = -10 * canvas.ratio;
    context.fill();
    compareLayerAndCanvas(layer, canvas, 50);
  });

  // CACHING CONTAINERS
  test('cache group with simple rectangle', function() {
    var stage = addStage();

    var layer = new Konva.Layer();

    var group = new Konva.Group({
      x: 100,
      y: 50
    });

    var rect = new Konva.Rect({
      width: 100,
      height: 50,
      fill: 'green'
    });
    group.add(rect);
    group.cache();

    layer.add(group);
    stage.add(layer);

    var canvas = createCanvas();
    var context = canvas.getContext('2d');
    context.beginPath();
    context.rect(100, 50, 100, 50);
    context.closePath();
    context.fillStyle = 'green';
    context.fill();
    compareLayerAndCanvas(layer, canvas, 10);
    cloneAndCompareLayer(layer);
  });

  test('cache group with simple rectangle with transform', function() {
    var stage = addStage();

    var layer = new Konva.Layer();

    var group = new Konva.Group({
      x: 50,
      y: 25
    });

    var rect = new Konva.Rect({
      x: 50,
      y: 25,
      width: 100,
      height: 50,
      fill: 'green',
      rotation: 45
    });
    group.add(rect);
    group.cache();

    layer.add(group);
    stage.add(layer);
    cloneAndCompareLayer(layer, 200);
  });

  test('cache group with several shape with transform', function() {
    var stage = addStage();

    var layer = new Konva.Layer();

    var group = new Konva.Group({
      x: 50,
      y: 25
    });

    var rect = new Konva.Rect({
      x: 50,
      y: 25,
      width: 100,
      height: 50,
      fill: 'green',
      shadowOffsetX: 10,
      shadowOffsetY: 10,
      shadowBlur: 10
    });
    group.add(rect);

    var circle = new Konva.Circle({
      x: 250,
      y: 50,
      radius: 25,
      fill: 'red',
      // rotation on circle should not have any effects
      stroke: 'black',
      rotation: 45,
      scaleX: 2,
      scaleY: 2
    });
    group.add(circle);

    group.cache();

    layer.add(group);
    stage.add(layer);

    var canvas = createCanvas();
    var context = canvas.getContext('2d');

    // draw rect
    context.save();
    context.beginPath();
    context.rect(100, 50, 100, 50);
    context.closePath();
    context.fillStyle = 'green';
    context.shadowColor = 'black';
    context.shadowBlur = 10 * canvas.ratio;
    context.shadowOffsetX = 10 * canvas.ratio;
    context.shadowOffsetY = 10 * canvas.ratio;
    context.fill();
    context.restore();

    // circle
    context.save();
    context.beginPath();
    context.arc(300, 75, 50, 0, Math.PI * 2);
    context.closePath();
    context.fillStyle = 'red';
    context.lineWidth = 4;
    context.fill();
    context.stroke();
    context.restore();

    compareLayerAndCanvas(layer, canvas, 150);

    // recache
    group.cache();
    layer.draw();
    compareLayerAndCanvas(layer, canvas, 150);
  });

  test('cache group with rectangle and text', function() {
    var stage = addStage();

    var layer = new Konva.Layer();

    var button = new Konva.Group({
      width: 100,
      height: 50,
      draggable: true
    });

    var face = new Konva.Rect({
      fill: 'red',
      x: 0,
      y: 0,
      width: 100,
      height: 50
    });

    var text = new Konva.Text({
      text: 'Wrong button',
      x: 15,
      y: 20
    });

    button.add(face);
    button.add(text);

    button.cache();

    layer.add(button);
    stage.add(layer);

    cloneAndCompareLayer(layer, 100);
  });

  test('cache layer with several shape with transform', function() {
    var stage = addStage();

    var layer = new Konva.Layer({
      draggable: true
    });

    var group = new Konva.Group({
      x: 50,
      y: 25
    });

    var rect = new Konva.Rect({
      x: 50,
      y: 25,
      width: 100,
      height: 50,
      fill: 'green',
      shadowOffsetX: 10,
      shadowOffsetY: 10,
      shadowBlur: 10
    });
    group.add(rect);

    var circle = new Konva.Circle({
      x: 250,
      y: 50,
      radius: 25,
      fill: 'red',
      // rotation on circle should not have any effects
      rotation: 45,
      stroke: 'black',
      scaleX: 2,
      scaleY: 2
    });
    group.add(circle);

    group.cache();

    layer.add(group);
    stage.add(layer);

    var canvas = createCanvas();
    var context = canvas.getContext('2d');

    // draw rect
    context.save();
    context.beginPath();
    context.rect(100, 50, 100, 50);
    context.closePath();
    context.fillStyle = 'green';
    context.shadowColor = 'black';
    context.shadowBlur = 10 * canvas.ratio;
    context.shadowOffsetX = 10 * canvas.ratio;
    context.shadowOffsetY = 10 * canvas.ratio;
    context.fill();
    context.restore();

    // circle
    context.save();
    context.beginPath();
    context.arc(300, 75, 50, 0, Math.PI * 2);
    context.closePath();
    context.fillStyle = 'red';
    context.lineWidth = 4;
    context.fill();
    context.stroke();
    context.restore();

    compareLayerAndCanvas(layer, canvas, 150);

    // recache
    group.cache();
    layer.draw();
    compareLayerAndCanvas(layer, canvas, 150);
  });

  test('cache shape that is larger than stage', function() {
    var stage = addStage();
    var layer = new Konva.Layer();
    var group = new Konva.Group();
    var circle = new Konva.Circle({
      x: 74,
      y: 74,
      radius: 300,
      fill: 'red',
      stroke: 'black',
      strokeWidth: 4,
      scaleX: 1 / 2,
      scaleY: 1 / 2
    });

    group.add(circle);
    layer.add(group);
    stage.add(layer);

    assert.equal(circle._getCanvasCache(), undefined);

    var canvas = createCanvas();
    var context = canvas.getContext('2d');
    // circle
    context.save();
    context.beginPath();
    context.arc(74, 74, 150, 0, Math.PI * 2);
    context.closePath();
    context.fillStyle = 'red';
    context.lineWidth = 2;
    context.fill();
    context.stroke();
    context.restore();

    compareLayerAndCanvas(layer, canvas, 150);
  });

  test('cache shape that is larger than stage but need buffer canvas', function() {
    var stage = addStage();
    var layer = new Konva.Layer();
    var group = new Konva.Group();
    var circle = new Konva.Circle({
      x: stage.width() / 2,
      y: stage.height() / 2,
      radius: 400,
      fill: 'red',
      stroke: 'black',
      strokeWidth: 50,
      opacity: 0.5,
      scaleX: 1 / 5,
      scaleY: 1 / 5
    });

    group.add(circle);
    layer.add(group);
    stage.add(layer);
    circle.cache();
    layer.draw();

    cloneAndCompareLayer(layer, 200);
  });

  test('cache nested groups', function() {
    var stage = addStage();
    var layer = new Konva.Layer();

    var groupOuter = new Konva.Group({
      x: 50,
      y: 10
    });

    var groupInner = new Konva.Group({
      x: 10,
      y: 10,
      draggable: true
    });
    var rect = new Konva.Rect({
      width: 50,
      height: 50,
      stroke: 'grey',
      strokeWidth: 3,
      fill: 'yellow'
    });

    var text = new Konva.Text({
      x: 18,
      y: 15,
      text: 'A',
      fill: 'black',
      fontSize: 24
    });

    groupInner.add(rect);
    groupInner.add(text);

    groupOuter.add(groupInner);

    layer.add(groupOuter);
    stage.add(layer);

    groupInner.cache();

    layer.draw();
    cloneAndCompareLayer(layer, 150);

    groupInner.clearCache();
    groupOuter.cache();
    layer.draw();
    cloneAndCompareLayer(layer, 150);

    groupOuter.clearCache();
    groupInner.clearCache();
    rect.cache();
    layer.draw();
    cloneAndCompareLayer(layer, 150);
  });

  test('test group with circle + buffer canvas usage', function() {
    var stage = addStage();
    var layer = new Konva.Layer();
    stage.add(layer);

    var group = new Konva.Group({
      x: 100,
      y: 100,
      draggable: true
    });
    layer.add(group);

    var circle = new Konva.Circle({
      radius: 10,
      // fill: 'white',
      fillRadialGradientStartRadius: 0,
      fillRadialGradientEndRadius: 10,
      fillRadialGradientColorStops: [0, 'red', 0.5, 'yellow', 1, 'black'],
      opacity: 0.4,
      strokeHitEnabled: false,
      stroke: 'rgba(0,0,0,0)'
    });
    group.add(circle);
    group.cache();
    stage.draw();

    cloneAndCompareLayer(layer, 200);
  });

  test('test group with opacity', function() {
    var stage = addStage();
    var layer = new Konva.Layer();
    stage.add(layer);

    var group = new Konva.Group({
      x: 100,
      y: 100,
      draggable: true
    });
    layer.add(group);

    var circle = new Konva.Circle({
      radius: 10,
      fillRadialGradientStartRadius: 0,
      fillRadialGradientEndRadius: 10,
      fillRadialGradientColorStops: [0, 'red', 0.5, 'yellow', 1, 'black'],
      opacity: 0.4,
      strokeHitEnabled: false,
      stroke: 'rgba(0,0,0,0)'
    });
    group.add(circle);
    group.cache();
    stage.draw();

    cloneAndCompareLayer(layer, 210);
  });

  test('cache group with rectangle with fill and opacity', function() {
    var stage = addStage();

    var layer = new Konva.Layer();

    var group = new Konva.Group({
      opacity: 0.5
    });

    var rect = new Konva.Rect({
      x: 100,
      y: 50,
      width: 100,
      height: 50,
      fill: 'green'
    });

    group.add(rect);
    layer.add(group);
    stage.add(layer);

    group.cache();
    layer.draw();

    var canvas = createCanvas();
    var context = canvas.getContext('2d');
    context.globalAlpha = 0.5;
    context.beginPath();
    context.rect(100, 50, 100, 50);
    context.closePath();
    context.fillStyle = 'green';
    context.fill();
    compareLayerAndCanvas(layer, canvas, 5);
  });

  test('even if parent is not visible cache should be created', function() {
    var stage = addStage();

    var layer = new Konva.Layer({
      visible: false
    });

    var rect = new Konva.Rect({
      x: 100,
      y: 50,
      width: 100,
      height: 100,
      fill: 'green'
    });

    layer.add(rect);
    stage.add(layer);

    rect.cache();
    layer.visible(true);
    layer.draw();

    var canvas = createCanvas();
    var context = canvas.getContext('2d');
    context.beginPath();
    context.rect(100, 50, 100, 100);
    context.closePath();
    context.fillStyle = 'green';
    context.fill();
    showHit(layer);
    compareLayerAndCanvas(layer, canvas, 5);
    assert.equal(stage.getIntersection({ x: 150, y: 100 }), rect);
  });

  // hard to fix
  test.skip('even if parent is not visible cache should be created - test for group', function() {
    var stage = addStage();

    var layer = new Konva.Layer({
      visible: false
    });

    var group = new Konva.Group({
      opacity: 0.5
    });

    var rect = new Konva.Rect({
      x: 100,
      y: 50,
      width: 100,
      height: 100,
      fill: 'green'
    });

    group.add(rect);
    layer.add(group);
    stage.add(layer);

    group.cache();
    layer.visible(true);
    layer.draw();

    var canvas = createCanvas();
    var context = canvas.getContext('2d');
    context.globalAlpha = 0.5;
    context.beginPath();
    context.rect(100, 50, 100, 100);
    context.closePath();
    context.fillStyle = 'green';
    context.fill();
    compareLayerAndCanvas(layer, canvas, 5);
    assert.equal(stage.getIntersection({ x: 150, y: 100 }), rect);
  });

  it('listening false on a shape should not create hit area', function() {
    var stage = addStage();

    var layer = new Konva.Layer();
    stage.add(layer);

    var bigCircle = new Konva.Circle({
      x: 100,
      y: 100,
      radius: 100,
      fill: 'green'
    });

    layer.add(bigCircle);

    var smallCircle = new Konva.Circle({
      x: 100,
      y: 100,
      radius: 50,
      fill: 'red',
      listening: false
    });

    layer.add(smallCircle);
    smallCircle.cache();
    layer.draw();

    var shape = stage.getIntersection({ x: 100, y: 100 });
    assert.equal(shape, bigCircle);
  });

  it('listening false on a shape inside group should not create hit area', function() {
    var stage = addStage();

    var layer = new Konva.Layer();
    stage.add(layer);

    var group = new Konva.Group();
    layer.add(group);

    var bigCircle = new Konva.Circle({
      x: 100,
      y: 100,
      radius: 100,
      fill: 'green'
    });

    group.add(bigCircle);

    var smallCircle = new Konva.Circle({
      x: 100,
      y: 100,
      radius: 50,
      fill: 'red',
      listening: false
    });

    group.add(smallCircle);
    group.cache();

    layer.draw();
    var shape = stage.getIntersection({ x: 100, y: 100 });
    assert.equal(shape, bigCircle);
  });
  it('listening false on a group inside a group should not create hit area', function() {
    var stage = addStage();

    var layer = new Konva.Layer();
    stage.add(layer);

    var group = new Konva.Group();
    layer.add(group);

    var bigCircle = new Konva.Circle({
      x: 100,
      y: 100,
      radius: 100,
      fill: 'green'
    });
    group.add(bigCircle);

    var innerGroup = new Konva.Group({
      listening: false
    });
    group.add(innerGroup);

    var smallCircle = new Konva.Circle({
      x: 100,
      y: 100,
      radius: 50,
      fill: 'red'
    });

    innerGroup.add(smallCircle);
    group.cache();

    layer.draw();
    var shape = stage.getIntersection({ x: 100, y: 100 });
    assert.equal(shape, bigCircle);
  });

  // for performance reasons
  it('do no call client rect calculation, if we do not need it', function() {
    var stage = addStage();

    var layer = new Konva.Layer();
    stage.add(layer);

    var group = new Konva.Group();
    layer.add(group);

    var bigCircle = new Konva.Circle({
      x: 100,
      y: 100,
      radius: 100,
      fill: 'green'
    });
    group.add(bigCircle);

    layer.draw();

    var called = false;
    group.getClientRect = function() {
      called = true;
    };
    group.cache({
      x: 0,
      y: 0,
      width: 100,
      height: 100
    });

    assert.equal(called, false);
  });

  // for performance reasons
  it('caching should skip clearing internal caching for perf boos', function() {
    var stage = addStage();

    var layer = new Konva.Layer();
    stage.add(layer);

    var bigCircle = new Konva.Circle({
      x: 100,
      y: 100,
      radius: 100,
      fill: 'green'
    });
    layer.add(bigCircle);

    layer.cache();

    var callCount = 0;
    bigCircle._clearSelfAndDescendantCache = function() {
      callCount += 1;
    };

    layer.x(10);
    assert.equal(callCount, 0);
    layer.clearCache();
    // make sure all cleared for children
    assert.equal(callCount, 1);
  });

  it('check caching with global composite operation', function() {
    var stage = addStage();

    const layer = new Konva.Layer();
    stage.add(layer);

    const bg = new Konva.Rect({
      x: 0,
      y: 0,
      width: stage.width(),
      height: stage.height(),
      fill: 'lightgray'
    });
    layer.add(bg);

    const group = new Konva.Group();
    layer.add(group);

    const rect = new Konva.Rect({
      x: 10,
      y: 0,
      width: 200,
      height: 100,
      fill: 'blue',
      draggable: true
    });
    group.add(rect);

    const maskgroup = new Konva.Group({});
    group.add(maskgroup);

    const mask = new Konva.Rect({
      x: 50,
      y: 0,
      width: 100,
      height: 100,
      fill: 'black'
    });
    maskgroup.add(mask);

    maskgroup.cache();
    var canvasBefore = maskgroup._cache.get('canvas').scene._canvas;

    maskgroup.globalCompositeOperation('destination-in');
    maskgroup.cache();
    var canvasAfter = maskgroup._cache.get('canvas').scene._canvas;

    compareCanvases(canvasBefore, canvasAfter);

    maskgroup.clearCache();

    layer.draw();
    // no caches - mask group clipped all drawing
    assert.equal(stage.getIntersection({ x: 5, y: 20 }), null);
    assert.equal(stage.getIntersection({ x: 55, y: 20 }), rect);

    // cache inner mask group - same result
    maskgroup.cache();
    layer.draw();
    assert.equal(stage.getIntersection({ x: 5, y: 20 }), null);
    assert.equal(stage.getIntersection({ x: 55, y: 20 }), rect);

    // cache group
    // background will be visible now, because globalCompositeOperation
    // will work inside cached parent only
    group.cache();
    layer.draw();

    assert.equal(stage.getIntersection({ x: 5, y: 20 }), bg);
    assert.equal(stage.getIntersection({ x: 55, y: 20 }), rect);
  });

  it('recache should update internal caching', function() {
    var stage = addStage();

    var layer = new Konva.Layer();
    stage.add(layer);

    var bigCircle = new Konva.Circle({
      x: 100,
      y: 100,
      radius: 100,
      fill: 'red',
      draggable: true
    });
    layer.add(bigCircle);

    bigCircle.cache();

    layer.draw();

    var d = layer.getContext().getImageData(100, 100, 1, 1).data;
    assert.equal(d[0], 255, 'see red');

    bigCircle.fill('blue');
    bigCircle.cache();

    layer.draw();
    d = layer.getContext().getImageData(100, 100, 1, 1).data;
    assert.equal(d[0], 0, 'no red');
    assert.equal(d[2], 255, 'see blue');
  });

  it('recache with filters', function() {
    var stage = addStage();

    var layer = new Konva.Layer();
    stage.add(layer);

    var bigCircle = new Konva.Circle({
      x: 100,
      y: 100,
      radius: 100,
      fill: 'red',
      draggable: true
    });
    layer.add(bigCircle);

    bigCircle.filters([Konva.Filters.Blur]);
    bigCircle.blurRadius(10);
    bigCircle.cache();

    layer.draw();
    bigCircle.cache();

    layer.draw();

    var d = layer.getContext().getImageData(100, 100, 1, 1).data;
    assert.equal(d[0], 255, 'see red');
  });
});
