Update v1.0.6

This commit is contained in:
Bhanu Slathia
2016-02-16 23:22:09 +05:30
parent 62d04a0372
commit c710c20b9e
7620 changed files with 244752 additions and 1070312 deletions

View File

@@ -0,0 +1,68 @@
{
/* Enforcing options */
"bitwise": true,
"camelcase": true,
"curly": true,
"eqeqeq": true,
"es3": true,
"es5": false,
"forin": true,
"freeze": true,
"immed": true,
"indent": 2,
"latedef": true,
"newcap": true,
"noarg": true,
"noempty": true,
"nonbsp": true,
"nonew": true,
"plusplus": false,
"quotmark": "double",
"undef": true,
"unused": true,
"strict": true,
"trailing": true,
"maxparams": 2,
"maxdepth": 3,
"maxstatements": false,
"maxlen": false, /* IDEAL: 120? */
/* Relaxing options */
"asi": false,
"boss": false,
"debug": false,
"eqnull": true,
"esnext": false,
"evil": false,
"expr": false,
"funcscope": false,
"gcl": false,
"globalstrict": false,
"iterator": false,
"lastsemic": false,
"laxbreak": false,
"laxcomma": false,
"loopfunc": false,
"maxerr": 50,
"moz": false,
"multistr": false,
"notypeof": false,
"proto": false,
"scripturl": false,
"smarttabs": false,
"shadow": false,
"sub": false,
"supernew": false,
"validthis": false,
"noyield": false,
/* Environments */
"browser": true,
/* Global variables */
"globals": {
"$": false,
"QUnit": false
}
}

View File

@@ -0,0 +1,67 @@
/*global ZeroClipboard */
(function(module, test) {
"use strict";
// Helper functions
var TestUtils = {
getHtmlBridge: function() {
return document.getElementById(ZeroClipboard.config("containerId"));
}
};
var originalConfig, originalFlashDetect;
module("ZeroClipboard.Core.js (built) unit tests", {
setup: function() {
// Store
originalConfig = ZeroClipboard.config();
originalFlashDetect = ZeroClipboard.isFlashUnusable;
// Modify
ZeroClipboard.isFlashUnusable = function() {
return false;
};
},
teardown: function() {
// Restore
ZeroClipboard.destroy();
ZeroClipboard.config(originalConfig);
ZeroClipboard.isFlashUnusable = originalFlashDetect;
}
});
test("`swfPath` finds the expected default URL", function(assert) {
assert.expect(1);
// Assert, act, assert
var rootOrigin = window.location.protocol + "//" + window.location.host + "/";
var indexOfTest = window.location.pathname.toLowerCase().indexOf("/test/");
var rootDir = window.location.pathname.slice(1, indexOfTest + 1);
var rootPath = rootOrigin + rootDir;
//var zcJsUrl = rootPath + "dist/ZeroClipboard.Core.js";
var swfPathBasedOnZeroClipboardJsPath = rootPath + "dist/ZeroClipboard.swf";
// Test that the client has the expected default URL [even if it's not correct]
assert.strictEqual(ZeroClipboard.config("swfPath"), swfPathBasedOnZeroClipboardJsPath);
});
test("`destroy` destroys the bridge", function(assert) {
assert.expect(3);
// Arrange
ZeroClipboard.isFlashUnusable = function() {
return false;
};
// Assert, arrange, assert, act, assert
assert.equal(TestUtils.getHtmlBridge(), null, "The bridge does not exist before creating a client");
ZeroClipboard.create();
assert.notEqual(TestUtils.getHtmlBridge(), null, "The bridge does exist after creating a client");
ZeroClipboard.destroy();
assert.equal(TestUtils.getHtmlBridge(), null, "The bridge does not exist after calling `destroy`");
});
})(QUnit.module, QUnit.test);

View File

@@ -0,0 +1,43 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>ZeroClipboard.Core.js unit tests</title>
<link rel="stylesheet" href="../../node_modules/qunitjs/qunit/qunit.css">
<script src="../../node_modules/qunitjs/qunit/qunit.js"></script>
<script>
// Polyfill in future functionality: https://github.com/jquery/qunit/issues/490
if (!QUnit.assert.expect) {
QUnit.assert.expect = QUnit.expect;
}
// Require `expect` calls
QUnit.config.requireExpects = true;
// Prevent against Firefox/Firebug failing the global pollution check
var getInterface = null;
// Prevent against failing the global pollution check in all browsers other than IE
if (typeof window.ActiveXObject === "undefined") {
window.ActiveXObject = null;
}
// Prevent against Flash's ExternalInterface failing the global pollution check (seems to be only in IE < 11)
var __flash__arrayToXML = null,
__flash__argumentsToXML = null,
__flash__objectToXML = null,
__flash__escapeXML = null,
__flash__toXML = null,
__flash__addCallback = null,
__flash__removeCallback = null,
__flash__request = null;
</script>
<script src="../../dist/ZeroClipboard.Core.js"></script>
<script src="../../node_modules/jquery/dist/jquery.js"></script>
<script src="ZeroClipboard.Core.tests.js"></script>
</head>
<body>
<div id="qunit"></div>
<div id="qunit-fixture"></div>
</body>
</html>

View File

@@ -0,0 +1,228 @@
/*global ZeroClipboard */
(function(module, test) {
"use strict";
var originalConfig, originalFlashDetect;
// Helper functions
var TestUtils = {
getHtmlBridge: function() {
return document.getElementById(ZeroClipboard.config("containerId"));
}
};
module("ZeroClipboard.js (built) unit tests - Core", {
setup: function() {
// Store
originalConfig = ZeroClipboard.config();
originalFlashDetect = ZeroClipboard.isFlashUnusable;
// Modify
ZeroClipboard.isFlashUnusable = function() {
return false;
};
ZeroClipboard.config({ swfPath: originalConfig.swfPath.replace(/\/(?:src|test)\/.*$/i, "/dist/ZeroClipboard.swf") });
},
teardown: function() {
// Restore
ZeroClipboard.destroy();
ZeroClipboard.config(originalConfig);
ZeroClipboard.isFlashUnusable = originalFlashDetect;
}
});
test("`swfPath` finds the expected default URL", function(assert) {
assert.expect(1);
// Assert, act, assert
var rootOrigin = window.location.protocol + "//" + window.location.host + "/";
var indexOfTest = window.location.pathname.toLowerCase().indexOf("/test/");
var rootDir = window.location.pathname.slice(1, indexOfTest + 1);
var rootPath = rootOrigin + rootDir;
//var zcJsUrl = rootPath + "dist/ZeroClipboard.js";
var swfPathBasedOnZeroClipboardJsPath = rootPath + "dist/ZeroClipboard.swf";
// Test that the client has the expected default URL [even if it's not correct]
assert.strictEqual(ZeroClipboard.config("swfPath"), swfPathBasedOnZeroClipboardJsPath);
});
test("`destroy` destroys the bridge", function(assert) {
assert.expect(3);
// Arrange
ZeroClipboard.isFlashUnusable = function() {
return false;
};
// Assert, arrange, assert, act, assert
assert.equal(TestUtils.getHtmlBridge(), null, "The bridge does not exist before creating a client");
/*jshint nonew:false */
new ZeroClipboard();
assert.notEqual(TestUtils.getHtmlBridge(), null, "The bridge does exist after creating a client");
ZeroClipboard.destroy();
assert.equal(TestUtils.getHtmlBridge(), null, "The bridge does not exist after calling `destroy`");
});
module("ZeroClipboard.js (built) unit tests - Client", {
setup: function() {
// Store
originalConfig = ZeroClipboard.config();
originalFlashDetect = ZeroClipboard.isFlashUnusable;
// Modify
ZeroClipboard.isFlashUnusable = function() {
return false;
};
ZeroClipboard.config({ swfPath: originalConfig.swfPath.replace(/\/(?:src|test)\/.*$/i, "/dist/ZeroClipboard.swf") });
},
teardown: function() {
// Restore
ZeroClipboard.destroy();
ZeroClipboard.config(originalConfig);
ZeroClipboard.isFlashUnusable = originalFlashDetect;
}
});
test("`ZeroClipboard` exists", function(assert) {
assert.expect(1);
// Arrange -> N/A
// Act -> N/A
// Assert
assert.ok(ZeroClipboard);
});
test("Client is created properly", function(assert) {
assert.expect(2);
// Arrange & Act
var client = new ZeroClipboard();
// Assert
assert.ok(client);
assert.ok(client.id);
});
test("Client without selector doesn't have elements", function(assert) {
assert.expect(2);
// Arrange & Act
var client = new ZeroClipboard();
// Assert
assert.ok(client);
assert.deepEqual(client.elements(), []);
});
test("Object has a title", function(assert) {
assert.expect(1);
// Arrange
var client = new ZeroClipboard();
var currentEl = document.getElementById("d_clip_button");
// Act
client.clip(currentEl);
ZeroClipboard.activate(currentEl);
// Assert
assert.strictEqual(TestUtils.getHtmlBridge().getAttribute("title"), "Click me to copy to clipboard.");
// Revert
ZeroClipboard.deactivate();
});
test("Object has no title", function(assert) {
assert.expect(1);
// Arrange
var client = new ZeroClipboard();
var currentEl = document.getElementById("d_clip_button_no_title");
// Act
client.clip(currentEl);
ZeroClipboard.activate(currentEl);
// Assert
assert.ok(!TestUtils.getHtmlBridge().getAttribute("title"));
});
test("Object doesn't have data-clipboard-text", function(assert) {
assert.expect(1);
// Arrange
var client = new ZeroClipboard();
var currentEl = document.getElementById("d_clip_button_no_text");
// Act
client.clip(currentEl);
ZeroClipboard.activate(currentEl);
// Assert
assert.ok(!TestUtils.getHtmlBridge().getAttribute("data-clipboard-text"));
});
test("New client is not the same client (no singleton) but does share the same bridge", function(assert) {
assert.expect(6);
// Assert, arrange, assert, act, assert
var containerClass = "." + ZeroClipboard.config("containerClass");
assert.strictEqual($(containerClass).length, 0);
var client1 = new ZeroClipboard();
assert.ok(client1.id);
assert.strictEqual($(containerClass).length, 1);
var client2 = new ZeroClipboard();
assert.strictEqual($(containerClass).length, 1);
assert.notEqual(client2.id, client1.id);
assert.notEqual(client2, client1);
});
test("Calculations based on borderWidth never return NaN", function(assert) {
assert.expect(4);
// Arrange
var client = new ZeroClipboard();
var currentEl = document.getElementById("d_clip_button");
// Act
client.clip(currentEl);
ZeroClipboard.activate(currentEl);
// Assert
var htmlBridge = TestUtils.getHtmlBridge();
assert.strictEqual(/^-?[0-9\.]+px$/.test(htmlBridge.style.top), true);
assert.strictEqual(/^-?[0-9\.]+px$/.test(htmlBridge.style.left), true);
assert.strictEqual(/^-?[0-9\.]+px$/.test(htmlBridge.style.width), true);
assert.strictEqual(/^-?[0-9\.]+px$/.test(htmlBridge.style.height), true);
});
test("No more client singleton!", function(assert) {
assert.expect(7);
// Arrange
ZeroClipboard.isFlashUnusable = function() {
return false;
};
// Assert, arrange, assert, act, assert
assert.ok(!ZeroClipboard.prototype._singleton, "The client singleton does not exist on the prototype before creating a client");
var client1 = new ZeroClipboard();
assert.ok(!ZeroClipboard.prototype._singleton, "The client singleton does not exist on the prototype after creating a client");
assert.ok(!client1._singleton, "The client singleton does not exist on the client instance after creating a client");
var client2 = new ZeroClipboard();
assert.ok(!ZeroClipboard.prototype._singleton, "The client singleton does not exist on the prototype after creating a second client");
assert.ok(!client1._singleton, "The client singleton does not exist on the first client instance after creating a second client");
assert.ok(!client2._singleton, "The client singleton does not exist on the second client instance after creating a second client");
ZeroClipboard.destroy();
assert.ok(!ZeroClipboard.prototype._singleton, "The client singleton does not exist on the prototype after calling `destroy`");
});
})(QUnit.module, QUnit.test);

