Fix canvas cropping with type: 'view'

This commit is contained in:
Niklas von Hertzen 2014-10-15 20:28:26 +03:00
parent 199685ebd1
commit 7e13231807
22 changed files with 8332 additions and 2425 deletions

View File

@ -9,7 +9,7 @@ module.exports = function(grunt) {
'<%= pkg.homepage ? " <" + pkg.homepage + ">" : "" %>' + '\n' + '<%= pkg.homepage ? " <" + pkg.homepage + ">" : "" %>' + '\n' +
' Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>' + ' Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>' +
'\n\n Released under <%= _.pluck(pkg.licenses, "type").join(", ") %> License\n*/\n', '\n\n Released under <%= _.pluck(pkg.licenses, "type").join(", ") %> License\n*/\n',
pre: '\n(function(window, document, module, exports, undefined){\n\n', pre: '\n(function(window, document, module, exports, global, define, undefined){\n\n',
post: '\n}).call({}, window, document);' post: '\n}).call({}, window, document);'
}; };
@ -18,9 +18,6 @@ module.exports = function(grunt) {
pkg: grunt.file.readJSON('package.json'), pkg: grunt.file.readJSON('package.json'),
qunit: {
files: ['tests/qunit/index.html']
},
concat: { concat: {
dist: { dist: {
src: [ src: [
@ -123,6 +120,9 @@ module.exports = function(grunt) {
all: ['src/*.js', 'src/renderers/*.js', '!src/promise.js'], all: ['src/*.js', 'src/renderers/*.js', '!src/promise.js'],
options: grunt.file.readJSON('./.jshintrc') options: grunt.file.readJSON('./.jshintrc')
}, },
mocha_phantomjs: {
all: ['tests/mocha/**/*.html']
},
webdriver: { webdriver: {
chrome: { chrome: {
browserName: "chrome", browserName: "chrome",
@ -179,17 +179,17 @@ module.exports = function(grunt) {
}); });
}); });
grunt.loadNpmTasks('grunt-mocha-phantomjs');
grunt.loadNpmTasks('grunt-contrib-watch'); grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-concat'); grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-uglify'); grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-jshint'); grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-qunit');
grunt.loadNpmTasks('grunt-contrib-connect'); grunt.loadNpmTasks('grunt-contrib-connect');
grunt.loadNpmTasks('grunt-execute'); grunt.loadNpmTasks('grunt-execute');
grunt.registerTask('server', ['connect:cors', 'connect:proxy', 'connect:server']); grunt.registerTask('server', ['connect:cors', 'connect:proxy', 'connect:server']);
grunt.registerTask('build', ['execute', 'concat', 'uglify']); grunt.registerTask('build', ['execute', 'concat', 'uglify']);
grunt.registerTask('default', ['jshint', 'build', 'qunit']); grunt.registerTask('default', ['jshint', 'build', 'mocha_phantomjs']);
grunt.registerTask('travis', ['jshint', 'build','qunit', 'connect:ci', 'connect:proxy', 'connect:cors', 'webdriver']); grunt.registerTask('travis', ['jshint', 'build','mocha_phantomjs', 'connect:ci', 'connect:proxy', 'connect:cors', 'webdriver']);
}; };

47
dist/html2canvas.js vendored
View File

