Typescript conversion (#1828)

* initial typescript conversion

* test: update overflow+transform ref test

* fix: correctly render pseudo element content

* fix: testrunner build

* fix: karma test urls

* test: update underline tests with <u> elements

* test: update to es6-promise polyfill

* test: remove watch from server

* test: remove flow

* format: update prettier for typescript

* test: update eslint to use typescript parser

* test: update linear gradient reftest

* test: update test runner

* test: update testrunner promise polyfill

* fix: handle display: -webkit-flex correctly (fix #1817)

* fix: correctly render gradients with clip & repeat (fix #1773)

* fix: webkit-gradient function support

* fix: implement radial gradients

* fix: text-decoration rendering

* fix: missing scroll positions for elements

* ci: fix ios 11 tests

* fix: ie logging

* ci: improve device availability logging

* fix: lint errors

* ci: update to ios 12

* fix: check for console availability

* ci: fix build dependency

* test: update text reftests

* fix: window reference for unit tests

* feat: add hsl/hsla color support

* fix: render options

* fix: CSSKeyframesRule cssText Permission Denied on Internet Explorer 11 (#1830)

* fix: option lint

* fix: list type rendering

* test: fix platform import

* fix: ie css parsing for numbers

* ci: add minified build

* fix: form element rendering

* fix: iframe rendering

* fix: re-introduce experimental foreignobject renderer

* fix: text-shadow rendering

* feat: improve logging

* fix: unit test logging

* fix: cleanup resources

* test: update overflow scrolling to work with ie

* build: update build to include typings

* fix: do not parse select element children

* test: fix onclone test to work with older IEs

* test: reduce reftest canvas sizes

* test: remove dynamic setUp from list tests

* test: update linear-gradient tests

* build: remove old source files

* build: update docs dependencies

* build: fix typescript definition path

* ci: include test.js on docs website
This commit is contained in:
MoyuScript
2019-05-25 15:54:41 -07:00
parent cb369ffdb2
commit 7fd1bc3d2a
221 changed files with 13668 additions and 23699 deletions

View File

@ -1,18 +0,0 @@
{
"curly": true,
"eqeqeq": true,
"immed": true,
"latedef": false,
"newcap": true,
"noarg": true,
"sub": true,
"undef": true,
"boss": true,
"eqnull": true,
"browser": true,
"globals": {
"jQuery": true
},
"predef": ["deepEqual", "module", "test", "$", "QUnit", "NodeParser", "NodeContainer", "StackingContext", "TextContainer", "ImageLoader", "CanvasRenderer", "Renderer", "Support", "bind", "Promise",
"ImageContainer", "ProxyImageContainer", "DummyImageContainer", "Font", "FontMetrics", "GradientContainer", "LinearGradientContainer", "WebkitGradientContainer", "log", "smallImage", "parseBackgrounds"]
}

View File

@ -1,136 +0,0 @@
<html>
<head>
<meta charset="utf-8">
<title>Mocha Tests</title>
<link rel="stylesheet" href="lib/mocha.css" />
<script src="../../node_modules/bluebird/js/browser/bluebird.js"></script>
<script src="../../dist/html2canvas.js"></script>
<script src="../assets/jquery-1.6.2.js"></script>
<script src="lib/expect.js"></script>
<script src="lib/mocha.js"></script>
<style>
#block {
width: 200px;
height: 200px;
}
#green-block {
width: 200px;
height: 200px;
background: green;
}
#background-block {
width: 200px;
height: 200px;
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNgaGD4DwAChAGAJVtEDQAAAABJRU5ErkJggg==) red;
}
#gradient-block {
width: 200px;
height: 200px;
background-image: -webkit-linear-gradient(top, #008000, #008000);
background-image: -moz-linear-gradient(to bottom, #008000, #008000);
background-image: linear-gradient(to bottom, #008000, #008000);
}
</style>
</head>
<body>
<div id="mocha"></div>
<script>mocha.setup('bdd')</script>
<div id="block"></div>
<div id="green-block"></div>
<div id="background-block"></div>
<div id="gradient-block"></div>
<script>
describe("options.background", function() {
it("with hexcolor", function(done) {
html2canvas(document.querySelector("#block"), {background: '#008000'}).then(function(canvas) {
expect(canvas.width).to.equal(200);
expect(canvas.height).to.equal(200);
validCanvasPixels(canvas);
done();
}).catch(function(error) {
done(error);
});
});
it("with named color", function(done) {
html2canvas(document.querySelector("#block"), {background: 'green'}).then(function(canvas) {
expect(canvas.width).to.equal(200);
expect(canvas.height).to.equal(200);
validCanvasPixels(canvas);
done();
}).catch(function(error) {
done(error);
});
});
it("with element background", function(done) {
html2canvas(document.querySelector("#green-block"), {background: 'red'}).then(function(canvas) {
expect(canvas.width).to.equal(200);
expect(canvas.height).to.equal(200);
validCanvasPixels(canvas);
done();
}).catch(function(error) {
done(error);
});
});
});
describe('element background', function() {
it('with background-color', function(done) {
html2canvas(document.querySelector("#green-block")).then(function(canvas) {
expect(canvas.width).to.equal(200);
expect(canvas.height).to.equal(200);
validCanvasPixels(canvas);
done();
}).catch(function(error) {
done(error);
});
});
it('with background-image', function(done) {
html2canvas(document.querySelector("#background-block")).then(function(canvas) {
expect(canvas.width).to.equal(200);
expect(canvas.height).to.equal(200);
validCanvasPixels(canvas);
done();
}).catch(function(error) {
done(error);
});
});
it('with gradient background-image', function(done) {
html2canvas(document.querySelector("#gradient-block")).then(function(canvas) {
expect(canvas.width).to.equal(200);
expect(canvas.height).to.equal(200);
validCanvasPixels(canvas);
done();
}).catch(function(error) {
done(error);
});
});
});
function validCanvasPixels(canvas) {
var ctx = canvas.getContext("2d");
var data = ctx.getImageData(0, 0, canvas.width, canvas.height).data;
for (var i = 0, len = data.length; i < len; i+=4) {
if (data[i] !== 0 || data[i+1] !== 128 || data[i+2] !== 0 || data[i+3] !== 255) {
expect().fail("Invalid canvas data");
}
}
}
mocha.checkLeaks();
mocha.globals(['jQuery']);
if (window.mochaPhantomJS) {
mochaPhantomJS.run();
}
else {
mocha.run();
}
mocha.suite.afterAll(function() {
document.body.setAttribute('data-complete', 'true');
});
</script>
</body>
</html>

View File

@ -1 +0,0 @@
document.querySelector('#block').className += 'class';

View File

@ -1,145 +0,0 @@
<html>
<head>
<meta charset="utf-8">
<title>Mocha Tests</title>
<link rel="stylesheet" href="lib/mocha.css" />
<script src="../../node_modules/bluebird/js/browser/bluebird.js"></script>
<script src="../../dist/html2canvas.js"></script>
<script src="../assets/jquery-1.6.2.js"></script>
<script src="lib/expect.js"></script>
<script src="lib/mocha.js"></script>
</head>
<body>
<div id="mocha"></div>
<script>mocha.setup('bdd')</script>
<div style="background: green; width: 40px; height:40px;" id="block"></div>
<div style="visibility: hidden">
<iframe src="iframe1.htm" style="height: 350px; width: 450px; border: 0;" scrolling="no" id="frame1"></iframe>
<iframe src="iframe2.htm" style="height: 350px; width: 450px; border: 0;" scrolling="yes" id="frame2"></iframe>
</div>
<script>
describe("Cropping", function() {
it("window view with body", function(done) {
html2canvas(document.body, {type: 'view'}).then(function(canvas) {
expect(canvas.width).to.equal(window.innerWidth);
expect(canvas.height).to.equal(window.innerHeight);
done();
}).catch(function(error) {
done(error);
});
});
it("window view with documentElement", function(done) {
html2canvas(document.documentElement, {type: 'view'}).then(function(canvas) {
expect(canvas.width).to.equal(window.innerWidth);
expect(canvas.height).to.equal(window.innerHeight);
done();
}).catch(function(error) {
done(error);
});
});
it("iframe with body", function(done) {
html2canvas(document.querySelector("#frame1").contentWindow.document.body, {type: 'view'}).then(function(canvas) {
expect(canvas.width).to.equal(450);
expect(canvas.height).to.equal(350);
validCanvasPixels(canvas);
done();
}).catch(function(error) {
done(error);
});
});
it("iframe with document element", function(done) {
html2canvas(document.querySelector("#frame1").contentWindow.document.documentElement, {type: 'view'}).then(function(canvas) {
expect(canvas.width).to.equal(450);
expect(canvas.height).to.equal(350);
validCanvasPixels(canvas);
done();
}).catch(function(error) {
done(error);
});
});
it("with node", function(done) {
html2canvas(document.querySelector("#block")).then(function(canvas) {
expect(canvas.width).to.equal(40);
expect(canvas.height).to.equal(40);
validCanvasPixels(canvas);
done();
}).catch(function(error) {
done(error);
});
});
it("with node and size", function(done) {
html2canvas(document.querySelector("#block"), {width: 20, height: 20}).then(function(canvas) {
expect(canvas.width).to.equal(20);
expect(canvas.height).to.equal(20);
validCanvasPixels(canvas);
done();
}).catch(function(error) {
done(error);
});
});
document.querySelector("#frame2").addEventListener("load", function() {
document.querySelector("#frame2").contentWindow.scrollTo(0, 350);
describe("with scrolled content", function() {
it("iframe with body", function(done) {
html2canvas(document.querySelector("#frame2").contentWindow.document.body, {type: 'view'}).then(function(canvas) {
// phantomjs issue https://github.com/ariya/phantomjs/issues/10581
if (canvas.height !== 1200) {
expect(canvas.width).to.equal(450);
expect(canvas.height).to.equal(350);
validCanvasPixels(canvas);
}
done();
}).catch(function(error) {
done(error);
});
});
it("iframe with document element", function(done) {
html2canvas(document.querySelector("#frame2").contentWindow.document.documentElement, {type: 'view'}).then(function(canvas) {
// phantomjs issue https://github.com/ariya/phantomjs/issues/10581
if (canvas.height !== 1200) {
expect(canvas.width).to.equal(450);
expect(canvas.height).to.equal(350);
validCanvasPixels(canvas);
}
done();
}).catch(function(error) {
done(error);
});
});
});
}, false);
});
function validCanvasPixels(canvas) {
var ctx = canvas.getContext("2d");
var data = ctx.getImageData(0, 0, canvas.width, canvas.height).data;
for (var i = 0, len = data.length; i < len; i+=4) {
if (data[i] !== 0 || data[i+1] !== 128 || data[i+2] !== 0 || data[i+3] !== 255) {
expect().fail("Invalid canvas data");
}
}
}
mocha.checkLeaks();
mocha.globals(['jQuery']);
if (window.mochaPhantomJS) {
mochaPhantomJS.run();
}
else {
mocha.run();
}
mocha.suite.afterAll(function() {
document.body.setAttribute('data-complete', 'true');
});
</script>
</body>
</html>

View File

@ -1,241 +0,0 @@
var NodeContainer = html2canvas.NodeContainer;
describe('Borders', function() {
$('#borders div').each(function(i, node) {
it($(this).attr('style'), function() {
[
'borderTopWidth',
'borderRightWidth',
'borderBottomWidth',
'borderLeftWidth'
].forEach(function(prop) {
var result = $(node).css(prop);
// older IE's don't necessarily return px even with jQuery
if (result === 'thin') {
result = '1px';
} else if (result === 'medium') {
result = '3px';
} else if (result === 'thick') {
result = '5px';
}
var container = new NodeContainer(node, null);
expect(container.css(prop)).to.be(result);
});
});
});
});
describe('Padding', function() {
$('#padding div').each(function(i, node) {
it($(this).attr('style'), function() {
['paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft'].forEach(function(prop) {
var container = new NodeContainer(node, null);
var result = container.css(prop);
expect(result).to.contain('px');
expect(result, $(node).css(prop));
});
});
});
});
describe('Background-position', function() {
$('#backgroundPosition div').each(function(i, node) {
it($(this).attr('style'), function() {
var prop = 'backgroundPosition';
var img = new Image();
img.width = 50;
img.height = 50;
var container = new NodeContainer(node, null);
var item = container.css(prop),
backgroundPosition = container.parseBackgroundPosition(
html2canvas.utils.getBounds(node),
img
),
split = window.getComputedStyle
? $(node).css(prop).split(' ')
: [$(node).css(prop + 'X'), $(node).css(prop + 'Y')];
var testEl = $('<div />').css({
position: 'absolute',
left: split[0],
top: split[1]
});
testEl.appendTo(node);
expect(backgroundPosition.left).to.equal(Math.floor(parseFloat(testEl.css('left'))));
expect(backgroundPosition.top).to.equal(Math.floor(parseFloat(testEl.css('top'))));
testEl.remove();
});
});
});
describe('Text-shadow', function() {
$('#textShadows div').each(function(i, node) {
var index = i + 1;
var container = new NodeContainer(node, null);
var shadows = container.parseTextShadows();
it(node.style.textShadow, function() {
if (i === 0) {
expect(shadows.length).to.equal(0);
} else {
expect(shadows.length).to.equal(i >= 6 ? 2 : 1);
expect(shadows[0].offsetX).to.equal(i);
expect(shadows[0].offsetY).to.equal(i);
if (i < 2) {
expect(shadows[0].color.toString()).to.equal('rgba(0,0,0,0)');
} else if (i % 2 === 0) {
expect(shadows[0].color.toString()).to.equal('rgb(2,2,2)');
} else {
var opacity = '0.2';
expect(shadows[0].color.toString()).to.match(/rgba\(2,2,2,(0.2|0\.199219)\)/);
}
// only testing blur once
if (i === 1) {
expect(shadows[0].blur).to.equal('1');
}
}
});
});
});
describe('Background-image', function() {
test_parse_background_image(
'url("te)st")',
{
prefix: '',
method: 'url',
value: 'url("te)st")',
args: ['te)st'],
image: null
},
'test quoted'
);
test_parse_background_image(
'url("te,st")',
{
prefix: '',
method: 'url',
value: 'url("te,st")',
args: ['te,st'],
image: null
},
'test quoted'
);
test_parse_background_image(
'url(te,st)',
{
prefix: '',
method: 'url',
value: 'url(te,st)',
args: ['te,st'],
image: null
},
'test quoted'
);
test_parse_background_image(
'url(test)',
{
prefix: '',
method: 'url',
value: 'url(test)',
args: ['test'],
image: null
},
'basic url'
);
test_parse_background_image(
'url("test")',
{
prefix: '',
method: 'url',
value: 'url("test")',
args: ['test'],
image: null
},
'quoted url'
);
test_parse_background_image(
'url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)',
{
prefix: '',
method: 'url',
value:
'url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)',
args: [
'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'
],
image: null
},
'data url'
);
test_parse_background_image(
'linear-gradient(red,black)',
{
prefix: '',
method: 'linear-gradient',
value: 'linear-gradient(red,black)',
args: ['red', 'black'],
image: null
},
'linear-gradient'
);
test_parse_background_image(
'linear-gradient(top,rgb(255,0,0),rgb(0,0,0))',
{
prefix: '',
method: 'linear-gradient',
value: 'linear-gradient(top,rgb(255,0,0),rgb(0,0,0))',
args: ['top', 'rgb(255,0,0)', 'rgb(0,0,0)'],
image: null
},
'linear-gradient w/ rgb()'
);
test_parse_background_image(
'-webkit-linear-gradient(red,black)',
{
prefix: '-webkit-',
method: 'linear-gradient',
value: '-webkit-linear-gradient(red,black)',
args: ['red', 'black'],
image: null
},
'prefixed linear-gradient'
);
test_parse_background_image(
'linear-gradient(red,black), url(test), url("test"),\n none, ',
[
{
prefix: '',
method: 'linear-gradient',
value: 'linear-gradient(red,black)',
args: ['red', 'black'],
image: null
},
{prefix: '', method: 'url', value: 'url(test)', args: ['test'], image: null},
{prefix: '', method: 'url', value: 'url("test")', args: ['test'], image: null},
{prefix: '', method: 'none', value: 'none', args: [], image: null}
],
'multiple backgrounds'
);
function test_parse_background_image(value, expected, name) {
it(name, function() {
expect(html2canvas.utils.parseBackgrounds(value)).to.eql(
Array.isArray(expected) ? expected : [expected]
);
});
}
});

View File

@ -1,166 +0,0 @@
<html>
<head>
<meta charset="utf-8">
<title>Mocha Tests</title>
<link rel="stylesheet" href="lib/mocha.css" />
<script src="../../node_modules/bluebird/js/browser/bluebird.js"></script>
<script src="../../dist/html2canvas.js"></script>
<script src="../assets/jquery-1.6.2.js"></script>
<script src="lib/expect.js"></script>
<script src="lib/mocha.js"></script>
<style>
.block {
width: 200px;
height: 200px;
}
</style>
</head>
<body>
<div id="mocha"></div>
<script>mocha.setup('bdd')</script>
<div id="block1" class="block">
<input type="text" value="text" />
</div>
<div id="block2" class="block">
<input type="password" value="password" />
</div>
<div id="block3" class="block">
<input type="text" value="text" />
</div>
<div id="block4" class="block">
<textarea>text</textarea>
</div>
<div id="block5" class="block">
<select>
<option value="1">1</option>
<option value="2" selected>2</option>
<option value="3">3</option>
</select>
</div>
<div id="green-block"></div>
<script>
var CanvasRenderer = html2canvas.CanvasRenderer;
describe("Rendering input values", function() {
it("uses default value for input[type='text']", function(done) {
CanvasRenderer.prototype.text = function(text) {
expect(text).to.equal('text');
};
html2canvas(document.querySelector("#block1"), {renderer: CanvasRenderer, strict: true}).then(function(canvas) {
expect(canvas.width).to.equal(200);
expect(canvas.height).to.equal(200);
done();
}).catch(function(error) {
done(error);
});
});
it("uses transformed value for input[type='password']", function(done) {
var count = 0;
CanvasRenderer.prototype.text = function(text) {
expect(text).to.equal('•');
count++;
};
html2canvas(document.querySelector("#block2"), {renderer: CanvasRenderer, strict: true}).then(function(canvas) {
expect(canvas.width).to.equal(200);
expect(canvas.height).to.equal(200);
expect(count).to.equal("password".length);
done();
}).catch(function(error) {
done(error);
});
});
it("used property and not attribute for rendering", function(done) {
document.querySelector("#block3 input").value = 'updated';
CanvasRenderer.prototype.text = function(text) {
expect(text).to.equal('updated');
};
html2canvas(document.querySelector("#block3"), {renderer: CanvasRenderer, strict: true}).then(function(canvas) {
expect(canvas.width).to.equal(200);
expect(canvas.height).to.equal(200);
done();
}).catch(function(error) {
done(error);
});
});
describe("Rendering textarea values", function() {
it("uses default value correctly", function(done) {
CanvasRenderer.prototype.text = function(text) {
expect(text).to.equal('text');
};
html2canvas(document.querySelector("#block4"), {renderer: CanvasRenderer, strict: true}).then(function(canvas) {
expect(canvas.width).to.equal(200);
expect(canvas.height).to.equal(200);
done();
}).catch(function(error) {
done(error);
});
});
it("used property and not attribute for rendering", function(done) {
document.querySelector("#block4 textarea").value = 'updated';
CanvasRenderer.prototype.text = function(text) {
expect(text).to.equal('updated');
};
html2canvas(document.querySelector("#block4"), {renderer: CanvasRenderer, strict: true}).then(function(canvas) {
expect(canvas.width).to.equal(200);
expect(canvas.height).to.equal(200);
done();
}).catch(function(error) {
done(error);
});
});
});
describe("Select values", function() {
it("uses default value correctly", function(done) {
CanvasRenderer.prototype.text = function(text) {
expect(text).to.equal('2');
};
html2canvas(document.querySelector("#block5"), {renderer: CanvasRenderer, strict: true}).then(function(canvas) {
expect(canvas.width).to.equal(200);
expect(canvas.height).to.equal(200);
done();
}).catch(function(error) {
done(error);
});
});
it("used property and not attribute for rendering", function(done) {
document.querySelector("#block5 select").value = '3';
CanvasRenderer.prototype.text = function(text) {
expect(text).to.equal('3');
};
html2canvas(document.querySelector("#block5"), {renderer: CanvasRenderer, strict: true}).then(function(canvas) {
expect(canvas.width).to.equal(200);
expect(canvas.height).to.equal(200);
done();
}).catch(function(error) {
done(error);
});
});
});
});
mocha.checkLeaks();
mocha.globals(['jQuery']);
if (window.mochaPhantomJS) {
mochaPhantomJS.run();
}
else {
mocha.run();
}
mocha.suite.afterAll(function() {
document.body.setAttribute('data-complete', 'true');
});
</script>
</body>
</html>

View File

@ -1,145 +0,0 @@
describe('Gradients', function() {
var expected = [
{
method: 'linear-gradient',
args: ['left', ' rgb(255, 0, 0)', ' rgb(255, 255, 0)', ' rgb(0, 255, 0)']
},
{
method: 'linear-gradient',
args: ['left', ' red', ' rgb(255, 255, 0)', ' rgb(0, 255, 0)']
},
{
method: 'linear-gradient',
args: [
'left',
' rgb(206, 219, 233) 0%',
' rgb(170, 197, 222) 17%',
' rgb(97, 153, 199) 50%',
' rgb(58, 132, 195) 51%',
' rgb(65, 154, 214) 59%',
' rgb(75, 184, 240) 71%',
' rgb(58, 139, 194) 84%',
' rgb(38, 85, 139) 100%'
]
},
{
method: 'linear-gradient',
args: [
'left',
' rgb(206, 219, 233) 0%',
' rgb(170, 197, 222) 17px',
' rgb(97, 153, 199) 50%',
' rgb(58, 132, 195) 51px',
' rgb(65, 154, 214) 59%',
' rgb(75, 184, 240) 71px',
' rgb(58, 139, 194) 84%',
' rgb(38, 85, 139) 100px'
]
},
{
method: 'gradient',
args: [
'linear',
' 50% 0%',
' 50% 100%',
' from(rgb(240, 183, 161))',
' color-stop(0.5, rgb(140, 51, 16))',
' color-stop(0.51, rgb(117, 34, 1))',
' to(rgb(191, 110, 78))'
]
},
{
method: 'gradient',
args: [
'linear',
' 50% 0%',
' 50% 100%',
' from(rgb(255, 0, 0))',
' color-stop(0.314159, green)',
' color-stop(0.51, rgb(0, 0, 255))',
// temporary workaround for Blink/WebKit bug: crbug.com/453414
//" to(rgba(0, 0, 0, 0.5))"
' to(rgba(0, 0, 0, 0))'
]
},
{
method: 'linear-gradient',
args: ['0deg', ' rgb(221, 221, 221)', ' rgb(221, 221, 221) 50%', ' transparent 50%']
},
{
method: 'radial-gradient',
args: [
'75% 19%',
' ellipse closest-side',
' rgb(171, 171, 171)',
' rgb(0, 0, 255) 33%',
' rgb(153, 31, 31) 100%'
]
},
{
method: 'radial-gradient',
args: [
'75% 19%',
' ellipse closest-corner',
' rgb(171, 171, 171)',
' rgb(0, 0, 255) 33%',
' rgb(153, 31, 31) 100%'
]
},
{
method: 'radial-gradient',
args: [
'75% 19%',
' ellipse farthest-side',
' rgb(171, 171, 171)',
' rgb(0, 0, 255) 33%',
' rgb(153, 31, 31) 100%'
]
},
{
method: 'radial-gradient',
args: [
'75% 19%',
' ellipse farthest-corner',
' rgb(171, 171, 171)',
' rgb(0, 0, 255) 33%',
' rgb(153, 31, 31) 100%'
]
},
{
method: 'radial-gradient',
args: [
'75% 19%',
' ellipse contain',
' rgb(171, 171, 171)',
' rgb(0, 0, 255) 33%',
' rgb(153, 31, 31) 100%'
]
},
{
method: 'radial-gradient',
args: [
'75% 19%',
' ellipse cover',
' rgb(171, 171, 171)',
' rgb(0, 0, 255) 33%',
' rgb(153, 31, 31) 100%'
]
}
];
[].slice
.call(document.querySelectorAll('#backgroundGradients div'), 0)
.forEach(function(node, i) {
var container = new html2canvas.NodeContainer(node, null);
var value = container.css('backgroundImage');
it(value, function() {
var parsedBackground = html2canvas.utils.parseBackgrounds(value);
if (parsedBackground[0].args[0] === '0% 50%') {
parsedBackground[0].args[0] = 'left';
}
expect(parsedBackground[0].args).to.eql(expected[i].args);
expect(parsedBackground[0].method).to.eql(expected[i].method);
});
});
});

View File

@ -1,67 +0,0 @@
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>Proxy tests</title>
<link rel="stylesheet" href="lib/mocha.css" />
<script src="../../node_modules/bluebird/js/browser/bluebird.js"></script>
<script src="../assets/jquery-1.6.2.js"></script>
<script src="lib/expect.js"></script>
<script src="lib/mocha.js"></script>
<style>
#block {
background: red;
}
#block.class {
background: green;
}
</style>
</head>
<body>
<div style="width: 200px; height:200px;" id="block"></div>
<script src="../../dist/html2canvas.js"></script>
<script src="clone.js"></script>
<div id="mocha"></div>
<script>mocha.setup('bdd')</script>
<script>
// https://github.com/niklasvh/html2canvas/issues/503
describe("Document clone should not re-execute javascript", function() {
it("with mutating className", function (done) {
this.timeout(10000);
html2canvas(document.querySelector("#block")).then(function (canvas) {
expect(canvas.width).to.equal(200);
expect(canvas.height).to.equal(200);
validCanvasPixels(canvas);
done();
}).catch(function (error) {
done(error);
});
});
});
function validCanvasPixels(canvas) {
var ctx = canvas.getContext("2d");
var data = ctx.getImageData(0, 0, canvas.width, canvas.height).data;
for (var i = 0, len = data.length; i < len; i+=4) {
if (data[i] !== 0 || data[i+1] !== 128 || data[i+2] !== 0 || data[i+3] !== 255) {
expect().fail("Invalid canvas data");
}
}
}
mocha.checkLeaks();
mocha.globals(['jQuery']);
if (window.mochaPhantomJS) {
mochaPhantomJS.run();
}
else {
mocha.run();
}
mocha.suite.afterAll(function() {
document.body.setAttribute('data-complete', 'true');
});
</script>
</body>
</html>