View File

@@ -0,0 +1,73 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>ZeroClipboard.js unit tests</title>
<link rel="stylesheet" href="../../node_modules/qunitjs/qunit/qunit.css">
<script src="../../node_modules/qunitjs/qunit/qunit.js"></script>
<script>
// Polyfill in future functionality: https://github.com/jquery/qunit/issues/490
if (!QUnit.assert.expect) {
QUnit.assert.expect = QUnit.expect;
}
// Require `expect` calls
QUnit.config.requireExpects = true;
// Prevent against Firefox/Firebug failing the global pollution check
var getInterface = null;
// Prevent against failing the global pollution check in all browsers other than IE
if (typeof window.ActiveXObject === "undefined") {
window.ActiveXObject = null;
}
// Prevent against Flash's ExternalInterface failing the global pollution check (seems to be only in IE < 11)
var __flash__arrayToXML = null,
__flash__argumentsToXML = null,
__flash__objectToXML = null,
__flash__escapeXML = null,
__flash__toXML = null,
__flash__addCallback = null,
__flash__removeCallback = null,
__flash__request = null;
</script>
<script src="../../dist/ZeroClipboard.js"></script>
<script src="../../node_modules/jquery/dist/jquery.js"></script>
<script src="ZeroClipboard.tests.js"></script>
</head>
<body>
<div id="qunit"></div>
<div id="qunit-fixture">
<p>
<button id="d_clip_button" class="my_clip_button" title="Click me to copy to clipboard." data-clipboard-text="Copy me!"><b>Copy To Clipboard...</b></button>
</p>
<p>
<button id="d_clip_button_no_title" class="my_clip_button" data-clipboard-text="Copy me!"><b>Copy To Clipboard...</b></button>
</p>
<p>
<button id="d_clip_button_no_text" class="my_clip_button"><b>Copy To Clipboard...</b></button>
</p>
<p>
<button id="d_clip_button_input_text" class="my_clip_button" data-clipboard-target="clipboard_text"><b>Copy To Clipboard...</b></button>
</p>
<p>
<button id="d_clip_button_textarea_text" class="my_clip_button" data-clipboard-target="clipboard_textarea"><b>Copy To Clipboard...</b></button>
</p>
<button id="d_clip_button_pre_text" class="my_clip_button" data-clipboard-target="clipboard_pre"><b>Copy To Clipboard...</b></button>
<input type="text" id="clipboard_text" value="Clipboard Text"/>
<textarea id="clipboard_textarea">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</textarea>
<pre id="clipboard_pre">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</pre>
</div>
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,83 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>ZeroClipboard unit tests: client/api.js</title>
<link rel="stylesheet" href="../../node_modules/qunitjs/qunit/qunit.css">
<script src="../../node_modules/qunitjs/qunit/qunit.js"></script>
<script>
// Polyfill in future functionality: https://github.com/jquery/qunit/issues/490
if (!QUnit.assert.expect) {
QUnit.assert.expect = QUnit.expect;
}
// Require `expect` calls
QUnit.config.requireExpects = true;
// Prevent against Firefox/Firebug failing the global pollution check
var getInterface = null;
// Prevent against failing the global pollution check in all browsers other than IE
if (typeof window.ActiveXObject === "undefined") {
window.ActiveXObject = null;
}
// Prevent against Flash's ExternalInterface failing the global pollution check (seems to be only in IE < 11)
var __flash__arrayToXML = null,
__flash__argumentsToXML = null,
__flash__objectToXML = null,
__flash__escapeXML = null,
__flash__toXML = null,
__flash__addCallback = null,
__flash__removeCallback = null,
__flash__request = null;
</script>
<script src="../../src/js/shared/state.js"></script>
<script src="../../src/js/shared/private.js"></script>
<script src="../../src/js/core/state.js"></script>
<script src="../../src/js/core/private.js"></script>
<script src="../../src/js/core/api.js"></script>
<script src="../../src/js/client/state.js"></script>
<script src="../../src/js/client/private.js"></script>
<script src="../../src/js/client/api.js"></script>
<script src="../../node_modules/jquery/dist/jquery.js"></script>
<script src="api.tests.js"></script>
</head>
<body>
<div id="qunit"></div>
<div id="qunit-fixture">
<p>
<button id="d_clip_button" class="my_clip_button" title="Click me to copy to clipboard." data-clipboard-text="Copy me!"><b>Copy To Clipboard...</b></button>
</p>
<p>
<button id="d_clip_button2" class="my_clip_button" title="Click me to copy to clipboard.2" data-clipboard-text="Copy me!"><b>Copy To Clipboard...</b></button>
</p>
<p>
<button id="d_clip_button3" class="my_clip_button" title="Click me to copy to clipboard.3" data-clipboard-text="Copy me!"><b>Copy To Clipboard...</b></button>
</p>
<p>
<button id="d_clip_button_no_text" class="my_clip_button"><b>Copy To Clipboard...</b></button>
</p>
<p>
<button id="d_clip_button_input_text" class="my_clip_button" data-clipboard-target="clipboard_text"><b>Copy To Clipboard...</b></button>
</p>
<p>
<button id="d_clip_button_textarea_text" class="my_clip_button" data-clipboard-target="clipboard_textarea"><b>Copy To Clipboard...</b></button>
</p>
<button id="d_clip_button_pre_text" class="my_clip_button" data-clipboard-target="clipboard_pre"><b>Copy To Clipboard...</b></button>
<input type="text" id="clipboard_text" value="Clipboard Text"/>
<textarea id="clipboard_textarea">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</textarea>
<pre id="clipboard_pre">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</pre>
</div>
</body>
</html>

View File

@@ -0,0 +1,40 @@
/*global ZeroClipboard, _clientConstructor, _clientClip, _clientShouldEmit */
(function(module, test) {
"use strict";
module("client/private.js unit tests");
test("`_clientShouldEmit` works", function(assert) {
assert.expect(9);
// Arrange
var currentEl = document.getElementById("d_clip_button");
var client = new ZeroClipboard();
_clientConstructor.call(client);
// Act
var actual1 = _clientShouldEmit.call(client, null);
var actual2 = _clientShouldEmit.call(client, {});
var actual3 = _clientShouldEmit.call(client, { type: "beforecopy", client: {} });
var actual4 = _clientShouldEmit.call(client, { type: "beforecopy", target: {} });
_clientClip.call(client, currentEl);
var actual5 = _clientShouldEmit.call(client, { type: "beforecopy", target: {}, relatedTarget: {} });
var actual6 = _clientShouldEmit.call(client, { type: "beforecopy", client: client });
var actual7 = _clientShouldEmit.call(client, { type: "beforecopy", target: null });
var actual8 = _clientShouldEmit.call(client, { type: "beforecopy", target: currentEl });
var actual9 = _clientShouldEmit.call(client, { type: "beforecopy", relatedTarget: currentEl });
// Assert
assert.strictEqual(actual1, false, "Non-event returns `false`");
assert.strictEqual(actual2, false, "Event without `type` returns `false`");
assert.strictEqual(actual3, false, "Event with non-matching `client` returns `false`");
assert.strictEqual(actual4, false, "Event with non-clipped `target` returns `false`");
assert.strictEqual(actual5, false, "Event with non-clipped `relatedTarget` returns `false`");
assert.strictEqual(actual6, true, "Event with matching `client` returns `true`");
assert.strictEqual(actual7, true, "Event with `target` of `null` returns `true`");
assert.strictEqual(actual8, true, "Event with clipped `target` returns `true`");
assert.strictEqual(actual9, true, "Event with clipped `relatedTarget` returns `true`");
});
})(QUnit.module, QUnit.test);

View File

@@ -0,0 +1,53 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>ZeroClipboard unit tests: client/private.js</title>
<link rel="stylesheet" href="../../node_modules/qunitjs/qunit/qunit.css">
<script src="../../node_modules/qunitjs/qunit/qunit.js"></script>
<script>
// Polyfill in future functionality: https://github.com/jquery/qunit/issues/490
if (!QUnit.assert.expect) {
QUnit.assert.expect = QUnit.expect;
}
// Require `expect` calls
QUnit.config.requireExpects = true;
// Prevent against Firefox/Firebug failing the global pollution check
var getInterface = null;
// Prevent against failing the global pollution check in all browsers other than IE
if (typeof window.ActiveXObject === "undefined") {
window.ActiveXObject = null;
}
// Prevent against Flash's ExternalInterface failing the global pollution check (seems to be only in IE < 11)
var __flash__arrayToXML = null,
__flash__argumentsToXML = null,
__flash__objectToXML = null,
__flash__escapeXML = null,
__flash__toXML = null,
__flash__addCallback = null,
__flash__removeCallback = null,
__flash__request = null;
</script>
<script src="../../src/js/shared/state.js"></script>
<script src="../../src/js/shared/private.js"></script>
<script src="../../src/js/core/state.js"></script>
<script src="../../src/js/core/private.js"></script>
<script src="../../src/js/core/api.js"></script>
<script src="../../src/js/client/state.js"></script>
<script src="../../src/js/client/private.js"></script>
<script src="../../node_modules/jquery/dist/jquery.js"></script>
<script src="private.tests.js"></script>
</head>
<body>
<div id="qunit"></div>
<div id="qunit-fixture">
<p>
<button id="d_clip_button" class="my_clip_button" title="Click me to copy to clipboard." data-clipboard-text="Copy me!"><b>Copy To Clipboard...</b></button>
</p>
</div>
</body>
</html>

View File