@ -622,13 +622,22 @@ function renderWindow(node, container, options, windowWidth, windowHeight) {
var support = new Support(clonedWindow.document); var support = new Support(clonedWindow.document);
var imageLoader = new ImageLoader(options, support); var imageLoader = new ImageLoader(options, support);
var bounds = getBounds(node); var bounds = getBounds(node);
var width = options.width != null ? options.width : options.type === "view" ? Math.min(bounds.width, windowWidth) : documentWidth(clonedWindow.document); var width = options.type === "view" ? windowWidth : documentWidth(clonedWindow.document);
var height = options.height != null ? options.height : options.type === "view" ? Math.min(bounds.height, windowHeight) : documentHeight(clonedWindow.document); var height = options.type === "view" ? windowHeight : documentHeight(clonedWindow.document);
var renderer = new CanvasRenderer(width, height, imageLoader, options, document); var renderer = new CanvasRenderer(width, height, imageLoader, options, document);
var parser = new NodeParser(node, renderer, support, imageLoader, options); var parser = new NodeParser(node, renderer, support, imageLoader, options);
return parser.ready.then(function() { return parser.ready.then(function() {
log("Finished rendering"); log("Finished rendering");
var canvas = (options.type !== "view" && (node === clonedWindow.document.body || node === clonedWindow.document.documentElement || options.canvas != null)) ? renderer.canvas : crop(renderer.canvas, {width: width, height: height, top: bounds.top, left: bounds.left}); var canvas;
if (options.type === "view") {
canvas = crop(renderer.canvas, {width: renderer.canvas.width, height: renderer.canvas.height, top: 0, left: 0, x: 0, y: 0});
} else if (node === clonedWindow.document.body || node === clonedWindow.document.documentElement || options.canvas != null) {
canvas = renderer.canvas;
} else {
canvas = crop(renderer.canvas, {width: options.width != null ? options.width : bounds.width, height: options.height != null ? options.height : bounds.height, top: bounds.top, left: bounds.left, x: clonedWindow.pageXOffset, y: clonedWindow.pageYOffset});
}
cleanupContainer(container, options); cleanupContainer(container, options);
return canvas; return canvas;
}); });
@ -647,11 +656,11 @@ function crop(canvas, bounds) {
var x2 = Math.min(canvas.width, Math.max(1, bounds.left + bounds.width)); var x2 = Math.min(canvas.width, Math.max(1, bounds.left + bounds.width));
var y1 = Math.min(canvas.height - 1, Math.max(0, bounds.top)); var y1 = Math.min(canvas.height - 1, Math.max(0, bounds.top));
var y2 = Math.min(canvas.height, Math.max(1, bounds.top + bounds.height)); var y2 = Math.min(canvas.height, Math.max(1, bounds.top + bounds.height));
var width = croppedCanvas.width = x2 - x1; croppedCanvas.width = bounds.width;
var height = croppedCanvas.height = y2 - y1; croppedCanvas.height = bounds.height;
log("Cropping canvas at:", "left:", bounds.left, "top:", bounds.top, "width:", bounds.width, "height:", bounds.height); log("Cropping canvas at:", "left:", bounds.left, "top:", bounds.top, "width:", (x2-x1), "height:", (y2-y1));
log("Resulting crop with width", width, "and height", height, " with x", x1, "and y", y1); log("Resulting crop with width", bounds.width, "and height", bounds.height, " with x", x1, "and y", y1);
croppedCanvas.getContext("2d").drawImage(canvas, x1, y1, width, height, 0, 0, width, height); croppedCanvas.getContext("2d").drawImage(canvas, x1, y1, x2-x1, y2-y1, bounds.x, bounds.y, x2-x1, y2-y1);
return croppedCanvas; return croppedCanvas;
} }
@ -698,19 +707,27 @@ function createWindowClone(ownerDocument, containerDocument, width, height, opti
if (documentClone.body.childNodes.length > 0) { if (documentClone.body.childNodes.length > 0) {
cloneCanvasContents(ownerDocument, documentClone); cloneCanvasContents(ownerDocument, documentClone);
clearInterval(interval); clearInterval(interval);
if (options.type === "view") {
container.contentWindow.scrollTo(x, y);
}
resolve(container); resolve(container);
} }
}, 50); }, 50);
}; };
var x = ownerDocument.defaultView.pageXOffset;
var y = ownerDocument.defaultView.pageYOffset;
documentClone.open(); documentClone.open();
documentClone.write("<!DOCTYPE html>"); documentClone.write("<!DOCTYPE html>");
documentClone.close(); documentClone.close();
documentClone.replaceChild(options.javascriptEnabled === true ? documentClone.adoptNode(documentElement) : removeScriptNodes(documentClone.adoptNode(documentElement)), documentClone.documentElement); // Chrome scrolls the parent document for some reason after the write to the cloned window???
if (options.type === "view") { if (x !== ownerDocument.defaultView.pageXOffset || y !== ownerDocument.defaultView.pageYOffset) {
container.contentWindow.scrollTo(window.pageXOffset, window.pageYOffset); ownerDocument.defaultView.scrollTo(x, y);
} }
documentClone.replaceChild(options.javascriptEnabled === true ? documentClone.adoptNode(documentElement) : removeScriptNodes(documentClone.adoptNode(documentElement)), documentClone.documentElement);
}); });
} }
@ -1344,8 +1361,8 @@ NodeContainer.prototype.parseTextShadows = function() {
var s = shadows[i].match(this.TEXT_SHADOW_VALUES); var s = shadows[i].match(this.TEXT_SHADOW_VALUES);
results.push({ results.push({
color: s[0], color: s[0],
offsetX: s[1] ? s[1].replace('px', '') : 0, offsetX: s[1] ? parseFloat(s[1].replace('px', '')) : 0,
offsetY: s[2] ? s[2].replace('px', '') : 0, offsetY: s[2] ? parseFloat(s[2].replace('px', '')) : 0,
blur: s[3] ? s[3].replace('px', '') : 0 blur: s[3] ? s[3].replace('px', '') : 0
}); });
} }
@ -1592,9 +1609,11 @@ function NodeParser(element, renderer, support, imageLoader, options) {
resolve(); resolve();
} else if (typeof(options.async) === "function") { } else if (typeof(options.async) === "function") {
options.async.call(this, this.renderQueue, resolve); options.async.call(this, this.renderQueue, resolve);
} else { } else if (this.renderQueue.length > 0){
this.renderIndex = 0; this.renderIndex = 0;
this.asyncRenderer(this.renderQueue, resolve); this.asyncRenderer(this.renderQueue, resolve);
} else {
resolve();
} }
}, this)); }, this));
}, this)); }, this));