View File

@ -1,23 +0,0 @@
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
html, body {
background: green;
margin: 0;
padding: 0;
}
.invalid {
margin-top: 350px;
height: 500px;
background: red;
display: block;
}
</style>
</head>
<body>
&nbsp;<div class="invalid">&nbsp;</div>
</body>
</html>

View File

@ -1,23 +0,0 @@
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
html, body {
background: red;
margin: 0;
padding: 0;
}
.valid {
margin-top: 350px;
height: 350px;
background: green;
display: block;
margin-bottom: 500px;
}
</style>
</head>
<body><div class="valid">&nbsp;</div></body>
</html>

View File

@ -1,21 +0,0 @@
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
html, body {
background: red;
margin: 0;
padding: 0;
}
.valid {
height: 350px;
background: green;
display: block;
}
</style>
</head>
<body><div class="valid">&nbsp;</div></body>
</html>

File diff suppressed because it is too large Load Diff

View File

@ -1,270 +0,0 @@
@charset "utf-8";
body {
margin:0;
}
#mocha {
font: 20px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif;
margin: 60px 50px;
}
#mocha ul,
#mocha li {
margin: 0;
padding: 0;
}
#mocha ul {
list-style: none;
}
#mocha h1,
#mocha h2 {
margin: 0;
}
#mocha h1 {
margin-top: 15px;
font-size: 1em;
font-weight: 200;
}
#mocha h1 a {
text-decoration: none;
color: inherit;
}
#mocha h1 a:hover {
text-decoration: underline;
}
#mocha .suite .suite h1 {
margin-top: 0;
font-size: .8em;
}
#mocha .hidden {
display: none;
}
#mocha h2 {
font-size: 12px;
font-weight: normal;
cursor: pointer;
}
#mocha .suite {
margin-left: 15px;
}
#mocha .test {
margin-left: 15px;
overflow: hidden;
}
#mocha .test.pending:hover h2::after {
content: '(pending)';
font-family: arial, sans-serif;
}
#mocha .test.pass.medium .duration {
background: #c09853;
}
#mocha .test.pass.slow .duration {
background: #b94a48;
}
#mocha .test.pass::before {
content: '✓';
font-size: 12px;
display: block;
float: left;
margin-right: 5px;
color: #00d6b2;
}
#mocha .test.pass .duration {
font-size: 9px;
margin-left: 5px;
padding: 2px 5px;
color: #fff;
-webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
-moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
-ms-border-radius: 5px;
-o-border-radius: 5px;
border-radius: 5px;
}
#mocha .test.pass.fast .duration {
display: none;
}
#mocha .test.pending {
color: #0b97c4;
}
#mocha .test.pending::before {
content: '◦';
color: #0b97c4;
}
#mocha .test.fail {
color: #c00;
}
#mocha .test.fail pre {
color: black;
}
#mocha .test.fail::before {
content: '✖';
font-size: 12px;
display: block;
float: left;
margin-right: 5px;
color: #c00;
}
#mocha .test pre.error {
color: #c00;
max-height: 300px;
overflow: auto;
}
/**
* (1): approximate for browsers not supporting calc
* (2): 42 = 2*15 + 2*10 + 2*1 (padding + margin + border)
* ^^ seriously
*/
#mocha .test pre {
display: block;
float: left;
clear: left;
font: 12px/1.5 monaco, monospace;
margin: 5px;
padding: 15px;
border: 1px solid #eee;
max-width: 85%; /*(1)*/
max-width: calc(100% - 42px); /*(2)*/
word-wrap: break-word;
border-bottom-color: #ddd;
-webkit-border-radius: 3px;
-webkit-box-shadow: 0 1px 3px #eee;
-moz-border-radius: 3px;
-moz-box-shadow: 0 1px 3px #eee;
border-radius: 3px;
}
#mocha .test h2 {
position: relative;
}
#mocha .test a.replay {
position: absolute;
top: 3px;
right: 0;
text-decoration: none;
vertical-align: middle;
display: block;
width: 15px;
height: 15px;
line-height: 15px;
text-align: center;
background: #eee;
font-size: 15px;
-moz-border-radius: 15px;
border-radius: 15px;
-webkit-transition: opacity 200ms;
-moz-transition: opacity 200ms;
transition: opacity 200ms;
opacity: 0.3;
color: #888;
}
#mocha .test:hover a.replay {
opacity: 1;
}
#mocha-report.pass .test.fail {
display: none;
}
#mocha-report.fail .test.pass {
display: none;
}
#mocha-report.pending .test.pass,
#mocha-report.pending .test.fail {
display: none;
}
#mocha-report.pending .test.pass.pending {
display: block;
}
#mocha-error {
color: #c00;
font-size: 1.5em;
font-weight: 100;
letter-spacing: 1px;
}
#mocha-stats {
position: fixed;
top: 15px;
right: 10px;
font-size: 12px;
margin: 0;
color: #888;
z-index: 1;
}
#mocha-stats .progress {
float: right;
padding-top: 0;
}
#mocha-stats em {
color: black;
}
#mocha-stats a {
text-decoration: none;
color: inherit;
}
#mocha-stats a:hover {
border-bottom: 1px solid #eee;
}
#mocha-stats li {
display: inline-block;
margin: 0 5px;
list-style: none;
padding-top: 11px;
}
#mocha-stats canvas {
width: 40px;
height: 40px;
}
#mocha code .comment { color: #ddd; }
#mocha code .init { color: #2f6fad; }
#mocha code .string { color: #5890ad; }
#mocha code .keyword { color: #8a6343; }
#mocha code .number { color: #2f6fad; }
@media screen and (max-device-width: 480px) {
#mocha {
margin: 60px 0px;
}
#mocha #stats {
position: absolute;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,99 +0,0 @@
<html>
<head>
<meta charset="utf-8">
<title>Mocha Tests</title>
<link rel="stylesheet" href="lib/mocha.css" />
<script src="../../node_modules/bluebird/js/browser/bluebird.js"></script>
<script src="../../dist/html2canvas.js"></script>
<script src="../assets/jquery-1.6.2.js"></script>
<script src="lib/expect.js"></script>
<script src="lib/mocha.js"></script>
<style>
#block {
width: 200px;
height: 200px;
}
#green-block {
width: 200px;
height: 200px;
background: green;
}
</style>
</head>
<body>
<div id="mocha"></div>
<div id="block"></div>
<div id="green-block"></div>
<script>mocha.setup('bdd')</script>
<script>
describe("Multiple renders", function() {
it("render correctly", function(done) {
this.timeout(10000);
var d = 0;
var count = 3;
for (var i = 0; i < count; i++) {
html2canvas(document.querySelector('#green-block')).then(function (canvas) {
expect(canvas.width).to.equal(200);
expect(canvas.height).to.equal(200);
validCanvasPixels(canvas);
canvas.width = canvas.height = 10;
d++;
if (d === count) {
done();
}
});
}
});
it("render correctly when non sequential", function(done) {
this.timeout(10000);
var d = 0;
var count = 3;
for (var i = 0; i < count; i++) {
html2canvas(document.querySelector('#block'), {onclone: function(document) {
return new Promise(function(resolve) {
document.querySelector('#block').style.backgroundColor = 'green';
setTimeout(function() {
resolve();
}, 100);
});
}}).then(function (canvas) {
expect(canvas.width).to.equal(200);
expect(canvas.height).to.equal(200);
validCanvasPixels(canvas);
canvas.width = canvas.height = 10;
d++;
if (d === count) {
done();
}
});
}
});
});
function validCanvasPixels(canvas) {
var ctx = canvas.getContext("2d");
var data = ctx.getImageData(0, 0, canvas.width, canvas.height).data;
for (var i = 0, len = 200*199*4; i < len; i+=4) {
if (data[i] !== 0 || data[i+1] !== 128 || data[i+2] !== 0 || data[i+3] !== 255) {
console.log(i, data[i], data[i+1], data[i+2], data[i+3]);
expect().fail("Invalid canvas data");
}
}
}
mocha.suite.afterAll(function() {
document.body.setAttribute('data-complete', 'true');
});
mocha.checkLeaks();
mocha.globals(['jQuery']);
if (window.mochaPhantomJS) {
mochaPhantomJS.run();
}
else {
mocha.run();
}
</script>
</body>
</html>