@@ -0,0 +1,441 @@
/*global ZeroClipboard, _globalConfig:true, _flashState, _clipData, _clipDataFormatMap, _deleteOwnProperties */
(function(module, test) {
"use strict";
// Helper functions
var TestUtils = {
getHtmlBridge: function() {
return document.getElementById("global-zeroclipboard-html-bridge");
}
};
var originalConfig, originalFlashDetect;
module("core/api.js unit tests - state");
test("`state` produces expected result", function(assert) {
assert.expect(8);
// Act
var result = ZeroClipboard.state();
// Assert
assert.deepEqual(Object.keys(result), ["browser", "flash", "zeroclipboard"], "Has all expected keys");
assert.strictEqual(typeof result.browser, "object", ".browser is an object");
assert.notStrictEqual(result.browser, null, ".browser is a non-null object");
assert.strictEqual(typeof result.flash, "object", ".flash is an object");
assert.notStrictEqual(result.flash, null, ".flash is a non-null object");
assert.strictEqual(typeof result.zeroclipboard, "object", ".zeroclipboard is an object");
assert.notStrictEqual(result.zeroclipboard, null, ".zeroclipboard is a non-null object");
assert.deepEqual(Object.keys(result.zeroclipboard), ["version", "config"], ".zeroclipboard has all expected keys");
});
module("core/api.js unit tests - config", {
setup: function() {
originalConfig = ZeroClipboard.config();
},
teardown: function() {
_globalConfig = originalConfig;
}
});
test("`swfPath` finds the expected default URL", function(assert) {
assert.expect(1);
// Assert, act, assert
var rootOrigin = window.location.protocol + "//" + window.location.host + "/";
var indexOfTest = window.location.pathname.toLowerCase().indexOf("/test/");
var rootDir = window.location.pathname.slice(1, indexOfTest + 1);
var rootPath = rootOrigin + rootDir;
//var stateJsUrl = rootPath + "src/js/core/state.js";
// This is, for the record, a totally incorrect path due to being the development
// file structure but it IS the correct URL based on calculated assumption of using
// the built distributable versions of the library
var swfPathBasedOnStateJsPath = rootPath + "src/js/core/ZeroClipboard.swf";
// Test that the client has the expected default URL [even if it's not correct]
assert.strictEqual(ZeroClipboard.config("swfPath"), swfPathBasedOnStateJsPath);
});
test("Changing `trustedDomains` works", function(assert) {
assert.expect(5);
// Arrange
var currentHost = window.location.host;
var originalValue = currentHost ? [currentHost] : [];
var updatedValue = currentHost ? [currentHost, "otherDomain.com"] : ["otherDomain.com"];
// Assert, act, assert
// Test that the client has the default value
assert.deepEqual(ZeroClipboard.config("trustedDomains"), originalValue);
assert.deepEqual(ZeroClipboard.config().trustedDomains, originalValue);
// Change the value
var updatedConfig = ZeroClipboard.config({ trustedDomains: updatedValue });
// Test that the client has the changed value
assert.deepEqual(updatedConfig.trustedDomains, updatedValue);
assert.deepEqual(ZeroClipboard.config("trustedDomains"), updatedValue);
assert.deepEqual(ZeroClipboard.config().trustedDomains, updatedValue);
});
test("Some config values are ignored if SWF is actively embedded", function(assert) {
assert.expect(2);
// Arrange
var _swfPath = ZeroClipboard.config("swfPath");
var expectedBefore = {
swfPath: _swfPath,
trustedDomains: window.location.host ? [window.location.host] : [],
cacheBust: true,
forceEnhancedClipboard: false,
flashLoadTimeout: 30000,
autoActivate: true,
containerId: "global-zeroclipboard-html-bridge",
containerClass: "global-zeroclipboard-container",
swfObjectId: "global-zeroclipboard-flash-bridge",
hoverClass: "zeroclipboard-is-hover",
activeClass: "zeroclipboard-is-active",
// These configuration values CAN be modified while a SWF is actively embedded.
bubbleEvents: true,
forceHandCursor: false,
title: null,
zIndex: 999999999
};
var expectedAfter = {
swfPath: _swfPath,
trustedDomains: window.location.host ? [window.location.host] : [],
cacheBust: true,
forceEnhancedClipboard: false,
flashLoadTimeout: 30000,
autoActivate: true,
containerId: "global-zeroclipboard-html-bridge",
containerClass: "global-zeroclipboard-container",
swfObjectId: "global-zeroclipboard-flash-bridge",
hoverClass: "zeroclipboard-is-hover",
activeClass: "zeroclipboard-is-active",
// These configuration values CAN be modified while a SWF is actively embedded.
bubbleEvents: false,
forceHandCursor: true,
title: "test",
zIndex: 1000
};
// Act
var actualBefore = ZeroClipboard.config();
_flashState.bridge = {};
var actualAfter = ZeroClipboard.config({
swfPath: "/path/to/test.swf",
trustedDomains: ["test.domain.com"],
cacheBust: false,
forceEnhancedClipboard: true,
flashLoadTimeout: 15000,
autoActivate: false,
containerId: "test-id",
containerClass: "test-class",
swfObjectId: "test-swf",
hoverClass: "test-hover",
activeClass: "test-active",
// These configuration values CAN be modified while a SWF is actively embedded.
bubbleEvents: false,
forceHandCursor: true,
title: "test",
zIndex: 1000
});
// Assert
assert.deepEqual(actualBefore, expectedBefore, "Original config is as expected");
assert.deepEqual(actualAfter, expectedAfter, "Updated config is as expected");
});
module("core/api.js unit tests - clipboard", {
teardown: function() {
_deleteOwnProperties(_clipData);
}
});
test("`setData` works", function(assert) {
assert.expect(4);
// Assert, Act, repeat ad nauseam
assert.deepEqual(_clipData, {}, "`_clipData` is empty");
ZeroClipboard.setData("text/plain", "zc4evar");
assert.deepEqual(_clipData, { "text/plain": "zc4evar" }, "`_clipData` contains expected text");
ZeroClipboard.setData("text/x-markdown", "**ZeroClipboard**");
assert.deepEqual(_clipData, { "text/plain": "zc4evar", "text/x-markdown": "**ZeroClipboard**" }, "`_clipData` contains expected text and custom format");
ZeroClipboard.setData({ "text/html": "<b>Win</b>" });
assert.deepEqual(_clipData, { "text/html": "<b>Win</b>" }, "`_clipData` contains expected HTML and cleared out old data because an object was passed in");
});
test("`clearData` works", function(assert) {
assert.expect(4);
// Assert
assert.deepEqual(_clipData, {}, "`_clipData` is empty");
// Arrange & Assert
_clipData["text/plain"] = "zc4evar";
_clipData["text/html"] = "<b>Win</b>";
_clipData["text/x-markdown"] = "**ZeroClipboard**";
assert.deepEqual(_clipData, {
"text/plain": "zc4evar",
"text/html": "<b>Win</b>",
"text/x-markdown": "**ZeroClipboard**"
}, "`_clipData` contains all expected data");
// Act & Assert
ZeroClipboard.clearData("text/html");
assert.deepEqual(_clipData, {
"text/plain": "zc4evar",
"text/x-markdown": "**ZeroClipboard**"
}, "`_clipData` had 'text/html' successfully removed");
// Act & Assert
ZeroClipboard.clearData();
assert.deepEqual(_clipData, {}, "`_clipData` had all data successfully removed");
});
module("core/api.js unit tests - flash", {
setup: function() {
// Store
originalFlashDetect = ZeroClipboard.isFlashUnusable;
// Modify
ZeroClipboard.isFlashUnusable = function() {
return false;
};
},
teardown: function() {
// Restore
ZeroClipboard.isFlashUnusable = originalFlashDetect;
ZeroClipboard.destroy();
}
});
test("Flash object is ready after emitting `ready`", function(assert) {
assert.expect(2);
// Arrange
ZeroClipboard.isFlashUnusable = function() {
return false;
};
ZeroClipboard.create();
// Assert, act, assert
assert.strictEqual(_flashState.ready, false);
// `emit`-ing event handlers are async (generally) but the internal `ready` state is set synchronously
ZeroClipboard.emit("ready");
assert.strictEqual(_flashState.ready, true);
});
test("Object has a title", function(assert) {
assert.expect(1);
// Arrange
var currentEl = document.getElementById("d_clip_button");
ZeroClipboard.create();
// Act
ZeroClipboard.activate(currentEl);
// Assert
assert.strictEqual(TestUtils.getHtmlBridge().getAttribute("title"), "Click me to copy to clipboard.");
// Revert
ZeroClipboard.deactivate();
});
test("Object has no title", function(assert) {
assert.expect(1);
// Arrange
var currentEl = document.getElementById("d_clip_button_no_title");
ZeroClipboard.create();
// Act
ZeroClipboard.activate(currentEl);
// Assert
assert.ok(!TestUtils.getHtmlBridge().getAttribute("title"));
// Revert
ZeroClipboard.deactivate();
});
test("Object has data-clipboard-text", function(assert) {
assert.expect(3);
// Arrange
var currentEl = document.getElementById("d_clip_button");
ZeroClipboard.create();
// Act
ZeroClipboard.activate(currentEl);
var pendingText = ZeroClipboard.emit("copy");
// Assert
assert.deepEqual(_clipData, { "text/plain": "Copy me!" });
assert.deepEqual(pendingText, { "text": "Copy me!" });
assert.deepEqual(_clipDataFormatMap, { "text": "text/plain" });
// Revert
ZeroClipboard.deactivate();
});
test("Object has data-clipboard-target textarea", function(assert) {
assert.expect(3);
// Arrange
var currentEl = document.getElementById("d_clip_button_textarea_text");
var expectedText =
"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod\n"+
"tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,\n"+
"quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo\n"+
"consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n"+
"cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non\n"+
"proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";
ZeroClipboard.create();
// Act
ZeroClipboard.activate(currentEl);
var pendingText = ZeroClipboard.emit("copy");
// Assert
assert.strictEqual(_clipData["text/plain"].replace(/\r\n/g, "\n"), expectedText);
assert.strictEqual(pendingText.text.replace(/\r\n/g, "\n"), expectedText);
assert.deepEqual(_clipDataFormatMap, { "text": "text/plain" });
// Revert
ZeroClipboard.deactivate();
});
test("Object has data-clipboard-target pre", function(assert) {
assert.expect(5);
// Arrange
var currentEl = document.getElementById("d_clip_button_pre_text");
var expectedText =
"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod\n"+
"tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,\n"+
"quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo\n"+
"consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n"+
"cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non\n"+
"proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";
var expectedHtml =
"<pre id=\"clipboard_pre\">"+
"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod\n"+
"tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,\n"+
"quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo\n"+
"consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n"+
"cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non\n"+
"proident, sunt in culpa qui officia deserunt mollit anim id est laborum."+
"</pre>";
ZeroClipboard.create();
// Act
ZeroClipboard.activate(currentEl);
var pendingText = ZeroClipboard.emit("copy");
// Assert
assert.strictEqual(_clipData["text/plain"].replace(/\r\n/g, "\n"), expectedText);
assert.strictEqual(
_clipData["text/html"]
.replace(/\r\n/g, "\n")
.replace(/<\/?pre(?:\s+[^>]*)?>/gi, function($0) { return $0.toLowerCase(); }),
expectedHtml
);
assert.strictEqual(pendingText.text.replace(/\r\n/g, "\n"), expectedText);
assert.strictEqual(
pendingText.html
.replace(/\r\n/g, "\n")
.replace(/<\/?pre(?:\s+[^>]*)?>/gi, function($0) { return $0.toLowerCase(); }),
expectedHtml
);
assert.deepEqual(_clipDataFormatMap, { "text": "text/plain", "html": "text/html" });
// Revert
ZeroClipboard.deactivate();
});
test("Object has data-clipboard-target input", function(assert) {
assert.expect(3);
// Arrange
var currentEl = document.getElementById("d_clip_button_input_text");
ZeroClipboard.create();
// Act
ZeroClipboard.activate(currentEl);
var pendingText = ZeroClipboard.emit("copy");
// Assert
assert.deepEqual(_clipData, { "text/plain": "Clipboard Text" });
assert.deepEqual(pendingText, { "text": "Clipboard Text" });
assert.deepEqual(_clipDataFormatMap, { "text": "text/plain" });
// Revert
ZeroClipboard.deactivate();
});
test("Object doesn't have data-clipboard-text", function(assert) {
assert.expect(1);
// Arrange
var currentEl = document.getElementById("d_clip_button_no_text");
ZeroClipboard.create();
// Act
ZeroClipboard.activate(currentEl);
// Assert
assert.ok(!TestUtils.getHtmlBridge().getAttribute("data-clipboard-text"));
// Revert
ZeroClipboard.deactivate();
});
test("Calculations based on borderWidth never return NaN", function(assert) {
assert.expect(4);
// Arrange
var currentEl = document.getElementById("d_clip_button");
ZeroClipboard.create();
// Act
ZeroClipboard.activate(currentEl);
// Assert
assert.strictEqual(/^-?[0-9\.]+px$/.test(TestUtils.getHtmlBridge().style.top), true);
assert.strictEqual(/^-?[0-9\.]+px$/.test(TestUtils.getHtmlBridge().style.left), true);
assert.strictEqual(/^-?[0-9\.]+px$/.test(TestUtils.getHtmlBridge().style.width), true);
assert.strictEqual(/^-?[0-9\.]+px$/.test(TestUtils.getHtmlBridge().style.height), true);
});
})(QUnit.module, QUnit.test);