File diff suppressed because one or more lines are too long

View File

@ -26,10 +26,10 @@
"grunt-contrib-concat": "^0.5.0", "grunt-contrib-concat": "^0.5.0",
"grunt-contrib-connect": "^0.8.0", "grunt-contrib-connect": "^0.8.0",
"grunt-contrib-jshint": "^0.10.0", "grunt-contrib-jshint": "^0.10.0",
"grunt-contrib-qunit": "^0.5.2",
"grunt-contrib-uglify": "^0.6.0", "grunt-contrib-uglify": "^0.6.0",
"grunt-contrib-watch": "^0.6.1", "grunt-contrib-watch": "^0.6.1",
"grunt-execute": "^0.2.2", "grunt-execute": "^0.2.2",
"grunt-mocha-phantomjs": "^0.6.0",
"html2canvas-proxy": "0.0.5", "html2canvas-proxy": "0.0.5",
"humanize-duration": "^2.0.1", "humanize-duration": "^2.0.1",
"lodash": "^2.4.1", "lodash": "^2.4.1",

View File

@ -54,13 +54,22 @@ function renderWindow(node, container, options, windowWidth, windowHeight) {
var support = new Support(clonedWindow.document); var support = new Support(clonedWindow.document);
var imageLoader = new ImageLoader(options, support); var imageLoader = new ImageLoader(options, support);
var bounds = getBounds(node); var bounds = getBounds(node);
var width = options.width != null ? options.width : options.type === "view" ? Math.min(bounds.width, windowWidth) : documentWidth(clonedWindow.document); var width = options.type === "view" ? windowWidth : documentWidth(clonedWindow.document);
var height = options.height != null ? options.height : options.type === "view" ? Math.min(bounds.height, windowHeight) : documentHeight(clonedWindow.document); var height = options.type === "view" ? windowHeight : documentHeight(clonedWindow.document);
var renderer = new CanvasRenderer(width, height, imageLoader, options, document); var renderer = new CanvasRenderer(width, height, imageLoader, options, document);
var parser = new NodeParser(node, renderer, support, imageLoader, options); var parser = new NodeParser(node, renderer, support, imageLoader, options);
return parser.ready.then(function() { return parser.ready.then(function() {
log("Finished rendering"); log("Finished rendering");
var canvas = (options.type !== "view" && (node === clonedWindow.document.body || node === clonedWindow.document.documentElement || options.canvas != null)) ? renderer.canvas : crop(renderer.canvas, {width: width, height: height, top: bounds.top, left: bounds.left}); var canvas;
if (options.type === "view") {
canvas = crop(renderer.canvas, {width: renderer.canvas.width, height: renderer.canvas.height, top: 0, left: 0, x: 0, y: 0});
} else if (node === clonedWindow.document.body || node === clonedWindow.document.documentElement || options.canvas != null) {
canvas = renderer.canvas;
} else {
canvas = crop(renderer.canvas, {width: options.width != null ? options.width : bounds.width, height: options.height != null ? options.height : bounds.height, top: bounds.top, left: bounds.left, x: clonedWindow.pageXOffset, y: clonedWindow.pageYOffset});
}
cleanupContainer(container, options); cleanupContainer(container, options);
return canvas; return canvas;
}); });
@ -79,11 +88,11 @@ function crop(canvas, bounds) {
var x2 = Math.min(canvas.width, Math.max(1, bounds.left + bounds.width)); var x2 = Math.min(canvas.width, Math.max(1, bounds.left + bounds.width));
var y1 = Math.min(canvas.height - 1, Math.max(0, bounds.top)); var y1 = Math.min(canvas.height - 1, Math.max(0, bounds.top));
var y2 = Math.min(canvas.height, Math.max(1, bounds.top + bounds.height)); var y2 = Math.min(canvas.height, Math.max(1, bounds.top + bounds.height));
var width = croppedCanvas.width = x2 - x1; croppedCanvas.width = bounds.width;
var height = croppedCanvas.height = y2 - y1; croppedCanvas.height = bounds.height;
log("Cropping canvas at:", "left:", bounds.left, "top:", bounds.top, "width:", bounds.width, "height:", bounds.height); log("Cropping canvas at:", "left:", bounds.left, "top:", bounds.top, "width:", (x2-x1), "height:", (y2-y1));
log("Resulting crop with width", width, "and height", height, " with x", x1, "and y", y1); log("Resulting crop with width", bounds.width, "and height", bounds.height, " with x", x1, "and y", y1);
croppedCanvas.getContext("2d").drawImage(canvas, x1, y1, width, height, 0, 0, width, height); croppedCanvas.getContext("2d").drawImage(canvas, x1, y1, x2-x1, y2-y1, bounds.x, bounds.y, x2-x1, y2-y1);
return croppedCanvas; return croppedCanvas;
} }
@ -130,19 +139,27 @@ function createWindowClone(ownerDocument, containerDocument, width, height, opti
if (documentClone.body.childNodes.length > 0) { if (documentClone.body.childNodes.length > 0) {
cloneCanvasContents(ownerDocument, documentClone); cloneCanvasContents(ownerDocument, documentClone);
clearInterval(interval); clearInterval(interval);
if (options.type === "view") {
container.contentWindow.scrollTo(x, y);
}
resolve(container); resolve(container);
} }
}, 50); }, 50);
}; };
var x = ownerDocument.defaultView.pageXOffset;
var y = ownerDocument.defaultView.pageYOffset;
documentClone.open(); documentClone.open();
documentClone.write("<!DOCTYPE html>"); documentClone.write("<!DOCTYPE html>");
documentClone.close(); documentClone.close();
documentClone.replaceChild(options.javascriptEnabled === true ? documentClone.adoptNode(documentElement) : removeScriptNodes(documentClone.adoptNode(documentElement)), documentClone.documentElement); // Chrome scrolls the parent document for some reason after the write to the cloned window???
if (options.type === "view") { if (x !== ownerDocument.defaultView.pageXOffset || y !== ownerDocument.defaultView.pageYOffset) {
container.contentWindow.scrollTo(window.pageXOffset, window.pageYOffset); ownerDocument.defaultView.scrollTo(x, y);
} }
documentClone.replaceChild(options.javascriptEnabled === true ? documentClone.adoptNode(documentElement) : removeScriptNodes(documentClone.adoptNode(documentElement)), documentClone.documentElement);
}); });
} }