View File

@ -1,98 +0,0 @@
<html>
<head>
<meta charset="utf-8">
<title>Mocha Tests</title>
<link rel="stylesheet" href="lib/mocha.css" />
<script src="../../node_modules/bluebird/js/browser/bluebird.js"></script>
<script src="../../dist/html2canvas.js"></script>
<script src="../assets/jquery-1.6.2.js"></script>
<script src="lib/expect.js"></script>
<script src="lib/mocha.js"></script>
<style>
#block2 {
background: red;
}
.my-css-class #block2 {
background: green;
}
</style>
</head>
<body>
<div id="mocha"></div>
<script>mocha.setup('bdd')</script>
<div style="background: red; width: 200px; height:200px;" id="block"></div>
<div style="width: 200px; height:200px;" id="block2"></div>
<script>
describe("options.onclone", function() {
it("with a function", function(done) {
html2canvas(document.querySelector("#block"), {onclone: function(document) {
document.querySelector("#block").style.background = "green";
}}).then(function(canvas) {
expect(canvas.width).to.equal(200);
expect(canvas.height).to.equal(200);
expect(document.querySelector("#block").style.backgroundColor).to.equal("red");
validCanvasPixels(canvas);
done();
}).catch(function(error) {
done(error);
});
});
it("with a promise", function(done) {
html2canvas(document.querySelector("#block"), {onclone: function(document) {
return new Promise(function(resolve) {
setTimeout(function() {
document.querySelector("#block").style.background = "green";
resolve();
}, 500);
});
}}).then(function(canvas) {
expect(canvas.width).to.equal(200);
expect(canvas.height).to.equal(200);
expect(document.querySelector("#block").style.backgroundColor).to.equal("red");
validCanvasPixels(canvas);
done();
}).catch(function(error) {
done(error);
});
});
it("add class to node", function(done) {
html2canvas(document.querySelector("#block2"), {onclone: function(document) {
document.documentElement.className = "my-css-class";
}}).then(function(canvas) {
expect(canvas.width).to.equal(200);
expect(canvas.height).to.equal(200);
validCanvasPixels(canvas);
done();
}).catch(function(error) {
done(error);
});
});
});
function validCanvasPixels(canvas) {
var ctx = canvas.getContext("2d");
var data = ctx.getImageData(0, 0, canvas.width, canvas.height).data;
for (var i = 0, len = data.length; i < len; i+=4) {
if (data[i] !== 0 || data[i+1] !== 128 || data[i+2] !== 0 || data[i+3] !== 255) {
expect().fail("Invalid canvas data");
}
}
}
mocha.checkLeaks();
mocha.globals(['jQuery']);
if (window.mochaPhantomJS) {
mochaPhantomJS.run();
}
else {
mocha.run();
}
mocha.suite.afterAll(function() {
document.body.setAttribute('data-complete', 'true');
});
</script>
</body>
</html>