View File

@@ -0,0 +1,77 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>ZeroClipboard unit tests: core/api.js</title>
<link rel="stylesheet" href="../../node_modules/qunitjs/qunit/qunit.css">
<script src="../../node_modules/qunitjs/qunit/qunit.js"></script>
<script>
// Polyfill in future functionality: https://github.com/jquery/qunit/issues/490
if (!QUnit.assert.expect) {
QUnit.assert.expect = QUnit.expect;
}
// Require `expect` calls
QUnit.config.requireExpects = true;
// Prevent against Firefox/Firebug failing the global pollution check
var getInterface = null;
// Prevent against failing the global pollution check in all browsers other than IE
if (typeof window.ActiveXObject === "undefined") {
window.ActiveXObject = null;
}
// Prevent against Flash's ExternalInterface failing the global pollution check (seems to be only in IE < 11)
var __flash__arrayToXML = null,
__flash__argumentsToXML = null,
__flash__objectToXML = null,
__flash__escapeXML = null,
__flash__toXML = null,
__flash__addCallback = null,
__flash__removeCallback = null,
__flash__request = null;
</script>
<script src="../../src/js/shared/state.js"></script>
<script src="../../src/js/shared/private.js"></script>
<script src="../../src/js/core/state.js"></script>
<script src="../../src/js/core/private.js"></script>
<script src="../../src/js/core/api.js"></script>
<script src="../../node_modules/jquery/dist/jquery.js"></script>
<script src="api.tests.js"></script>
</head>
<body>
<div id="qunit"></div>
<div id="qunit-fixture">
<p>
<button id="d_clip_button" class="my_clip_button" title="Click me to copy to clipboard." data-clipboard-text="Copy me!"><b>Copy To Clipboard...</b></button>
</p>
<p>
<button id="d_clip_button_no_title" class="my_clip_button" data-clipboard-text="Copy me!"><b>Copy To Clipboard...</b></button>
</p>
<p>
<button id="d_clip_button_no_text" class="my_clip_button"><b>Copy To Clipboard...</b></button>
</p>
<p>
<button id="d_clip_button_input_text" class="my_clip_button" data-clipboard-target="clipboard_text"><b>Copy To Clipboard...</b></button>
</p>
<p>
<button id="d_clip_button_textarea_text" class="my_clip_button" data-clipboard-target="clipboard_textarea"><b>Copy To Clipboard...</b></button>
</p>
<button id="d_clip_button_pre_text" class="my_clip_button" data-clipboard-target="clipboard_pre"><b>Copy To Clipboard...</b></button>
<input type="text" id="clipboard_text" value="Clipboard Text"/>
<textarea id="clipboard_textarea">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</textarea>
<pre id="clipboard_pre">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</pre>
</div>
</body>
</html>

View File

