Commit 918e9906 918e990687f8a43441bd3c0521cb6f002c6ae85f by Nicolas Perriault

merged with master

2 parents 789f60d0 c335de2e
CasperJS Changelog
==================
XXXX-XX-XX, v0.6.11
-------------------
- fixed [#132](https://github.com/n1k0/casperjs/issues/132) - added ability to include js/coffee files using a dedicated option when using the [`casper test` command](http://casperjs.org/testing.html)
- fixed [#140](https://github.com/n1k0/casperjs/issues/140) - `casper test` now resolves local paths urls
- fixed [#148](https://github.com/n1k0/casperjs/issues/148) - [`utils.isWebPage()`](http://casperjs.org/api.html#utils.isWebPage) was broken
- fixed [#149](https://github.com/n1k0/casperjs/issues/149) - [`ClientUtils.fill()`](http://casperjs.org/api.html#casper.fill) was searching elements globally
- fixed [#144](https://github.com/n1k0/casperjs/issues/144) - added a [`safeLogs` option](http://casperjs.org/api.html#casper.options) to blur password values in debug logs. **This option is set to `true` by default.**
- added [`Casper.userAgent()`](http://casperjs.org/api.html#casper.userAgent) to ease a more dynamic setting of user-agent string
- added [`Tester.assertTitleMatch()`](http://casperjs.org/api.html#tester.assertTitleMatch) method
- added experimental support of custom headers sending in outgoing request (refs [#137](https://github.com/n1k0/casperjs/issues/137) - PhantomJS 1.6 required)
- switched to more standard `.textContent` property to get a node text; this allows a better compatibility of the clientutils bookmarklet with non-webkit browsers
- casper modules now all use [javascript strict mode](http://www.nczonline.net/blog/2012/03/13/its-time-to-start-using-javascript-strict-mode/)
2012-06-04, v0.6.10
-------------------
......
......@@ -4,15 +4,15 @@ CasperJS is a navigation scripting & testing utility for [PhantomJS](http://www.
It eases the process of defining a full navigation scenario and provides useful
high-level functions, methods & syntaxic sugar for doing common tasks such as:
- defining & ordering [navigation steps](http://casperjs.org/#quickstart)
- [filling forms](http://casperjs.org/#phantom_Casper_fill)
- [clicking links](http://casperjs.org/#phantom_Casper_click)
- [capturing screenshots](http://casperjs.org/#phantom_Casper_captureSelector) of a page (or an area)
- [making assertions on remote DOM](http://casperjs.org/#phantom_Casper_Tester)
- [logging](http://casperjs.org/#logging) & [events](http://casperjs.org/#events-filters)
- [downloading base64](http://casperjs.org/#phantom_Casper_download) encoded resources, even binary ones
- defining & ordering [navigation steps](http://casperjs.org/quickstart.html)
- [filling forms](http://casperjs.org/api.html#casper.fill)
- [clicking links](http://casperjs.org/api.html#casper.click)
- [capturing screenshots](http://casperjs.org/api.html#casper.captureSelector) of a page (or an area)
- [making assertions on remote DOM](http://casperjs.org/api.html#tester)
- [logging](http://casperjs.org/logging.html) & [events](http://casperjs.org/events-filters.html)
- [downloading base64](http://casperjs.org/api.html#casper.download) encoded resources, even binary ones
- catching errors and react accordingly
- writing [functional test suites](http://casperjs.org/#testing), exporting results as JUnit XML (xUnit)
- writing [functional test suites](http://casperjs.org/testing.html), exporting results as JUnit XML (xUnit)
Browse the [sample examples repository](https://github.com/n1k0/casperjs/tree/master/samples).
Don't hesitate to pull request for any cool example of yours as well!
......
......@@ -48,6 +48,6 @@ CASPER_COMMAND.extend(CASPER_ARGS)
try:
os.execvp(CASPER_COMMAND[0], CASPER_COMMAND)
except OSError, err:
print('Fatal: %s; did you install phantomjs?' % err)
except OSError as err:
print(('Fatal: %s; did you install phantomjs?' % err))
sys.exit(1)
......
Subproject commit ead2191ceb086cd5665e18a822f72689d90a6c3d
Subproject commit 76cc32f262a3ef924a67f33bb17432e3a5c33e03
......
......@@ -28,6 +28,8 @@
*
*/
/*global CasperError console exports phantom require*/
var utils = require('utils');
/**
......@@ -38,6 +40,7 @@ var utils = require('utils');
* @return Object
*/
exports.parse = function parse(phantomArgs) {
"use strict";
var extract = {
args: [],
options: {},
......@@ -110,6 +113,7 @@ exports.parse = function parse(phantomArgs) {
* @return Mixed
*/
function castArgument(arg) {
"use strict";
if (arg.match(/^-?\d+$/)) {
return parseInt(arg, 10);
} else if (arg.match(/^-?\d+\.\d+$/)) {
......
......@@ -27,15 +27,21 @@
* DEALINGS IN THE SOFTWARE.
*
*/
/*global console escape exports NodeList window*/
(function(exports) {
exports.create = function create() {
return new this.ClientUtils();
"use strict";
exports.create = function create(options) {
return new this.ClientUtils(options);
};
/**
* Casper client-side helpers.
*/
exports.ClientUtils = function ClientUtils() {
exports.ClientUtils = function ClientUtils(options) {
// private members
var BASE64_ENCODE_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var BASE64_DECODE_CHARS = new Array(
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
......@@ -49,6 +55,9 @@
);
var SUPPORTED_SELECTOR_TYPES = ['css', 'xpath'];
// public members
this.options = options || {};
/**
* Clicks on the DOM element behind the provided selector.
*
......@@ -70,35 +79,35 @@
while (i < len) {
do {
c1 = BASE64_DECODE_CHARS[str.charCodeAt(i++) & 0xff];
} while (i < len && c1 == -1);
if (c1 == -1) {
} while (i < len && c1 === -1);
if (c1 === -1) {
break;
}
do {
c2 = BASE64_DECODE_CHARS[str.charCodeAt(i++) & 0xff];
} while (i < len && c2 == -1);
if (c2 == -1) {
} while (i < len && c2 === -1);
if (c2 === -1) {
break;
}
out += String.fromCharCode((c1 << 2) | ((c2 & 0x30) >> 4));
do {
c3 = str.charCodeAt(i++) & 0xff;
if (c3 == 61)
if (c3 === 61)
return out;
c3 = BASE64_DECODE_CHARS[c3];
} while (i < len && c3 == -1);
if (c3 == -1) {
} while (i < len && c3 === -1);
if (c3 === -1) {
break;
}
out += String.fromCharCode(((c2 & 0XF) << 4) | ((c3 & 0x3C) >> 2));
do {
c4 = str.charCodeAt(i++) & 0xff;
if (c4 == 61) {
if (c4 === 61) {
return out;
}
c4 = BASE64_DECODE_CHARS[c4];
} while (i < len && c4 == -1);
if (c4 == -1) {
} while (i < len && c4 === -1);
if (c4 === -1) {
break;
}
out += String.fromCharCode(((c3 & 0x03) << 6) | c4);
......@@ -117,14 +126,14 @@
var out = "", i = 0, len = str.length, c1, c2, c3;
while (i < len) {
c1 = str.charCodeAt(i++) & 0xff;
if (i == len) {
if (i === len) {
out += BASE64_ENCODE_CHARS.charAt(c1 >> 2);
out += BASE64_ENCODE_CHARS.charAt((c1 & 0x3) << 4);
out += "==";
break;
}
c2 = str.charCodeAt(i++);
if (i == len) {
if (i === len) {
out += BASE64_ENCODE_CHARS.charAt(c1 >> 2);
out += BASE64_ENCODE_CHARS.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4));
out += BASE64_ENCODE_CHARS.charAt((c2 & 0xF) << 2);
......@@ -165,7 +174,7 @@
var text = '', elements = this.findAll(selector);
if (elements && elements.length) {
Array.prototype.forEach.call(elements, function _forEach(element) {
text += element.innerText;
text += element.textContent || element.innerText;
});
}
return text;
......@@ -185,7 +194,7 @@
files: []
};
if (!(form instanceof HTMLElement) || typeof form === "string") {
__utils__.log("attempting to fetch form element from selector: '" + form + "'", "info");
this.log("attempting to fetch form element from selector: '" + form + "'", "info");
try {
form = this.findOne(form);
} catch (e) {
......@@ -203,7 +212,7 @@
if (!vals.hasOwnProperty(name)) {
continue;
}
var field = this.findAll('[name="' + name + '"]');
var field = this.findAll('[name="' + name + '"]', form);
var value = vals[name];
if (!field) {
out.errors.push('no field named "' + name + '" in form');
......@@ -229,16 +238,18 @@
/**
* Finds all DOM elements matching by the provided selector.
*
* @param String selector CSS3 selector
* @param String selector CSS3 selector
* @param HTMLElement|null scope Element to search child elements within
* @return NodeList|undefined
*/
this.findAll = function findAll(selector) {
this.findAll = function findAll(selector, scope) {
scope = scope || document;
try {
var pSelector = this.processSelector(selector);
if (pSelector.type === 'xpath') {
return this.getElementsByXPath(pSelector.path);
} else {
return document.querySelectorAll(pSelector.path);
return scope.querySelectorAll(pSelector.path);
}
} catch (e) {
this.log('findAll(): invalid selector provided "' + selector + '":' + e, "error");
......@@ -248,16 +259,18 @@
/**
* Finds a DOM element by the provided selector.
*
* @param String selector CSS3 selector
* @param String selector CSS3 selector
* @param HTMLElement|null scope Element to search child elements within
* @return HTMLElement|undefined
*/
this.findOne = function findOne(selector) {
this.findOne = function findOne(selector, scope) {
scope = scope || document;
try {
var pSelector = this.processSelector(selector);
if (pSelector.type === 'xpath') {
return this.getElementByXPath(pSelector.path);
} else {
return document.querySelector(pSelector.path);
return scope.querySelector(pSelector.path);
}
} catch (e) {
this.log('findOne(): invalid selector provided "' + selector + '":' + e, "error");
......@@ -462,8 +475,8 @@
* @param mixed value The field value to set
*/
this.setField = function setField(field, value) {
var fields, out;
value = value || "";
var logValue, fields, out;
value = logValue = (value || "");
if (field instanceof NodeList) {
fields = field;
field = fields[0];
......@@ -471,11 +484,15 @@
if (!field instanceof HTMLElement) {
this.log("Invalid field type; only HTMLElement and NodeList are supported", "error");
}
this.log('Set "' + field.getAttribute('name') + '" field value to ' + value, "debug");
if (this.options && this.options.safeLogs && field.getAttribute('type') === "password") {
// obfuscate password value
logValue = new Array(value.length + 1).join("*");
}
this.log('Set "' + field.getAttribute('name') + '" field value to ' + logValue, "debug");
try {
field.focus();
} catch (e) {
__utils__.log("Unable to focus() input field " + field.getAttribute('name') + ": " + e, "warning");
this.log("Unable to focus() input field " + field.getAttribute('name') + ": " + e, "warning");
}
var nodeName = field.nodeName.toLowerCase();
switch (nodeName) {
......@@ -544,7 +561,7 @@
try {
field.blur();
} catch (err) {
__utils__.log("Unable to blur() input field " + field.getAttribute('name') + ": " + err, "warning");
this.log("Unable to blur() input field " + field.getAttribute('name') + ": " + err, "warning");
}
return out;
};
......@@ -570,7 +587,4 @@
}
};
};
// silly "hack" to force having an instance available
exports.__utils__ = new exports.ClientUtils();
})(typeof exports === "object" ? exports : window);
......
......@@ -28,10 +28,13 @@
*
*/
/*global exports console require*/
var fs = require('fs');
var utils = require('utils');
exports.create = function create(type) {
"use strict";
if (!type) {
return;
}
......@@ -48,6 +51,7 @@ exports.create = function create(type) {
* (c) Fabien Potencier, Symfony project, MIT license
*/
var Colorizer = function Colorizer() {
"use strict";
var options = { bold: 1, underscore: 4, blink: 5, reverse: 7, conceal: 8 };
var foreground = { black: 30, red: 31, green: 32, yellow: 33, blue: 34, magenta: 35, cyan: 36, white: 37 };
var background = { black: 40, red: 41, green: 42, yellow: 43, blue: 44, magenta: 45, cyan: 46, white: 47 };
......@@ -104,7 +108,7 @@ var Colorizer = function Colorizer() {
if (typeof pad === "number" && text.length < pad) {
text += new Array(pad - text.length + 1).join(' ');
}
return "\033[" + codes.join(';') + 'm' + text + "\033[0m";
return "\u001b[" + codes.join(';') + 'm' + text + "\u001b[0m";
};
};
exports.Colorizer = Colorizer;
......@@ -114,6 +118,7 @@ exports.Colorizer = Colorizer;
*
*/
var Dummy = function Dummy() {
"use strict";
this.colorize = function colorize(text, styleName, pad) {
return text;
};
......
......@@ -28,9 +28,12 @@
*
*/
/*global CasperError console encodeURIComponent escape exports require*/
var utils = require('utils');
exports.create = function create(fn) {
"use strict";
return new FunctionArgsInjector(fn);
};
......@@ -40,6 +43,7 @@ exports.create = function create(fn) {
* FIXME: use new Function() instead of eval()
*/
var FunctionArgsInjector = function FunctionArgsInjector(fn) {
"use strict";
if (!utils.isFunction(fn)) {
throw new CasperError("FunctionArgsInjector() can only process functions");
}
......
......@@ -28,13 +28,17 @@
*
*/
/*global CasperError exports require*/
var utils = require('utils');
exports.create = function create(casper) {
"use strict";
return new Mouse(casper);
};
var Mouse = function Mouse(casper) {
"use strict";
if (!utils.isCasperObject(casper)) {
throw new CasperError('Mouse() needs a Casper instance');
}
......
......@@ -28,7 +28,7 @@
*
*/
/*global exports:false, phantom:false, require:false, CasperError:false*/
/*global CasperError exports phantom require*/
var fs = require('fs');
var events = require('events');
......@@ -55,6 +55,7 @@ var Tester = function Tester(casper, options) {
this.currentTestFile = null;
this.exporter = require('xunit').create();
this.includes = [];
this.running = false;
this.suites = [];
this.options = utils.mergeObjects({
......@@ -287,7 +288,7 @@ var Tester = function Tester(casper, options) {
standard: "Subject matches the provided pattern",
values: {
subject: subject,
pattern: pattern
pattern: pattern.toString()
}
});
};
......@@ -361,7 +362,7 @@ var Tester = function Tester(casper, options) {
*/
this.assertTextExists = this.assertTextExist = function assertTextExists(text, message) {
var textFound = (casper.evaluate(function _evaluate() {
return document.body.innerText;
return document.body.textContent || document.body.innerText;
}).indexOf(text) !== -1);
return this.assert(textFound, message, {
type: "assertTextExists",
......@@ -392,6 +393,25 @@ var Tester = function Tester(casper, options) {
};
/**
* Asserts that title of the remote page matched the provided pattern.
*
* @param RegExp pattern The pattern to test the title against
* @param String message Test description
* @return Object An assertion result object
*/
this.assertTitleMatch = this.assertTitleMatches = function assertTitleMatch(pattern, message) {
var currentTitle = casper.getTitle();
return this.assert(pattern.test(currentTitle), message, {
type: "assertTitle",
details: "Page title does not match the provided pattern",
values: {
subject: currentTitle,
pattern: pattern.toString()
}
});
};
/**
* Asserts that the provided subject is of the given type.
*
* @param mixed subject The value to test
......@@ -427,7 +447,7 @@ var Tester = function Tester(casper, options) {
standard: "Current url matches the provided pattern",
values: {
currentUrl: currentUrl,
pattern: pattern
pattern: pattern.toString()
}
});
};
......@@ -695,6 +715,9 @@ var Tester = function Tester(casper, options) {
this.runTest = function runTest(testFile) {
this.bar(f('Test file: %s', testFile), 'INFO_BAR');
this.running = true; // this.running is set back to false with done()
this.includes.forEach(function(include) {
phantom.injectJs(include);
});
this.exec(testFile);
};
......
This diff could not be displayed because it is too large.
......@@ -27,13 +27,15 @@
* DEALINGS IN THE SOFTWARE.
*
*/
/*global exports, phantom, require, CasperError*/
/*global CasperError console exports phantom require*/
var utils = require('utils');
var fs = require('fs');
exports.create = function create() {
"use strict";
return new this.XUnitExporter();
return new XUnitExporter();
};
/**
......
casper = require("casper").create
verbose: true
# If we don't set a limit, it could go on forever
upTo = ~~casper.cli.get(0) || 10
###
Fetch all <a> elements from the page and return
the ones which contains a href starting with 'http://'
###
searchLinks = ->
filter = Array::filter
map = Array::map
map.call filter.call(document.querySelectorAll("a"), (a) ->
(/^http:\/\/.*/i).test a.getAttribute("href")
), (a) ->
a.getAttribute "href"
# The base links array
links = [
"http://google.com/"
......@@ -23,10 +8,10 @@ links = [
"http://bing.com/"
]
# Just opens the page and prints the title
start = (link) ->
@start link, ->
@echo "Page title: #{ @getTitle() }"
currentLink = 0;
# If we don't set a limit, it could go on forever
upTo = ~~casper.cli.get(0) || 10
###
Get the links, and add them to the links array
......@@ -38,12 +23,22 @@ addLinks = (link) ->
@echo "#{found.length} links found on #{link}"
links = links.concat found
casper.start()
casper.then ->
@echo "Starting"
###
Fetch all <a> elements from the page and return
the ones which contains a href starting with 'http://'
###
searchLinks = ->
filter = Array::filter
map = Array::map
map.call filter.call(document.querySelectorAll("a"), (a) ->
(/^http:\/\/.*/i).test a.getAttribute("href")
), (a) ->
a.getAttribute "href"
currentLink = 0;
# Just opens the page and prints the title
start = (link) ->
@start link, ->
@echo "Page title: #{ @getTitle() }"
# As long as it has a next link, and is under the maximum limit, will keep running
check = ->
......@@ -57,4 +52,9 @@ check = ->
@echo "All done."
@exit()
casper.start()
casper.then ->
@echo "Starting"
casper.run check
......
......@@ -2,24 +2,6 @@ var casper = require("casper").create({
verbose: true
});
// If we don't set a limit, it could go on forever
var upTo = ~~casper.cli.get(0) || 10;
/*
Fetch all <a> elements from the page and return
the ones which contains a href starting with 'http://'
*/
var searchLinks = function() {
var filter, map;
filter = Array.prototype.filter;
map = Array.prototype.map;
return map.call(filter.call(document.querySelectorAll("a"), function(a) {
return /^http:\/\/.*/i.test(a.getAttribute("href"));
}), function(a) {
return a.getAttribute("href");
});
};
// The base links array
var links = [
"http://google.com/",
......@@ -27,30 +9,40 @@ var links = [
"http://bing.com/"
];
// Just opens the page and prints the title
var start = function(link) {
this.start(link, function() {
this.echo('Page title: ' + this.getTitle());
});
};
// If we don't set a limit, it could go on forever
var upTo = ~~casper.cli.get(0) || 10;
var currentLink = 0;
// Get the links, and add them to the links array
// (It could be done all in one step, but it is intentionally splitted)
var addLinks = function(link) {
function addLinks(link) {
this.then(function() {
var found = this.evaluate(searchLinks);
this.echo(found.length + " links found on " + link);
links = links.concat(found);
});
};
}
casper.start();
casper.then(function() {
this.echo("Starting");
});
// Fetch all <a> elements from the page and return
// the ones which contains a href starting with 'http://'
function searchLinks() {
var filter, map;
filter = Array.prototype.filter;
map = Array.prototype.map;
return map.call(filter.call(document.querySelectorAll("a"), function(a) {
return (/^http:\/\/.*/i).test(a.getAttribute("href"));
}), function(a) {
return a.getAttribute("href");
});
}
var currentLink = 0;
// Just opens the page and prints the title
function start(link) {
this.start(link, function() {
this.echo('Page title: ' + this.getTitle());
});
}
// As long as it has a next link, and is under the maximum limit, will keep running
function check() {
......@@ -64,6 +56,10 @@ function check() {
this.echo("All done.");
this.exit();
}
};
}
casper.start().then(function() {
this.echo("Starting");
});
casper.run(check);
......
......@@ -6,24 +6,47 @@ if (!phantom.casperLoaded) {
var fs = require('fs');
var utils = require('utils');
var f = utils.format;
var includes = [];
var tests = [];
var casper = require('casper').create({
exitOnError: false
});
// Options from cli
// local utils
function checkIncludeFile(include) {
var absInclude = fs.absolute(include.trim());
if (!fs.exists(absInclude)) {
casper.warn("%s file not found, can't be included", absInclude);
return;
}
if (!utils.isJsFile(absInclude)) {
casper.warn("%s is not a supported file type, can't be included", absInclude);
return;
}
if (fs.isDirectory(absInclude)) {
casper.warn("%s is a directory, can't be included", absInclude);
return;
}
if (tests.indexOf(include) > -1 || tests.indexOf(absInclude) > -1) {
casper.warn("%s is a test file, can't be included", absInclude);
return;
}
return absInclude;
}
// parse some options from cli
casper.options.verbose = casper.cli.get('direct') || false;
casper.options.logLevel = casper.cli.get('log-level') || "error";
// Overriding Casper.open to prefix all test urls
// overriding Casper.open to prefix all test urls
casper.setFilter('open.location', function(location) {
if (!/^http/.test(location)) {
return f('file://%s/%s', phantom.casperPath, location);
return f('file://%s/%s', fs.workingDirectory, location);
}
return location;
});
var tests = [];
// test paths are passed as args
if (casper.cli.args.length) {
tests = casper.cli.args.filter(function(path) {
return fs.isFile(path) || fs.isDirectory(path);
......@@ -33,8 +56,21 @@ if (casper.cli.args.length) {
casper.exit(1);
}
// includes handling
if (casper.cli.has('includes')) {
includes = casper.cli.get('includes').split(',').map(function(include) {
// we can't use filter() directly because of abspath transformation
return checkIncludeFile(include);
}).filter(function(include) {
return utils.isString(include);
});
casper.test.includes = utils.unique(includes);
}
// test suites completion listener
casper.test.on('tests.complete', function() {
this.renderResults(true, undefined, casper.cli.get('xunit') || undefined);
});
// run all the suites
casper.test.runSuites.apply(casper.test, tests);
......
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>CasperJS test form</title>
</head>
<body>
<form action="result.html" enctype="multipart/form-data">
<input type="text" name="email" placeholder="email" />
<input type="text" name="email" placeholder="email">
<input type="password" name="password" placeholder="password">
<textarea name="content"></textarea>
<select name="topic">
<option>foo</option>
<option value="bar">baz</option>
</select>
<input type="checkbox" name="check" />
<input type="radio" name="choice" value="yes"/>
<input type="radio" name="choice" value="no"/>
<input type="file" name="file"/>
<input type="checkbox" name="checklist[]" value="1" />
<input type="checkbox" name="checklist[]" value="2" />
<input type="checkbox" name="checklist[]" value="3" />
<input type="submit" name="submit" value="submit" />
<input type="checkbox" name="check">
<input type="radio" name="choice" value="yes">
<input type="radio" name="choice" value="no">
<input type="file" name="file">
<input type="checkbox" name="checklist[]" value="1">
<input type="checkbox" name="checklist[]" value="2">
<input type="checkbox" name="checklist[]" value="3">
<input type="submit" name="submit" value="submit">
</form>
</body>
</html>
......
<!DOCTYPE html>
<html>
<head>
<title>Multiple forms test</title>
</head>
<body>
<form name="f1">
<input type="hidden" name="f" value="f1">
<input type="text" name="yo">
</form>
<form name="f2">
<input type="hidden" name="f" value="f2">
<input type="text" name="yo">
</form>
</body>
</html>
function testUA(ua, match) {
casper.test.assertMatch(
ua, match, 'Default user agent matches ' + match
);
}
function fetchUA(request) {
testUA(request.headers.filter(function(header) {
return header.name === "User-Agent";
}).pop().value, /plop/);
}
testUA(casper.options.pageSettings.userAgent, /CasperJS/);
casper.start();
casper.userAgent('plop').on('resource.requested', fetchUA);
casper.thenOpen('tests/site/index.html');
casper.run(function() {
this.removeListener('resource.requested', fetchUA);
this.test.done();
});
var fs = require('fs');
var clientutils = require('clientutils').create();
var testCases = {
'an empty string': '',
'a word': 'plop',
'a null char': 'a\u0000',
'an utf8 string': 'ÀÁÃÄÅÇÈÉÊËÌÍÎÏÒÓÔÕÖÙÚÛÜÝàáâãäåçèéêëìíîïðòóôõöùúûüýÿ',
'song lyrics': ("Voilà l'été, j'aperçois le soleil\n" +
"Les nuages filent et le ciel s'éclaircit\n" +
"Et dans ma tête qui bourdonnent?\n" +
"Les abeilles!"),
'a file contents': fs.read(phantom.casperPath + '/tests/site/alert.html')
};
casper.test.comment('ClientUtils.encode()');
for (var what in testCases) {
var source = testCases[what];
var encoded = clientutils.encode(source);
casper.test.assertEquals(clientutils.decode(encoded), source, 'ClientUtils can encode and decode ' + what);
}
casper.test.done();
......@@ -2,6 +2,7 @@ casper.start('tests/site/form.html', function() {
this.test.comment('Casper.fill()');
this.fill('form[action="result.html"]', {
email: 'chuck@norris.com',
password: 'chuck',
content: 'Am watching thou',
check: true,
choice: 'no',
......@@ -13,6 +14,9 @@ casper.start('tests/site/form.html', function() {
return document.querySelector('input[name="email"]').value;
}, 'chuck@norris.com', 'Casper.fill() can fill an input[type=text] form field');
this.test.assertEvalEquals(function() {
return document.querySelector('input[name="password"]').value;
}, 'chuck', 'Casper.fill() can fill an input[type=password] form field');
this.test.assertEvalEquals(function() {
return document.querySelector('textarea[name="content"]').value;
}, 'Am watching thou', 'Casper.fill() can fill a textarea form field');
this.test.assertEvalEquals(function() {
......@@ -41,12 +45,25 @@ casper.start('tests/site/form.html', function() {
casper.then(function() {
this.test.comment('Form submitted');
this.test.assertUrlMatch(/email=chuck@norris.com/, 'Casper.fill() input[type=email] field was submitted');
this.test.assertUrlMatch(/password=chuck/, 'Casper.fill() input[type=password] field was submitted');
this.test.assertUrlMatch(/content=Am\+watching\+thou/, 'Casper.fill() textarea field was submitted');
this.test.assertUrlMatch(/check=on/, 'Casper.fill() input[type=checkbox] field was submitted');
this.test.assertUrlMatch(/choice=no/, 'Casper.fill() input[type=radio] field was submitted');
this.test.assertUrlMatch(/topic=bar/, 'Casper.fill() select field was submitted');
});
// multiple forms
casper.thenOpen('tests/site/multiple-forms.html', function() {
this.test.comment('Multiple forms');
this.fill('form[name="f2"]', {
yo: "ok"
}, true);
});
casper.then(function() {
this.test.assertUrlMatch(/\?f=f2&yo=ok$/, 'Casper.fill() handles multiple forms');
}),
casper.run(function() {
this.test.done();
});
......
var fs = require('fs');
var x = require('casper').selectXPath;
function fakeDocument(html) {
window.document.body.innerHTML = html;
}
(function(casper) {
casper.test.comment('ClientUtils.encode()');
var clientutils = require('clientutils').create();
var testCases = {
'an empty string': '',
'a word': 'plop',
'a null char': 'a\u0000',
'an utf8 string': 'ÀÁÃÄÅÇÈÉÊËÌÍÎÏÒÓÔÕÖÙÚÛÜÝàáâãäåçèéêëìíîïðòóôõöùúûüýÿ',
'song lyrics': ("Voilà l'été, j'aperçois le soleil\n" +
"Les nuages filent et le ciel s'éclaircit\n" +
"Et dans ma tête qui bourdonnent?\n" +
"Les abeilles!"),
'a file contents': fs.read(phantom.casperPath + '/tests/site/alert.html')
};
for (var what in testCases) {
var source = testCases[what];
var encoded = clientutils.encode(source);
casper.test.assertEquals(clientutils.decode(encoded), source, 'ClientUtils.encode() encodes and decodes ' + what);
}
})(casper);
(function(casper) {
casper.test.comment('ClientUtils.exists()');
var clientutils = require('clientutils').create();
fakeDocument('<ul class="foo"><li>bar</li><li>baz</li></ul>');
casper.test.assert(clientutils.exists('ul'), 'ClientUtils.exists() checks that an element exist');
casper.test.assertNot(clientutils.exists('ol'), 'ClientUtils.exists() checks that an element exist');
casper.test.assert(clientutils.exists('ul.foo li'), 'ClientUtils.exists() checks that an element exist');
// xpath
casper.test.assert(clientutils.exists(x('//ul')), 'ClientUtils.exists() checks that an element exist using XPath');
casper.test.assertNot(clientutils.exists(x('//ol')), 'ClientUtils.exists() checks that an element exist using XPath');
fakeDocument(null);
})(casper);
(function(casper) {
casper.test.comment('ClientUtils.findAll()');
var clientutils = require('clientutils').create();
fakeDocument('<ul class="foo"><li>bar</li><li>baz</li></ul>');
casper.test.assertType(clientutils.findAll('li'), 'nodelist', 'ClientUtils.findAll() can find matching DOM elements');
casper.test.assertEquals(clientutils.findAll('li').length, 2, 'ClientUtils.findAll() can find matching DOM elements');
casper.test.assertType(clientutils.findAll('ol'), 'nodelist', 'ClientUtils.findAll() can find matching DOM elements');
casper.test.assertEquals(clientutils.findAll('ol').length, 0, 'ClientUtils.findAll() can find matching DOM elements');
// scoped
var scope = clientutils.findOne('ul');
casper.test.assertType(clientutils.findAll('li', scope), 'nodelist', 'ClientUtils.findAll() can find matching DOM elements within a given scope');
fakeDocument(null);
})(casper);
(function(casper) {
casper.test.comment('ClientUtils.findOne()');
var clientutils = require('clientutils').create();
fakeDocument('<ul class="foo"><li>bar</li><li>baz</li></ul>');
casper.test.assertType(clientutils.findOne('ul'), 'htmlulistelement', 'ClientUtils.findOne() can find a matching DOM element');
casper.test.assertNot(clientutils.findOne('ol'), 'ClientUtils.findOne() can find a matching DOM element');
// scoped
var scope = clientutils.findOne('ul');
casper.test.assertType(clientutils.findAll('li', scope), 'nodelist', 'ClientUtils.findAll() can find matching DOM elements within a given scope');
casper.test.assertEquals(clientutils.findAll('li', scope).length, 2, 'ClientUtils.findAll() can find matching DOM elements within a given scope');
fakeDocument(null);
})(casper);
(function(casper) {
casper.test.comment('ClientUtils.processSelector()');
var clientutils = require('clientutils').create();
// CSS3 selector
var cssSelector = clientutils.processSelector('html body > ul.foo li');
casper.test.assertType(cssSelector, 'object', 'ClientUtils.processSelector() can process a CSS3 selector');
casper.test.assertEquals(cssSelector.type, 'css', 'ClientUtils.processSelector() can process a CSS3 selector');
casper.test.assertEquals(cssSelector.path, 'html body > ul.foo li', 'ClientUtils.processSelector() can process a CSS3 selector');
// XPath selector
var xpathSelector = clientutils.processSelector(x('//li[text()="blah"]'));
casper.test.assertType(xpathSelector, 'object', 'ClientUtils.processSelector() can process a XPath selector');
casper.test.assertEquals(xpathSelector.type, 'xpath', 'ClientUtils.processSelector() can process a XPath selector');
casper.test.assertEquals(xpathSelector.path, '//li[text()="blah"]', 'ClientUtils.processSelector() can process a XPath selector');
})(casper);
casper.test.done();
......@@ -96,6 +96,9 @@ casper.then(function() {
t.comment('Tester.assertTitle()');
t.assertTitle('CasperJS test index', 'Tester.assertTitle() works as expected');
t.comment('Tester.assertTitleMatch()');
t.assertTitleMatch(/test index/, 'Tester.assertTitleMatch() works as expected');
t.comment('Tester.assertType()');
t.assertType("plop", "string", "Tester.assertType() works as expected");
......
......@@ -29,6 +29,13 @@ t.comment('fillBlanks()');
}
})();
t.comment('isArray()');
(function() {
t.assertEquals(utils.isArray([]), true, 'isArray() checks for an Array');
t.assertEquals(utils.isArray({}), false, 'isArray() checks for an Array');
t.assertEquals(utils.isArray("foo"), false, 'isArray() checks for an Array');
})();
t.comment('isClipRect()');
(function() {
testCases = [
......@@ -44,6 +51,26 @@ t.comment('isClipRect()');
});
})();
t.comment('isObject()');
(function() {
t.assertEquals(utils.isObject({}), true, 'isObject() checks for an Object');
t.assertEquals(utils.isObject([]), true, 'isObject() checks for an Object');
t.assertEquals(utils.isObject(1), false, 'isObject() checks for an Object');
t.assertEquals(utils.isObject("1"), false, 'isObject() checks for an Object');
t.assertEquals(utils.isObject(function(){}), false, 'isObject() checks for an Object');
t.assertEquals(utils.isObject(new Function('return {};')()), true, 'isObject() checks for an Object');
t.assertEquals(utils.isObject(require('webpage').create()), true, 'isObject() checks for an Object');
t.assertEquals(utils.isObject(null), false, 'isObject() checks for an Object');
})();
t.comment('isWebPage()');
(function() {
var pageModule = require('webpage');
t.assertEquals(utils.isWebPage(pageModule), false, 'isWebPage() checks for a WebPage instance');
t.assertEquals(utils.isWebPage(pageModule.create()), true, 'isWebPage() checks for a WebPage instance');
t.assertEquals(utils.isWebPage(null), false, 'isWebPage() checks for a WebPage instance');
})();
t.comment('isJsFile()');
(function() {
testCases = {
......@@ -90,4 +117,29 @@ t.comment('mergeObjects()');
});
})();
t.comment('unique()');
(function() {
testCases = [
{
input: [1,2,3],
output: [1,2,3]
},
{
input: [1,2,3,2,1],
output: [1,2,3]
},
{
input: ["foo", "bar", "foo"],
output: ["foo", "bar"]
},
{
input: [],
output: []
}
];
testCases.forEach(function(testCase) {
t.assertEquals(utils.unique(testCase.input), testCase.output, 'unique() computes unique values of an array');
});
})();
t.done();
......