View File

@ -1,235 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Mocha Tests</title>
<link rel="stylesheet" href="lib/mocha.css" />
<script src="../../dist/html2canvas.js"></script>
<script src="../assets/jquery-1.6.2.js"></script>
<script src="lib/expect.js"></script>
<script src="lib/mocha.js"></script>
</head>
<body>
<div id="mocha"></div>
<script>mocha.setup('bdd')</script>
<div style="visibility: hidden">
<div id="borders">Yep, here's some more.
<div style="border-width: 1px 0;">Div 1</div>
<div style="border-width: 1em 0;">Div 2</div>
<div style="border-width: thin medium thick;">Some more divs</div>
<div style="border-width: 5% 6px 12%;"></div> <!-- percentages aren't valid -->
<div style="border-width: 5em 5ex 5in 5cm;"></div>
<div style="border-width: 500em 500ex 500in 500cm;"></div>
<div style="border-width: 5mm 5pt 5pc 5px;"></div>
<div style="border-width: auto inherit;"></div>
<div style="border-width: 500mm 500pt 500pc 500px;"></div>
</div>
<div id="padding">
<div style="padding: 1px 0;"></div>
<div style="padding: 1em 0;"></div>
<div style="padding: thin medium thick;"></div>
<div style="padding: 5em 5ex 5in 5cm;"></div>
<div style="padding: 500em 500ex 500in 500cm;"></div>
<div style="padding: 5mm 5pt 5pc 5px;"></div>
<div style="padding: 500mm 500pt 500pc 500px;"></div>
<div style="padding: 1px 5%;"></div>
<div style="padding: 15% 0 3%;"></div>
</div>
<div id="textShadows">
<div style=""></div>
<div style="text-shadow: 1px 1px 1px"></div>
<div style="text-shadow: 2px 2px rgb(2, 2, 2)"></div>
<div style="text-shadow: 3px 3px rgba(2, 2, 2, .2)"></div>
<div style="text-shadow: rgb(2, 2, 2) 4px 4px"></div>
<div style="text-shadow: rgba(2, 2, 2, .2) 5px 5px"></div>
<div style="text-shadow: rgb(2, 2, 2) 6px 6px, #222222 2px 2px"></div>
<div style="text-shadow: 7px 7px rgba(2, 2, 2, .2), #222222 2px 2px"></div>
</div>
<div id="backgroundPosition">
<div style="background-position: 1px 0;"></div>
<div style="background-position: 1em 0;"></div>
<div style="background-position: thin medium;"></div>
<div style="background-position: 5em 5ex;"></div>
<div style="background-position: 5in 5cm;"></div>
<div style="background-position: 500in 500cm;"></div>
<div style="background-position: 500em 500ex;"></div>
<div style="background-position: 5pc 5px;"></div>
<div style="background-position: 500pc 500px;"></div>
<div style="background-position: 5mm 5pt;"></div>
<div style="background-position: 500mm 500pt;"></div>
</div>
<div id="backgroundPositionPercentage">
<div style="background-position: 5% 6px;"></div>
<div style="background-position: center center;"></div>
<div style="background-position: left bottom;"></div>
</div>
<div id="backgroundGradients">
<style scoped>
.linearGradientSimple {
/* FF 3.6+ */
background: -moz-linear-gradient(left, #ff0000, #ffff00, #00ff00);
/* Chrome,Safari4+ */
background: -webkit-gradient(linear, left center, right center, color-stop(#ff0000), color-stop(#ffff00), color-stop(#00ff00));
/* Chrome 10+, Safari 5.1+ */
background: -webkit-linear-gradient(left, #ff0000, #ffff00, #00ff00);
/* Opera 11.10+ */
background: -o-linear-gradient(left, #ff0000, #ffff00, #00ff00);
/* IE 10+ */
background: -ms-linear-gradient(left, #ff0000, #ffff00, #00ff00);
/* W3C */
background: linear-gradient(left, #ff0000, #ffff00, #00ff00);
}
.linearGradientSimple2 {
/* FF 3.6+ */
background: -moz-linear-gradient(left, red, #ff0, #0f0);
/* Chrome,Safari4+ */
background: -webkit-gradient(linear, left center, right center, color-stop(red), color-stop(#ff0), color-stop(#0f0));
/* Chrome 10+, Safari 5.1+ */
background: -webkit-linear-gradient(left, red, #ff0, #0f0);
/* Opera 11.10+ */
background: -o-linear-gradient(left, red, #ff0, #0f0);
/* IE 10+ */
background: -ms-linear-gradient(left, red, #ff0, #0f0);
/* W3C */
background: linear-gradient(left, red, #ff0, #0f0);
}
.linearGradientWithStops {
/* FF 3.6+ */
background: -moz-linear-gradient(left, #cedbe9 0%, #aac5de 17%, #6199c7 50%, #3a84c3 51%, #419ad6 59%, #4bb8f0 71%, #3a8bc2 84%, #26558b 100%);
/* Chrome, Safari 4+ */
background: -webkit-gradient(linear, left center, right center, color-stop(0%, #cedbe9), color-stop(17%, #aac5de), color-stop(50%, #6199c7), color-stop(51%, #3a84c3), color-stop(59%, #419ad6), color-stop(71%, #4bb8f0), color-stop(84%, #3a8bc2), color-stop(100%, #26558b));
/* Chrome 10+, Safari 5.1+ */
background: -webkit-linear-gradient(left, #cedbe9 0%, #aac5de 17%, #6199c7 50%, #3a84c3 51%, #419ad6 59%, #4bb8f0 71%, #3a8bc2 84%, #26558b 100%);
/* Opera 11.10+ */
background: -o-linear-gradient(left, #cedbe9 0%, #aac5de 17%, #6199c7 50%, #3a84c3 51%, #419ad6 59%, #4bb8f0 71%, #3a8bc2 84%, #26558b 100%);
/* IE 10+ */
background: -ms-linear-gradient(left, #cedbe9 0%, #aac5de 17%, #6199c7 50%, #3a84c3 51%, #419ad6 59%, #4bb8f0 71%, #3a8bc2 84%, #26558b 100%);
/* W3C */
background: linear-gradient(left, #cedbe9 0%, #aac5de 17%, #6199c7 50%, #3a84c3 51%, #419ad6 59%, #4bb8f0 71%, #3a8bc2 84%, #26558b 100%);
}
.linearGradientWithPixelLengthStops {
width: 100px;
height: 100px;
/* FF 3.6+ */
background: -moz-linear-gradient(left, #cedbe9 0%, #aac5de 17px, #6199c7 50%, #3a84c3 51px, #419ad6 59%, #4bb8f0 71px, #3a8bc2 84%, #26558b 100px);
/* Chrome, Safari 4+ */
background: -webkit-gradient(linear, left center, right center, color-stop(0%, #cedbe9), color-stop(17px, #aac5de), color-stop(50%, #6199c7), color-stop(51%, #3a84c3), color-stop(59%, #419ad6), color-stop(71px, #4bb8f0), color-stop(84%, #3a8bc2), color-stop(100px, #26558b));
/* Chrome 10+, Safari 5.1+ */
background: -webkit-linear-gradient(left, #cedbe9 0%, #aac5de 17px, #6199c7 50%, #3a84c3 51px, #419ad6 59%, #4bb8f0 71px, #3a8bc2 84%, #26558b 100px);
/* Opera 11.10+ */
background: -o-linear-gradient(left, #cedbe9 0%, #aac5de 17px, #6199c7 50%, #3a84c3 51px, #419ad6 59%, #4bb8f0 71px, #3a8bc2 84%, #26558b 100px);
/* IE 10+ */
background: -ms-linear-gradient(left, #cedbe9 0%, #aac5de 17px, #6199c7 50%, #3a84c3 51px, #419ad6 59%, #4bb8f0 71px, #3a8bc2 84%, #26558b 100px);
/* W3C */
background: linear-gradient(left, #cedbe9 0%, #aac5de 17px, #6199c7 50%, #3a84c3 51px, #419ad6 59%, #4bb8f0 71px, #3a8bc2 84%, #26558b 100px);
}
.linearGradient5 {
/* FF 3.6+ */
background: -moz-linear-gradient(top, #f0b7a1 0%, #8c3310 50%, #752201 51%, #bf6e4e 100%);
/* Chrome, Safari 4+ */
background: -webkit-gradient(linear, center top, center bottom, color-stop(0%, #f0b7a1), color-stop(50%, #8c3310), color-stop(51%, #752201), color-stop(100%, #bf6e4e));
/* Opera 11.10+ */
background: -o-linear-gradient(top, #f0b7a1 0%, #8c3310 50%, #752201 51%, #bf6e4e 100%);
/* IE 10+ */
background: -ms-linear-gradient(top, #f0b7a1 0%, #8c3310 50%, #752201 51%, #bf6e4e 100%);
/* W3C */
background: linear-gradient(top, #f0b7a1 0%, #8c3310 50%, #752201 51%, #bf6e4e 100%);
}
.linearGradient6 {
/* FF 3.6+ */
background: -moz-linear-gradient(top, #F00 0, green 31.4159%, #0000fF 51%, rgba(0, 0, 0, 0.0) 100%);
/* Chrome, Safari 4+ */
background: -webkit-gradient(linear, center top, center bottom, color-stop(0, #F00), color-stop(31.4159%, green), color-stop(51%, #0000fF), color-stop(100%, rgba(0, 0, 0, 0.0)));
/* Opera 11.10+ */
background: -o-linear-gradient(top, #F00 0, green 31.4159%, #0000fF 51%, rgba(0, 0, 0, 0.0) 100%);
/* IE 10+ */
background: -ms-linear-gradient(top, #F00 0, green 31.4159%, #0000fF 51%, rgba(0, 0, 0, 0.0) 100%);
/* W3C */
background: linear-gradient(top, #F00 0, green 31.4159%, #0000fF 51%, rgba(0, 0, 0, 0.0) 100%);
}
.linearGradient7 {
background: -webkit-linear-gradient(0deg, #ddd, #ddd 50%, transparent 50%);
background: linear-gradient(0deg, #ddd, #ddd 50%, transparent 50%);
}
.radialGradient {
background: -moz-radial-gradient(75% 19%, ellipse closest-side, #ababab, #0000ff 33%,#991f1f 100%);
background: -webkit-radial-gradient(75% 19%, ellipse closest-side, #ababab, #0000ff 33%,#991f1f 100%);
background: -o-radial-gradient(75% 19%, ellipse closest-side, #ababab, #0000ff 33%,#991f1f 100%);
background: -ms-radial-gradient(75% 19%, ellipse closest-side, #ababab, #0000ff 33%,#991f1f 100%);
background: radial-gradient(75% 19%, ellipse closest-side, #ababab, #0000ff 33%,#991f1f 100%);
}
.radialGradient2 {
background: -moz-radial-gradient(75% 19%, ellipse closest-corner, #ababab, #0000ff 33%,#991f1f 100%);
background: -webkit-radial-gradient(75% 19%, ellipse closest-corner, #ababab, #0000ff 33%,#991f1f 100%);
background: -o-radial-gradient(75% 19%, ellipse closest-corner, #ababab, #0000ff 33%,#991f1f 100%);
background: -ms-radial-gradient(75% 19%, ellipse closest-corner, #ababab, #0000ff 33%,#991f1f 100%);
background: radial-gradient(75% 19%, ellipse closest-corner, #ababab, #0000ff 33%,#991f1f 100%);
}
.radialGradient3 {
background: -moz-radial-gradient(75% 19%, ellipse farthest-side, #ababab, #0000ff 33%,#991f1f 100%);
background: -webkit-radial-gradient(75% 19%, ellipse farthest-side, #ababab, #0000ff 33%,#991f1f 100%);
background: -o-radial-gradient(75% 19%, ellipse farthest-side, #ababab, #0000ff 33%,#991f1f 100%);
background: -ms-radial-gradient(75% 19%, ellipse farthest-side, #ababab, #0000ff 33%,#991f1f 100%);
background: radial-gradient(75% 19%, ellipse farthest-side, #ababab, #0000ff 33%,#991f1f 100%)
}
.radialGradient4 {
background: -moz-radial-gradient(75% 19%, ellipse farthest-corner, #ababab, #0000ff 33%,#991f1f 100%);
background: -webkit-radial-gradient(75% 19%, ellipse farthest-corner, #ababab, #0000ff 33%,#991f1f 100%);
background: -o-radial-gradient(75% 19%, ellipse farthest-corner, #ababab, #0000ff 33%,#991f1f 100%);
background: -ms-radial-gradient(75% 19%, ellipse farthest-corner, #ababab, #0000ff 33%,#991f1f 100%);
background: radial-gradient(75% 19%, ellipse farthest-corner, #ababab, #0000ff 33%,#991f1f 100%);
}
.radialGradient5 {
background: -moz-radial-gradient(75% 19%, ellipse contain, #ababab, #0000ff 33%,#991f1f 100%);
background: -webkit-radial-gradient(75% 19%, ellipse contain, #ababab, #0000ff 33%,#991f1f 100%);
background: -o-radial-gradient(75% 19%, ellipse contain, #ababab, #0000ff 33%,#991f1f 100%);
background: -ms-radial-gradient(75% 19%, ellipse contain, #ababab, #0000ff 33%,#991f1f 100%);
background: radial-gradient(75% 19%, ellipse contain, #ababab, #0000ff 33%,#991f1f 100%);
}
.radialGradient6 {
background: -moz-radial-gradient(75% 19%, ellipse cover, #ababab, #0000ff 33%,#991f1f 100%);
background: -webkit-radial-gradient(75% 19%, ellipse cover, #ababab, #0000ff 33%,#991f1f 100%);
background: -o-radial-gradient(75% 19%, ellipse cover, #ababab, #0000ff 33%,#991f1f 100%);
background: -ms-radial-gradient(75% 19%, ellipse cover, #ababab, #0000ff 33%,#991f1f 100%);
background: radial-gradient(75% 19%, ellipse cover, #ababab, #0000ff 33%,#991f1f 100%);
}
</style>
<div class="linearGradientSimple"></div>
<div class="linearGradientSimple2"></div>
<div class="linearGradientWithStops"></div>
<div class="linearGradientWithPixelLengthStops"></div>
<div class="linearGradient5"></div>
<div class="linearGradient6"></div>
<div class="linearGradient7"></div>
<div class="radialGradient"></div>
<div class="radialGradient2"></div>
<div class="radialGradient3"></div>
<div class="radialGradient4"></div>
<div class="radialGradient5"></div>
<div class="radialGradient6"></div>
</div>
</div>
<script src="css.js"></script>
<script src="gradients.js"></script>
<script>
mocha.checkLeaks();
mocha.globals(['jQuery']);
if (window.mochaPhantomJS) {
mochaPhantomJS.run();
}
else {
mocha.run();
}
mocha.suite.afterAll(function() {
document.body.setAttribute('data-complete', 'true');
});
</script>
</body>
</html>

View File

@ -1,89 +0,0 @@
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>Proxy tests</title>
<link rel="stylesheet" href="lib/mocha.css" />
<script src="../../dist/html2canvas.js"></script>
<script src="../assets/jquery-1.6.2.js"></script>
<script src="lib/expect.js"></script>
<script src="lib/mocha.js"></script>
<style>
#content {
width: 200px;
height: 200px;
}
</style>
</head>
<body>
<div id="mocha"></div>
<script>mocha.setup('bdd')</script>
<div id="content" style="display: inline-block;background: red;">
<iframe src="http://localhost:8083/tests/mocha/iframe3.htm" style="border: 0; width: 200px; height: 200px;" scrolling="no"></iframe>
</div>
<script>
describe("Proxy", function() {
it("with iframe through proxy", function (done) {
this.timeout(10000);
html2canvas(document.querySelector("#content"), {proxy: 'http://localhost:8082'}).then(function (canvas) {
validCanvasPixels(canvas);
done();
}).catch(function (error) {
done(error);
});
});
it("with iframe without proxy", function (done) {
html2canvas(document.querySelector("#content")).then(function (canvas) {
expect(canvas.width).to.equal(200);
expect(canvas.height).to.equal(200);
done();
}).catch(function (error) {
done(error);
});
});
it("with url using proxy", function (done) {
html2canvas("http://localhost:8083/tests/mocha/iframe3.htm", {proxy: 'http://localhost:8082', width: 200, height: 200, type: 'view'}).then(function (canvas) {
expect(canvas.width).to.equal(200);
expect(canvas.height).to.equal(200);
done();
}).catch(function (error) {
done(error);
});
});
it("with url without proxy", function (done) {
html2canvas("http://localhost:8083/tests/mocha/iframe3.htm").then(function () {
done("Should throw error");
}).catch(function (error) {
expect(error).to.equal("Proxy must be used when rendering url");
done();
});
});
});
function validCanvasPixels(canvas) {
var ctx = canvas.getContext("2d");
var data = ctx.getImageData(0, 0, canvas.width, canvas.height).data;
for (var i = 0, len = data.length; i < len; i+=4) {
if (data[i] !== 0 || data[i+1] !== 128 || data[i+2] !== 0 || data[i+3] !== 255) {
expect().fail("Invalid canvas data");
}
}
}
mocha.checkLeaks();
mocha.globals(['jQuery']);
if (window.mochaPhantomJS) {
mochaPhantomJS.run();
}
else {
mocha.run();
}
mocha.suite.afterAll(function() {
document.body.setAttribute('data-complete', 'true');
});
</script>
</body>
</html>

View File

@ -1,117 +0,0 @@
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>Scrolling tests</title>
<link rel="stylesheet" href="lib/mocha.css" />
<script src="../../node_modules/bluebird/js/browser/bluebird.js"></script>
<script src="../../dist/html2canvas.js"></script>
<script src="../assets/jquery-1.6.2.js"></script>
<script src="lib/expect.js"></script>
<script src="lib/mocha.js"></script>
</head>
<body>
<div id="mocha"></div>
<script>mocha.setup('bdd')</script>
<div id="scroll-render" style="height: 200px; width: 200px;">
<div style="height: 500px; width: 400px;overflow: scroll;" id="scrollable">
<div style="height: 500px;background: red;"></div>
<div style="height: 650px; background: green"></div>
</div>
</div>
<div style="height: 2200px"></div>
<div style="height: 500px;background: green;" id="bottom-content"><a name="content">&nbsp;</a></div>
<script>
describe("Scrolling", function() {
it("with random scroll", function (done) {
$(window).scrollTop(123);
setTimeout(function() {
html2canvas(document.body, {type: 'view'}).then(function () {
expect($(window).scrollTop()).to.equal(123);
done();
}).catch(function (error) {
done(error);
});
}, 0);
});
it("with url anchor", function (done) {
window.location.hash = "#content";
setTimeout(function() {
var top = $(window).scrollTop();
html2canvas(document.body, {type: 'view'}).then(function () {
var currentTop = $(window).scrollTop();
window.location.hash = "";
expect(currentTop).to.be.greaterThan(1500);
if ((currentTop - top) !== 200) { // phantomjs issue
expect(currentTop).to.equal(top);
}
done();
}).catch(function (error) {
done(error);
});
}, 0);
});
it("with content scroll", function (done) {
$("#scrollable").scrollTop(500);
setTimeout(function() {
html2canvas(document.querySelector("#scroll-render")).then(function (canvas) {
expect($("#scrollable").scrollTop()).to.equal(500);
expect(canvas.width).to.equal(200);
expect(canvas.height).to.equal(200);
validCanvasPixels(canvas);
done();
}).catch(function (error) {
done(error);
});
}, 0);
});
it("with window scroll", function (done) {
$(window).scrollTop(500);
setTimeout(function() {
console.log(document.querySelector("#bottom-content").getBoundingClientRect().top);
html2canvas(document.querySelector("#bottom-content")).then(function (canvas) {
expect($(window).scrollTop()).to.equal(500);
validCanvasPixels(canvas);
done();
}).catch(function (error) {
done(error);
});
}, 0);
});
});
function validCanvasPixels(canvas) {
var ctx = canvas.getContext("2d");
var data = ctx.getImageData(0, 0, canvas.width, canvas.height).data;
for (var i = 0, len = 200*199*4; i < len; i+=4) {
if (data[i] !== 0 || data[i+1] !== 128 || data[i+2] !== 0 || data[i+3] !== 255) {
console.log(i, data[i], data[i+1], data[i+2], data[i+3]);
expect().fail("Invalid canvas data");
}
}
}
after(function() {
if (history) {
history.pushState("", document.title, window.location.pathname + window.location.search);
}
});
mocha.checkLeaks();
mocha.globals(['jQuery']);
if (window.mochaPhantomJS) {
mochaPhantomJS.run();
}
else {
mocha.run();
}
mocha.suite.afterAll(function() {
document.body.setAttribute('data-complete', 'true');
});
</script>
</body>
</html>

View File

@ -1,99 +0,0 @@
var wd = require('wd');
var http = require('http');
var https = require('https');
var url = require('url');
var path = require('path');
var Promise = require('bluebird');
var _ = require('lodash');
var humanizeDuration = require('humanize-duration');
var utils = require('../utils');
var colors = utils.colors;
var port = 8080;
function runTestWithRetries(browser, test, retries) {
retries = retries || 0;
return runTest(browser, test).timeout(30000).catch(Promise.TimeoutError, function() {
if (retries < 3) {
console.log(colors.violet, 'Retry', retries + 1, test);
return runTestWithRetries(browser, test, retries + 1);
} else {
throw new Error("Couldn't run test after 3 retries");
}
});
}
function getResults(browser) {
return function() {
return Promise.props({
dataUrl: browser
.waitForElementByCss("body[data-complete='true']", 90000)
.then(function() {
return browser.elementsByCssSelector('.test.fail');
})
.then(function(nodes) {
return Array.isArray(nodes)
? Promise.map(nodes, function(node) {
return browser.text(node).then(function(error) {
return Promise.reject(error);
});
})
: Promise.resolve([]);
})
});
};
}
function runTest(browser, test) {
return Promise.resolve(
browser.then(utils.loadTestPage(browser, test, port)).then(getResults(browser))
).cancellable();
}
exports.tests = function(browsers, singleTest) {
var path = 'tests/mocha';
return (singleTest ? Promise.resolve([singleTest]) : utils.getTests(path)).then(function(
tests
) {
return Promise.map(
browsers,
function(settings) {
var name = [settings.browserName, settings.version, settings.platform].join('-');
var count = 0;
var browser = utils.initBrowser(settings);
return Promise.using(browser, function() {
return Promise.map(
tests,
function(test, index, total) {
console.log(
colors.green,
'STARTING',
'(' + ++count + '/' + total + ')',
name,
test,
colors.clear
);
var start = Date.now();
return runTestWithRetries(browser, test).then(function() {
console.log(
colors.green,
'COMPLETE',
humanizeDuration(Date.now() - start),
'(' + count + '/' + total + ')',
name,
colors.clear
);
});
},
{concurrency: 1}
)
.settle()
.catch(function(error) {
console.error(colors.red, 'ERROR', name, error);
throw error;
});
});
},
{concurrency: 3}
);
});
};

View File

@ -0,0 +1,50 @@
<!DOCTYPE html>
<html>
<head>
<title>Animation</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="../test.js"></script>
<style>
span {
color:blue;
}
p {
background-color: green;
}
div {
background: red;
border: 5px solid blue;
animation: spin 3s linear 1s infinite;
}
body {
font-family: Arial;
}
@-webkit-keyframes spin {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
/* Firefox 16+, IE 10+, Opera */ }
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
/* Firefox 16+, IE 10+, Opera */ } }
@keyframes spin {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
/* Firefox 16+, IE 10+, Opera */ }
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
/* Firefox 16+, IE 10+, Opera */ } }
</style>
</head>
<body>
<div style="clip: rect(0px, 400px, 50px, 200px); ">Some inline text <span> followed by text in span </span> followed by more inline text.
<p>Then a block level element.</p>
Then more inline text.</div>
</body>
</html>

View File

@ -20,13 +20,14 @@
}
.medium div{
width:200px;
height:200px;
width:100px;
height:100px;
float:left;
margin:10px;
border:20px solid transparent;
border-width: 10px 20px 30px 40px;
background: green;
padding: 25px 15px;
}
.small, .medium{
@ -51,6 +52,8 @@
<div class="medium">
<div style="background:url(../../assets/image.jpg);background-clip: border-box; background-repeat: no-repeat;"></div>
<div style="background:url(../../assets/image.jpg);background-clip: padding-box; background-repeat: repeat-y;"></div>
<div style="background:url(../../assets/image.jpg);background-clip: padding-box; background-repeat: repeat-x;"></div>
<div style="background:url(../../assets/image.jpg);background-clip: content-box; background-repeat: repeat-y;"></div>
<div style="background:url(../../assets/image.jpg);background-clip: content-box; background-repeat: repeat-x;"></div>
<div style="background:url(../../assets/image.jpg); background-repeat: no-repeat;"></div>
</div>

View File

@ -49,7 +49,7 @@
}
.linearGradient2 {
background: -webkit-gradient(linear, 0% 0, 0% 100%, from(rgb(252, 252, 252)), to(rgb(232, 232, 232)));
background: -webkit-gradient(linear, 0% 0, 0% 100%, from(rgb(252, 252, 252)), color-stop(0.3, #000000), to(rgb(232, 232, 232)));
}
.linearGradient3 {

View File

@ -14,8 +14,14 @@
width: 100px;
height: 100px;
padding: 10px;
border: 15px solid black;
border: 15px solid transparent;
}
.linearGradient {
width: 200px;
height: 200px;
background-image: linear-gradient(rgba(0, 0, 0, 0.7) 0.1em, transparent 0.1em), linear-gradient(90deg, rgba(0, 0, 0, 0.7) 0.1em, transparent 0.1em);
background-size: 1em 1em;
}
</style>
</head>
<body>
@ -38,5 +44,8 @@
<div style="background: linear-gradient(to right, rgba(255,255,255,0) 0%,rgba(255,255,255,1) 100%); "></div>
<div style="background: linear-gradient(90deg, yellow 0%, orange 10%, red 50%, blue 90%, cyan 100%) content-box;"></div>
<div style="background: linear-gradient(60deg, hsla(120,80%,50%,0.8) 0%, transparent 50%, rgba(255,100,100,0.5) 100%);"></div>
<div style="background: linear-gradient(to right, red 20%, orange 20% 40%, yellow 40% 60%, green 60% 80%, blue 80%);"></div>
<div style="background: linear-gradient(-45deg, #FF0000 40%, #00FF00 50%);"></div>
<div class="linearGradient"></div>
</body>
</html>
</html>

View File

@ -56,6 +56,6 @@
<div style='background-size: auto 100%;'></div>
<div style='background-size: auto;'></div>
</div>
<div class="container" style="padding: 10px; background-size: contain; background-origin: content-box; background-clip: content-box"></div>
</body>
</html>

View File

@ -36,7 +36,7 @@
<input type="text" value="textbox" />
<input type="password" value="textbox" />
<input type="text" value="textbox" style="border:5px solid navy;" />
<input type="text" value="textbox" style="border:5px solid navy;height:40px;" />
<input type="text" value="textbox with very long text that overflows" style="border:5px solid navy;height:40px;" />
<input type="text" value="textbox" style="border:5px solid navy;height:40px;padding:10px;" />

View File

@ -5,18 +5,9 @@
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="../../test.js"></script>
<script type="text/javascript">
function setUp() {
var supportedTypes = ["decimal","decimal-leading-zero","upper-roman","lower-roman","lower-alpha","upper-alpha"];
for (var i = 1;i<=15;i++){
$('#dynamic').append($('<li />').text(i).css('list-style-type',supportedTypes[1]));
}
}
</script>
<style>
#dynamic{
list-style-type:decimal;
list-style-type:decimal-leading-zero;
list-style-position: outside;
font-size:20px;
line-height:50px;
@ -53,6 +44,23 @@
</head>
<body>
<ol id="dynamic"></ol>
<ol id="dynamic">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
<li>11</li>
<li>12</li>
<li>13</li>
<li>14</li>
<li>15</li>
</ol>
</body>
</html>

View File

@ -5,15 +5,6 @@
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="../../test.js"></script>
<script type="text/javascript">
function setUp() {
var supportedTypes = ["decimal","decimal-leading-zero","upper-roman","lower-roman","lower-alpha","upper-alpha"];
for (var i = 1;i<=15;i++){
$('#dynamic').append($('<li />').text(i).css('list-style-type',supportedTypes[0]));
}
}
</script>
<style>
#dynamic{
list-style-type:decimal;
@ -54,7 +45,23 @@
</head>
<body>
<ol id="dynamic"></ol>
<ol id="dynamic">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
<li>11</li>
<li>12</li>
<li>13</li>
<li>14</li>
<li>15</li>
</ol>
</body>
</html>

View File

@ -1,102 +1,102 @@
<!doctype html>
<html>
<head>
<title>List tests</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="../../test.js"></script>
<head>
<title>List tests</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="../../test.js"></script>
<style>
li {
margin: 10px 5%;
}
.list1 {
list-style-type: circle;
}
<style>
li {
margin: 10px 5%;
}
.list1 {
list-style-type: circle;
}
.list2 {
list-style-image: url(../../assets/image.jpg);
}
.list2 {
list-style-image: url(../../assets/image.jpg);
}
.list3 {
list-style-image: linear-gradient(60deg, deeppink, aquamarine);
list-style-position: inside;
}
.list3 {
list-style-image: linear-gradient(60deg, deeppink, aquamarine);
list-style-position: inside;
}
.list4 {
}
.list4 {
}
.list5 {
list-style-type: lower-roman;
}
.list5 {
list-style-type: lower-roman;
}
.list6 {
list-style-type: hiragana;
}
.list6 {
list-style-type: hiragana;
}
.list7 {
list-style-type: simp-chinese-informal;
}
.list7 {
list-style-type: simp-chinese-informal;
}
.list8 {
list-style-type: lower-roman;
}
.list8 {
list-style-type: lower-roman;
}
.list8 li {
display: block;
}
.list8 li {
display: block;
}
.list9 {
display: list-item;
list-style-type: lower-alpha;
margin: 10px;
position: relative;
left: 200px;
}
</style>
</head>
<body>
<ul class="list1">
<li>Alpha</li>
<li>Beta</li>
<li>Gamma</li>
</ul>
<ul class="list2">
<li>Alpha</li>
<li>Beta</li>
<li>Gamma</li>
</ul>
<ul class="list3">
<li>Alpha</li>
<li>Beta</li>
<li>Gamma</li>
</ul>
<ol class="list4" start="-1">
<li>Alpha</li>
<li>Beta</li>
<li>Gamma</li>
</ol>
<ol class="list5">
<li>Alpha</li>
<li value="5">Beta</li>
<li>Gamma</li>
</ol>
<ol class="list6">
<li>Alpha</li>
<li>Beta</li>
<li>Gamma</li>
</ol>
<ol class="list7">
<li>Alpha</li>
<li>Beta</li>
<li>Gamma</li>
</ol>
<ol class="list8">
<li>Alpha</li>
<li>Beta</li>
<li>Gamma</li>
</ol>
<div class="list9">Alpha</div>
<div class="list9">Beta</div>
<div class="list9">Gamma</div>
</body>
.list9 {
display: list-item;
list-style-type: lower-alpha;
margin: 10px;
position: relative;
left: 200px;
}
</style>
</head>
<body>
<ul class="list1">
<li>Alpha</li>
<li>Beta</li>
<li>Gamma</li>
</ul>
<ul class="list2">
<li>Alpha</li>
<li>Beta</li>
<li>Gamma</li>
</ul>
<ul class="list3">
<li>Alpha</li>
<li>Beta</li>
<li>Gamma</li>
</ul>
<ol class="list4" start="-1">
<li>Alpha</li>
<li>Beta</li>
<li>Gamma</li>
</ol>
<ol class="list5">
<li>Alpha</li>
<li value="5">Beta</li>
<li>Gamma</li>
</ol>
<ol class="list6">
<li>Alpha</li>
<li>Beta</li>
<li>Gamma</li>
</ol>
<ol class="list7">
<li>Alpha</li>
<li>Beta</li>
<li>Gamma</li>
</ol>
<ol class="list8">
<li>Alpha</li>
<li>Beta</li>
<li>Gamma</li>
</ol>
<div class="list9">list-less Alpha</div>
<div class="list9">list-less Beta</div>
<div class="list9">list-less Gamma</div>
</body>
</html>

View File

@ -4,19 +4,9 @@
<title>List tests</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="../../test.js"></script>
<script type="text/javascript">
function setUp() {
var supportedTypes = ["decimal","decimal-leading-zero","upper-roman","lower-roman","lower-alpha","upper-alpha"];
for (var i = 1;i<=15;i++){
$('#dynamic').append($('<li />').text(i).css('list-style-type',supportedTypes[4]));
}
}
</script>
<style>
#dynamic{
list-style-type:decimal;
list-style-type:lower-alpha;
list-style-position: outside;
font-size:20px;
line-height:50px;
@ -54,7 +44,23 @@
</head>
<body>
<ol id="dynamic"></ol>
<ol id="dynamic">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
<li>11</li>
<li>12</li>
<li>13</li>
<li>14</li>
<li>15</li>
</ol>
</body>
</html>

View File

@ -5,18 +5,9 @@
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="../../test.js"></script>
<script type="text/javascript">
function setUp() {
var supportedTypes = ["decimal","decimal-leading-zero","upper-roman","lower-roman","lower-alpha","upper-alpha"];
for (var i = 1;i<=15;i++){
$('#dynamic').append($('<li />').text(i).css('list-style-type',supportedTypes[2]));
}
}
</script>
<style>
#dynamic{
list-style-type:decimal;
list-style-type:upper-roman;
list-style-position: outside;
font-size:20px;
line-height:50px;
@ -54,7 +45,24 @@
</head>
<body>
<ol id="dynamic"></ol>
<ol id="dynamic">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
<li>11</li>
<li>12</li>
<li>13</li>
<li>14</li>
<li>15</li>
</ol>
</body>
</html>

View File

@ -5,7 +5,7 @@
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script>
h2cOptions = {onclone: function(document) {
const remove = document.querySelector('.ignored');
var remove = document.querySelector('.ignored');
remove.parentNode.removeChild(remove);
}};
</script>

View File

@ -40,6 +40,29 @@
line-height: 17px;
font-size: 1em;
}
#app {
background-color: lightcoral;
width: 300px;
color: #333;
margin-top: 20px;
}
#box {
background-color: lightgreen;
width: 200px;
height: 200px;
overflow: hidden;
}
.content {
background-color: lightskyblue;
width: 150px;
height: 150px;
transform: translate(100px, 0);
}
</style>
</head>
@ -51,5 +74,16 @@
<div class="img-2"></div>
</div>
<div id="app">
This is app
<div id="box">
This is box, overflow hidden
<div class="content">
This is content
</div>
</div>
</div>
</body>
</html>

View File

@ -115,7 +115,13 @@
</div>
<script>
document.querySelector('#scroll').scrollTo(0, 200);
try {
document.querySelector('#scroll').scrollTo(0, 200);
} catch(e) {
// internet explorer
document.querySelector('#scroll').scrollTop = 200;
}
</script>
</div>
</body>

View File

@ -1,104 +1,167 @@
<!doctype html>
<html>
<head>
<script type="text/javascript" src="../test.js"></script>
<head>
<script type="text/javascript" src="../test.js"></script>
<style>
body {
quotes: "<{" "}>" "->" "<-" "(" ")" "-:" ":-";
}
<style>
body {
quotes: "<{" "}>" "->" "<-" "(" ")" "-:" ":-";
}
.counter1,
.counter2,
.quotes1,
.attr-url {
border: 1px solid deepskyblue;
padding: 5px;
margin-bottom: 10px;
}
.counter1,
.counter2,
.quotes1,
.attr-url {
border: 1px solid deepskyblue;
padding: 5px;
margin-bottom: 10px;
}
.counter1 {
counter-reset: c1 3;
}
.counter1 {
counter-reset: c1 3;
}
.counter1 > div::before {
content: "«\"" counter(c1) "\»";
counter-increment: c1 -1;
}
.counter1 > div::before {
content: "«\"" counter(c1) "\»";
counter-increment: c1 -1;
}
.counter2 {
counter-reset: c2;
}
.counter2 {
counter-reset: c2;
}
.counter2 > div::before {
content: "["counters(c2, " < ", upper-roman) ']';
counter-increment: c2 2;
}
.counter2 > div::before {
content: "["counters(c2, " < ", upper-roman) ']';
counter-increment: c2 2;
}
.quotes1::before {
content: open-quote "!" open-quote close-quote open-quote;
}
.counter-divs {
counter-reset: c5 3;
}
.quotes1::after {
content: "!" close-quote close-quote;
}
.counter-divs div {
counter-increment: c5 1;
}
.quotes2 {
quotes: "«" "»" "“" "”";
}
.counter-divs > div::before {
content: "["counter(c5) ']';
counter-increment: c5 2;
}
.quotes2::before {
content: open-quote;
}
.quotes1::before {
content: open-quote "!" open-quote close-quote open-quote;
}
.quotes2::after {
content: close-quote;
}
.quotes1::after {
content: "!" close-quote close-quote;
}
.attr-url > div::after {
content: url(../assets/image.jpg) "///" attr(data-text);
}
</style>
</head>
<body>
<div class="counter1">
<div>A</div>
<div>B</div>
<div>C</div>
<div>D</div>
</div>
.quotes2 {
quotes: "«" "»" "“" "”";
}
<div class="counter2">
<div>A</div>
<div>B</div>
<div>
C
<div class="counter2">
<div>a</div>
<div>b</div>
<div>
c
<div class="counter2">
<div>Aa</div>
<div>Bb</div>
<div>Cc</div>
</div>
</div>
</div>
</div>
<div>D</div>
</div>
.quotes2::before {
content: open-quote;
}
<div class="quotes1">
Hello
<div class="quotes2">
Quoted
<div class="quotes2">World</div>
</div>
</div>
.quotes2::after {
content: close-quote close-quote close-quote close-quote;
}
<div class="attr-url">
<div data-text="Hello World"></div>
</div>
</body>
</html>
.attr-url > div::after {
content: url(../assets/image.jpg) "///" attr(data-text);
}
ol {
counter-reset: section; /* Creates a new instance of the
section counter with each ol
element */
list-style-type: none;
}
li::before {
counter-increment: section; /* Increments only this instance
of the section counter */
content: counters(section, ".") " "; /* Combines the values of all instances
of the section counter, separated
by a period */
}
</style>
</head>
<body>
<div class="counter1">
<div>A</div>
<div>B</div>
<div>C</div>
<div>D</div>
</div>
<div class="counter2">
<div>A</div>
<div>B</div>
<div>
C
<div class="counter2">
<div>a</div>
<div>b</div>
<div>
c
<div class="counter2">
<div>Aa</div>
<div>Bb</div>
<div>Cc</div>
</div>
</div>
</div>
</div>
<div>D</div>
</div>
<div class="quotes1">
Hello
<div class="quotes2">
Quoted
<div class="quotes2">World</div>
</div>
</div>
<div class="attr-url">
<div data-text="Hello World"></div>
</div>
<div class="counter-divs">
<div>A</div>
<div>B</div>
<div>C</div>
<div>D</div>
</div>
<ol>
<li>item</li> <!-- 1 -->
<li>item <!-- 2 -->
<ol>
<li>item</li> <!-- 2.1 -->
<li>item</li> <!-- 2.2 -->
<li>item <!-- 2.3 -->
<ol>
<li>item</li> <!-- 2.3.1 -->
<li>item</li> <!-- 2.3.2 -->
</ol>
<ol>
<li>item</li> <!-- 2.3.1 -->
<li>item</li> <!-- 2.3.2 -->
<li>item</li> <!-- 2.3.3 -->
</ol>
</li>
<li>item</li> <!-- 2.4 -->
</ol>
</li>
<li>item</li> <!-- 3 -->
<li>item</li> <!-- 4 -->
</ol>
<ol>
<li>item</li> <!-- 1 -->
<li>item</li> <!-- 2 -->
</ol>
</body>
</html>

View File

@ -12,7 +12,7 @@
background-color: green;
}
body {
font-family: Arial;
font-family: "Helvetica Neue", Arial, sans-serif;
}
</style>

View File

@ -7,7 +7,7 @@
<script type="text/javascript">
function setUp() {
$('body').empty();
$.each(['arial','verdana','tahoma','courier new'],function(i,e){
$.each(['arial','verdana','courier new'],function(i,e){
var div = $('<div />').css('font-family',e).appendTo('body');
for(var i=0;i<=5;i++){
$('<div />').text('Testing texts').css('margin-top',1).css('border','1px solid black').css('font-size',(16+i*6)).appendTo(div);

View File

@ -7,7 +7,7 @@
<script type="text/javascript">
function setUp() {
$('body').empty();
$.each(['arial','verdana','tahoma','courier new'],function(i,e){
$.each(['arial','verdana','courier new'],function(i,e){
var div = $('<div />').css('font-family',e).appendTo('body');
for(var i=0;i<=5;i++){
$('<div />').text('Testing texts').css('margin-top',1).css('border','1px solid black').css('font-size',(16+i*6)).appendTo(div);

View File

@ -6,13 +6,20 @@
<script type="text/javascript" src="../../test.js"></script>
<script type="text/javascript">
function setUp() {
$('body').empty();
$.each(['arial','verdana','tahoma','courier new'],function(i,e){
var div = $('<div />').css('font-family',e).appendTo('body');
for(var i=1;i<=10;i*=2){
$('<div />').text('Testing texts').css('margin-top',1).css('font-size',(16+i*6)).appendTo(div);
}
var container = document.querySelector('#test');
container.innerHTML = '';
['arial','verdana','courier new'].forEach(function(e) {
var div = document.createElement('div');
div.style.fontFamily = e;
container.appendChild(div);
for(var i=1;i<=10;i*=2) {
var text = document.createElement('div');
text.innerText = 'Testing texts';
text.style.marginTop = '1px';
text.style.fontSize = (16+i*6) + 'px';
div.appendChild(text);
}
});
}
</script>
@ -45,6 +52,9 @@
</head>
<body>
Creating content through JavaScript
test <u>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</u> label u
<div id="test">
Creating content through JavaScript
</div>
</body>
</html>

52
tests/rollup.config.ts Normal file
View File

@ -0,0 +1,52 @@
import nodeResolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import sourceMaps from 'rollup-plugin-sourcemaps';
import typescript from 'rollup-plugin-typescript2';
import json from 'rollup-plugin-json';
import {resolve} from 'path';
const pkg = require('../package.json');
const banner = `/*
* ${pkg.title} ${pkg.version} <${pkg.homepage}>
* Copyright (c) ${new Date().getFullYear()} ${pkg.author.name} <${pkg.author.url}>
* Released under ${pkg.license} License
*/`;
export default {
input: `tests/testrunner.ts`,
output: [
{
file: resolve(__dirname, '../build/testrunner.js'),
name: 'testrunner',
format: 'iife',
banner,
sourcemap: true
}
],
external: [],
watch: {
include: 'tests/**'
},
plugins: [
// Allow node_modules resolution, so you can use 'external' to control
// which external modules to include in the bundle
// https://github.com/rollup/rollup-plugin-node-resolve#usage
nodeResolve(),
// Allow json resolution
json(),
// Compile TypeScript files
typescript({useTsconfigDeclarationDir: true}),
// Allow bundling cjs modules (unlike webpack, rollup doesn't understand cjs)
commonjs({
include: 'node_modules/**',
namedModules: {
'node_modules/platform/platform.js': ['name', 'version'],
'node_modules/es6-promise/dist/es6-promise.js': ['Promise']
}
}),
// Resolve source maps to the original source
sourceMaps()
]
};

View File

@ -2,8 +2,6 @@ const express = require('express');
const cors = require('cors');
const path = require('path');
const fs = require('fs');
const webpack = require('webpack');
const config = require('../webpack.config');
const serveIndex = require('serve-index');
const proxy = require('html2canvas-proxy');
@ -24,20 +22,3 @@ corsApp.use('/', express.static(path.resolve(__dirname, '.')));
corsApp.listen(CORS_PORT, () => {
console.log(`CORS server running on port ${CORS_PORT}`);
});
const compiler = webpack(config);
compiler.watch(
{
aggregateTimeout: 300 // wait so long for more changes
},
(err, stats) => {
console.error(err);
console.log(
stats.toString({
chunks: false, // Makes the build much quieter
colors: true
})
);
}
);

View File

@ -17,7 +17,7 @@ var REFTEST = window.location.search.indexOf('reftest') !== -1;
);
}
(typeof Promise === 'undefined' ? ['/node_modules/promise-polyfill/promise.min'] : [])
(typeof Promise === 'undefined' ? ['/node_modules/es6-promise/dist/es6-promise.auto.min'] : [])
.concat([
'/node_modules/jquery/dist/jquery.min',
'/dist/html2canvas'
@ -25,9 +25,6 @@ var REFTEST = window.location.search.indexOf('reftest') !== -1;
.forEach(appendScript);
window.onload = function() {
var targets = REFTEST
? [new html2canvas.CanvasRenderer(), new RefTestRenderer()]
: new html2canvas.CanvasRenderer();
(function($) {
$.fn.html2canvas = function(options) {
var date = new Date(),
@ -40,18 +37,7 @@ var REFTEST = window.location.search.indexOf('reftest') !== -1;
console.log('html2canvas threw an error', err);
});
promise.then(function(output) {
var canvas = Array.isArray(targets) ? output[0] : output;
if (Array.isArray(targets)) {
console.log(
output[1]
.split('\n')
.map(function(line, i) {
return i + 1 + ':' + line;
})
.join('\n')
);
}
promise.then(function(canvas) {
var $canvas = $(canvas),
finishTime = new Date();
@ -155,8 +141,7 @@ var REFTEST = window.location.search.indexOf('reftest') !== -1;
logging: true,
proxy: 'http://localhost:8081/proxy',
useCORS: false,
removeContainer: false,
target: targets
removeContainer: true
},
h2cOptions,
REFTEST ? {windowWidth: 800, windowHeight: 600} : {}

View File

@ -1,385 +0,0 @@
import {expect} from 'chai';
import parseRefTest from '../scripts/parse-reftest';
import reftests from './reftests';
import querystring from 'querystring';
import platform from 'platform';
import Promise from 'promise-polyfill';
const DOWNLOAD_REFTESTS = false;
const query = querystring.parse(location.search.replace(/^\?/, ''));
const downloadResult = (filename, data) => {
const downloadUrl = URL.createObjectURL(new Blob([data], {type: 'text/plain'}));
const a = document.createElement('a');
a.href = downloadUrl;
a.download = filename;
setTimeout(() => {
a.click();
URL.revokeObjectURL(downloadUrl);
document.body.removeChild(a);
}, 100);
document.body.appendChild(a);
};
const assertPath = (result, expected, desc) => {
expect(result.length).to.equal(expected.length, `${desc} path length`);
expected.forEach((e, i) => {
const r = result[i];
expect(r.type).to.equal(e.type, `${desc} type`);
if (Array.isArray(r)) {
assertPath(r, e, desc);
} else {
switch (r.type) {
case 'Circle':
expect(r.x).to.be.closeTo(e.x, 10, `${desc} Circle #${i + 1} x`);
expect(r.y).to.be.closeTo(e.y, 10, `${desc} Circle #${i + 1} y`);
expect(r.r).to.be.closeTo(e.r, 5, `${desc} Circle #${i + 1} r`);
break;
case 'Vector':
expect(r.x).to.be.closeTo(e.x, 10, `${desc} vector #${i + 1} x`);
expect(r.y).to.be.closeTo(e.y, 10, `${desc} vector #${i + 1} y`);
break;
case 'BezierCurve':
expect(r.x0).to.be.closeTo(e.x0, 10, `${desc} beziercurve #${i + 1} x0`);
expect(r.y0).to.be.closeTo(e.y0, 10, `${desc} beziercurve #${i + 1} y0`);
expect(r.x1).to.be.closeTo(e.x1, 10, `${desc} beziercurve #${i + 1} x1`);
expect(r.y1).to.be.closeTo(e.y1, 10, `${desc} beziercurve #${i + 1} y1`);
expect(r.cx0).to.be.closeTo(e.cx0, 10, `${desc} beziercurve #${i + 1} cx0`);
expect(r.cy0).to.be.closeTo(e.cy0, 10, `${desc} beziercurve #${i + 1} cy0`);
expect(r.cx1).to.be.closeTo(e.cx1, 10, `${desc} beziercurve #${i + 1} cx1`);
expect(r.cy1).to.be.closeTo(e.cy1, 10, `${desc} beziercurve #${i + 1} cy1`);
break;
default:
throw new Error(`Unknown path type ${r.type}`);
}
}
});
};
(() => {
const testRunnerUrl = location.href;
const hasHistoryApi =
typeof window.history !== 'undefined' && typeof window.history.replaceState !== 'undefined';
if (typeof reftests === 'undefined') {
it('Test harness prerequisite check', () => {
throw new Error(
'No reftests list defined, run "npm run create-reftest-list" to create it'
);
});
} else {
Object.keys(reftests.testList)
.filter(test => {
return (
!Array.isArray(reftests.ignoredTests[test]) ||
reftests.ignoredTests[test].indexOf(platform.name) === -1
);
})
.forEach(url => {
describe(url, function() {
this.timeout(60000);
this.retries(2);
const windowWidth = 800;
const windowHeight = 600;
const testContainer = document.createElement('iframe');
const REFTEST = reftests.testList[url];
testContainer.width = windowWidth;
testContainer.height = windowHeight;
testContainer.style.visibility = 'hidden';
testContainer.style.position = 'fixed';
testContainer.style.left = '10000px';
before(done => {
testContainer.onload = () => done();
testContainer.src = url + '?selenium&run=false&reftest&' + Math.random();
if (hasHistoryApi) {
// Chrome does not resolve relative background urls correctly inside of a nested iframe
try {
history.replaceState(null, '', url);
} catch (e) {}
}
document.body.appendChild(testContainer);
});
after(() => {
if (hasHistoryApi) {
try {
history.replaceState(null, '', testRunnerUrl);
} catch (e) {}
}
document.body.removeChild(testContainer);
});
it('Should render untainted canvas', () => {
return testContainer.contentWindow
.html2canvas(
testContainer.contentWindow.forceElement ||
testContainer.contentWindow.document.documentElement,
{
removeContainer: true,
backgroundColor: '#ffffff',
proxy: 'http://localhost:8081/proxy',
...(testContainer.contentWindow.h2cOptions || {})
}
)
.then(canvas => {
try {
canvas
.getContext('2d')
.getImageData(0, 0, canvas.width, canvas.height);
} catch (e) {
return Promise.reject('Canvas is tainted');
}
const delta = 10;
if (REFTEST && query.refTest === 'true') {
const RESULTS = parseRefTest(result);
REFTEST.forEach(({action, line, ...args}, i) => {
const RESULT = RESULTS[i];
expect(RESULT.action).to.equal(action, `Line ${line}`);
const desc = `Line ${line} ${action}`;
switch (action) {
case 'Window':
expect(RESULT.width).to.equal(
args.width,
`${desc} width`
);
expect(RESULT.height).to.be.closeTo(
args.height,
delta,
`${desc} height`
);
break;
case 'Rectangle':
expect(RESULT.x).to.equal(args.x, `${desc} x`);
expect(RESULT.y).to.equal(args.y, `${desc} y`);
expect(RESULT.width).to.equal(
args.width,
`${desc} width`
);
expect(RESULT.height).to.be.closeTo(
args.height,
delta,
`${desc} height`
);
break;
case 'Fill':
expect(RESULT.color).to.equal(
args.color,
`${desc} color`
);
break;
case 'Opacity':
expect(RESULT.opacity).to.equal(
args.opacity,
`${desc} opacity`
);
break;
case 'Text':
expect(RESULT.font).to.equal(
args.font,
`${desc} font`
);
break;
case 'T':
expect(RESULT.x).to.be.closeTo(
args.x,
10,
`${desc} x`
);
expect(RESULT.y).to.be.closeTo(
args.y,
10,
`${desc} y`
);
expect(RESULT.text).to.equal(
args.text,
`${desc} text`
);
break;
case 'Transform':
expect(RESULT.x).to.be.closeTo(
args.x,
10,
`${desc} x`
);
expect(RESULT.y).to.be.closeTo(
args.y,
10,
`${desc} y`
);
expect(RESULT.matrix).to.equal(
args.matrix,
`${desc} matrix`
);
break;
case 'Repeat':
expect(RESULT.x).to.be.closeTo(
args.x,
10,
`${desc} x`
);
expect(RESULT.y).to.be.closeTo(
args.y,
10,
`${desc} y`
);
expect(RESULT.width).to.be.closeTo(
args.width,
3,
`${desc} width`
);
expect(RESULT.height).to.be.closeTo(
args.height,
3,
`${desc} height`
);
expect(RESULT.imageSrc).to.equal(
args.imageSrc,
`${desc} imageSrc`
);
assertPath(RESULT.path, args.path, desc);
break;
case 'Gradient':
expect(RESULT.x).to.be.closeTo(
args.x,
10,
`${desc} x`
);
expect(RESULT.y).to.be.closeTo(
args.y,
10,
`${desc} y`
);
expect(RESULT.x0).to.be.closeTo(
args.x0,
5,
`${desc} x0`
);
expect(RESULT.y0).to.be.closeTo(
args.y0,
5,
`${desc} y0`
);
expect(RESULT.x1).to.be.closeTo(
args.x1,
5,
`${desc} x1`
);
expect(RESULT.y1).to.be.closeTo(
args.y1,
5,
`${desc} y1`
);
expect(RESULT.stops).to.equal(
args.stops,
`${desc} stops`
);
expect(RESULT.width).to.equal(
args.width,
`${desc} width`
);
expect(RESULT.height).to.equal(
args.height,
`${desc} height`
);
break;
case 'Draw image':
expect(RESULT.imageSrc).to.equal(
args.imageSrc,
`${desc} stops`
);
expect(RESULT.sx).to.equal(args.sx, `${desc} sx`);
expect(RESULT.sy).to.equal(args.sy, `${desc} sy`);
expect(RESULT.dx).to.equal(args.dx, `${desc} dx`);
expect(RESULT.dy).to.equal(args.dy, `${desc} dy`);
expect(RESULT.sw).to.equal(args.sw, `${desc} sw`);
expect(RESULT.sh).to.equal(args.sh, `${desc} sh`);
expect(RESULT.dw).to.equal(args.dw, `${desc} dw`);
expect(RESULT.dh).to.equal(args.dh, `${desc} dh`);
break;
case 'Clip':
assertPath(RESULT.path, args.path, desc);
break;
case 'Shape':
expect(RESULT.color).to.equal(
args.color,
`${desc} color`
);
assertPath(RESULT.path, args.path, desc);
break;
default:
console.log(RESULT);
throw new Error(`Unrecognized action ${action}`);
}
});
} else if (DOWNLOAD_REFTESTS) {
downloadResult(
url
.slice(url.lastIndexOf('/') + 1)
.replace(/\.html$/i, '.txt'),
result
);
}
if (window.__karma__) {
return new Promise((resolve, reject) => {
const xhr =
'withCredentials' in new XMLHttpRequest()
? new XMLHttpRequest()
: new XDomainRequest();
xhr.onload = () => {
if (
typeof xhr.status !== 'number' ||
xhr.status === 200
) {
resolve();
} else {
reject(
`Failed to send screenshot with status ${xhr.status}`
);
}
};
xhr.onerror = reject;
xhr.open('POST', 'http://localhost:8000/screenshot', true);
xhr.send(JSON.stringify({
screenshot: canvas.toDataURL(),
test: url,
platform: {
name: platform.name,
version: platform.version
},
devicePixelRatio: window.devicePixelRatio || 1,
windowWidth: window.innerWidth,
windowHeight: window.innerHeight
}));
});
}
});
});
});
});
}
})();

115
tests/testrunner.ts Normal file
View File

@ -0,0 +1,115 @@
import {testList, ignoredTests} from '../build/reftests';
// @ts-ignore
import {default as platform} from 'platform';
// @ts-ignore
import Promise from 'es6-promise';
const testRunnerUrl = location.href;
const hasHistoryApi = typeof window.history !== 'undefined' && typeof window.history.replaceState !== 'undefined';
const uploadResults = (canvas: HTMLCanvasElement, url: string) => {
return new Promise((resolve: () => void, reject: (error: string) => void) => {
// @ts-ignore
const xhr = 'withCredentials' in new XMLHttpRequest() ? new XMLHttpRequest() : new XDomainRequest();
xhr.onload = () => {
if (typeof xhr.status !== 'number' || xhr.status === 200) {
resolve();
} else {
reject(`Failed to send screenshot with status ${xhr.status}`);
}
};
xhr.onerror = reject;
xhr.open('POST', 'http://localhost:8000/screenshot', true);
xhr.send(
JSON.stringify({
screenshot: canvas.toDataURL(),
test: url,
platform: {
name: platform.name,
version: platform.version
},
devicePixelRatio: window.devicePixelRatio || 1,
windowWidth: window.innerWidth,
windowHeight: window.innerHeight
})
);
});
};
testList
.filter(test => {
return !Array.isArray(ignoredTests[test]) || ignoredTests[test].indexOf(platform.name || '') === -1;
})
.forEach(url => {
describe(url, function() {
this.timeout(60000);
this.retries(2);
const windowWidth = 800;
const windowHeight = 600;
const testContainer = document.createElement('iframe');
testContainer.width = windowWidth.toString();
testContainer.height = windowHeight.toString();
testContainer.style.visibility = 'hidden';
testContainer.style.position = 'fixed';
testContainer.style.left = '10000px';
before(done => {
testContainer.onload = () => done();
testContainer.src = url + '?selenium&run=false&reftest&' + Math.random();
if (hasHistoryApi) {
// Chrome does not resolve relative background urls correctly inside of a nested iframe
try {
history.replaceState(null, '', url);
} catch (e) {}
}
document.body.appendChild(testContainer);
});
after(() => {
if (hasHistoryApi) {
try {
history.replaceState(null, '', testRunnerUrl);
} catch (e) {}
}
document.body.removeChild(testContainer);
});
it('Should render untainted canvas', () => {
const contentWindow = testContainer.contentWindow;
if (!contentWindow) {
throw new Error('Window not found for iframe');
}
return (
contentWindow
// @ts-ignore
.html2canvas(contentWindow.forceElement || contentWindow.document.documentElement, {
removeContainer: true,
backgroundColor: '#ffffff',
proxy: 'http://localhost:8081/proxy',
// @ts-ignore
...(contentWindow.h2cOptions || {})
})
.then((canvas: HTMLCanvasElement) => {
try {
(canvas.getContext('2d') as CanvasRenderingContext2D).getImageData(
0,
0,
canvas.width,
canvas.height
);
} catch (e) {
return Promise.reject('Canvas is tainted');
}
// @ts-ignore
if (window.__karma__) {
return uploadResults(canvas, url);
}
})
);
});
});
});