View File

@ -190,8 +190,8 @@ NodeContainer.prototype.parseTextShadows = function() {
var s = shadows[i].match(this.TEXT_SHADOW_VALUES); var s = shadows[i].match(this.TEXT_SHADOW_VALUES);
results.push({ results.push({
color: s[0], color: s[0],
offsetX: s[1] ? s[1].replace('px', '') : 0, offsetX: s[1] ? parseFloat(s[1].replace('px', '')) : 0,
offsetY: s[2] ? s[2].replace('px', '') : 0, offsetY: s[2] ? parseFloat(s[2].replace('px', '')) : 0,
blur: s[3] ? s[3].replace('px', '') : 0 blur: s[3] ? s[3].replace('px', '') : 0
}); });
} }

View File

@ -38,9 +38,11 @@ function NodeParser(element, renderer, support, imageLoader, options) {
resolve(); resolve();
} else if (typeof(options.async) === "function") { } else if (typeof(options.async) === "function") {
options.async.call(this, this.renderQueue, resolve); options.async.call(this, this.renderQueue, resolve);
} else { } else if (this.renderQueue.length > 0){
this.renderIndex = 0; this.renderIndex = 0;
this.asyncRenderer(this.renderQueue, resolve); this.asyncRenderer(this.renderQueue, resolve);
} else {
resolve();
} }
}, this)); }, this));
}, this)); }, this));