@@ -0,0 +1,494 @@
/*global _flashState:true, _currentElement:true, _copyTarget:true, _extend, _getStyle, _removeClass, _addClass, _vars, _cacheBust, _extractDomain, _determineScriptAccess, _mapClipDataToFlash, _mapClipResultsFromFlash, _createEvent, _preprocessEvent, _getRelatedTarget, _shouldPerformAsync, _dispatchCallback, _detectFlashSupport */
(function(module, test) {
"use strict";
var mimeType, ax, flashState;
module("core/private.js unit tests - utils");
test("`_getStyle` returns computed styles", function(assert) {
assert.expect(5);
// Arrange
var pointerEl = $("a.no_cursor_style")[0];
var nonPointerEl = $("a.no_pointer_anchor")[0];
var zIndexAutoEl = $(".zindex-auto")[0];
var clipButtonEl = $("#d_clip_button")[0];
var bigBorderEl = $(".big-border")[0];
// Act
var pointerElComputedCursor = _getStyle(pointerEl, "cursor");
var nonPointerElComputedCursor = _getStyle(nonPointerEl, "cursor");
var zIndexAutoElComputedZIndex = _getStyle(zIndexAutoEl, "z-index");
var clipButtonElComputedBorderLeftWidth = _getStyle(clipButtonEl, "border-left-width");
var bigBorderElComputedBorderLeftWith = _getStyle(bigBorderEl, "border-left-width");
// Assert
assert.strictEqual(pointerElComputedCursor, "pointer");
assert.notStrictEqual(nonPointerElComputedCursor, "pointer");
// Returns 0 in IE7, "auto" everywhere else
assert.strictEqual(/^(?:auto|0)$/.test(zIndexAutoElComputedZIndex), true);
// This varies between "0px" and "3px" depending on the browser (WAT?)
assert.strictEqual(/^[0-3]px$/.test(clipButtonElComputedBorderLeftWidth), true);
assert.strictEqual(bigBorderElComputedBorderLeftWith, "10px");
});
test("`_removeClass` removes classes from element", function(assert) {
assert.expect(5);
// Arrange
var div = $("<div></div>").addClass("class1 class-2 class_3")[0];
// Act & Assert
_removeClass(div, "class1");
assert.strictEqual(div.className, "class-2 class_3");
_removeClass(div, "classd");
assert.strictEqual(div.className, "class-2 class_3");
_removeClass(div, "class-2");
assert.strictEqual(div.className, "class_3");
_removeClass(div, "class_3");
assert.strictEqual(div.className, "");
_removeClass(div, "class-3");
assert.strictEqual(div.className, "");
div = null;
});
test("`_removeClass` doesn't remove partial class names", function(assert) {
assert.expect(3);
// Arrange
var div = $("<div></div>").addClass("class1 class-2 class_3")[0];
// Act & Assert
_removeClass(div, "ass");
assert.strictEqual(div.className, "class1 class-2 class_3");
_removeClass(div, "-2");
assert.strictEqual(div.className, "class1 class-2 class_3");
_removeClass(div, "_3");
assert.strictEqual(div.className, "class1 class-2 class_3");
div = null;
});
test("`_addClass` adds a class name", function(assert) {
assert.expect(4);
// Arrange
var div = $("<div></div>")[0];
// Act & Assert
_addClass(div, "class1");
assert.strictEqual(div.className, "class1");
_addClass(div, "class-2");
assert.strictEqual(div.className, "class1 class-2");
_addClass(div, "class_3");
assert.strictEqual(div.className, "class1 class-2 class_3");
_addClass(div, "class_3");
assert.strictEqual(div.className, "class1 class-2 class_3");
div = null;
});
test("`_vars` builds FlashVars", function(assert) {
assert.expect(6);
// Arrange
var clipOptionsEmpty = {};
var clipOptionsTrustedDomains = {
trustedDomains: ["*"]
};
var clipOptionsEnhancedClipboardFalse = {
forceEnhancedClipboard: false
};
var clipOptionsEnhancedClipboardTrue = {
forceEnhancedClipboard: true
};
var clipOptionsTrustedDomainsPlusEnhancedClipboardFalse = {
trustedDomains: ["*"],
forceEnhancedClipboard: false
};
var clipOptionsTrustedDomainsPlusEnhancedClipboardTrue = {
trustedDomains: ["*"],
forceEnhancedClipboard: true
};
// Act & Assert
assert.strictEqual(_vars(clipOptionsEmpty), "");
assert.strictEqual(_vars(clipOptionsTrustedDomains), "trustedOrigins=*");
assert.strictEqual(_vars(clipOptionsEnhancedClipboardFalse), "");
assert.strictEqual(_vars(clipOptionsEnhancedClipboardTrue), "forceEnhancedClipboard=true");
assert.strictEqual(_vars(clipOptionsTrustedDomainsPlusEnhancedClipboardFalse), "trustedOrigins=*");
assert.strictEqual(_vars(clipOptionsTrustedDomainsPlusEnhancedClipboardTrue), "trustedOrigins=*&forceEnhancedClipboard=true");
});
test("`_cacheBust` adds cache-buster appropriately", function(assert) {
assert.expect(2);
// Arrange
var pathWithoutQuery = "path.com/z.swf";
var pathWithQuery = "path.com/z.swf?q=jon";
// Act & Assert
assert.strictEqual(_cacheBust(pathWithoutQuery).indexOf("?noCache="), 0);
assert.strictEqual(_cacheBust(pathWithQuery).indexOf("&noCache="), 0);
});
test("`_cacheBust` can be disabled", function(assert) {
assert.expect(2);
// Arrange
var pathWithoutQuery = "path.com/z.swf";
var pathWithQuery = "path.com/z.swf?q=jon";
var options = {
cacheBust: false
};
// Act & Assert
assert.strictEqual(_cacheBust(pathWithoutQuery, options), "");
assert.strictEqual(_cacheBust(pathWithQuery, options), "");
});
test("`_extractDomain` extracts domains from origins and URLs", function(assert) {
assert.expect(20);
// Arrange
var inputToExpectedMap = {
"": null,
" ": null,
"ZeroClipboard.swf": null,
"js/ZeroClipboard.swf": null,
"/js/ZeroClipboard.swf": null,
"/zeroclipboard/zeroclipboard/": null,
"zeroclipboard/zeroclipboard/": null,
"*": "*",
"github.com": "github.com",
"http://github.com": "github.com",
"https://github.com": "github.com",
"github.com:80": "github.com:80",
"http://github.com:80": "github.com:80",
"https://github.com:443": "github.com:443",
"http://github.com/zeroclipboard/zeroclipboard/": "github.com",
"https://github.com/zeroclipboard/zeroclipboard/": "github.com",
"http://github.com:80/zeroclipboard/zeroclipboard/": "github.com:80",
"https://github.com:443/zeroclipboard/zeroclipboard/": "github.com:443"
};
// Act & Assert
assert.strictEqual(_extractDomain(undefined), null, "Processing: `undefined`");
assert.strictEqual(_extractDomain(null), null, "Processing: `null`");
for (var originOrUrl in inputToExpectedMap) {
if (inputToExpectedMap.hasOwnProperty(originOrUrl)) {
assert.strictEqual(_extractDomain(originOrUrl), inputToExpectedMap[originOrUrl], "Processing: \"" + originOrUrl + "\"");
}
}
});
test("`_determineScriptAccess` determines the appropriate script access level", function(assert) {
// Arrange
var i, len, tmp;
var currentDomain = window.location.host || "localhost";
var _globalConfig = {
swfPath: "ZeroClipboard.swf",
trustedDomains: [currentDomain]
};
var inputToExpectedMap = [
// Same-domain SWF
{ args: [currentDomain, _globalConfig], result: "sameDomain" },
{ args: [currentDomain, _extend({}, _globalConfig, { trustedDomains: [] })], result: "never" },
{ args: [currentDomain, _extend({}, _globalConfig, { trustedDomains: ["*"] })], result: "always" },
{ args: [currentDomain, _extend({}, _globalConfig, { trustedDomains: [currentDomain, "otherDomain.com"] })], result: "always" },
{ args: [currentDomain, _extend({}, _globalConfig, { trustedDomains: ["otherDomain.com"] })], result: "never" },
// Cross-domain SWF
{ args: [currentDomain, _extend({}, _globalConfig, { swfPath: "//otherDomain.com/ZeroClipboard.swf" })], result: "always" },
{ args: [currentDomain, _extend({}, _globalConfig, { swfPath: "//otherDomain.com/ZeroClipboard.swf", trustedDomains: [] })], result: "never" },
{ args: [currentDomain, _extend({}, _globalConfig, { swfPath: "//otherDomain.com/ZeroClipboard.swf", trustedDomains: ["*"] })], result: "always" },
{ args: [currentDomain, _extend({}, _globalConfig, { swfPath: "//otherDomain.com/ZeroClipboard.swf", trustedDomains: [currentDomain, "otherDomain.com"] })], result: "always" }
];
// Act & Assert
assert.expect(9);
for (i = 0, len = inputToExpectedMap.length; i < len; i++) {
tmp = inputToExpectedMap[i];
assert.strictEqual(_determineScriptAccess.apply(this, tmp.args), tmp.result, "Processing: " + JSON.stringify(tmp));
}
});
test("`_mapClipDataToFlash` works", function(assert) {
assert.expect(1);
// Arrange
var clipData = {
"text/plain": "Zero",
"text/html": "<b>Zero</b>"
};
var expectedOutput = {
data: {
"text": "Zero",
"html": "<b>Zero</b>"
},
formatMap: {
"text": "text/plain",
"html": "text/html"
}
};
// Act
var actual = _mapClipDataToFlash(clipData);
// Assert
assert.deepEqual(actual, expectedOutput, "Converted keys to Flash-friendly names and provided a format map");
});
test("`_mapClipResultsFromFlash` works", function(assert) {
assert.expect(2);
// Arrange
var clipResults = {
type: "aftercopy",
success: {
"text": true,
"html": false
},
data: {
"text": "Zero",
"html": "<b>Zero</b>"
}
};
var formatMap = {
"text": "text/plain",
"html": "text/html"
};
var expectedOutput = {
type: "aftercopy",
success: {
"text/plain": true,
"text/html": false
},
data: {
"text/plain": "Zero",
"text/html": "<b>Zero</b>"
}
};
// Act & Assert
var thisWontChange = _mapClipResultsFromFlash(clipResults, null);
assert.deepEqual(thisWontChange, clipResults, "Should return the original object if it cannot map it");
// Act & Assert
var revisedClipResults = _mapClipResultsFromFlash(clipResults, formatMap);
assert.deepEqual(revisedClipResults, expectedOutput, "Should reverse the key mapping process");
});
test("`_createEvent` works", function(assert) {
assert.expect(2);
var actual = _createEvent("ready");
assert.strictEqual(typeof actual === "object" && actual != null, true, "Returns non-null object");
assert.strictEqual(actual.type, "ready", "Object has a `type` property of 'ready'");
// etc.
});
// Tests fix for: https://github.com/zeroclipboard/zeroclipboard/issues/467
test("`_copyTarget` element is handled appropriately", function(assert) {
assert.expect(18);
// Arrange
var el1 = $("#d_clip_button")[0];
var el2 = $("#goodTargetId")[0];
_currentElement = el1;
_copyTarget = null;
// Act
var evt = _createEvent("beforecopy");
_preprocessEvent(evt);
// Assert
assert.strictEqual(_currentElement, el1, "`_currentElement` is 'el1'");
assert.strictEqual(_copyTarget, el1, "`_copyTarget` is 'el1'");
assert.strictEqual(evt.target, el1, "`beforecopy` target is 'el1'");
// Act some more
_currentElement = el2;
evt = _createEvent("copy");
_preprocessEvent(evt);
// Assert some more
assert.strictEqual(_currentElement, el2, "`_currentElement` is 'el2'");
assert.strictEqual(_copyTarget, el1, "`_copyTarget` is 'el1'");
assert.strictEqual(evt.target, el1, "`copy` target is 'el1'");
// Act some more: interruption due to mouse movement (only happens in Firefox,
// though similar issues occur in Chrome for Windows if the user clicks on
// another clipped element)
evt = _createEvent("_mouseover");
_preprocessEvent(evt);
// Assert some more
assert.strictEqual(_currentElement, el2, "`_currentElement` is 'el2'");
assert.strictEqual(_copyTarget, el1, "`_copyTarget` is 'el1'");
assert.strictEqual(evt.target, el2, "`_mouseover` target is 'el2'");
// Act some more
evt = _createEvent("aftercopy");
_preprocessEvent(evt);
// Assert some more
assert.strictEqual(_currentElement, el2, "`_currentElement` is 'el2'");
assert.strictEqual(_copyTarget, el1, "`_copyTarget` is 'el1'");
assert.strictEqual(evt.target, el1, "`aftercopy` target is 'el1'");
// Act some more
evt = _createEvent("_click");
// Assert some more
assert.strictEqual(_currentElement, el2, "`_currentElement` is 'el2'");
assert.strictEqual(_copyTarget, el1, "`_copyTarget` is 'el1'");
assert.strictEqual(evt.target, el1, "`_click` target is 'el1'");
// Act some more
_preprocessEvent(evt);
// Assert some more
assert.strictEqual(_currentElement, el2, "`_currentElement` is 'el2'");
assert.strictEqual(_copyTarget, null, "`_copyTarget` is `null`");
assert.strictEqual(evt.target, el1, "`_click` target is 'el1'");
// Reset
_currentElement = _copyTarget = el1 = el2 = null;
});
test("`_getRelatedTarget` works", function(assert) {
assert.expect(4);
var relTarget = $("#relTargetId")[0];
var goodTarget = $("#goodTargetId")[0];
var badTarget1 = $("#badTargetId1")[0];
var badTarget2 = $("#badTargetId2")[0];
assert.notEqual(relTarget, null, "The related target is `null`");
assert.strictEqual(_getRelatedTarget(goodTarget), relTarget, "Element with `data-clipboard-target` returns `null`");
assert.strictEqual(_getRelatedTarget(badTarget1), null, "Element with `data-clipboard-target` that doesn't much any elements returns `null`");
assert.strictEqual(_getRelatedTarget(badTarget2), null, "Element without `data-clipboard-target` returns `null`");
});
test("`_shouldPerformAsync` works", function(assert) {
assert.expect(4);
// Act & Assert
assert.strictEqual(_shouldPerformAsync({ type: "beforecopy" }), false, "`beforecopy` should be performed synchronously");
assert.strictEqual(_shouldPerformAsync({ type: "copy" }), false, "`copy` should be performed synchronously");
assert.strictEqual(_shouldPerformAsync({ type: "destroy" }), false, "`destroy` should be performed synchronously");
assert.strictEqual(_shouldPerformAsync({ type: "ready" }), true, "All other event types should be performed asynchronously");
});
test("`_dispatchCallback` can fire asynchronously", function(assert) {
assert.expect(6);
// Arrange
var syncExec = false;
var syncProof = false;
var syncProveIt = function() {
syncProof = true;
};
var asyncExec = true;
var asyncProof = false;
var asyncProveIt = function() {
// Resume test evaluation
QUnit.start();
assert.strictEqual(asyncProof, false);
asyncProof = true;
assert.strictEqual(asyncProof, true);
};
// Act & Assert
// Synchronous
assert.strictEqual(syncProof, false);
_dispatchCallback(syncProveIt, null, null, syncExec);
assert.strictEqual(syncProof, true);
// Asynchronous
assert.strictEqual(asyncProof, false);
_dispatchCallback(asyncProveIt, null, null, asyncExec);
assert.strictEqual(asyncProof, false);
// Stop test evaluation
QUnit.stop();
});
module("core/private.js unit tests - flash", {
setup: function() {
flashState = _flashState;
mimeType = window.navigator.mimeTypes["application/x-shockwave-flash"];
ax = window.ActiveXObject;
},
teardown: function() {
window.navigator.mimeTypes["application/x-shockwave-flash"] = mimeType;
window.ActiveXObject = ax;
_flashState = flashState;
}
});
test("Detecting no Flash", function(assert) {
assert.expect(1);
// Arrange
window.navigator.mimeTypes["application/x-shockwave-flash"] = undefined;
window.ActiveXObject = undefined;
// Act
_detectFlashSupport(window.ActiveXObject);
// Assert
assert.strictEqual(_flashState.disabled, true);
});
test("Detecting has Flash mimetype", function(assert) {
assert.expect(1);
// Arrange
window.navigator.mimeTypes["application/x-shockwave-flash"] = {};
window.ActiveXObject = function() { };
// Act
_detectFlashSupport(window.ActiveXObject);
// Assert
assert.strictEqual(_flashState.disabled, false);
});
})(QUnit.module, QUnit.test);

View File

@@ -0,0 +1,68 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>ZeroClipboard unit tests: core/private.js</title>
<link rel="stylesheet" href="../../node_modules/qunitjs/qunit/qunit.css">
<script src="../../node_modules/qunitjs/qunit/qunit.js"></script>
<script>
// Polyfill in future functionality: https://github.com/jquery/qunit/issues/490
if (!QUnit.assert.expect) {
QUnit.assert.expect = QUnit.expect;
}
// Require `expect` calls
QUnit.config.requireExpects = true;
// Prevent against Firefox/Firebug failing the global pollution check
var getInterface = null;
// Prevent against failing the global pollution check in all browsers other than IE
if (typeof window.ActiveXObject === "undefined") {
window.ActiveXObject = null;
}
// Prevent against Flash's ExternalInterface failing the global pollution check (seems to be only in IE < 11)
var __flash__arrayToXML = null,
__flash__argumentsToXML = null,
__flash__objectToXML = null,
__flash__escapeXML = null,
__flash__toXML = null,
__flash__addCallback = null,
__flash__removeCallback = null,
__flash__request = null;
// Provide a shell of the `ZeroClipboard` object to pass through a few tests
var ZeroClipboard = {
setData: function() {},
clearData: function() {},
focus: function(el) {
_currentElement = el;
}
};
</script>
<script src="../../src/js/shared/state.js"></script>
<script src="../../src/js/shared/private.js"></script>
<script src="../../src/js/core/state.js"></script>
<script src="../../src/js/core/private.js"></script>
<script src="../../node_modules/jquery/dist/jquery.js"></script>
<script src="private.tests.js"></script>
</head>
<body>
<div id="qunit"></div>
<div id="qunit-fixture">
<div id="goodTargetId" data-clipboard-target="relTargetId"></div>
<div id="relTargetId"></div>
<div id="badTargetId1" data-clipboard-target="elementIdWithoutMatch"></div>
<div id="badTargetId2"></div>
<button id="d_clip_button" class="my_clip_button" title="Click me to copy to clipboard." data-clipboard-text="Copy me!">
<b>Copy To Clipboard...</b>
</button>
<a href="" class="no_pointer_anchor" style="cursor:default;"></a>
<a href="" class="no_cursor_style" style="cursor:auto;"></a>
<span class="zindex-auto" style="z-index:auto;"></span>
<span class="big-border" style="border: 10px solid red;"></span>
</div>
</body>
</html>

View File

@@ -0,0 +1,28 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>ZeroClipboard unit tests</title>
<link rel="stylesheet" href="../node_modules/qunitjs/qunit/qunit.css">
<link rel="stylesheet" href="../node_modules/qunit-composite/qunit-composite.css">
<script src="../node_modules/qunitjs/qunit/qunit.js"></script>
<script src="../node_modules/qunit-composite/qunit-composite.js"></script>
<script>
(function() {
var queryParams = "?noglobals=true";
QUnit.testSuites([
"shared/private.tests.js.html" + queryParams,
"core/private.tests.js.html" + queryParams,
"core/api.tests.js.html" + queryParams,
"client/private.tests.js.html" + queryParams,
"client/api.tests.js.html" + queryParams,
"built/ZeroClipboard.Core.tests.js.html" + queryParams,
"built/ZeroClipboard.tests.js.html" + queryParams
]);
})();
</script>
</head>
<body>
<div id="qunit"></div>
</body>
</html>