141
tests/mocha/cropping.html Normal file
View File

@ -0,0 +1,141 @@
<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="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();
}
</script>
</body>
</html>

216
tests/mocha/css.js Normal file
View File

@ -0,0 +1,216 @@
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(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();
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).to.match(/rgba?\(0, 0, 0(, 0)?\)/);
} else if (i % 2 === 0) {
expect(shadows[0].color).to.equal('rgb(2, 2, 2)');
} else {
var opacity = '0.2';
expect(shadows[0].color).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(parseBackgrounds(value)).to.eql(Array.isArray(expected) ? expected : [expected]);
});
}
});

View File

@ -1,11 +1,5 @@
$(function() { describe("Gradients", function() {
var propsToTest = {}, var expected = [
numDivs = {},
expected = {};
propsToTest['parseBackgrounds Gradient'] = ["backgroundImage"];
numDivs['parseBackgrounds Gradient'] = $('#backgroundGradients div').length;
expected['parseBackgrounds Gradient'] = [
{ {
method: "linear-gradient", method: "linear-gradient",
args: [ args: [
@ -103,18 +97,13 @@ $(function() {
} }
]; ];
test('parseBackgrounds Gradient', numDivs['parseBackgrounds Gradient'] * 2, function() { $('#backgroundGradients div').each(function(i, node) {
$('#backgroundGradients div').each(function(i, node) { var container = new NodeContainer(node, null);
var container = new NodeContainer(node, null); var value = container.css("backgroundImage");
var value = container.css("backgroundImage"); it(value, function() {
var parsedBackground = parseBackgrounds(value);
if (/^(-webkit|-o|-moz|-ms|linear)-/.test(value)) { expect(parsedBackground[0].args).to.eql(expected[i].args);
var parsedBackground = parseBackgrounds(value); expect(parsedBackground[0].method).to.eql(expected[i].method);
QUnit.deepEqual(parsedBackground[0].args, expected['parseBackgrounds Gradient'][i].args, 'Parsed gradient with CSS: ' + value);
QUnit.deepEqual(parsedBackground[0].method, expected['parseBackgrounds Gradient'][i].method, 'Parsed gradient with CSS: ' + value);
} else {
QUnit.ok(true, 'No CSS Background Gradient support');
}
}); });
}); });
}); });

23
tests/mocha/iframe1.htm Normal file
View File

@ -0,0 +1,23 @@
<!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>

23
tests/mocha/iframe2.htm Normal file
View File

@ -0,0 +1,23 @@
<!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>

195
tests/mocha/index.html Normal file
View File

@ -0,0 +1,195 @@
<html>
<head>
<meta charset="utf-8">
<title>Mocha Tests</title>
<link rel="stylesheet" href="lib/mocha.css" />
<script type="text/javascript" src="../../src/log.js"></script>
<script type="text/javascript" src="../../src/nodecontainer.js"></script>
<script type="text/javascript" src="../../src/stackingcontext.js"></script>
<script type="text/javascript" src="../../src/textcontainer.js"></script>
<script type="text/javascript" src="../../src/support.js"></script>
<script type="text/javascript" src="../../src/imagecontainer.js"></script>
<script type="text/javascript" src="../../src/gradientcontainer.js"></script>
<script type="text/javascript" src="../../src/lineargradientcontainer.js"></script>
<script type="text/javascript" src="../../src/webkitgradientcontainer.js"></script>
<script type="text/javascript" src="../../src/imageloader.js"></script>
<script type="text/javascript" src="../../src/nodeparser.js"></script>
<script type="text/javascript" src="../../src/font.js"></script>
<script type="text/javascript" src="../../src/fontmetrics.js"></script>
<script type="text/javascript" src="../../src/renderer.js"></script>
<script type="text/javascript" src="../../src/promise.js"></script>
<script type="text/javascript" src="../../src/renderers/canvas.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>
<style>
.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);
}
.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%);
}
.linearGradient3 {
/* 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%);
}
.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 id="backgroundGradients">
<div class="linearGradientSimple"></div>
<div class="linearGradientWithStops"></div>
<div class="linearGradient3"></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();
}
</script>
</body>
</html>

1284
tests/mocha/lib/expect.js Normal file

File diff suppressed because it is too large Load Diff

270
tests/mocha/lib/mocha.css Normal file
View File

@ -0,0 +1,270 @@
@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;
}
}

6095
tests/mocha/lib/mocha.js Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,230 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>QUnit Test Suite</title>
<link rel="stylesheet" href="lib/qunit.css">
<script src="lib/qunit.js"></script>
<!-- src files -->
<script type="text/javascript" src="../assets/jquery-1.6.2.js"></script>
<script type="text/javascript" src="../../src/log.js"></script>
<script type="text/javascript" src="../../src/nodecontainer.js"></script>
<script type="text/javascript" src="../../src/stackingcontext.js"></script>
<script type="text/javascript" src="../../src/textcontainer.js"></script>
<script type="text/javascript" src="../../src/support.js"></script>
<script type="text/javascript" src="../../src/imagecontainer.js"></script>
<script type="text/javascript" src="../../src/gradientcontainer.js"></script>
<script type="text/javascript" src="../../src/lineargradientcontainer.js"></script>
<script type="text/javascript" src="../../src/webkitgradientcontainer.js"></script>
<script type="text/javascript" src="../../src/imageloader.js"></script>
<script type="text/javascript" src="../../src/nodeparser.js"></script>
<script type="text/javascript" src="../../src/font.js"></script>
<script type="text/javascript" src="../../src/fontmetrics.js"></script>
<script type="text/javascript" src="../../src/renderer.js"></script>
<script type="text/javascript" src="../../src/promise.js"></script>
<script type="text/javascript" src="../../src/renderers/canvas.js"></script>
<script src="unit/css.js"></script>
<script src="unit/generate.js"></script>
<!-- <script src="unit/utils.js"></script> -->
<style>
#borders div {
border-color: #000;
border-style: solid;
}
#backgroundPosition div {
width:50px;
height:50px;
}
#paddingPercentage div {
width:50px;
height:50px;
}
</style>
</head>
<body>
<div id="qunit"></div>
<div id="qunit-fixture" style="visibility:none; height:1px; overflow:scroll;">
All the tests here. <b>Testing different <span>stuff</span> for contents()</b>
<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>
<style>
.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);
}
.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%);
}
.linearGradient3 {
/* 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%);
}
.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 id="backgroundGradients">
<div class="linearGradientSimple"></div>
<div class="linearGradientWithStops"></div>
<div class="linearGradient3"></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>
<!--
<div id="fixture-iframes"></div>
<script>
var pages = ["background","borders","external-content","forms","images","lists","origin","overflow","proxy","text-linethrough"],
fixtures = $("#fixture-iframes");
$.each(pages, function(i, page){
var iframe = $('<iframe />').attr('src',"../" + page + ".html");
iframe.insertAfter( fixtures );
});
</script>
<iframe src="../borders.html" id="borders"></iframe> -->
</body>
</html>

View File

@ -1,232 +0,0 @@
/**
* QUnit v1.4.0pre - A JavaScript Unit Testing Framework
*
* http://docs.jquery.com/QUnit
*
* Copyright (c) 2012 John Resig, Jörn Zaefferer
* Dual licensed under the MIT (MIT-LICENSE.txt)
* or GPL (GPL-LICENSE.txt) licenses.
*/
/** Font Family and Sizes */
#qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult {
font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif;
}
#qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; }
#qunit-tests { font-size: smaller; }
/** Resets */
#qunit-tests, #qunit-tests ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult {
margin: 0;
padding: 0;
}
/** Header */
#qunit-header {
padding: 0.5em 0 0.5em 1em;
color: #8699a4;
background-color: #0d3349;
font-size: 1.5em;
line-height: 1em;
font-weight: normal;
border-radius: 15px 15px 0 0;
-moz-border-radius: 15px 15px 0 0;
-webkit-border-top-right-radius: 15px;
-webkit-border-top-left-radius: 15px;
}
#qunit-header a {
text-decoration: none;
color: #c2ccd1;
}
#qunit-header a:hover,
#qunit-header a:focus {
color: #fff;
}
#qunit-header label {
display: inline-block;
}
#qunit-banner {
height: 5px;
}
#qunit-testrunner-toolbar {
padding: 0.5em 0 0.5em 2em;
color: #5E740B;
background-color: #eee;
}
#qunit-userAgent {
padding: 0.5em 0 0.5em 2.5em;
background-color: #2b81af;
color: #fff;
text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
}
/** Tests: Pass/Fail */
#qunit-tests {
list-style-position: inside;
}
#qunit-tests li {
padding: 0.4em 0.5em 0.4em 2.5em;
border-bottom: 1px solid #fff;
list-style-position: inside;
}
#qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running {
display: none;
}
#qunit-tests li strong {
cursor: pointer;
}
#qunit-tests li a {
padding: 0.5em;
color: #c2ccd1;
text-decoration: none;
}
#qunit-tests li a:hover,
#qunit-tests li a:focus {
color: #000;
}
#qunit-tests ol {
margin-top: 0.5em;
padding: 0.5em;
background-color: #fff;
border-radius: 15px;
-moz-border-radius: 15px;
-webkit-border-radius: 15px;
box-shadow: inset 0px 2px 13px #999;
-moz-box-shadow: inset 0px 2px 13px #999;
-webkit-box-shadow: inset 0px 2px 13px #999;
}
#qunit-tests table {
border-collapse: collapse;
margin-top: .2em;
}
#qunit-tests th {
text-align: right;
vertical-align: top;
padding: 0 .5em 0 0;
}
#qunit-tests td {
vertical-align: top;
}
#qunit-tests pre {
margin: 0;
white-space: pre-wrap;
word-wrap: break-word;
}
#qunit-tests del {
background-color: #e0f2be;
color: #374e0c;
text-decoration: none;
}
#qunit-tests ins {
background-color: #ffcaca;
color: #500;
text-decoration: none;
}
/*** Test Counts */
#qunit-tests b.counts { color: black; }
#qunit-tests b.passed { color: #5E740B; }
#qunit-tests b.failed { color: #710909; }
#qunit-tests li li {
margin: 0.5em;
padding: 0.4em 0.5em 0.4em 0.5em;
background-color: #fff;
border-bottom: none;
list-style-position: inside;
}
/*** Passing Styles */
#qunit-tests li li.pass {
color: #5E740B;
background-color: #fff;
border-left: 26px solid #C6E746;
}
#qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; }
#qunit-tests .pass .test-name { color: #366097; }
#qunit-tests .pass .test-actual,
#qunit-tests .pass .test-expected { color: #999999; }
#qunit-banner.qunit-pass { background-color: #C6E746; }
/*** Failing Styles */
#qunit-tests li li.fail {
color: #710909;
background-color: #fff;
border-left: 26px solid #EE5757;
white-space: pre;
}
#qunit-tests > li:last-child {
border-radius: 0 0 15px 15px;
-moz-border-radius: 0 0 15px 15px;
-webkit-border-bottom-right-radius: 15px;
-webkit-border-bottom-left-radius: 15px;
}
#qunit-tests .fail { color: #000000; background-color: #EE5757; }
#qunit-tests .fail .test-name,
#qunit-tests .fail .module-name { color: #000000; }
#qunit-tests .fail .test-actual { color: #EE5757; }
#qunit-tests .fail .test-expected { color: green; }
#qunit-banner.qunit-fail { background-color: #EE5757; }
/** Result */
#qunit-testresult {
padding: 0.5em 0.5em 0.5em 2.5em;
color: #2b81af;
background-color: #D2E0E6;
border-bottom: 1px solid white;
}
/** Fixture */
#qunit-fixture {
position: absolute;
top: -10000px;
left: -10000px;
width: 1000px;
height: 1000px;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,227 +0,0 @@
module("CSS");
$(function() {
var propsToTest = {},
numDivs = {};
propsToTest['border-width'] = ["borderTopWidth", "borderRightWidth", "borderBottomWidth", "borderLeftWidth"],
numDivs['border-width'] = $('#borders div').length;
test('border-width', propsToTest['border-width'].length * numDivs['border-width'], function() {
$('#borders div').each(function(i, node) {
$.each(propsToTest['border-width'], function(s, prop) {
var expect = $(node).css(prop);
// older IE's don't necessarily return px even with jQuery
if (expect === "thin") {
expect = "1px";
} else if (expect === "medium") {
expect = "3px";
} else if (expect === "thick") {
expect = "5px";
}
var container = new NodeContainer(node, null);
QUnit.equal(container.css(prop), expect, "div #" + (i + 1) + " property " + prop + " equals " + expect );
});
});
});
propsToTest['padding width'] = ["paddingTop", "paddingRight", "paddingBottom", "paddingLeft"];
numDivs['padding width'] = $('#padding div').length;
test('padding width', propsToTest['padding width'].length * numDivs['padding width'] * 2, function() {
$('#padding div').each(function(i, node) {
$.each(propsToTest['padding width'], function(s, prop) {
var container = new NodeContainer(node, null);
var isPx = container.css(prop).indexOf("px");
QUnit.notEqual(isPx, -1, "div #" + (i + 1) + " property " + prop + " is in pixels");
QUnit.equal(container.css(prop), $(node).css(prop), "div #" + (i + 1) + " property " + prop + " equals " + $(node).css(prop));
});
});
});
propsToTest['background-position'] = ["backgroundPosition"];
numDivs['background-position'] = $('#backgroundPosition div').length;
test('background-position', propsToTest['background-position'].length * numDivs['background-position'] * 2, function() {
$('#backgroundPosition div').each(function(i, node) {
$.each(propsToTest['background-position'], function(s, prop) {
var img = new Image();
img.width = 50;
img.height = 50;
var container = new NodeContainer(node, null);
var item = container.css(prop),
backgroundPosition = container.parseBackgroundPosition(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);
QUnit.equal(backgroundPosition.left, Math.round(parseFloat(testEl.css('left'))), "div #" + (i + 1) + " background-position-x equals " + backgroundPosition.left + " from " + item);
QUnit.equal(backgroundPosition.top, Math.round(parseFloat(testEl.css('top'))), "div #" + (i + 1) + " background-position-y equals " + backgroundPosition.top);
testEl.remove();
});
});
});
test('text-shadow', function() {
$('#textShadows div').each(function(i, node) {
var index = i + 1;
var container = new NodeContainer(node, null);
var shadows = container.parseTextShadows();
if (i === 0) {
QUnit.equal(shadows.length, 0, 'div #' + index);
} else {
QUnit.equal(shadows.length, (i >= 6 ? 2 : 1), 'div #' + index);
QUnit.equal(shadows[0].offsetX, i, 'div #' + index + ' offsetX');
QUnit.equal(shadows[0].offsetY, i, 'div #' + index + ' offsetY');
if (i < 2) {
QUnit.equal(shadows[0].color, 'rgba(0, 0, 0, 0)', 'div #' + index + ' color');
} else if (i % 2 === 0) {
QUnit.equal(shadows[0].color, 'rgb(2, 2, 2)', 'div #' + index + ' color');
} else {
var opacity = '0.199219';
QUnit.equal(shadows[0].color, 'rgba(2, 2, 2, '+opacity+')', 'div #' + index + ' color');
}
// only testing blur once
if (i === 1) {
QUnit.equal(shadows[0].blur, '1', 'div #' + index + ' blur');
}
}
});
});
test('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) {
deepEqual(
parseBackgrounds(value),
Array.isArray(expected) ? expected : [expected],
name
);
}
// TODO add backgroundPosition % tests
});

View File

@ -1,46 +0,0 @@
$(function() {
var el = $('#qunit-fixture');
test('Children()', 1, function() {
var arr = [],
cont = el.contents();
$.each(cont, function(i,e){
arr.push(e);
});
// text nodes differ
QUnit.equal( _html2canvas.Util.Children(el[0]), arr, "Util.Children === jQuery.children()" );
});
test('resizeBounds', function(){
QUnit.deepEqual(
_html2canvas.Util.resizeBounds(100, 100, 100, 100),
{ width: 100, height: 100 },
'no resize'
);
QUnit.deepEqual(
_html2canvas.Util.resizeBounds(100, 100, 2, 100),
{ width: 20, height: 100 },
'stretch'
);
QUnit.deepEqual(
_html2canvas.Util.resizeBounds(100, 100, 2, 100, 'contain'),
{ width: 2, height: 2 },
'contain'
);
QUnit.deepEqual(
_html2canvas.Util.resizeBounds(100, 100, 2, 100, 'cover'),
{ width: 100, height: 100 },
'contain'
);
});
});