View File

@@ -0,0 +1,911 @@
/*global _document:true, _Error:true, _args, _extend, _deepCopy, _pick, _omit, _deleteOwnProperties, _containedBy, _getDirPathOfUrl, _getCurrentScriptUrlFromErrorStack, _getCurrentScriptUrlFromError:true, _getCurrentScriptUrl, _getUnanimousScriptParentDir, _getDefaultSwfPath */
(function(module, test) {
"use strict";
var doc, errorDef, getUrlFromError;
module("shared/private.js unit tests", {
setup: function() {
doc = _document;
errorDef = _Error;
getUrlFromError = _getCurrentScriptUrlFromError;
},
teardown: function() {
_document = doc;
_Error = errorDef;
_getCurrentScriptUrlFromError = getUrlFromError;
}
});
test("`_args` works", function(assert) {
assert.expect(4);
// Arrange
var _arguments = function() {
return arguments;
};
var fn = function() {};
var expectedOutput1 = [1, 2, 3];
var expectedOutput2 = [fn];
var expectedOutput3 = [{ foo: "bar" }];
var expectedOutput4 = [[1, 2, 3]];
var inputArgs1 = _arguments(1, 2, 3);
var inputArgs2 = _arguments(fn);
var inputArgs3 = _arguments({ foo: "bar" });
var inputArgs4 = _arguments([1, 2, 3]);
// Act
var actualOutput1 = _args(inputArgs1);
var actualOutput2 = _args(inputArgs2);
var actualOutput3 = _args(inputArgs3);
var actualOutput4 = _args(inputArgs4);
// Arrange
assert.deepEqual(actualOutput1, expectedOutput1);
assert.deepEqual(actualOutput2, expectedOutput2);
assert.deepEqual(actualOutput3, expectedOutput3);
assert.deepEqual(actualOutput4, expectedOutput4);
});
test("`_extend` works on plain objects", function(assert) {
assert.expect(5);
// Plain objects
var a = {
"a": "apple",
"c": "cantalope"
},
b = {
"b": "banana",
"c": "cherry" // cuz cantalope sucks ;)
},
c = {
"a": "apple",
"b": "banana",
"c": "cherry"
};
assert.deepEqual(_extend({}, a), a, "actual equals expected, `target` is updated, `source` is unaffected");
assert.deepEqual(_extend({}, b), b, "actual equals expected, `target` is updated, `source` is unaffected");
assert.deepEqual(_extend({}, c), c, "actual equals expected, `target` is updated, `source` is unaffected");
assert.deepEqual(_extend(a, b), c, "actual equals expected");
assert.deepEqual(a, c, "`a` equals `c` because `_extend` updates the `target` argument");
});
test("`_extend` only copies owned properties", function(assert) {
assert.expect(1);
// Now prototypes...
var SomeClass = function() {
this.b = "banana";
};
SomeClass.prototype.c = "cantalope"; // cuz cantalope sucks ;)
var a = {
"a": "apple",
"c": "cherry"
},
b = new SomeClass(),
c = {
"a": "apple",
"b": "banana",
"c": "cherry"
};
assert.deepEqual(_extend(a, b), c, "actual equals expected because `_extend` does not copy over prototype properties");
});
test("`_extend` only copies owned properties from Array source", function(assert) {
assert.expect(3);
var a = {
"a": "apple",
"b": "banana"
},
b = ["zero", "one", "two"],
c = {
"a": "apple",
"b": "banana",
"0": "zero",
"1": "one",
"2": "two"
};
assert.deepEqual(_extend(a, b), c, "actual equals expected because `_extend` does not copy over prototype properties");
assert.strictEqual("length" in a, false, "`a` should not have gained a `length` property");
assert.strictEqual("length" in b, true, "`b` should still have a `length` property");
});
test("`_extend` will merge multiple objects", function(assert) {
assert.expect(2);
var a = {
"a": "apple",
"c": "cantalope",
"d": "dragon fruit"
},
b = {
"b": "banana",
"c": "cherry" // cuz cantalope sucks ;)
},
c = {
"a": "apricot",
"b": "blueberry"
},
d = {
"a": "apricot",
"b": "blueberry",
"c": "cherry",
"d": "dragon fruit"
};
assert.deepEqual(_extend({}, a, b, c), d, "actual equals expected, `target` is updated, `source` is unaffected");
assert.deepEqual(_extend(a, b, c), d, "actual equals expected");
});
test("`_deepCopy` works", function(assert) {
assert.expect(13);
// Arrange
var input1 = {
"a": "b",
"b": {
"c": "d"
}
};
var input2 = [[1, 2], 2];
var expected1 = {
"a": "b",
"b": {
"c": "d"
}
};
var expected2 = [[1, 2], 2];
// Act
var actual1 = _deepCopy(input1);
var actual2 = _deepCopy(input2);
// Assert
assert.deepEqual(actual1, expected1, "Objects are deeply equal");
assert.notStrictEqual(actual1, expected1, "Objects are not strictly equal");
assert.strictEqual(actual1.a, expected1.a, "Objects' non-object properties are strictly equal");
assert.deepEqual(actual1.b, expected1.b, "Objects' object properties are deeply equal");
assert.notStrictEqual(actual1.b, expected1.b, "Objects' object properties are not strictly equal");
assert.strictEqual(actual1.b.c, expected1.b.c, "Objects' object properties' non-object properties are strictly equal");
assert.deepEqual(actual2, expected2, "Arrays are deeply equal");
assert.notStrictEqual(actual2, expected2, "Arrays are not strictly equal");
assert.deepEqual(actual2[0], expected2[0], "Sub-arrays are deeply equal");
assert.notStrictEqual(actual2[0], expected2[0], "Sub-arrays are not strictly equal");
assert.strictEqual(actual2[0][0], expected2[0][0], "Sub-arrays' first items are strictly equal");
assert.strictEqual(actual2[0][1], expected2[0][1], "Sub-arrays' second items are strictly equal");
assert.strictEqual(actual2[1], expected2[1], "Sub-items are strictly equal");
});
test("`_pick` works", function(assert) {
assert.expect(6);
// Arrange
var obj1 = {};
var obj2 = {
"name": "Zero",
"version": "v2.x",
"other": "test"
};
var filter1 = [];
var filter2 = ["name", "version"];
var filter3 = ["name", "version", "other"];
var expected1x = {};
var expected21 = {};
var expected22 = {
"name": "Zero",
"version": "v2.x"
};
var expected23 = {
"name": "Zero",
"version": "v2.x",
"other": "test"
};
// Act
var result11 = _pick(obj1, filter1);
var result12 = _pick(obj1, filter2);
var result13 = _pick(obj1, filter3);
var result21 = _pick(obj2, filter1);
var result22 = _pick(obj2, filter2);
var result23 = _pick(obj2, filter3);
// Assert
assert.deepEqual(result11, expected1x, "An empty object cannot have any properties picked");
assert.deepEqual(result12, expected1x, "An empty object cannot have any properties picked");
assert.deepEqual(result13, expected1x, "An empty object cannot have any properties picked");
assert.deepEqual(result21, expected21, "An object with an empty pick list will have nothing picked");
assert.deepEqual(result22, expected22, "An object with a subset pick list will have only those properties picked");
assert.deepEqual(result23, expected23, "An object with a complete pick list will have all of its properties picked");
});
test("`_omit` works", function(assert) {
assert.expect(6);
// Arrange
var obj1 = {};
var obj2 = {
"name": "Zero",
"version": "v2.x",
"other": "test"
};
var filter1 = [];
var filter2 = ["name", "version"];
var filter3 = ["name", "version", "other"];
var expected1x = {};
var expected21 = {
"name": "Zero",
"version": "v2.x",
"other": "test"
};
var expected22 = {
"other": "test"
};
var expected23 = {};
// Act
var result11 = _omit(obj1, filter1);
var result12 = _omit(obj1, filter2);
var result13 = _omit(obj1, filter3);
var result21 = _omit(obj2, filter1);
var result22 = _omit(obj2, filter2);
var result23 = _omit(obj2, filter3);
// Assert
assert.deepEqual(result11, expected1x, "An empty object cannot have any properties picked");
assert.deepEqual(result12, expected1x, "An empty object cannot have any properties picked");
assert.deepEqual(result13, expected1x, "An empty object cannot have any properties picked");
assert.deepEqual(result21, expected21, "An object with an empty omit list will have everything picked");
assert.deepEqual(result22, expected22, "An object with a subset omit list will have everything but those properties picked");
assert.deepEqual(result23, expected23, "An object with a complete omit list will have nothing picked");
});
test("`_deleteOwnProperties` will delete all owned enumerable properties", function(assert) {
assert.expect(24);
var getNonObjectKeys = function(obj) {
var prop,
keys = [];
if (obj) {
for (prop in obj) {
if (obj.hasOwnProperty(prop)) {
keys.push(prop);
}
}
}
return keys;
};
var getProtoKeys = function(obj) {
var prop,
keys = [];
if (obj) {
for (prop in obj) {
if (!obj.hasOwnProperty(prop)) {
keys.push(prop);
}
}
}
return keys;
};
var a = {
"a": "apple",
"c": "cantalope",
"d": "dragon fruit"
},
b = {},
c = ["banana", "cherry"],
d = (function() {
function SomePrototype() {
this.protoProp = "foo";
}
function SomeClass() {
this.ownedProp = "bar";
}
SomeClass.prototype = new SomePrototype();
SomeClass.prototype.constructor = SomeClass;
return new SomeClass();
})(),
e = null,
f; // = undefined;
assert.deepEqual(Object.keys(a), ["a", "c", "d"]);
assert.deepEqual(getProtoKeys(a), []);
_deleteOwnProperties(a);
assert.deepEqual(Object.keys(a), []);
assert.deepEqual(getProtoKeys(a), []);
assert.deepEqual(Object.keys(b), []);
assert.deepEqual(getProtoKeys(b), []);
_deleteOwnProperties(b);
assert.deepEqual(Object.keys(b), []);
assert.deepEqual(getProtoKeys(b), []);
assert.deepEqual(getNonObjectKeys(c), ["0", "1"]);
assert.deepEqual(getProtoKeys(c), []);
_deleteOwnProperties(c);
assert.deepEqual(getNonObjectKeys(c), []);
assert.deepEqual(getProtoKeys(c), []);
assert.deepEqual(Object.keys(d), ["ownedProp"]);
assert.deepEqual(getProtoKeys(d), ["protoProp", "constructor"]);
_deleteOwnProperties(d);
assert.deepEqual(Object.keys(d), []);
assert.deepEqual(getProtoKeys(d), ["protoProp", "constructor"]);
assert.deepEqual(getNonObjectKeys(e), []);
assert.deepEqual(getProtoKeys(e), []);
_deleteOwnProperties(e);
assert.deepEqual(getNonObjectKeys(e), []);
assert.deepEqual(getProtoKeys(e), []);
assert.deepEqual(getNonObjectKeys(f), []);
assert.deepEqual(getProtoKeys(f), []);
_deleteOwnProperties(f);
assert.deepEqual(getNonObjectKeys(f), []);
assert.deepEqual(getProtoKeys(f), []);
});
test("`_containedBy` works", function(assert) {
/*jshint camelcase:false */
assert.expect(29);
// Arrange
var fixture = document.getElementById("qunit-fixture");
fixture.innerHTML =
"<div id='container'>" +
"<div id='contained1'>" +
"<div id='contained1_1'></div>" +
"<div id='contained1_2'>" +
"<div id='contained1_2_1'></div>" +
"</div>" +
"</div>" +
"<div id='contained2'></div>" +
"</div>" +
"<div id='not_container'>" +
"<div id='not_contained'></div>" +
"</div>";
var container = document.getElementById("container");
var contained1 = document.getElementById("contained1");
var contained1_1 = document.getElementById("contained1_1");
var contained1_2 = document.getElementById("contained1_2");
var contained1_2_1 = document.getElementById("contained1_2_1");
var contained2 = document.getElementById("contained2");
var not_container = document.getElementById("not_container");
var not_contained = document.getElementById("not_contained");
// Act & Assert
assert.strictEqual(_containedBy(contained1_2_1, contained1_2_1), true);
assert.strictEqual(_containedBy(contained1_2_1, contained1_2), true);
assert.strictEqual(_containedBy(contained1_2_1, contained1), true);
assert.strictEqual(_containedBy(contained1_2_1, container), true);
assert.strictEqual(_containedBy(contained1_2_1, fixture), true);
assert.strictEqual(_containedBy(contained1_2_1, not_container), false);
assert.strictEqual(_containedBy(contained1_1, contained1_1), true);
assert.strictEqual(_containedBy(contained1_1, contained1), true);
assert.strictEqual(_containedBy(contained1_1, container), true);
assert.strictEqual(_containedBy(contained1_1, fixture), true);
assert.strictEqual(_containedBy(contained1_1, not_container), false);
assert.strictEqual(_containedBy(contained1, contained1), true);
assert.strictEqual(_containedBy(contained1, container), true);
assert.strictEqual(_containedBy(contained1, fixture), true);
assert.strictEqual(_containedBy(contained1, not_container), false);
assert.strictEqual(_containedBy(contained2, contained2), true);
assert.strictEqual(_containedBy(contained2, container), true);
assert.strictEqual(_containedBy(contained2, fixture), true);
assert.strictEqual(_containedBy(contained2, not_container), false);
assert.strictEqual(_containedBy(container, container), true);
assert.strictEqual(_containedBy(container, fixture), true);
assert.strictEqual(_containedBy(container, not_container), false);
assert.strictEqual(_containedBy(not_contained, not_contained), true);
assert.strictEqual(_containedBy(not_contained, not_container), true);
assert.strictEqual(_containedBy(not_contained, fixture), true);
assert.strictEqual(_containedBy(not_contained, container), false);
assert.strictEqual(_containedBy(not_container, not_container), true);
assert.strictEqual(_containedBy(not_container, fixture), true);
assert.strictEqual(_containedBy(not_container, container), false);
});
test("`_getDirPathOfUrl` works", function(assert) {
assert.expect(8);
// Arrange
var input1 = "http://example.com/blah/foo/index.html";
var input2 = "http://example.com/blah/foo/index.html?q=p";
var input3 = "http://example.com/blah/foo/index.html?q=p&x=z";
var input4 = "http://example.com/blah/foo/index.html?#xyz";
var input5 = "http://example.com/blah/foo/index.html?q=p#xyz";
var input6 = "http://example.com/blah/foo/index.html?q=p&x=z#xyz";
var input7 = "http://example.com/blah/foo/";
var input8 = "";
var expected1 = "http://example.com/blah/foo/";
var expected2 = "http://example.com/blah/foo/";
var expected3 = "http://example.com/blah/foo/";
var expected4 = "http://example.com/blah/foo/";
var expected5 = "http://example.com/blah/foo/";
var expected6 = "http://example.com/blah/foo/";
var expected7 = "http://example.com/blah/foo/";
var expected8;
// Act
var actual1 = _getDirPathOfUrl(input1);
var actual2 = _getDirPathOfUrl(input2);
var actual3 = _getDirPathOfUrl(input3);
var actual4 = _getDirPathOfUrl(input4);
var actual5 = _getDirPathOfUrl(input5);
var actual6 = _getDirPathOfUrl(input6);
var actual7 = _getDirPathOfUrl(input7);
var actual8 = _getDirPathOfUrl(input8);
// Assert
assert.strictEqual(actual1, expected1);
assert.strictEqual(actual2, expected2);
assert.strictEqual(actual3, expected3);
assert.strictEqual(actual4, expected4);
assert.strictEqual(actual5, expected5);
assert.strictEqual(actual6, expected6);
assert.strictEqual(actual7, expected7);
assert.strictEqual(actual8, expected8);
});
test("`_getCurrentScriptUrlFromErrorStack` works", function(assert) {
assert.expect(25);
// Arrange
var localStacks = [
"Error: my uncaught error\n at http://example.com/index.html:123:4\n at jQuery.event.dispatch (http://code.jquery.com/blah.js:567:8)\n at foo",
"http://example.com/index.html:123:4\ndispatch@http://code.jquery.com/blah.js:567:8\nfoo",
"@http://example.com/index.html:123\ndispatch@http://code.jquery.com/blah.js:567\nfoo",
"<anonymous function>([arguments not available])@http://example.com/index.html:123\n<anonymous function: dispatch>([arguments not available])@http://code.jquery.com/blah.js:567\nfoo",
"Error: my error\n at http://example.com/index.html:123\n at http://code.jquery.com/blah.js:567\nfoo",
"Error(\"my error\")@:0\u000a([object Object])@http://example.com/index.html:123\u000a([object Object])@http://code.jquery.com/blah.js:567\u000afoo",
"Error: my error\n at Anonymous function (http://example.com/index.html:123:4)\n at dispatch (http://code.jquery.com/blah.js:567:8)\n at foo",
"Error: my sneaky error message has a URL in it at http://google.com/mean.js:987\n at Anonymous function (http://example.com/index.html:123:4)\n at dispatch (http://code.jquery.com/blah.js:567:8)\n at foo"
];
var remoteStacks = [
"Error: my error\n at window.onload (http://example.com/blah/foo.js:95:11)\n at jQuery.event.dispatch (http://code.jquery.com/blah.js:567:8)\n at foo",
"onload@http://example.com/blah/foo.js:95:11\ndispatch@http://code.jquery.com/blah.js:567:8\nfoo",
"onload@http://example.com/blah/foo.js:95\ndispatch@http://code.jquery.com/blah.js:567\nfoo",
"<anonymous function: window.onload>([arguments not available])@http://example.com/blah/foo.js:95\n<anonymous function: dispatch>([arguments not available])@http://code.jquery.com/blah.js:567\nfoo",
"Error: my error\n at http://example.com/blah/foo.js:95\n at http://code.jquery.com/blah.js:567\nfoo",
"Error(\"my error\")@:0\u000a@http://example.com/blah/foo.js:95\u000a([object Object])@http://code.jquery.com/blah.js:567\u000afoo",
"Error: my error\n at onload (http://example.com/blah/foo.js:95:11)\n at dispatch (http://code.jquery.com/blah.js:567:8)\n at foo",
"Error: my sneaky error message has a URL in it at http://google.com/mean.js:987\n at onload (http://example.com/blah/foo.js:95:11)\n at dispatch (http://code.jquery.com/blah.js:567:8)\n at foo"
];
var badStacks = [
"blah",
"",
[],
{},
null,
undefined
];
var localExpected = "http://example.com/index.html",
remoteExpected = "http://example.com/blah/foo.js",
badExpected;
// Act & Assert
assert.strictEqual(localStacks.length, 8, "Local stacks x 8");
assert.strictEqual(_getCurrentScriptUrlFromErrorStack(localStacks[0]), localExpected, "Inline script: Chrome");
assert.strictEqual(_getCurrentScriptUrlFromErrorStack(localStacks[1]), localExpected, "Inline script: Safari 6.1+");
assert.strictEqual(_getCurrentScriptUrlFromErrorStack(localStacks[2]), localExpected, "Inline script: Safari 6.0");
assert.strictEqual(_getCurrentScriptUrlFromErrorStack(localStacks[3]), localExpected, "Inline script: Opera");
assert.strictEqual(_getCurrentScriptUrlFromErrorStack(localStacks[4]), localExpected, "Inline script: PhantomJS");
assert.strictEqual(_getCurrentScriptUrlFromErrorStack(localStacks[5]), localExpected, "Inline script: Firefox 3.6");
assert.strictEqual(_getCurrentScriptUrlFromErrorStack(localStacks[6]), localExpected, "Inline script: IE 10.0");
assert.strictEqual(_getCurrentScriptUrlFromErrorStack(localStacks[7]), localExpected, "Inline script: SneakyError");
assert.strictEqual(remoteStacks.length, 8, "Remote stacks x 8");
assert.strictEqual(_getCurrentScriptUrlFromErrorStack(remoteStacks[0]), remoteExpected, "External script: Chrome");
assert.strictEqual(_getCurrentScriptUrlFromErrorStack(remoteStacks[1]), remoteExpected, "External script: Safari 6.1+");
assert.strictEqual(_getCurrentScriptUrlFromErrorStack(remoteStacks[2]), remoteExpected, "External script: Safari 6.0");
assert.strictEqual(_getCurrentScriptUrlFromErrorStack(remoteStacks[3]), remoteExpected, "External script: Opera");
assert.strictEqual(_getCurrentScriptUrlFromErrorStack(remoteStacks[4]), remoteExpected, "External script: PhantomJS");
assert.strictEqual(_getCurrentScriptUrlFromErrorStack(remoteStacks[5]), remoteExpected, "External script: Firefox 3.6");
assert.strictEqual(_getCurrentScriptUrlFromErrorStack(remoteStacks[6]), remoteExpected, "External script: IE 10.0");
assert.strictEqual(_getCurrentScriptUrlFromErrorStack(remoteStacks[7]), remoteExpected, "External script: SneakyError");
assert.strictEqual(badStacks.length, 6, "Bad stacks x 6");
assert.strictEqual(_getCurrentScriptUrlFromErrorStack(badStacks[0]), badExpected, "Useless stack");
assert.strictEqual(_getCurrentScriptUrlFromErrorStack(badStacks[1]), badExpected, "Empty string");
assert.strictEqual(_getCurrentScriptUrlFromErrorStack(badStacks[2]), badExpected, "Array");
assert.strictEqual(_getCurrentScriptUrlFromErrorStack(badStacks[3]), badExpected, "Object");
assert.strictEqual(_getCurrentScriptUrlFromErrorStack(badStacks[4]), badExpected, "`null`");
assert.strictEqual(_getCurrentScriptUrlFromErrorStack(badStacks[5]), badExpected, "`undefined`");
});
test("`_getCurrentScriptUrlFromError` works", function(assert) {
assert.expect(4);
// Arrange
var actual1, actual2, actual3, actual4;
var expected = "http://example.com/blah/foo.js";
var _sourceUrl, _fileName, _stack;
// Do NOT inherit from the real `Error` definition
_Error = function() {
this.sourceURL = _sourceUrl;
this.fileName = _fileName;
this.stack = _stack;
};
// Act
_sourceUrl = expected;
_fileName = undefined;
_stack = undefined;
actual1 = _getCurrentScriptUrlFromError();
_sourceUrl = undefined;
_fileName = expected;
_stack = undefined;
actual2 = _getCurrentScriptUrlFromError();
_sourceUrl = undefined;
_fileName = undefined;
_stack = "Error: my uncaught error\n at " + expected + ":123:4\n at jQuery.event.dispatch (http://code.jquery.com/blah.js:123:0)\n at foo";
actual3 = _getCurrentScriptUrlFromError();
_sourceUrl = undefined;
_fileName = undefined;
_stack = undefined;
actual4 = _getCurrentScriptUrlFromError();
// Assert
assert.strictEqual(actual1, expected, "Current script derived from `err.sourceURL`");
assert.strictEqual(actual2, expected, "Current script derived from `err.fileName`");
assert.strictEqual(actual3, expected, "Current script derived from `err.stack`");
assert.strictEqual(actual4, undefined, "Current script cannot be derived from the Error");
});
test("`_getCurrentScriptUrl` works", function(assert) {
assert.expect(9);
// Arrange
var actual1, actual2, actual3, actual4, actual5, actual6, actual7, actual8, actual9;
var expected1, expected2, expected3, expected4, expected5, expected6, expected7, expected8, expected9;
expected1 = expected2 = expected3 = expected4 = expected5 = "http://example.com/blah/foo/bar.js";
// Arrange & Act
_document = {
currentScript: {
src: "http://example.com/blah/foo/bar.js"
}
};
_getCurrentScriptUrlFromError = function() {};
actual1 = _getCurrentScriptUrl();
_document = {
getElementsByTagName: function(/* tagName */) {
return [
{ src: "http://example.com/blah/foo/bar.js" }
];
}
};
actual2 = _getCurrentScriptUrl();
_document = {
getElementsByTagName: function(/* tagName */) {
return [
{ src: "http://example.com/blah/foo.js", readyState: "complete" },
{ src: "http://example.com/blah/foo/bar.js", readyState: "interactive" }
];
}
};
actual3 = _getCurrentScriptUrl();
_document = {
readyState: "loading",
getElementsByTagName: function(/* tagName */) {
return [
{ src: "http://example.com/blah/foo.js" },
{ src: "http://example.com/blah/wat.js" },
{ src: "http://example.com/blah/foo/bar.js" }
];
}
};
actual4 = _getCurrentScriptUrl();
_document = {
getElementsByTagName: function(/* tagName */) {
return [
{ src: "http://example.com/blah/foo.js" },
{ src: "http://example.com/blah/wat.js" },
{ src: "http://example.com/blah/foo/bar.js" }
];
}
};
_getCurrentScriptUrlFromError = function() {
return "http://example.com/blah/foo/bar.js";
};
actual5 = _getCurrentScriptUrl();
_document = {
getElementsByTagName: function(/* tagName */) {
return [
{ src: "http://example.com/blah/foo.js" },
{ src: "http://example.com/blah/wat.js" }
];
}
};
_getCurrentScriptUrlFromError = function() {};
actual6 = _getCurrentScriptUrl();
_document = {
getElementsByTagName: function(/* tagName */) {
return [
{ src: "http://example.com/blah/foo.js" },
{ /* inline script */ },
{ src: "http://example.com/blah/wat.js" }
];
}
};
actual7 = _getCurrentScriptUrl();
_document = {
getElementsByTagName: function(/* tagName */) {
return [
{ src: "http://example.com/blah/foo.js" },
{ src: "http://example.com/blah/wat.js" },
{ /* inline script */ }
];
}
};
actual8 = _getCurrentScriptUrl();
_document = {
getElementsByTagName: function(/* tagName */) {
return [
{ /* inline script */ }
];
}
};
actual9 = _getCurrentScriptUrl();
assert.strictEqual(actual1, expected1, "Value from `document.currentScript`");
assert.strictEqual(actual2, expected2, "Value from the only script");
assert.strictEqual(actual3, expected3, "Value from `scripts[i].readyState === \"interactive\"`");
assert.strictEqual(actual4, expected4, "Value from last script while `document.readyState === \"loading\"");
assert.strictEqual(actual5, expected5, "Value from `_getCurrentScriptUrlFromError`");
assert.strictEqual(actual6, expected6, "No value can be confirmed");
assert.strictEqual(actual7, expected7, "No value can be confirmed as there is at least one inline script (middle)");
assert.strictEqual(actual8, expected8, "No value can be confirmed as there is at least one inline script (last)");
assert.strictEqual(actual9, expected9, "No value can be confirmed as the only script tag is an inline script");
});
test("`_getUnanimousScriptParentDir` works", function(assert) {
assert.expect(5);
// Arrange
var actual1, actual2, actual3, actual4, actual5;
var expected1, expected2, expected3, expected4, expected5;
var _scripts = [];
_document = {
getElementsByTagName: function(/* tagName */) {
return _scripts;
}
};
expected1 = "http://example.com/blah/";
// Arrange & Act
_scripts.length = 0;
_scripts.push.apply(_scripts, [
{ src: "http://example.com/blah/foo.js" },
{ src: "http://example.com/blah/wat.js" },
{ src: "http://example.com/blah/bar.js" }
]);
actual1 = _getUnanimousScriptParentDir();
_scripts.length = 0;
_scripts.push.apply(_scripts, [
{ src: "http://example.org/blah/foo.js" },
{ src: "http://example.net/blah/wat.js" },
{ src: "http://example.com/blah/bar.js" }
]);
actual2 = _getUnanimousScriptParentDir();
_scripts.length = 0;
_scripts.push.apply(_scripts, [
{ src: "http://example.com/blah/foo.js" },
{ src: "http://example.com/blah/wat.js" },
{ src: "http://example.com/blah/foo/bar.js" }
]);
actual3 = _getUnanimousScriptParentDir();
_scripts.length = 0;
_scripts.push.apply(_scripts, [
{ src: "http://example.com/blah/foo.js" },
{ /* inline script */ },
{ src: "http://example.com/blah/foo/bar.js" }
]);
actual4 = _getUnanimousScriptParentDir();
_scripts.length = 0;
_scripts.push.apply(_scripts, [
{ src: "http://example.com/blah/foo.js" },
{ src: "http://example.com/blah/wat.js" },
{ /* inline script */ }
]);
actual5 = _getUnanimousScriptParentDir();
// Assert
assert.strictEqual(actual1, expected1, "All script tags have the same parent directory");
assert.strictEqual(actual2, expected2, "Not all script tags have the same domains");
assert.strictEqual(actual3, expected3, "Not all script tags have the same parent directory");
assert.strictEqual(actual4, expected4, "Not all script tags have `src` URLs (middle)");
assert.strictEqual(actual5, expected5, "Not all script tags have `src` URLs (last)");
});
test("`_getDefaultSwfPath` works", function(assert) {
assert.expect(11);
// Arrange
var actual1, actual2, actual3, actual4, actual5, actual6, actual7, actual8, actual9, actual10, actual11;
var expected1, expected2, expected3, expected4, expected5, expected6, expected7, expected8, expected9, expected10, expected11;
expected1 = expected2 = expected3 = expected4 = expected5 = "http://example.com/blah/foo/ZeroClipboard.swf";
expected6 = "http://example.com/blah/ZeroClipboard.swf";
expected7 = expected8 = expected9 = expected10 = expected11 = "ZeroClipboard.swf";
// Arrange & Act
_document = {
currentScript: {
src: "http://example.com/blah/foo/bar.js"
}
};
actual1 = _getDefaultSwfPath();
_document = {
getElementsByTagName: function(/* tagName */) {
return [
{ src: "http://example.com/blah/foo/bar.js" }
];
}
};
actual2 = _getDefaultSwfPath();
_document = {
getElementsByTagName: function(/* tagName */) {
return [
{ src: "http://example.com/blah/foo.js", readyState: "complete" },
{ src: "http://example.com/blah/foo/bar.js", readyState: "interactive" }
];
}
};
actual3 = _getDefaultSwfPath();
_document = {
readyState: "loading",
getElementsByTagName: function(/* tagName */) {
return [
{ src: "http://example.com/blah/foo.js" },
{ src: "http://example.com/blah/wat.js" },
{ src: "http://example.com/blah/foo/bar.js" }
];
}
};
actual4 = _getDefaultSwfPath();
_document = {
getElementsByTagName: function(/* tagName */) {
return [
{ src: "http://example.com/blah/foo.js" },
{ src: "http://example.com/blah/wat.js" },
{ src: "http://example.com/blah/foo/bar.js" }
];
}
};
_getCurrentScriptUrlFromError = function() {
return "http://example.com/blah/foo/bar.js";
};
actual5 = _getDefaultSwfPath();
_document = {
getElementsByTagName: function(/* tagName */) {
return [
{ src: "http://example.com/blah/foo.js" },
{ src: "http://example.com/blah/wat.js" },
{ src: "http://example.com/blah/bar.js" }
];
}
};
_getCurrentScriptUrlFromError = function() {};
actual6 = _getDefaultSwfPath();
_document = {
getElementsByTagName: function(/* tagName */) {
return [
{ src: "http://example.org/blah/foo.js" },
{ src: "http://example.net/blah/wat.js" },
{ src: "http://example.com/blah/bar.js" }
];
}
};
actual7 = _getDefaultSwfPath();
_document = {
getElementsByTagName: function(/* tagName */) {
return [
{ src: "http://example.com/blah/foo.js" },
{ src: "http://example.com/blah/wat.js" },
{ src: "http://example.com/blah/foo/bar.js" }
];
}
};
actual8 = _getDefaultSwfPath();
_document = {
getElementsByTagName: function(/* tagName */) {
return [
{ src: "http://example.com/blah/foo.js" },
{ /* inline script */ },
{ src: "http://example.com/blah/foo/bar.js" }
];
}
};
actual9 = _getDefaultSwfPath();
_document = {
getElementsByTagName: function(/* tagName */) {
return [
{ src: "http://example.com/blah/foo.js" },
{ src: "http://example.com/blah/wat.js" },
{ /* inline script */ }
];
}
};
actual10 = _getDefaultSwfPath();
_document = {
getElementsByTagName: function(/* tagName */) {
return [
{ /* inline script */ }
];
}
};
actual11 = _getDefaultSwfPath();
assert.strictEqual(actual1, expected1, "Value derived from `document.currentScript`");
assert.strictEqual(actual2, expected2, "Value derived from the only script");
assert.strictEqual(actual3, expected3, "Value derived from `scripts[i].readyState === \"interactive\"`");
assert.strictEqual(actual4, expected4, "Value derived from last script while `document.readyState === \"loading\"");
assert.strictEqual(actual5, expected5, "Value derived from Error stack");
assert.strictEqual(actual6, expected6, "Value derived from confirming all scripts have the same parent directory");
assert.strictEqual(actual7, expected7, "No value can be confirmed due to differing script domains");
assert.strictEqual(actual8, expected8, "No value can be confirmed due to differing script parent directories");
assert.strictEqual(actual9, expected9, "No value can be confirmed due to the existence of inline scripts");
assert.strictEqual(actual10, expected10, "No value can be confirmed as the last script is an inline script");
assert.strictEqual(actual11, expected11, "No value can be confirmed as the only script is an inline script");
});
})(QUnit.module, QUnit.test);

View File

@@ -0,0 +1,28 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>ZeroClipboard unit tests: shared/private.js</title>
<link rel="stylesheet" href="../../node_modules/qunitjs/qunit/qunit.css">
<script src="../../node_modules/qunitjs/qunit/qunit.js"></script>
<script>
// Polyfill in future functionality: https://github.com/jquery/qunit/issues/490
if (!QUnit.assert.expect) {
QUnit.assert.expect = QUnit.expect;
}
// Require `expect` calls
QUnit.config.requireExpects = true;
// Prevent against Firefox/Firebug failing the global pollution check
var getInterface = null;
</script>
<script src="../../src/js/shared/state.js"></script>
<script src="../../src/js/shared/private.js"></script>
<script src="private.tests.js"></script>
</head>
<body>
<div id="qunit"></div>
<div id="qunit-fixture"></div>
</body>
</html>