mirror of
https://github.com/zulip/zulip.git
synced 2025-11-08 07:52:19 +00:00
Update casperjs to 1.0.2.
(imported from commit 9e34b51c4588dce6419ea86024b2e8c06346a685)
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
"maxdepth": 3,
|
||||
"maxstatements": 15,
|
||||
"maxcomplexity": 7,
|
||||
"proto": true,
|
||||
"regexdash": true,
|
||||
"strict": true,
|
||||
"sub": true,
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- "master"
|
||||
- "1.0"
|
||||
before_script:
|
||||
- "npm install -g jshint"
|
||||
- "phantomjs --version"
|
||||
- "export PHANTOMJS_EXECUTABLE='phantomjs --local-to-remote-url-access=yes --ignore-ssl-errors=yes'"
|
||||
- "export DISPLAY=:99.0"
|
||||
- "sh -e /etc/init.d/xvfb start"
|
||||
script:
|
||||
- "DISPLAY=:99.0 ./bin/casperjs selftest"
|
||||
- "./bin/casperjs selftest"
|
||||
- "./bin/casperjs __selfcommandtest"
|
||||
after_script:
|
||||
- "jshint --config=.jshintconfig ."
|
||||
notifications:
|
||||
irc:
|
||||
channels:
|
||||
|
||||
@@ -1,6 +1,186 @@
|
||||
CasperJS Changelog
|
||||
==================
|
||||
|
||||
2013-02-08, v1.0.2
|
||||
------------------
|
||||
|
||||
- fixed [#375](https://github.com/n1k0/casperjs/pull/375) - Fixes a bug with getting form values for radio inputs, and introduces a minor optimization to avoid processing the same form fields more than once.
|
||||
- closed [#373](https://github.com/n1k0/casperjs/issues/373) - added RegExp support to `Casper.waitForText()`
|
||||
- fixed [#368](https://github.com/n1k0/casperjs/issues/368) - Remote JS error is thrown when a click target is missing after `click()`
|
||||
- merged PR [#357](https://github.com/n1k0/casperjs/pull/357) - fire the `input` event after setting input value (required to support [angular.js](http://angularjs.org/) apps)
|
||||
|
||||
2013-01-17, v1.0.1
|
||||
------------------
|
||||
|
||||
- fixed [#336](https://github.com/n1k0/casperjs/issues/336) - Test result duration may have an exotic value
|
||||
- Added `casper.mouse.doubleclick()`
|
||||
- fixed [#343](https://github.com/n1k0/casperjs/issues/343) - Better script checks
|
||||
- fixed an edge case with xunit export when `phantom.casperScript` may be not defined
|
||||
|
||||
2012-12-24, v1.0.0
|
||||
------------------
|
||||
|
||||
### Important Changes & Caveats
|
||||
|
||||
- PhantomJS 1.6.x support has been dropped. Both PhantomJS [1.7](http://phantomjs.org/release-1.7.html) & [1.8](http://phantomjs.org/release-1.8.html) will be supported.
|
||||
- the deprecated `injector` module has been removed from the codebase (RIP dude)
|
||||
- a [`1.0` maintenance branch](https://github.com/n1k0/casperjs/tree/1.0) has been created
|
||||
- CasperJS 1.1 development is now taking place on the `master` branch
|
||||
|
||||
### Bugfixes & enhancements
|
||||
|
||||
- fixed `page.initialized` event didn't get the initialized `WebPage` instance
|
||||
- fixed a bug preventing `Casper.options.onPageInitialized()` from being called
|
||||
- fixed [#215](https://github.com/n1k0/casperjs/issues/215) - fixed broken `--fail-fast` option creating an endless loop on error
|
||||
- fixed `Tester.renderFailureDetails()` which couldn't print failure details correctly in certain circumstances
|
||||
- fixed `Casper.getHTML()` wasn't retrieving active frame contents when using `Casper.withFrame()`
|
||||
- fixed [#327](https://github.com/n1k0/casperjs/issues/327) - event handler for `page.confirm` always returns true
|
||||
- merged PR [#322](https://github.com/n1k0/casperjs/pull/322) - Support number in `Casper.withFrame()`
|
||||
- fixed [#323](https://github.com/n1k0/casperjs/issues/323) - `thenEvaluate()` should be updated to take the same parameters as `evaluate()`, while maintaining backwards compatibility.
|
||||
- merged PR [#319](https://github.com/n1k0/casperjs/pull/319), fixed [#209](https://github.com/n1k0/casperjs/issues/209) - test duration has been added to XUnit XML result file.
|
||||
- `Casper.userAgent()` does not require the instance to be started anymore
|
||||
- dubious tests now have dedicated color & styling
|
||||
- added hint printing when a possible `casperjs` command call is detected
|
||||
|
||||
2012-12-14, v1.0.0-RC6
|
||||
----------------------
|
||||
|
||||
I'm still expecting a 1.0 stable for Christmas. Feedback: bring it on.
|
||||
|
||||
### Important Changes & Caveats
|
||||
|
||||
#### Added experimental support for frames
|
||||
|
||||
A minimal convenient API has been added to Casper in order to ease the switch of current page context:
|
||||
|
||||
```js
|
||||
casper.start('tests/site/frames.html', function() {
|
||||
this.test.assertTitle('CasperJS frameset');
|
||||
});
|
||||
|
||||
casper.withFrame('frame1', function() {
|
||||
this.test.assertTitle('CasperJS frame 1');
|
||||
});
|
||||
|
||||
casper.then(function() {
|
||||
this.test.assertTitle('CasperJS frameset');
|
||||
});
|
||||
```
|
||||
|
||||
#### Reverted to emulated mouse events
|
||||
|
||||
Native mouse events didn't play well with (i)frames, because the computed element coordinates of the clicked element were erroneous.
|
||||
|
||||
So programmatic mouse events are reintroduced back into this corrective RC until a better solution is found.
|
||||
|
||||
### Bugfixes & enhancements
|
||||
|
||||
- merged [#269](https://github.com/n1k0/casperjs/issues/269) - Windows Batch script: fixed unsupported spaces in path and argument splitting
|
||||
|
||||
2012-12-10, v1.0.0-RC5
|
||||
----------------------
|
||||
|
||||
I told you there won't be an 1.0.0-RC5? I lied. Expect 1.0 stable for Christmas, probably.
|
||||
|
||||
### Important Changes & Caveats
|
||||
|
||||
#### Casper.evaluate() signature compatibility with PhantomJS
|
||||
|
||||
`Casper.evaluate()` method signature is now compatible with PhantomJS' one, so you can now write:
|
||||
|
||||
```js
|
||||
casper.evaluate(function(a, b) {
|
||||
return a === "foo" && b === "bar";
|
||||
}, "foo", "bar"); // true
|
||||
```
|
||||
|
||||
The old way to pass arguments has been kept backward compatible in order not to break your existing scripts though:
|
||||
|
||||
```js
|
||||
casper.evaluate(function(a, b) {
|
||||
return a === "foo" && b === "bar";
|
||||
}, {a: "foo", b: "bar"}); // true
|
||||
```
|
||||
|
||||
#### Specification of planned tests
|
||||
|
||||
In order to check that every planned test has actuall been executed, a new optional `planned` parameter has been added to `Tester.done()`:
|
||||
|
||||
```js
|
||||
casper.test.assert(true);
|
||||
casper.test.assert(true);
|
||||
casper.test.assert(true);
|
||||
casper.test.done(4);
|
||||
```
|
||||
|
||||
Will trigger a failure:
|
||||
|
||||
```
|
||||
fail: 4 tests planned, 3 tests executed.
|
||||
```
|
||||
|
||||
That's especially useful in case a given test script is abruptly interrupted leaving you with no obvious way to know it and an erroneous success status.
|
||||
|
||||
The whole [CapserJS test suite](https://github.com/n1k0/casperjs/tree/master/tests/) has been migrated to use this new feature.
|
||||
|
||||
#### Experimental support for popups
|
||||
|
||||
PhantomJS 1.7 ships with support for new opened pages — aka popups. CasperJS can now wait for a popup to be opened and loaded to react accordingly using the new [`Casper.waitForPopup()`](http://casperjs.org/api.html#casper.waitForPopup) and [`Casper.withPopup()`](http://casperjs.org/api.html#casper.withPopup) methods:
|
||||
|
||||
```js
|
||||
casper.start('http://foo.bar/').then(function() {
|
||||
this.test.assertTitle('Main page title');
|
||||
this.clickLabel('Open me a popup');
|
||||
});
|
||||
|
||||
// this will wait for the popup to be opened and loaded
|
||||
casper.waitForPopup(/popup\.html$/, function() {
|
||||
this.test.assertEquals(this.popups.length, 1);
|
||||
});
|
||||
|
||||
// this will set the popup DOM as the main active one only for time the
|
||||
// step closure being executed
|
||||
casper.withPopup(/popup\.html$/, function() {
|
||||
this.test.assertTitle('Popup title');
|
||||
});
|
||||
|
||||
// next step will automatically revert the current page to the initial one
|
||||
casper.then(function() {
|
||||
this.test.assertTitle('Main page title');
|
||||
});
|
||||
```
|
||||
|
||||
#### `Casper.mouseEvent()` now uses native events for most operations
|
||||
|
||||
Native mouse events from PhantomJS bring a far more accurate behavior.
|
||||
|
||||
Also, `Casper.mouseEvent()` will now directly trigger an error on failure instead of just logging an `error` event.
|
||||
|
||||
### Bugfixes & enhancements
|
||||
|
||||
- fixed [#308](https://github.com/n1k0/casperjs/issues/308) & [#309](https://github.com/n1k0/casperjs/issues/309) - proper module error backtraces
|
||||
- fixed [#306](https://github.com/n1k0/casperjs/issues/306) - Raise an explicit error on invalid test path
|
||||
- fixed [#300](https://github.com/n1k0/casperjs/issues/300) - Ensure that `findOne()` and `findAll()` observe the scope for XPath expressions, not just when passed CSS selectors
|
||||
- fixed [#294](https://github.com/n1k0/casperjs/issues/294) - Automatically fail test on any runtime error or timeout
|
||||
- fixed [#281](https://github.com/n1k0/casperjs/issues/281) - `Casper.evaluate()` should take an array as context not object
|
||||
- fixed [#266](https://github.com/n1k0/casperjs/issues/266) - Fix `tester` module and its self tests
|
||||
- fixed [#268](https://github.com/n1k0/casperjs/issues/266) - Wrong message on step timeout
|
||||
- fixed [#215](https://github.com/n1k0/casperjs/issues/215) - added a `--fail-fast` option to the `casper test` command, in order to terminate a test suite execution as soon as any failure is encountered
|
||||
- fixed [#274](https://github.com/n1k0/casperjs/issues/274) - some headers couldn't be set
|
||||
- fixed [#277](https://github.com/n1k0/casperjs/issues/277) - multiline support in `ClientUtils.echo()`
|
||||
- fixed [#282](https://github.com/n1k0/casperjs/issues/282) - added support for remote client scripts loading with a new `remoteScripts` casper option
|
||||
- fixed [#290](https://github.com/n1k0/casperjs/issues/#290) - add a simplistic RPM spec file to make it easier to (un)install casperjs
|
||||
- fixed [`utils.betterTypeOf()`](http://casperjs.org/api.html#casper.betterTypeOf) to properly handle `undefined` and `null` values
|
||||
- fixed `Casper.die()` and `Casper.evaluateOrDie()` were not printing the error onto the console
|
||||
- added JSON support to `require()`
|
||||
- added [`Tester.assertTruthy()`](http://casperjs.org/api.html#tester.assertTruthy) and [`Tester.assertFalsy()`](http://casperjs.org/api.html#tester.assertFalsy)
|
||||
- added [`Casper.sendKeys()`](http://casperjs.org/api.html#casper.sendKeys) to send native keyboard events to the element matching a given selector
|
||||
- added [`Casper.getFormValues()`](http://casperjs.org/api.html#casper.getFormValues) to check for the field values of a given form
|
||||
- added [`Tester.assertTextDoesntExist()`](http://casperjs.org/api.html#tester.assertTextDoesntExist)
|
||||
- added `Tester.assertFalse()` as an alias of `Tester.assertNot()`
|
||||
- added `page.resource.requested` and `page.resource.received` events
|
||||
- added [`translate.js`](https://github.com/n1k0/casperjs/tree/master/samples/translate.js) and [`translate.coffee`](https://github.com/n1k0/casperjs/tree/master/samples/translate.coffee) samples
|
||||
|
||||
2012-10-31, v1.0.0-RC4
|
||||
----------------------
|
||||
|
||||
|
||||
@@ -3,44 +3,51 @@
|
||||
You can check out the [contribution graphs on github](https://github.com/n1k0/casperjs/graphs/contributors).
|
||||
|
||||
```
|
||||
$ git shortlog -s -n
|
||||
689 Nicolas Perriault
|
||||
14 oncletom
|
||||
14 Brikou CARRE
|
||||
8 hannyu
|
||||
6 Chris Lorenzo
|
||||
4 pborreli
|
||||
4 nrabinowitz
|
||||
3 Andrew Childs
|
||||
3 Solomon White
|
||||
3 reina.sweet
|
||||
2 Reina Sweet
|
||||
2 Jason Funk
|
||||
2 Michael Geers
|
||||
2 Julien Moulin
|
||||
2 Donovan Hutchinson
|
||||
2 Clochix
|
||||
1 Marcel Duran
|
||||
1 Mathieu Agopian
|
||||
1 Mehdi Kabab
|
||||
1 Mikko Peltonen
|
||||
1 Pascal Borreli
|
||||
1 Rafael
|
||||
1 Rafael Garcia
|
||||
1 Raphaël Benitte
|
||||
1 Andrew de Andrade
|
||||
1 Tim Bunce
|
||||
1 Victor Yap
|
||||
1 alfetopito
|
||||
1 Christophe Benz
|
||||
1 jean-philippe serafin
|
||||
1 Chris Winters
|
||||
1 Ben Lowery
|
||||
1 Jan Pochyla
|
||||
1 Harrison Reiser
|
||||
1 Julian Gruber
|
||||
1 Justine Tunney
|
||||
1 KaroDidi
|
||||
1 Leandro Boscariol
|
||||
1 Maisons du monde
|
||||
$ git shortlog -s -n | cut -c8-
|
||||
Nicolas Perriault
|
||||
Brikou CARRE
|
||||
oncletom
|
||||
hannyu
|
||||
Chris Lorenzo
|
||||
Victor Yap
|
||||
nrabinowitz
|
||||
pborreli
|
||||
Rob Barreca
|
||||
Andrew Childs
|
||||
Solomon White
|
||||
reina.sweet
|
||||
Dave Lee
|
||||
Reina Sweet
|
||||
Elmar Langholz
|
||||
Jason Funk
|
||||
Donovan Hutchinson
|
||||
Julien Moulin
|
||||
Michael Geers
|
||||
Jan Schaumann
|
||||
Clochix
|
||||
Raphaël Benitte
|
||||
Tim Bunce
|
||||
alfetopito
|
||||
jean-philippe serafin
|
||||
snkashis
|
||||
Andrew de Andrade
|
||||
Ben Lowery
|
||||
Chris Winters
|
||||
Christophe Benz
|
||||
Harrison Reiser
|
||||
Jan Pochyla
|
||||
Jan-Martin Fruehwacht
|
||||
Julian Gruber
|
||||
Justin Slattery
|
||||
Justine Tunney
|
||||
KaroDidi
|
||||
Leandro Boscariol
|
||||
Maisons du monde
|
||||
Marcel Duran
|
||||
Mathieu Agopian
|
||||
Mehdi Kabab
|
||||
Mikko Peltonen
|
||||
Pascal Borreli
|
||||
Rafael
|
||||
Rafael Garcia
|
||||
```
|
||||
|
||||
@@ -1,22 +1,5 @@
|
||||
@ECHO OFF
|
||||
set CASPER_PATH=%~dp0..\
|
||||
set CASPER_BIN=%CASPER_PATH%bin\
|
||||
|
||||
set PHANTOMJS_NATIVE_ARGS=(--cookies-file --config --debug --disk-cache --ignore-ssl-errors --load-images --load-plugins --local-storage-path --local-storage-quota --local-to-remote-url-access --max-disk-cache-size --output-encoding --proxy --proxy-auth --proxy-type --remote-debugger-port --remote-debugger-autorun --script-encoding --web-security)
|
||||
|
||||
set PHANTOM_ARGS=
|
||||
set CASPER_ARGS=
|
||||
|
||||
:Loop
|
||||
if "%1"=="" goto Continue
|
||||
set IS_PHANTOM_ARG=0
|
||||
for %%i in %PHANTOMJS_NATIVE_ARGS% do (
|
||||
if "%%i"=="%1" set IS_PHANTOM_ARG=1
|
||||
)
|
||||
if %IS_PHANTOM_ARG%==0 set CASPER_ARGS=%CASPER_ARGS% %1
|
||||
if %IS_PHANTOM_ARG%==1 set PHANTOM_ARGS=%PHANTOM_ARGS% %1
|
||||
shift
|
||||
goto Loop
|
||||
:Continue
|
||||
|
||||
call phantomjs%PHANTOM_ARGS% %CASPER_BIN%bootstrap.js --casper-path=%CASPER_PATH% --cli%CASPER_ARGS%
|
||||
set CASPER_PATH=%~dp0..
|
||||
set CASPER_BIN=%CASPER_PATH%\bin\
|
||||
set ARGV=%*
|
||||
call phantomjs "%CASPER_BIN%bootstrap.js" --casper-path="%CASPER_PATH%" --cli %ARGV%
|
||||
80
zephyr/tests/frontend/casperjs/bin/bootstrap.js
vendored
80
zephyr/tests/frontend/casperjs/bin/bootstrap.js
vendored
@@ -33,14 +33,21 @@
|
||||
|
||||
if (!phantom) {
|
||||
console.error('CasperJS needs to be executed in a PhantomJS environment http://phantomjs.org/');
|
||||
phantom.exit(1);
|
||||
}
|
||||
|
||||
if (phantom.version.major === 1 && phantom.version.minor < 6) {
|
||||
console.error('CasperJS needs at least PhantomJS v1.6.0 or later.');
|
||||
if (phantom.version.major === 1 && phantom.version.minor < 7) {
|
||||
console.error('CasperJS needs at least PhantomJS v1.7 or later.');
|
||||
phantom.exit(1);
|
||||
} else {
|
||||
try {
|
||||
bootstrap(window);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
(e.stackArray || []).forEach(function(entry) {
|
||||
console.error(' In ' + entry.sourceURL + ':' + entry.line);
|
||||
});
|
||||
phantom.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Polyfills
|
||||
@@ -106,10 +113,13 @@ function patchRequire(require, requireDirs) {
|
||||
fileGuesses.push.apply(fileGuesses, [
|
||||
testPath,
|
||||
testPath + '.js',
|
||||
testPath + '.json',
|
||||
testPath + '.coffee',
|
||||
fs.pathJoin(testPath, 'index.js'),
|
||||
fs.pathJoin(testPath, 'index.json'),
|
||||
fs.pathJoin(testPath, 'index.coffee'),
|
||||
fs.pathJoin(testPath, 'lib', fs.basename(testPath) + '.js'),
|
||||
fs.pathJoin(testPath, 'lib', fs.basename(testPath) + '.json'),
|
||||
fs.pathJoin(testPath, 'lib', fs.basename(testPath) + '.coffee')
|
||||
]);
|
||||
});
|
||||
@@ -120,16 +130,25 @@ function patchRequire(require, requireDirs) {
|
||||
}
|
||||
}
|
||||
if (!file) {
|
||||
throw new Error("CasperJS couldn't find module " + path);
|
||||
throw new window.CasperError("CasperJS couldn't find module " + path);
|
||||
}
|
||||
if (file in requireCache) {
|
||||
return requireCache[file].exports;
|
||||
}
|
||||
if (/\.json/i.test(file)) {
|
||||
var parsed = JSON.parse(fs.read(file));
|
||||
requireCache[file] = parsed;
|
||||
return parsed;
|
||||
}
|
||||
var scriptCode = (function getScriptCode(file) {
|
||||
var scriptCode = fs.read(file);
|
||||
if (/\.coffee$/i.test(file)) {
|
||||
/*global CoffeeScript*/
|
||||
try {
|
||||
scriptCode = CoffeeScript.compile(scriptCode);
|
||||
} catch (e) {
|
||||
throw new Error('Unable to compile coffeescript:' + e);
|
||||
}
|
||||
}
|
||||
return scriptCode;
|
||||
})(file);
|
||||
@@ -137,8 +156,14 @@ function patchRequire(require, requireDirs) {
|
||||
try {
|
||||
fn(file, _require, module, module.exports);
|
||||
} catch (e) {
|
||||
var error = new window.CasperError('__mod_error(' + path + '):: ' + e);
|
||||
var error = new window.CasperError('__mod_error(' + path + ':' + e.line + '):: ' + e);
|
||||
error.file = file;
|
||||
error.line = e.line;
|
||||
error.stack = e.stack;
|
||||
error.stackArray = JSON.parse(JSON.stringify(e.stackArray));
|
||||
if (error.stackArray.length > 0) {
|
||||
error.stackArray[0].sourceURL = file;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
requireCache[file] = module;
|
||||
@@ -150,9 +175,20 @@ function patchRequire(require, requireDirs) {
|
||||
|
||||
function bootstrap(global) {
|
||||
"use strict";
|
||||
|
||||
var phantomArgs = require('system').args;
|
||||
|
||||
/**
|
||||
* Hooks in default phantomjs error handler to print a hint when a possible
|
||||
* casperjs command misuse is detected.
|
||||
*
|
||||
*/
|
||||
phantom.onError = function onPhantomError(msg, trace) {
|
||||
phantom.defaultErrorHandler.apply(phantom, arguments);
|
||||
if (msg.indexOf("ReferenceError: Can't find variable: casper") === 0) {
|
||||
console.error('Hint: you may want to use the `casperjs test` command.');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Loads and initialize the CasperJS environment.
|
||||
*/
|
||||
@@ -230,7 +266,7 @@ function bootstrap(global) {
|
||||
throw new global.CasperError('Cannot read package file contents: ' + e);
|
||||
}
|
||||
parts = pkg.version.trim().split(".");
|
||||
if (parts < 3) {
|
||||
if (parts.length < 3) {
|
||||
throw new global.CasperError("Invalid version number");
|
||||
}
|
||||
patchPart = parts[2].split('-');
|
||||
@@ -264,20 +300,21 @@ function bootstrap(global) {
|
||||
*/
|
||||
phantom.initCasperCli = function initCasperCli() {
|
||||
var fs = require("fs");
|
||||
var baseTestsPath = fs.pathJoin(phantom.casperPath, 'tests');
|
||||
|
||||
if (!!phantom.casperArgs.options.version) {
|
||||
console.log(phantom.casperVersion.toString());
|
||||
phantom.exit(0);
|
||||
return phantom.exit();
|
||||
} else if (phantom.casperArgs.get(0) === "test") {
|
||||
phantom.casperScript = fs.absolute(fs.pathJoin(phantom.casperPath, 'tests', 'run.js'));
|
||||
phantom.casperScript = fs.absolute(fs.pathJoin(baseTestsPath, 'run.js'));
|
||||
phantom.casperTest = true;
|
||||
phantom.casperArgs.drop("test");
|
||||
} else if (phantom.casperArgs.get(0) === "selftest") {
|
||||
phantom.casperScript = fs.absolute(fs.pathJoin(phantom.casperPath, 'tests', 'run.js'));
|
||||
phantom.casperSelfTest = true;
|
||||
phantom.casperArgs.options.includes = fs.pathJoin(phantom.casperPath, 'tests', 'selftest.js');
|
||||
phantom.casperScript = fs.absolute(fs.pathJoin(baseTestsPath, 'run.js'));
|
||||
phantom.casperSelfTest = phantom.casperTest = true;
|
||||
phantom.casperArgs.options.includes = fs.pathJoin(baseTestsPath, 'selftest.js');
|
||||
if (phantom.casperArgs.args.length <= 1) {
|
||||
phantom.casperArgs.args.push(fs.pathJoin(phantom.casperPath, 'tests', 'suites'));
|
||||
phantom.casperArgs.args.push(fs.pathJoin(baseTestsPath, 'suites'));
|
||||
}
|
||||
phantom.casperArgs.drop("selftest");
|
||||
} else if (phantom.casperArgs.args.length === 0 || !!phantom.casperArgs.options.help) {
|
||||
@@ -287,25 +324,30 @@ function bootstrap(global) {
|
||||
phantom.casperVersion.toString(),
|
||||
phantom.casperPath, phantomVersion));
|
||||
console.log(fs.read(fs.pathJoin(phantom.casperPath, 'bin', 'usage.txt')));
|
||||
phantom.exit(0);
|
||||
return phantom.exit(0);
|
||||
}
|
||||
|
||||
|
||||
if (!phantom.casperScript) {
|
||||
phantom.casperScript = phantom.casperArgs.get(0);
|
||||
}
|
||||
|
||||
if (phantom.casperScript) {
|
||||
if (!fs.isFile(phantom.casperScript)) {
|
||||
console.error('Unable to open file: ' + phantom.casperScript);
|
||||
phantom.exit(1);
|
||||
} else {
|
||||
return phantom.exit(1);
|
||||
}
|
||||
|
||||
// filter out the called script name from casper args
|
||||
phantom.casperArgs.drop(phantom.casperScript);
|
||||
|
||||
// passed casperjs script execution
|
||||
phantom.injectJs(phantom.casperScript);
|
||||
var injected = false;
|
||||
try {
|
||||
injected = phantom.injectJs(phantom.casperScript);
|
||||
} catch (e) {
|
||||
throw new global.CasperError('Error loading script ' + phantom.casperScript + ': ' + e);
|
||||
}
|
||||
if (!injected) {
|
||||
throw new global.CasperError('Unable to load script ' + phantom.casperScript + '; check file syntax');
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,8 +1,17 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
def test_cmd(cmd):
|
||||
try:
|
||||
return subprocess.check_output([__file__] + cmd.split(' '))
|
||||
except subprocess.CalledProcessError as err:
|
||||
sys.stderr.write('FAIL: %s\n' % ' '.join(err.cmd))
|
||||
sys.stderr.write(' %s\n' % err.output)
|
||||
sys.exit(1)
|
||||
|
||||
def resolve(path):
|
||||
if os.path.islink(path):
|
||||
@@ -32,9 +41,25 @@ PHANTOMJS_NATIVE_ARGS = [
|
||||
'web-security',
|
||||
]
|
||||
CASPER_ARGS = []
|
||||
CASPER_PATH = os.path.abspath(os.path.join(os.path.dirname(resolve(__file__)), '..'))
|
||||
PHANTOMJS_ARGS = []
|
||||
SYS_ARGS = sys.argv[1:]
|
||||
|
||||
for arg in sys.argv[1:]:
|
||||
if len(SYS_ARGS) and SYS_ARGS[0] == '__selfcommandtest':
|
||||
print('Starting Python executable tests...')
|
||||
pkg_version = json.loads(open('package.json').read()).get('version')
|
||||
scripts_path = os.path.join(CASPER_PATH, 'tests', 'commands')
|
||||
assert(test_cmd('--help').find(pkg_version) > -1)
|
||||
assert(test_cmd('--version').strip() == pkg_version)
|
||||
assert(test_cmd(os.path.join(scripts_path, 'script.js')) == 'it works\n')
|
||||
test_output = test_cmd('test --no-colors ' + os.path.join(scripts_path, 'mytest.js'))
|
||||
assert('PASS ok1' in test_output)
|
||||
assert('PASS ok2' in test_output)
|
||||
assert('PASS ok3' in test_output)
|
||||
print('Python executable tests passed.')
|
||||
sys.exit(0)
|
||||
|
||||
for arg in SYS_ARGS:
|
||||
found = False
|
||||
for native in PHANTOMJS_NATIVE_ARGS:
|
||||
if arg.startswith('--%s' % native):
|
||||
@@ -43,7 +68,6 @@ for arg in sys.argv[1:]:
|
||||
if not found:
|
||||
CASPER_ARGS.append(arg)
|
||||
|
||||
CASPER_PATH = os.path.abspath(os.path.join(os.path.dirname(resolve(__file__)), '..'))
|
||||
CASPER_COMMAND = os.environ.get('PHANTOMJS_EXECUTABLE', 'phantomjs').split(' ')
|
||||
CASPER_COMMAND.extend(PHANTOMJS_ARGS)
|
||||
CASPER_COMMAND.extend([
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
|
||||
Usage: casperjs [options] script.[js|coffee] [script argument [script argument ...]]
|
||||
casperjs [options] test [test path [test path ...]]
|
||||
casperjs [options] selftest
|
||||
|
||||
Options:
|
||||
|
||||
|
||||
@@ -19,5 +19,5 @@ high-level functions, methods & syntaxic sugar for doing common tasks."
|
||||
s.bindir = "rubybin"
|
||||
s.executables = [ "casperjs" ]
|
||||
s.license = "MIT"
|
||||
s.requirements = [ "PhantomJS v1.6" ]
|
||||
s.requirements = [ "PhantomJS v1.7" ]
|
||||
end
|
||||
|
||||
@@ -35,6 +35,7 @@ var events = require('events');
|
||||
var fs = require('fs');
|
||||
var http = require('http');
|
||||
var mouse = require('mouse');
|
||||
var pagestack = require('pagestack');
|
||||
var qs = require('querystring');
|
||||
var tester = require('tester');
|
||||
var utils = require('utils');
|
||||
@@ -75,7 +76,7 @@ exports.selectXPath = selectXPath;
|
||||
*/
|
||||
var Casper = function Casper(options) {
|
||||
"use strict";
|
||||
/*jshint maxstatements:30*/
|
||||
/*jshint maxstatements:40*/
|
||||
// init & checks
|
||||
if (!(this instanceof Casper)) {
|
||||
return new Casper(options);
|
||||
@@ -110,6 +111,7 @@ var Casper = function Casper(options) {
|
||||
localToRemoteUrlAccessEnabled: true,
|
||||
userAgent: defaultUserAgent
|
||||
},
|
||||
remoteScripts: [],
|
||||
stepTimeout: null,
|
||||
timeout: null,
|
||||
verbose: false,
|
||||
@@ -138,6 +140,7 @@ var Casper = function Casper(options) {
|
||||
this.mouse = mouse.create(this);
|
||||
this.page = null;
|
||||
this.pendingWait = false;
|
||||
this.popups = pagestack.create();
|
||||
this.requestUrl = 'about:blank';
|
||||
this.resources = [];
|
||||
this.result = {
|
||||
@@ -154,12 +157,14 @@ var Casper = function Casper(options) {
|
||||
this.initErrorHandler();
|
||||
|
||||
this.on('error', function(msg, backtrace) {
|
||||
if (msg === this.test.SKIP_MESSAGE) {
|
||||
return;
|
||||
}
|
||||
var c = this.getColorizer();
|
||||
var match = /^(.*): __mod_error(.*):: (.*)/.exec(msg);
|
||||
var notices = [];
|
||||
if (match && match.length === 4) {
|
||||
notices.push(' in module ' + match[2]);
|
||||
notices.push(' NOTICE: errors within modules cannot be backtraced yet.');
|
||||
msg = match[3];
|
||||
}
|
||||
console.error(c.colorize(msg, 'RED_BAR', 80));
|
||||
@@ -217,8 +222,8 @@ Casper.prototype.back = function back() {
|
||||
Casper.prototype.base64encode = function base64encode(url, method, data) {
|
||||
"use strict";
|
||||
return this.evaluate(function _evaluate(url, method, data) {
|
||||
return window.__utils__.getBase64(url, method, data);
|
||||
}, { url: url, method: method, data: data });
|
||||
return __utils__.getBase64(url, method, data);
|
||||
}, url, method, data);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -382,7 +387,14 @@ Casper.prototype.clear = function clear() {
|
||||
Casper.prototype.click = function click(selector) {
|
||||
"use strict";
|
||||
this.checkStarted();
|
||||
return this.mouseEvent('click', selector);
|
||||
var success = this.mouseEvent('click', selector);
|
||||
this.evaluate(function(selector) {
|
||||
var element = __utils__.findOne(selector);
|
||||
if (element) {
|
||||
element.focus();
|
||||
}
|
||||
}, selector);
|
||||
return success;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -402,6 +414,32 @@ Casper.prototype.clickLabel = function clickLabel(label, tag) {
|
||||
return this.click(selector);
|
||||
};
|
||||
|
||||
/**
|
||||
* Configures HTTP authentication parameters. Will try parsing auth credentials from
|
||||
* the passed location first, then check for configured settings if any.
|
||||
*
|
||||
* @param String location Requested url
|
||||
* @param Object settings Request settings
|
||||
* @return Casper
|
||||
*/
|
||||
Casper.prototype.configureHttpAuth = function configureHttpAuth(location, settings) {
|
||||
"use strict";
|
||||
var username, password, httpAuthMatch = location.match(/^https?:\/\/(.+):(.+)@/i);
|
||||
this.checkStarted();
|
||||
if (httpAuthMatch) {
|
||||
this.page.settings.userName = httpAuthMatch[1];
|
||||
this.page.settings.password = httpAuthMatch[2];
|
||||
} else if (utils.isObject(settings) && settings.username) {
|
||||
this.page.settings.userName = settings.username;
|
||||
this.page.settings.password = settings.password;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
this.emit('http.auth', username, password);
|
||||
this.log("Setting HTTP authentication for user " + username, "info");
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a step definition.
|
||||
*
|
||||
@@ -455,13 +493,13 @@ Casper.prototype.debugPage = function debugPage() {
|
||||
*/
|
||||
Casper.prototype.die = function die(message, status) {
|
||||
"use strict";
|
||||
this.checkStarted();
|
||||
this.result.status = "error";
|
||||
this.result.time = new Date().getTime() - this.startTime;
|
||||
if (!utils.isString(message) || !message.length) {
|
||||
message = "Suite explicitely interrupted without any message given.";
|
||||
}
|
||||
this.log(message, "error");
|
||||
this.echo(message, "ERROR");
|
||||
this.emit('die', message, status);
|
||||
if (utils.isFunction(this.options.onDie)) {
|
||||
this.options.onDie.call(this, this, message, status);
|
||||
@@ -549,13 +587,7 @@ Casper.prototype.echo = function echo(text, style, pad) {
|
||||
* document.querySelector('#username').value = username;
|
||||
* document.querySelector('#password').value = password;
|
||||
* document.querySelector('#submit').click();
|
||||
* }, {
|
||||
* username: 'Bazoonga',
|
||||
* password: 'baz00nga'
|
||||
* })
|
||||
*
|
||||
* FIXME: waiting for a patch of PhantomJS to allow direct passing of
|
||||
* arguments to the function.
|
||||
* }, 'Bazoonga', 'baz00nga');
|
||||
*
|
||||
* @param Function fn The function to be evaluated within current page DOM
|
||||
* @param Object context Object containing the parameters to inject into the function
|
||||
@@ -565,15 +597,27 @@ Casper.prototype.echo = function echo(text, style, pad) {
|
||||
Casper.prototype.evaluate = function evaluate(fn, context) {
|
||||
"use strict";
|
||||
this.checkStarted();
|
||||
// preliminary checks
|
||||
if (!utils.isFunction(fn) && !utils.isString(fn)) { // phantomjs allows functions defs as string
|
||||
throw new CasperError("evaluate() only accepts functions or strings");
|
||||
}
|
||||
// ensure client utils are always injected
|
||||
this.injectClientUtils();
|
||||
// function context
|
||||
context = utils.isObject(context) ? context : {};
|
||||
// the way this works is kept for BC with older casperjs versions
|
||||
var args = Object.keys(context).map(function(arg) {
|
||||
return context[arg];
|
||||
});
|
||||
return this.page.evaluate.apply(this.page, [fn].concat(args));
|
||||
if (arguments.length === 1) {
|
||||
return this.page.evaluate(fn);
|
||||
} else if (arguments.length === 2) {
|
||||
// check for closure signature if it matches context
|
||||
if (utils.isObject(context) && eval(fn).length === Object.keys(context).length) {
|
||||
context = utils.objectValues(context);
|
||||
} else {
|
||||
context = [context];
|
||||
}
|
||||
} else {
|
||||
// phantomjs-style signature
|
||||
context = [].slice.call(arguments).slice(1);
|
||||
}
|
||||
return this.page.evaluate.apply(this.page, [fn].concat(context));
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -606,8 +650,8 @@ Casper.prototype.exists = function exists(selector) {
|
||||
"use strict";
|
||||
this.checkStarted();
|
||||
return this.evaluate(function _evaluate(selector) {
|
||||
return window.__utils__.exists(selector);
|
||||
}, { selector: selector });
|
||||
return __utils__.exists(selector);
|
||||
}, selector);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -633,8 +677,8 @@ Casper.prototype.fetchText = function fetchText(selector) {
|
||||
"use strict";
|
||||
this.checkStarted();
|
||||
return this.evaluate(function _evaluate(selector) {
|
||||
return window.__utils__.fetchText(selector);
|
||||
}, { selector: selector });
|
||||
return __utils__.fetchText(selector);
|
||||
}, selector);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -653,11 +697,8 @@ Casper.prototype.fill = function fill(selector, vals, submit) {
|
||||
}
|
||||
this.emit('fill', selector, vals, submit);
|
||||
var fillResults = this.evaluate(function _evaluate(selector, values) {
|
||||
return window.__utils__.fill(selector, values);
|
||||
}, {
|
||||
selector: selector,
|
||||
values: vals
|
||||
});
|
||||
return __utils__.fill(selector, values);
|
||||
}, selector, vals);
|
||||
if (!fillResults) {
|
||||
throw new CasperError("Unable to fill form");
|
||||
} else if (fillResults.errors.length > 0) {
|
||||
@@ -681,17 +722,17 @@ Casper.prototype.fill = function fill(selector, vals, submit) {
|
||||
// Form submission?
|
||||
if (submit) {
|
||||
this.evaluate(function _evaluate(selector) {
|
||||
var form = window.__utils__.findOne(selector);
|
||||
var form = __utils__.findOne(selector);
|
||||
var method = (form.getAttribute('method') || "GET").toUpperCase();
|
||||
var action = form.getAttribute('action') || "unknown";
|
||||
window.__utils__.log('submitting form to ' + action + ', HTTP ' + method, 'info');
|
||||
__utils__.log('submitting form to ' + action + ', HTTP ' + method, 'info');
|
||||
if (typeof form.submit === "function") {
|
||||
form.submit();
|
||||
} else {
|
||||
// http://www.spiration.co.uk/post/1232/Submit-is-not-a-function
|
||||
form.submit.click();
|
||||
}
|
||||
}, { selector: selector });
|
||||
}, selector);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -732,7 +773,7 @@ Casper.prototype.getPageContent = function getPageContent() {
|
||||
this.checkStarted();
|
||||
var contentType = utils.getPropertyPath(this, 'currentResponse.contentType');
|
||||
if (!utils.isString(contentType)) {
|
||||
return this.page.content;
|
||||
return this.page.frameContent;
|
||||
}
|
||||
// for some reason webkit/qtwebkit will always enclose body contents within html tags
|
||||
var sanitizedHtml = this.evaluate(function checkHtml() {
|
||||
@@ -742,7 +783,7 @@ Casper.prototype.getPageContent = function getPageContent() {
|
||||
return __utils__.findOne('body pre').textContent.trim();
|
||||
}
|
||||
});
|
||||
return sanitizedHtml ? sanitizedHtml : this.page.content;
|
||||
return sanitizedHtml ? sanitizedHtml : this.page.frameContent;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -772,12 +813,13 @@ Casper.prototype.getCurrentUrl = function getCurrentUrl() {
|
||||
* @param String attribute The attribute name to lookup
|
||||
* @return String The requested DOM element attribute value
|
||||
*/
|
||||
Casper.prototype.getElementAttribute = Casper.prototype.getElementAttr = function getElementAttr(selector, attribute) {
|
||||
Casper.prototype.getElementAttribute =
|
||||
Casper.prototype.getElementAttr = function getElementAttr(selector, attribute) {
|
||||
"use strict";
|
||||
this.checkStarted();
|
||||
return this.evaluate(function _evaluate(selector, attribute) {
|
||||
return document.querySelector(selector).getAttribute(attribute);
|
||||
}, { selector: selector, attribute: attribute });
|
||||
}, selector, attribute);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -793,14 +835,31 @@ Casper.prototype.getElementBounds = function getElementBounds(selector) {
|
||||
throw new CasperError("No element matching selector found: " + selector);
|
||||
}
|
||||
var clipRect = this.evaluate(function _evaluate(selector) {
|
||||
return window.__utils__.getElementBounds(selector);
|
||||
}, { selector: selector });
|
||||
return __utils__.getElementBounds(selector);
|
||||
}, selector);
|
||||
if (!utils.isClipRect(clipRect)) {
|
||||
throw new CasperError('Could not fetch boundaries for element matching selector: ' + selector);
|
||||
}
|
||||
return clipRect;
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieves information about the node matching the provided selector.
|
||||
*
|
||||
* @param String|Objects selector CSS3/XPath selector
|
||||
* @return Object
|
||||
*/
|
||||
Casper.prototype.getElementInfo = function getElementInfo(selector) {
|
||||
"use strict";
|
||||
this.checkStarted();
|
||||
if (!this.exists(selector)) {
|
||||
throw new CasperError(f("Cannot get informations from %s: element not found.", selector));
|
||||
}
|
||||
return this.evaluate(function(selector) {
|
||||
return __utils__.getElementInfo(selector);
|
||||
}, selector);
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieves boundaries for all the DOM elements matching the provided DOM CSS3/XPath selector.
|
||||
*
|
||||
@@ -814,8 +873,25 @@ Casper.prototype.getElementsBounds = function getElementBounds(selector) {
|
||||
throw new CasperError("No element matching selector found: " + selector);
|
||||
}
|
||||
return this.evaluate(function _evaluate(selector) {
|
||||
return window.__utils__.getElementsBounds(selector);
|
||||
}, { selector: selector });
|
||||
return __utils__.getElementsBounds(selector);
|
||||
}, selector);
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieves a given form all of its field values.
|
||||
*
|
||||
* @param String selector A DOM CSS3/XPath selector
|
||||
* @return Object
|
||||
*/
|
||||
Casper.prototype.getFormValues = function(selector) {
|
||||
"use strict";
|
||||
this.checkStarted();
|
||||
if (!this.exists(selector)) {
|
||||
throw new CasperError(f('Form matching selector "%s" not found', selector));
|
||||
}
|
||||
return this.evaluate(function(selector) {
|
||||
return __utils__.getFormValues(selector);
|
||||
}, selector);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -833,19 +909,17 @@ Casper.prototype.getGlobal = function getGlobal(name) {
|
||||
result.value = JSON.stringify(window[name]);
|
||||
} catch (e) {
|
||||
var message = f("Unable to JSON encode window.%s: %s", name, e);
|
||||
window.__utils__.log(message, "error");
|
||||
__utils__.log(message, "error");
|
||||
result.error = message;
|
||||
}
|
||||
return result;
|
||||
}, {'name': name});
|
||||
if (typeof result !== "object") {
|
||||
}, name);
|
||||
if (!utils.isObject(result)) {
|
||||
throw new CasperError(f('Could not retrieve global value for "%s"', name));
|
||||
} else if ('error' in result) {
|
||||
throw new CasperError(result.error);
|
||||
} else if (utils.isString(result.value)) {
|
||||
return JSON.parse(result.value);
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -861,7 +935,7 @@ Casper.prototype.getHTML = function getHTML(selector, outer) {
|
||||
"use strict";
|
||||
this.checkStarted();
|
||||
if (!selector) {
|
||||
return this.page.content;
|
||||
return this.page.frameContent;
|
||||
}
|
||||
if (!this.exists(selector)) {
|
||||
throw new CasperError("No element matching selector found: " + selector);
|
||||
@@ -869,7 +943,7 @@ Casper.prototype.getHTML = function getHTML(selector, outer) {
|
||||
return this.evaluate(function getSelectorHTML(selector, outer) {
|
||||
var element = __utils__.findOne(selector);
|
||||
return outer ? element.outerHTML : element.innerHTML;
|
||||
}, { selector: selector, outer: !!outer });
|
||||
}, selector, !!outer);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -892,6 +966,7 @@ Casper.prototype.getTitle = function getTitle() {
|
||||
*/
|
||||
Casper.prototype.handleReceivedResource = function(resource) {
|
||||
"use strict";
|
||||
/*jshint maxstatements:20*/
|
||||
if (resource.stage !== "end") {
|
||||
return;
|
||||
}
|
||||
@@ -902,6 +977,7 @@ Casper.prototype.handleReceivedResource = function(resource) {
|
||||
this.currentHTTPStatus = null;
|
||||
this.currentResponse = undefined;
|
||||
if (utils.isHTTPResource(resource)) {
|
||||
this.emit('page.resource.received', resource);
|
||||
this.currentResponse = resource;
|
||||
this.currentHTTPStatus = resource.status;
|
||||
this.emit('http.status.' + resource.status, resource);
|
||||
@@ -931,7 +1007,7 @@ Casper.prototype.initErrorHandler = function initErrorHandler() {
|
||||
};
|
||||
|
||||
/**
|
||||
* Injects configured client scripts.
|
||||
* Injects configured local client scripts.
|
||||
*
|
||||
* @return Casper
|
||||
*/
|
||||
@@ -965,7 +1041,7 @@ Casper.prototype.injectClientUtils = function injectClientUtils() {
|
||||
"use strict";
|
||||
this.checkStarted();
|
||||
var clientUtilsInjected = this.page.evaluate(function() {
|
||||
return typeof window.__utils__ === "object";
|
||||
return typeof __utils__ === "object";
|
||||
});
|
||||
if (true === clientUtilsInjected) {
|
||||
return;
|
||||
@@ -984,6 +1060,32 @@ Casper.prototype.injectClientUtils = function injectClientUtils() {
|
||||
}.toString().replace('__options', JSON.stringify(this.options)));
|
||||
};
|
||||
|
||||
/**
|
||||
* Loads and include remote client scripts to current page.
|
||||
*
|
||||
* @return Casper
|
||||
*/
|
||||
Casper.prototype.includeRemoteScripts = function includeRemoteScripts() {
|
||||
"use strict";
|
||||
var numScripts = this.options.remoteScripts.length, loaded = 0;
|
||||
if (numScripts === 0) {
|
||||
return this;
|
||||
}
|
||||
this.waitStart();
|
||||
this.options.remoteScripts.forEach(function(scriptUrl) {
|
||||
this.log(f("Loading remote script: %s", scriptUrl), "debug");
|
||||
this.page.includeJs(scriptUrl, function() {
|
||||
loaded++;
|
||||
this.log(f("Remote script %s loaded", scriptUrl), "debug");
|
||||
if (loaded === numScripts) {
|
||||
this.log("All remote scripts loaded.", "debug");
|
||||
this.waitDone();
|
||||
}
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Logs a message.
|
||||
*
|
||||
@@ -1041,22 +1143,18 @@ Casper.prototype.mouseEvent = function mouseEvent(type, selector) {
|
||||
if (!this.exists(selector)) {
|
||||
throw new CasperError(f("Cannot dispatch %s event on nonexistent selector: %s", type, selector));
|
||||
}
|
||||
var eventSuccess = this.evaluate(function(type, selector) {
|
||||
if (this.evaluate(function(type, selector) {
|
||||
return window.__utils__.mouseEvent(type, selector);
|
||||
}, {
|
||||
type: type,
|
||||
selector: selector
|
||||
});
|
||||
if (!eventSuccess) {
|
||||
}, type, selector)) {
|
||||
return true;
|
||||
}
|
||||
// fallback onto native QtWebKit mouse events
|
||||
try {
|
||||
this.mouse.processEvent(type, selector);
|
||||
return this.mouse.processEvent(type, selector);
|
||||
} catch (e) {
|
||||
this.log(f("Couldn't emulate '%s' event on %s: %s", type, selector, e), "error");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1066,7 +1164,7 @@ Casper.prototype.mouseEvent = function mouseEvent(type, selector) {
|
||||
*
|
||||
* - String method: The HTTP method to use
|
||||
* - Object data: The data to use to perform the request, eg. {foo: 'bar'}
|
||||
* - Array headers: An array of request headers, eg. [{'Cache-Control': 'max-age=0'}]
|
||||
* - Object headers: Custom request headers object, eg. {'Cache-Control': 'max-age=0'}
|
||||
*
|
||||
* @param String location The url to open
|
||||
* @param Object settings The request settings (optional)
|
||||
@@ -1074,16 +1172,12 @@ Casper.prototype.mouseEvent = function mouseEvent(type, selector) {
|
||||
*/
|
||||
Casper.prototype.open = function open(location, settings) {
|
||||
"use strict";
|
||||
/*jshint maxstatements:30*/
|
||||
var baseCustomHeaders = this.page.customHeaders,
|
||||
customHeaders = settings && settings.headers || {};
|
||||
this.checkStarted();
|
||||
// settings validation
|
||||
if (!settings) {
|
||||
settings = {
|
||||
method: "get"
|
||||
};
|
||||
}
|
||||
if (!utils.isObject(settings)) {
|
||||
throw new CasperError("open(): request settings must be an Object");
|
||||
}
|
||||
settings = utils.isObject(settings) ? settings : {};
|
||||
settings.method = settings.method || "get";
|
||||
// http method
|
||||
// taken from https://github.com/ariya/phantomjs/blob/master/src/webpage.cpp#L302
|
||||
var methods = ["get", "head", "put", "post", "delete"];
|
||||
@@ -1101,28 +1195,21 @@ Casper.prototype.open = function open(location, settings) {
|
||||
// clean location
|
||||
location = utils.cleanUrl(location);
|
||||
// current request url
|
||||
this.configureHttpAuth(location, settings);
|
||||
this.requestUrl = this.filter('open.location', location) || location;
|
||||
// http auth
|
||||
if (settings.username && settings.password) {
|
||||
this.setHttpAuth(settings.username, settings.password);
|
||||
} else {
|
||||
var httpAuthMatch = location.match(/^https?:\/\/(.+):(.+)@/i);
|
||||
if (httpAuthMatch) {
|
||||
var httpAuth = {
|
||||
username: httpAuthMatch[1],
|
||||
password: httpAuthMatch[2]
|
||||
};
|
||||
this.setHttpAuth(httpAuth.username, httpAuth.password);
|
||||
}
|
||||
}
|
||||
this.emit('open', this.requestUrl, settings);
|
||||
this.log(f('opening url: %s, HTTP %s', this.requestUrl, settings.method.toUpperCase()), "debug");
|
||||
// reset resources
|
||||
this.resources = [];
|
||||
// custom headers
|
||||
this.page.customHeaders = utils.mergeObjects(utils.clone(baseCustomHeaders), customHeaders);
|
||||
// perfom request
|
||||
this.page.openUrl(this.requestUrl, {
|
||||
operation: settings.method,
|
||||
data: settings.data,
|
||||
headers: settings.headers
|
||||
data: settings.data
|
||||
}, this.page.settings);
|
||||
this.resources = [];
|
||||
// revert base custom headers
|
||||
this.page.customHeaders = baseCustomHeaders;
|
||||
return this;
|
||||
};
|
||||
|
||||
@@ -1203,8 +1290,7 @@ Casper.prototype.run = function run(onComplete, time) {
|
||||
"use strict";
|
||||
this.checkStarted();
|
||||
if (!this.steps || this.steps.length < 1) {
|
||||
this.log("No steps defined, aborting", "error");
|
||||
return this;
|
||||
throw new CasperError('No steps defined, aborting');
|
||||
}
|
||||
this.log(f("Running suite: %d step%s", this.steps.length, this.steps.length > 1 ? "s" : ""), "info");
|
||||
this.emit('run.start');
|
||||
@@ -1232,7 +1318,7 @@ Casper.prototype.runStep = function runStep(step) {
|
||||
if ((self.test.currentSuiteNum + "-" + self.step) === stepNum) {
|
||||
self.emit('step.timeout');
|
||||
if (utils.isFunction(self.options.onStepTimeout)) {
|
||||
self.options.onStepTimeout.call(self, self.options.onStepTimeout, stepNum);
|
||||
self.options.onStepTimeout.call(self, self.options.stepTimeout, stepNum);
|
||||
}
|
||||
}
|
||||
clearInterval(stepTimeoutCheckInterval);
|
||||
@@ -1251,22 +1337,53 @@ Casper.prototype.runStep = function runStep(step) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets HTTP authentication parameters.
|
||||
* Sends keys to given element.
|
||||
*
|
||||
* @param String username The HTTP_AUTH_USER value
|
||||
* @param String password The HTTP_AUTH_PW value
|
||||
* @param String selector A DOM CSS3 compatible selector
|
||||
* @param String keys A string representing the sequence of char codes to send
|
||||
* @param Object options Options
|
||||
* @return Casper
|
||||
*/
|
||||
Casper.prototype.sendKeys = function(selector, keys, options) {
|
||||
"use strict";
|
||||
this.checkStarted();
|
||||
options = utils.mergeObjects({
|
||||
eventType: 'keypress'
|
||||
}, options || {});
|
||||
var elemInfos = this.getElementInfo(selector),
|
||||
tag = elemInfos.nodeName.toLowerCase(),
|
||||
type = utils.getPropertyPath(elemInfos, 'attributes.type'),
|
||||
supported = ["color", "date", "datetime", "datetime-local", "email",
|
||||
"hidden", "month", "number", "password", "range", "search",
|
||||
"tel", "text", "time", "url", "week"];
|
||||
var isTextInput = false;
|
||||
if (tag === 'textarea' || (tag === 'input' && supported.indexOf(type) !== -1)) {
|
||||
// clicking on the input element brings it focus
|
||||
isTextInput = true;
|
||||
this.click(selector);
|
||||
}
|
||||
this.page.sendEvent(options.eventType, keys);
|
||||
if (isTextInput) {
|
||||
// remove the focus
|
||||
this.evaluate(function(selector) {
|
||||
__utils__.findOne(selector).blur();
|
||||
}, selector);
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets current WebPage instance the credentials for HTTP authentication.
|
||||
*
|
||||
* @param String username
|
||||
* @param String password
|
||||
* @return Casper
|
||||
*/
|
||||
Casper.prototype.setHttpAuth = function setHttpAuth(username, password) {
|
||||
"use strict";
|
||||
this.checkStarted();
|
||||
if (!utils.isString(username) || !utils.isString(password)) {
|
||||
throw new CasperError("Both username and password must be strings");
|
||||
}
|
||||
this.page.settings.userName = username;
|
||||
this.page.settings.password = password;
|
||||
this.emit('http.auth', username, password);
|
||||
this.log("Setting HTTP authentication for user " + username, "info");
|
||||
return this;
|
||||
};
|
||||
|
||||
@@ -1279,10 +1396,12 @@ Casper.prototype.setHttpAuth = function setHttpAuth(username, password) {
|
||||
*/
|
||||
Casper.prototype.start = function start(location, then) {
|
||||
"use strict";
|
||||
/*jshint maxstatements:30*/
|
||||
this.emit('starting');
|
||||
this.log('Starting...', "info");
|
||||
this.startTime = new Date().getTime();
|
||||
this.history = [];
|
||||
this.popups = pagestack.create();
|
||||
this.steps = [];
|
||||
this.step = 0;
|
||||
// Option checks
|
||||
@@ -1290,13 +1409,8 @@ Casper.prototype.start = function start(location, then) {
|
||||
this.log(f("Unknown log level '%d', defaulting to 'warning'", this.options.logLevel), "warning");
|
||||
this.options.logLevel = "warning";
|
||||
}
|
||||
// WebPage
|
||||
if (!utils.isWebPage(this.page)) {
|
||||
if (utils.isWebPage(this.options.page)) {
|
||||
this.page = this.options.page;
|
||||
} else {
|
||||
this.page = createPage(this);
|
||||
}
|
||||
this.page = this.mainPage = utils.isWebPage(this.options.page) ? this.options.page : createPage(this);
|
||||
}
|
||||
this.page.settings = utils.mergeObjects(this.page.settings, this.options.pageSettings);
|
||||
if (utils.isClipRect(this.options.clipRect)) {
|
||||
@@ -1305,8 +1419,7 @@ Casper.prototype.start = function start(location, then) {
|
||||
if (utils.isObject(this.options.viewportSize)) {
|
||||
this.page.viewportSize = this.options.viewportSize;
|
||||
}
|
||||
this.started = true;
|
||||
this.emit('started');
|
||||
// timeout handling
|
||||
if (utils.isNumber(this.options.timeout) && this.options.timeout > 0) {
|
||||
this.log(f("Execution timeout set to %dms", this.options.timeout), "info");
|
||||
setTimeout(function _check(self) {
|
||||
@@ -1316,10 +1429,12 @@ Casper.prototype.start = function start(location, then) {
|
||||
}
|
||||
}, this.options.timeout, this);
|
||||
}
|
||||
this.started = true;
|
||||
this.emit('started');
|
||||
if (utils.isString(location) && location.length > 0) {
|
||||
return this.thenOpen(location, utils.isFunction(then) ? then : this.createStep(function _step() {
|
||||
this.log("start page is loaded", "debug");
|
||||
}));
|
||||
}, {skipLog: true}));
|
||||
}
|
||||
return this;
|
||||
};
|
||||
@@ -1409,8 +1524,9 @@ Casper.prototype.thenClick = function thenClick(selector, then, fallbackToHref)
|
||||
Casper.prototype.thenEvaluate = function thenEvaluate(fn, context) {
|
||||
"use strict";
|
||||
this.checkStarted();
|
||||
var args = [fn].concat([].slice.call(arguments, 1));
|
||||
return this.then(function _step() {
|
||||
this.evaluate(fn, context);
|
||||
this.evaluate.apply(this, args);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1472,8 +1588,10 @@ Casper.prototype.toString = function toString() {
|
||||
*/
|
||||
Casper.prototype.userAgent = function userAgent(agent) {
|
||||
"use strict";
|
||||
this.checkStarted();
|
||||
this.options.pageSettings.userAgent = this.page.settings.userAgent = agent;
|
||||
this.options.pageSettings.userAgent = agent;
|
||||
if (this.started && this.page) {
|
||||
this.page.settings.userAgent = agent;
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
@@ -1510,8 +1628,8 @@ Casper.prototype.visible = function visible(selector) {
|
||||
"use strict";
|
||||
this.checkStarted();
|
||||
return this.evaluate(function _evaluate(selector) {
|
||||
return window.__utils__.visible(selector);
|
||||
}, { selector: selector });
|
||||
return __utils__.visible(selector);
|
||||
}, selector);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1617,6 +1735,28 @@ Casper.prototype.waitFor = function waitFor(testFx, then, onTimeout, timeout) {
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Waits for a popup page having its url matching the provided pattern to be opened
|
||||
* and loaded.
|
||||
*
|
||||
* @param String|RegExp urlPattern The popup url pattern
|
||||
* @param Function then The next step function (optional)
|
||||
* @param Function onTimeout Function to call on operation timeout (optional)
|
||||
* @param Number timeout Timeout in milliseconds (optional)
|
||||
* @return Casper
|
||||
*/
|
||||
Casper.prototype.waitForPopup = function waitForPopup(urlPattern, then, onTimeout, timeout) {
|
||||
"use strict";
|
||||
return this.waitFor(function() {
|
||||
try {
|
||||
this.popups.find(urlPattern);
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}, then, onTimeout, timeout);
|
||||
};
|
||||
|
||||
/**
|
||||
* Waits until a given resource is loaded
|
||||
*
|
||||
@@ -1656,20 +1796,24 @@ Casper.prototype.waitForSelector = function waitForSelector(selector, then, onTi
|
||||
};
|
||||
|
||||
/**
|
||||
* Waits until the page contains given HTML text.
|
||||
* Waits until the page contains given HTML text or matches a given RegExp.
|
||||
*
|
||||
* @param String text Text to wait for
|
||||
* @param String|RegExp pattern Text or RegExp to wait for
|
||||
* @param Function then The next step to perform (optional)
|
||||
* @param Function onTimeout A callback function to call on timeout (optional)
|
||||
* @param Number timeout The max amount of time to wait, in milliseconds (optional)
|
||||
* @return Casper
|
||||
*/
|
||||
Casper.prototype.waitForText = function(text, then, onTimeout, timeout) {
|
||||
Casper.prototype.waitForText = function(pattern, then, onTimeout, timeout) {
|
||||
"use strict";
|
||||
this.checkStarted();
|
||||
timeout = timeout ? timeout : this.options.waitTimeout;
|
||||
return this.waitFor(function _check() {
|
||||
return this.getPageContent().indexOf(text) !== -1;
|
||||
var content = this.getPageContent();
|
||||
if (utils.isRegExp(pattern)) {
|
||||
return pattern.test(content);
|
||||
}
|
||||
return content.indexOf(pattern) !== -1;
|
||||
}, then, onTimeout, timeout);
|
||||
};
|
||||
|
||||
@@ -1730,6 +1874,73 @@ Casper.prototype.waitWhileVisible = function waitWhileVisible(selector, then, on
|
||||
}, then, onTimeout, timeout);
|
||||
};
|
||||
|
||||
/**
|
||||
* Makes the provided frame page as the currently active one. Note that the
|
||||
* active page will be reverted when finished.
|
||||
*
|
||||
* @param String|Number frameInfo Target frame name or number
|
||||
* @param Function then Next step function
|
||||
* @return Casper
|
||||
*/
|
||||
Casper.prototype.withFrame = function withFrame(frameInfo, then) {
|
||||
"use strict";
|
||||
this.then(function _step() {
|
||||
if (utils.isNumber(frameInfo)) {
|
||||
if (frameInfo > this.page.childFramesCount() - 1) {
|
||||
throw new CasperError(f('Frame number "%d" is out of bounds.', frameInfo));
|
||||
}
|
||||
} else if (this.page.childFramesName().indexOf(frameInfo) === -1) {
|
||||
throw new CasperError(f('No frame named "%s" was found.', frameInfo));
|
||||
}
|
||||
// make the frame page the currently active one
|
||||
this.page.switchToChildFrame(frameInfo);
|
||||
});
|
||||
try {
|
||||
this.then(then);
|
||||
} catch (e) {
|
||||
// revert to main page on error
|
||||
this.warn("Error while processing frame step: " + e);
|
||||
this.page.switchToMainFrame();
|
||||
throw e;
|
||||
}
|
||||
return this.then(function _step() {
|
||||
// revert to main page
|
||||
this.page.switchToMainFrame();
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Makes the provided frame page as the currently active one. Note that the
|
||||
* active page will be reverted when finished.
|
||||
*
|
||||
* @param String|RegExp|WebPage popup Target frame page information
|
||||
* @param Function then Next step function
|
||||
* @return Casper
|
||||
*/
|
||||
Casper.prototype.withPopup = function withPopup(popupInfo, then) {
|
||||
"use strict";
|
||||
this.then(function _step() {
|
||||
var popupPage = this.popups.find(popupInfo);
|
||||
if (!utils.isFunction(then)) {
|
||||
throw new CasperError("withPopup() requires a step function.");
|
||||
}
|
||||
// make the popup page the currently active one
|
||||
this.page = popupPage;
|
||||
});
|
||||
try {
|
||||
this.then(then);
|
||||
} catch (e) {
|
||||
// revert to main page on error
|
||||
this.log("error while processing popup step: " + e, "error");
|
||||
this.page = this.mainPage;
|
||||
throw e;
|
||||
}
|
||||
return this.then(function _step() {
|
||||
// revert to main page
|
||||
this.page = this.mainPage;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Changes the current page zoom factor.
|
||||
*
|
||||
@@ -1771,6 +1982,7 @@ exports.Casper = Casper;
|
||||
* @return WebPage
|
||||
*/
|
||||
function createPage(casper) {
|
||||
/*jshint maxstatements:20*/
|
||||
"use strict";
|
||||
var page = require('webpage').create();
|
||||
page.onAlert = function onAlert(message) {
|
||||
@@ -1781,17 +1993,21 @@ function createPage(casper) {
|
||||
}
|
||||
};
|
||||
page.onConfirm = function onConfirm(message) {
|
||||
return casper.filter('page.confirm', message) || true;
|
||||
if ('page.confirm' in casper._filters) {
|
||||
return casper.filter('page.confirm', message);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
page.onConsoleMessage = function onConsoleMessage(msg) {
|
||||
// client utils casper console message
|
||||
var consoleTest = /^\[casper\.echo\]\s?(.*)/.exec(msg);
|
||||
var consoleTest = /^\[casper\.echo\]\s?([\s\S]*)/.exec(msg);
|
||||
if (consoleTest && consoleTest.length === 2) {
|
||||
casper.echo(consoleTest[1]);
|
||||
return; // don't trigger remote.message event for these
|
||||
}
|
||||
// client utils log messages
|
||||
var logLevel = "info", logTest = /^\[casper:(\w+)\]\s?(.*)/.exec(msg);
|
||||
var logLevel = "info",
|
||||
logTest = /^\[casper:(\w+)\]\s?([\s\S]*)/m.exec(msg);
|
||||
if (logTest && logTest.length === 3) {
|
||||
logLevel = logTest[1];
|
||||
msg = logTest[2];
|
||||
@@ -1803,9 +2019,9 @@ function createPage(casper) {
|
||||
casper.emit('page.error', msg, trace);
|
||||
};
|
||||
page.onInitialized = function onInitialized() {
|
||||
casper.emit('page.initialized', this);
|
||||
casper.emit('page.initialized', page);
|
||||
if (utils.isFunction(casper.options.onPageInitialized)) {
|
||||
this.log("Post-configuring WebPage instance", "debug");
|
||||
casper.log("Post-configuring WebPage instance", "debug");
|
||||
casper.options.onPageInitialized.call(casper, page);
|
||||
}
|
||||
};
|
||||
@@ -1814,6 +2030,7 @@ function createPage(casper) {
|
||||
casper.emit('load.started');
|
||||
};
|
||||
page.onLoadFinished = function onLoadFinished(status) {
|
||||
/*jshint maxstatements:20*/
|
||||
if (status !== "success") {
|
||||
casper.emit('load.failed', {
|
||||
status: status,
|
||||
@@ -1831,7 +2048,10 @@ function createPage(casper) {
|
||||
casper.options.onLoadError.call(casper, casper, casper.requestUrl, status);
|
||||
}
|
||||
}
|
||||
// local client scripts
|
||||
casper.injectClientScripts();
|
||||
// remote client scripts
|
||||
casper.includeRemoteScripts();
|
||||
// Client-side utils injection
|
||||
casper.injectClientUtils();
|
||||
// history
|
||||
@@ -1847,6 +2067,17 @@ function createPage(casper) {
|
||||
}
|
||||
casper.emit('navigation.requested', url, navigationType, navigationLocked, isMainFrame);
|
||||
};
|
||||
page.onPageCreated = function onPageCreated(popupPage) {
|
||||
casper.emit('popup.created', popupPage);
|
||||
popupPage.onLoadFinished = function onLoadFinished() {
|
||||
casper.popups.push(popupPage);
|
||||
casper.emit('popup.loaded', popupPage);
|
||||
};
|
||||
popupPage.onClosing = function onClosing(closedPopup) {
|
||||
casper.popups.clean(closedPopup);
|
||||
casper.emit('popup.closed', closedPopup);
|
||||
};
|
||||
};
|
||||
page.onPrompt = function onPrompt(message, value) {
|
||||
return casper.filter('page.prompt', message, value);
|
||||
};
|
||||
@@ -1860,6 +2091,9 @@ function createPage(casper) {
|
||||
};
|
||||
page.onResourceRequested = function onResourceRequested(request) {
|
||||
casper.emit('resource.requested', request);
|
||||
if (request.url === casper.requestUrl) {
|
||||
casper.emit('page.resource.requested', request);
|
||||
}
|
||||
if (utils.isFunction(casper.options.onResourceRequested)) {
|
||||
casper.options.onResourceRequested.call(casper, casper, request);
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
* Casper client-side helpers.
|
||||
*/
|
||||
exports.ClientUtils = function ClientUtils(options) {
|
||||
/*jshint maxstatements:40*/
|
||||
// private members
|
||||
var BASE64_ENCODE_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
var BASE64_DECODE_CHARS = new Array(
|
||||
@@ -200,6 +201,7 @@
|
||||
* @return Object An object containing setting result for each field, including file uploads
|
||||
*/
|
||||
this.fill = function fill(form, vals) {
|
||||
/*jshint maxcomplexity:8*/
|
||||
var out = {
|
||||
errors: [],
|
||||
fields: [],
|
||||
@@ -260,7 +262,7 @@
|
||||
try {
|
||||
var pSelector = this.processSelector(selector);
|
||||
if (pSelector.type === 'xpath') {
|
||||
return this.getElementsByXPath(pSelector.path);
|
||||
return this.getElementsByXPath(pSelector.path, scope);
|
||||
} else {
|
||||
return scope.querySelectorAll(pSelector.path);
|
||||
}
|
||||
@@ -281,7 +283,7 @@
|
||||
try {
|
||||
var pSelector = this.processSelector(selector);
|
||||
if (pSelector.type === 'xpath') {
|
||||
return this.getElementByXPath(pSelector.path);
|
||||
return this.getElementByXPath(pSelector.path, scope);
|
||||
} else {
|
||||
return scope.querySelector(pSelector.path);
|
||||
}
|
||||
@@ -390,14 +392,43 @@
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieves information about the node matching the provided selector.
|
||||
*
|
||||
* @param String|Object selector CSS3/XPath selector
|
||||
* @return Object
|
||||
*/
|
||||
this.getElementInfo = function getElementInfo(selector) {
|
||||
var element = this.findOne(selector);
|
||||
var bounds = this.getElementBounds(selector);
|
||||
var attributes = {};
|
||||
[].forEach.call(element.attributes, function(attr) {
|
||||
attributes[attr.name.toLowerCase()] = attr.value;
|
||||
});
|
||||
return {
|
||||
nodeName: element.nodeName.toLowerCase(),
|
||||
attributes: attributes,
|
||||
tag: element.outerHTML,
|
||||
html: element.innerHTML,
|
||||
text: element.innerText,
|
||||
x: bounds.left,
|
||||
y: bounds.top,
|
||||
width: bounds.width,
|
||||
height: bounds.height,
|
||||
visible: this.visible(selector)
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieves a single DOM element matching a given XPath expression.
|
||||
*
|
||||
* @param String expression The XPath expression
|
||||
* @param HTMLElement|null scope Element to search child elements within
|
||||
* @return HTMLElement or null
|
||||
*/
|
||||
this.getElementByXPath = function getElementByXPath(expression) {
|
||||
var a = document.evaluate(expression, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
|
||||
this.getElementByXPath = function getElementByXPath(expression, scope) {
|
||||
scope = scope || this.options.scope;
|
||||
var a = document.evaluate(expression, scope, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
|
||||
if (a.snapshotLength > 0) {
|
||||
return a.snapshotItem(0);
|
||||
}
|
||||
@@ -407,11 +438,13 @@
|
||||
* Retrieves all DOM elements matching a given XPath expression.
|
||||
*
|
||||
* @param String expression The XPath expression
|
||||
* @param HTMLElement|null scope Element to search child elements within
|
||||
* @return Array
|
||||
*/
|
||||
this.getElementsByXPath = function getElementsByXPath(expression) {
|
||||
this.getElementsByXPath = function getElementsByXPath(expression, scope) {
|
||||
scope = scope || this.options.scope;
|
||||
var nodes = [];
|
||||
var a = document.evaluate(expression, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
|
||||
var a = document.evaluate(expression, scope, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
|
||||
for (var i = 0; i < a.snapshotLength; i++) {
|
||||
nodes.push(a.snapshotItem(i));
|
||||
}
|
||||
@@ -445,7 +478,7 @@
|
||||
if (type === 'radio') {
|
||||
var value;
|
||||
[].forEach.call(inputs, function(radio) {
|
||||
value = radio.checked ? radio.value : undefined;
|
||||
value = radio.checked ? radio.value : value;
|
||||
});
|
||||
return value;
|
||||
} else if (type === 'checkbox') {
|
||||
@@ -466,6 +499,25 @@
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieves a given form all of its field values.
|
||||
*
|
||||
* @param String selector A DOM CSS3/XPath selector
|
||||
* @return Object
|
||||
*/
|
||||
this.getFormValues = function getFormValues(selector) {
|
||||
var form = this.findOne(selector);
|
||||
var values = {};
|
||||
var self = this;
|
||||
[].forEach.call(form.elements, function(element) {
|
||||
var name = element.getAttribute('name');
|
||||
if (name && !values[name]) {
|
||||
values[name] = self.getFieldValue(name);
|
||||
}
|
||||
});
|
||||
return values;
|
||||
};
|
||||
|
||||
/**
|
||||
* Logs a message. Will format the message a way CasperJS will be able
|
||||
* to log phantomjs side.
|
||||
@@ -569,24 +621,21 @@
|
||||
* Performs an AJAX request.
|
||||
*
|
||||
* @param String url Url.
|
||||
* @param String method HTTP method.
|
||||
* @param String method HTTP method (default: GET).
|
||||
* @param Object data Request parameters.
|
||||
* @param Boolean async Asynchroneous request? (default: false)
|
||||
* @return String Response text.
|
||||
*/
|
||||
this.sendAJAX = function sendAJAX(url, method, data, async) {
|
||||
var xhr = new XMLHttpRequest(), dataString = "";
|
||||
if (typeof method !== "string" || ["GET", "POST"].indexOf(method.toUpperCase()) === -1) {
|
||||
method = "GET";
|
||||
} else {
|
||||
method = method.toUpperCase();
|
||||
}
|
||||
var xhr = new XMLHttpRequest(),
|
||||
dataString = "",
|
||||
dataList = [];
|
||||
method = method && method.toUpperCase() || "GET";
|
||||
xhr.open(method, url, !!async);
|
||||
this.log("getBinary(): Using HTTP method: '" + method + "'", "debug");
|
||||
this.log("sendAJAX(): Using HTTP method: '" + method + "'", "debug");
|
||||
xhr.overrideMimeType("text/plain; charset=x-user-defined");
|
||||
if (method === "POST") {
|
||||
if (typeof data === "object") {
|
||||
var dataList = [];
|
||||
for (var k in data) {
|
||||
dataList.push(encodeURIComponent(k) + "=" + encodeURIComponent(data[k].toString()));
|
||||
}
|
||||
@@ -595,7 +644,7 @@
|
||||
} else if (typeof data === "string") {
|
||||
dataString = data;
|
||||
}
|
||||
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
|
||||
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
|
||||
}
|
||||
xhr.send(method === "POST" ? dataString : null);
|
||||
return xhr.responseText;
|
||||
@@ -609,6 +658,7 @@
|
||||
* @param mixed value The field value to set
|
||||
*/
|
||||
this.setField = function setField(field, value) {
|
||||
/*jshint maxcomplexity:99 */
|
||||
var logValue, fields, out;
|
||||
value = logValue = (value || "");
|
||||
if (field instanceof NodeList) {
|
||||
@@ -694,10 +744,14 @@
|
||||
out = 'Unsupported field type: ' + nodeName;
|
||||
break;
|
||||
}
|
||||
// firing the `change` event
|
||||
var changeEvent = document.createEvent("HTMLEvents");
|
||||
changeEvent.initEvent('change', true, true);
|
||||
field.dispatchEvent(changeEvent);
|
||||
|
||||
// firing the `change` and `input` events
|
||||
['change', 'input'].forEach(function(name) {
|
||||
var event = document.createEvent("HTMLEvents");
|
||||
event.initEvent(name, true, true);
|
||||
field.dispatchEvent(event);
|
||||
});
|
||||
|
||||
// blur the field
|
||||
try {
|
||||
field.blur();
|
||||
|
||||
@@ -64,7 +64,8 @@ var Colorizer = function Colorizer() {
|
||||
'WARNING': { fg: 'red', bold: true },
|
||||
'GREEN_BAR': { fg: 'white', bg: 'green', bold: true },
|
||||
'RED_BAR': { fg: 'white', bg: 'red', bold: true },
|
||||
'INFO_BAR': { bg: 'cyan', fg: 'white', bold: true }
|
||||
'INFO_BAR': { bg: 'cyan', fg: 'white', bold: true },
|
||||
'WARN_BAR': { bg: 'yellow', fg: 'white', bold: true }
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
/*global CasperError*/
|
||||
|
||||
var isArray = Array.isArray;
|
||||
|
||||
function EventEmitter() {
|
||||
@@ -230,6 +232,17 @@ EventEmitter.prototype.filter = function() {
|
||||
return filter.apply(this, Array.prototype.splice.call(arguments, 1));
|
||||
};
|
||||
|
||||
EventEmitter.prototype.removeAllFilters = function(type) {
|
||||
if (arguments.length === 0) {
|
||||
this._filters = {};
|
||||
return this;
|
||||
}
|
||||
if (type && this._filters && this._filters[type]) {
|
||||
this._filters[type] = null;
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
EventEmitter.prototype.setFilter = function(type, filterFn) {
|
||||
if (!this._filters) {
|
||||
this._filters = {};
|
||||
|
||||
@@ -62,6 +62,7 @@ responseHeaders.prototype.get = function get(name){
|
||||
*/
|
||||
exports.augmentResponse = function(response) {
|
||||
"use strict";
|
||||
/*jshint proto:true*/
|
||||
if (!utils.isHTTPResource(response)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
/*!
|
||||
* Casper is a navigation utility for PhantomJS.
|
||||
*
|
||||
* Documentation: http://casperjs.org/
|
||||
* Repository: http://github.com/n1k0/casperjs
|
||||
*
|
||||
* Copyright (c) 2011-2012 Nicolas Perriault
|
||||
*
|
||||
* Part of source code is Copyright Joyent, Inc. and other Node contributors.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
/*global CasperError console encodeURIComponent escape exports require*/
|
||||
|
||||
// WARNING: this module is deprecated since CasperJS 1.0.0-RC3
|
||||
|
||||
var utils = require('utils');
|
||||
|
||||
exports.create = function create(fn) {
|
||||
"use strict";
|
||||
return new FunctionArgsInjector(fn);
|
||||
};
|
||||
|
||||
/**
|
||||
* Function argument injector.
|
||||
*
|
||||
* FIXME: use new Function() instead of eval()
|
||||
*/
|
||||
var FunctionArgsInjector = function FunctionArgsInjector(fn) {
|
||||
"use strict";
|
||||
console.error('Warning: the injector module has been deprecated.');
|
||||
|
||||
if (!utils.isFunction(fn)) {
|
||||
throw new CasperError("FunctionArgsInjector() can only process functions");
|
||||
}
|
||||
this.fn = fn;
|
||||
|
||||
this.extract = function extract(fn) {
|
||||
var match = /^function\s?(\w+)?\s?\((.*)\)\s?\{([\s\S]*)\}/i.exec(fn.toString().trim());
|
||||
if (match && match.length > 1) {
|
||||
var args = match[2].split(',').map(function _map(arg) {
|
||||
return arg.replace(new RegExp(/\/\*+.*\*\//ig), "").trim();
|
||||
}).filter(function _filter(arg) {
|
||||
return arg;
|
||||
}) || [];
|
||||
return {
|
||||
name: match[1] ? match[1].trim() : null,
|
||||
args: args,
|
||||
body: match[3] ? match[3].trim() : ''
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
this.process = function process(values) {
|
||||
var fnObj = this.extract(this.fn);
|
||||
if (!utils.isObject(fnObj)) {
|
||||
throw new CasperError("Unable to process function " + this.fn.toString());
|
||||
}
|
||||
var inject = this.getArgsInjectionString(fnObj.args, values);
|
||||
var newFn = new Function([inject, fnObj.body].join('\n'));
|
||||
newFn.name = fnObj.name || '';
|
||||
return newFn;
|
||||
};
|
||||
|
||||
this.getArgsInjectionString = function getArgsInjectionString(args, values) {
|
||||
values = typeof values === "object" ? values : {};
|
||||
var jsonValues = escape(encodeURIComponent(JSON.stringify(values)));
|
||||
var inject = [
|
||||
'var __casper_params__ = JSON.parse(decodeURIComponent(unescape(\'' + jsonValues + '\')));'
|
||||
];
|
||||
args.forEach(function _forEach(arg) {
|
||||
if (arg in values) {
|
||||
inject.push('var ' + arg + '=__casper_params__["' + arg + '"];');
|
||||
}
|
||||
});
|
||||
return inject.join('\n') + '\n';
|
||||
};
|
||||
};
|
||||
exports.FunctionArgsInjector = FunctionArgsInjector;
|
||||
@@ -43,11 +43,13 @@ var Mouse = function Mouse(casper) {
|
||||
throw new CasperError('Mouse() needs a Casper instance');
|
||||
}
|
||||
|
||||
var slice = Array.prototype.slice;
|
||||
|
||||
var nativeEvents = ['mouseup', 'mousedown', 'click', 'mousemove'];
|
||||
var emulatedEvents = ['mouseover', 'mouseout'];
|
||||
var supportedEvents = nativeEvents.concat(emulatedEvents);
|
||||
var slice = Array.prototype.slice,
|
||||
nativeEvents = ['mouseup', 'mousedown', 'click', 'mousemove'];
|
||||
if (utils.gteVersion(phantom.version, '1.8.0')) {
|
||||
nativeEvents.push('doubleclick');
|
||||
}
|
||||
var emulatedEvents = ['mouseover', 'mouseout'],
|
||||
supportedEvents = nativeEvents.concat(emulatedEvents);
|
||||
|
||||
function computeCenter(selector) {
|
||||
var bounds = casper.getElementBounds(selector);
|
||||
@@ -72,8 +74,7 @@ var Mouse = function Mouse(casper) {
|
||||
throw new CasperError('Mouse.processEvent(): Too few arguments');
|
||||
case 1:
|
||||
// selector
|
||||
var selector = args[0];
|
||||
casper.page.sendEvent.apply(casper.page, [type].concat(computeCenter(selector)));
|
||||
casper.page.sendEvent.apply(casper.page, [type].concat(computeCenter(args[0])));
|
||||
break;
|
||||
case 2:
|
||||
// coordinates
|
||||
@@ -95,6 +96,10 @@ var Mouse = function Mouse(casper) {
|
||||
processEvent('click', arguments);
|
||||
};
|
||||
|
||||
this.doubleclick = function doubleclick() {
|
||||
processEvent('doubleclick', arguments);
|
||||
};
|
||||
|
||||
this.down = function down() {
|
||||
processEvent('mousedown', arguments);
|
||||
};
|
||||
|
||||
166
zephyr/tests/frontend/casperjs/modules/pagestack.js
Normal file
166
zephyr/tests/frontend/casperjs/modules/pagestack.js
Normal file
@@ -0,0 +1,166 @@
|
||||
/*!
|
||||
* Casper is a navigation utility for PhantomJS.
|
||||
*
|
||||
* Documentation: http://casperjs.org/
|
||||
* Repository: http://github.com/n1k0/casperjs
|
||||
*
|
||||
* Copyright (c) 2011-2012 Nicolas Perriault
|
||||
*
|
||||
* Part of source code is Copyright Joyent, Inc. and other Node contributors.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
/*global CasperError console exports phantom require*/
|
||||
|
||||
var utils = require('utils');
|
||||
var f = utils.format;
|
||||
|
||||
function create() {
|
||||
"use strict";
|
||||
return new Stack();
|
||||
}
|
||||
exports.create = create;
|
||||
|
||||
/**
|
||||
* Popups container. Implements Array prototype.
|
||||
*
|
||||
*/
|
||||
var Stack = function Stack(){};
|
||||
exports.Stack = Stack;
|
||||
|
||||
Stack.prototype = [];
|
||||
|
||||
/**
|
||||
* Cleans the stack from closed popup.
|
||||
*
|
||||
* @param WebPage closed Closed popup page instance
|
||||
* @return Number New stack length
|
||||
*/
|
||||
Stack.prototype.clean = function clean(closed) {
|
||||
"use strict";
|
||||
var closedIndex = -1;
|
||||
this.forEach(function(popup, index) {
|
||||
if (closed === popup) {
|
||||
closedIndex = index;
|
||||
}
|
||||
});
|
||||
if (closedIndex > -1) {
|
||||
this.splice(closedIndex, 1);
|
||||
}
|
||||
return this.length;
|
||||
};
|
||||
|
||||
/**
|
||||
* Finds a popup matching the provided information. Information can be:
|
||||
*
|
||||
* - RegExp: matching page url
|
||||
* - String: strict page url value
|
||||
* - WebPage: a direct WebPage instance
|
||||
*
|
||||
* @param Mixed popupInfo
|
||||
* @return WebPage
|
||||
*/
|
||||
Stack.prototype.find = function find(popupInfo) {
|
||||
"use strict";
|
||||
var popup, type = utils.betterTypeOf(popupInfo);
|
||||
switch (type) {
|
||||
case "regexp":
|
||||
popup = this.findByRegExp(popupInfo);
|
||||
break;
|
||||
case "string":
|
||||
popup = this.findByURL(popupInfo);
|
||||
break;
|
||||
case "qtruntimeobject": // WebPage
|
||||
popup = popupInfo;
|
||||
if (!utils.isWebPage(popup) || !this.some(function(popupPage) {
|
||||
if (popupInfo.id && popupPage.id) {
|
||||
return popupPage.id === popup.id;
|
||||
}
|
||||
return popupPage.url === popup.url;
|
||||
})) {
|
||||
throw new CasperError("Invalid or missing popup.");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new CasperError(f("Invalid popupInfo type: %s.", type));
|
||||
}
|
||||
return popup;
|
||||
};
|
||||
|
||||
/**
|
||||
* Finds the first popup which url matches a given RegExp.
|
||||
*
|
||||
* @param RegExp regexp
|
||||
* @return WebPage
|
||||
*/
|
||||
Stack.prototype.findByRegExp = function findByRegExp(regexp) {
|
||||
"use strict";
|
||||
var popup = this.filter(function(popupPage) {
|
||||
return regexp.test(popupPage.url);
|
||||
})[0];
|
||||
if (!popup) {
|
||||
throw new CasperError(f("Couldn't find popup with url matching pattern %s", regexp));
|
||||
}
|
||||
return popup;
|
||||
};
|
||||
|
||||
/**
|
||||
* Finds the first popup matching a given url.
|
||||
*
|
||||
* @param String url The child WebPage url
|
||||
* @return WebPage
|
||||
*/
|
||||
Stack.prototype.findByURL = function findByURL(string) {
|
||||
"use strict";
|
||||
var popup = this.filter(function(popupPage) {
|
||||
return popupPage.url.indexOf(string) !== -1;
|
||||
})[0];
|
||||
if (!popup) {
|
||||
throw new CasperError(f("Couldn't find popup with url containing '%s'", string));
|
||||
}
|
||||
return popup;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a human readable list of current active popup urls.
|
||||
*
|
||||
* @return Array Mapped stack.
|
||||
*/
|
||||
Stack.prototype.list = function list() {
|
||||
"use strict";
|
||||
return this.map(function(popup) {
|
||||
try {
|
||||
return popup.url;
|
||||
} catch (e) {
|
||||
return '<deleted>';
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* String representation of current instance.
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
Stack.prototype.toString = function toString() {
|
||||
"use strict";
|
||||
return f("[Object Stack], having %d popup(s)" % this.length);
|
||||
};
|
||||
@@ -48,13 +48,20 @@ exports.create = function create(casper, options) {
|
||||
*/
|
||||
var Tester = function Tester(casper, options) {
|
||||
"use strict";
|
||||
/*jshint maxstatements:30*/
|
||||
|
||||
if (!utils.isCasperObject(casper)) {
|
||||
throw new CasperError("Tester needs a Casper instance");
|
||||
}
|
||||
|
||||
var self = this;
|
||||
|
||||
this.casper = casper;
|
||||
|
||||
this.SKIP_MESSAGE = '__termination__';
|
||||
|
||||
this.aborted = false;
|
||||
this.executed = 0;
|
||||
this.currentTestFile = null;
|
||||
this.currentSuiteNum = 0;
|
||||
this.exporter = require('xunit').create();
|
||||
@@ -66,9 +73,11 @@ var Tester = function Tester(casper, options) {
|
||||
this.running = false;
|
||||
this.suites = [];
|
||||
this.options = utils.mergeObjects({
|
||||
failFast: false, // terminates a suite as soon as a test fails?
|
||||
failText: "FAIL", // text to use for a successful test
|
||||
passText: "PASS", // text to use for a failed test
|
||||
pad: 80 // maximum number of chars for a result line
|
||||
pad: 80 , // maximum number of chars for a result line
|
||||
warnText: "WARN" // text to use for a dubious test
|
||||
}, options);
|
||||
|
||||
// properties
|
||||
@@ -76,25 +85,39 @@ var Tester = function Tester(casper, options) {
|
||||
passed: 0,
|
||||
failed: 0,
|
||||
passes: [],
|
||||
failures: []
|
||||
failures: [],
|
||||
passesTime: [],
|
||||
failuresTime: []
|
||||
};
|
||||
|
||||
// measuring test duration
|
||||
this.currentTestStartTime = new Date();
|
||||
this.lastAssertTime = 0;
|
||||
|
||||
this.configure();
|
||||
|
||||
this.on('success', function onSuccess(success) {
|
||||
this.testResults.passes.push(success);
|
||||
this.exporter.addSuccess(fs.absolute(success.file), success.message || success.standard);
|
||||
var timeElapsed = new Date() - this.currentTestStartTime;
|
||||
this.testResults.passesTime.push(timeElapsed - this.lastAssertTime);
|
||||
this.exporter.addSuccess(fs.absolute(success.file), success.message || success.standard, timeElapsed - this.lastAssertTime);
|
||||
this.lastAssertTime = timeElapsed;
|
||||
});
|
||||
|
||||
this.on('fail', function onFail(failure) {
|
||||
// export
|
||||
var timeElapsed = new Date() - this.currentTestStartTime;
|
||||
this.testResults.failuresTime.push(timeElapsed - this.lastAssertTime);
|
||||
this.exporter.addFailure(
|
||||
fs.absolute(failure.file),
|
||||
failure.message || failure.standard,
|
||||
failure.standard || "test failed",
|
||||
failure.type || "unknown"
|
||||
failure.type || "unknown",
|
||||
(timeElapsed - this.lastAssertTime)
|
||||
);
|
||||
this.lastAssertTime = timeElapsed;
|
||||
this.testResults.failures.push(failure);
|
||||
|
||||
// special printing
|
||||
if (failure.type) {
|
||||
this.comment(' type: ' + failure.type);
|
||||
@@ -116,6 +139,33 @@ var Tester = function Tester(casper, options) {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// casper events
|
||||
this.casper.on('error', function onCasperError(msg, backtrace) {
|
||||
if (!phantom.casperTest) {
|
||||
return;
|
||||
}
|
||||
if (msg === self.SKIP_MESSAGE) {
|
||||
this.warn(f('--fail-fast: aborted remaining tests in "%s"', self.currentTestFile));
|
||||
self.aborted = true;
|
||||
return self.done();
|
||||
}
|
||||
var line = 0;
|
||||
if (!utils.isString(msg)) {
|
||||
try {
|
||||
line = backtrace[0].line;
|
||||
} catch (e) {}
|
||||
}
|
||||
self.uncaughtError(msg, self.currentTestFile, line);
|
||||
self.done();
|
||||
});
|
||||
|
||||
this.casper.on('step.error', function onStepError(e) {
|
||||
if (e.message !== self.SKIP_MESSAGE) {
|
||||
self.uncaughtError(e, self.currentTestFile);
|
||||
}
|
||||
self.done();
|
||||
});
|
||||
};
|
||||
|
||||
// Tester class is an EventEmitter
|
||||
@@ -138,6 +188,7 @@ exports.Tester = Tester;
|
||||
*/
|
||||
Tester.prototype.assert = Tester.prototype.assertTrue = function assert(subject, message, context) {
|
||||
"use strict";
|
||||
this.executed++;
|
||||
return this.processAssertionResult(utils.mergeObjects({
|
||||
success: subject === true,
|
||||
type: "assert",
|
||||
@@ -195,7 +246,7 @@ Tester.prototype.assertNotEquals = function assertNotEquals(subject, shouldnt, m
|
||||
*
|
||||
* @param Function fn A function to be evaluated in remote DOM
|
||||
* @param String message Test description
|
||||
* @param Object params Object containing the parameters to inject into the function (optional)
|
||||
* @param Object params Object/Array containing the parameters to inject into the function (optional)
|
||||
* @return Object An assertion result object
|
||||
*/
|
||||
Tester.prototype.assertEval = Tester.prototype.assertEvaluate = function assertEval(fn, message, params) {
|
||||
@@ -247,7 +298,7 @@ Tester.prototype.assertField = function assertField(inputName, expected, messag
|
||||
"use strict";
|
||||
var actual = this.casper.evaluate(function(inputName) {
|
||||
return __utils__.getFieldValue(inputName);
|
||||
}, { inputName: inputName });
|
||||
}, inputName);
|
||||
return this.assert(this.testEquals(actual, expected), message, {
|
||||
type: 'assertField',
|
||||
standard: f('"%s" input field has the value "%s"', inputName, expected),
|
||||
@@ -267,7 +318,7 @@ Tester.prototype.assertField = function assertField(inputName, expected, messag
|
||||
* @param String message Test description
|
||||
* @return Object An assertion result object
|
||||
*/
|
||||
Tester.prototype.assertExists = Tester.prototype.assertExist = this.assertSelectorExists = Tester.prototype.assertSelectorExist = function assertExists(selector, message) {
|
||||
Tester.prototype.assertExists = Tester.prototype.assertExist = Tester.prototype.assertSelectorExists = Tester.prototype.assertSelectorExist = function assertExists(selector, message) {
|
||||
"use strict";
|
||||
return this.assert(this.casper.exists(selector), message, {
|
||||
type: "assertExists",
|
||||
@@ -327,6 +378,9 @@ Tester.prototype.assertHttpStatus = function assertHttpStatus(status, message) {
|
||||
*/
|
||||
Tester.prototype.assertMatch = Tester.prototype.assertMatches = function assertMatch(subject, pattern, message) {
|
||||
"use strict";
|
||||
if (utils.betterTypeOf(pattern) !== "regexp") {
|
||||
throw new CasperError('Invalid regexp.');
|
||||
}
|
||||
return this.assert(pattern.test(subject), message, {
|
||||
type: "assertMatch",
|
||||
standard: "Subject matches the provided pattern",
|
||||
@@ -344,7 +398,7 @@ Tester.prototype.assertMatch = Tester.prototype.assertMatches = function assertM
|
||||
* @param String message Test description
|
||||
* @return Object An assertion result object
|
||||
*/
|
||||
Tester.prototype.assertNot = function assertNot(condition, message) {
|
||||
Tester.prototype.assertNot = Tester.prototype.assertFalse = function assertNot(condition, message) {
|
||||
"use strict";
|
||||
return this.assert(!condition, message, {
|
||||
type: "assertNot",
|
||||
@@ -382,7 +436,7 @@ Tester.prototype.assertNotVisible = Tester.prototype.assertInvisible = function
|
||||
* @param String message Test description
|
||||
* @return Object An assertion result object
|
||||
*/
|
||||
Tester.prototype.assertRaises = Tester.prototype.assertRaise = this.assertThrows = function assertRaises(fn, args, message) {
|
||||
Tester.prototype.assertRaises = Tester.prototype.assertRaise = Tester.prototype.assertThrows = function assertRaises(fn, args, message) {
|
||||
"use strict";
|
||||
var context = {
|
||||
type: "assertRaises",
|
||||
@@ -418,6 +472,27 @@ Tester.prototype.assertResourceExists = Tester.prototype.assertResourceExist = f
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Asserts that given text doesn't exist in the document body.
|
||||
*
|
||||
* @param String text Text not to be found
|
||||
* @param String message Test description
|
||||
* @return Object An assertion result object
|
||||
*/
|
||||
Tester.prototype.assertTextDoesntExist = Tester.prototype.assertTextDoesntExist = function assertTextDoesntExist(text, message) {
|
||||
"use strict";
|
||||
var textFound = (this.casper.evaluate(function _evaluate() {
|
||||
return document.body.textContent || document.body.innerText;
|
||||
}).indexOf(text) === -1);
|
||||
return this.assert(textFound, message, {
|
||||
type: "assertTextDoesntExists",
|
||||
standard: "Text doesn't exist within the document body",
|
||||
values: {
|
||||
text: text
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Asserts that given text exists in the document body.
|
||||
*
|
||||
@@ -439,6 +514,44 @@ Tester.prototype.assertTextExists = Tester.prototype.assertTextExist = function
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Asserts a subject is truthy.
|
||||
*
|
||||
* @param Mixed subject Test subject
|
||||
* @param String message Test description
|
||||
* @return Object An assertion result object
|
||||
*/
|
||||
Tester.prototype.assertTruthy = function assertTruthy(subject, message) {
|
||||
"use strict";
|
||||
/*jshint eqeqeq:false*/
|
||||
return this.assert(utils.isTruthy(subject), message, {
|
||||
type: "assertTruthy",
|
||||
standard: "Subject is truthy",
|
||||
values: {
|
||||
subject: subject
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Asserts a subject is falsy.
|
||||
*
|
||||
* @param Mixed subject Test subject
|
||||
* @param String message Test description
|
||||
* @return Object An assertion result object
|
||||
*/
|
||||
Tester.prototype.assertFalsy = function assertFalsy(subject, message) {
|
||||
"use strict";
|
||||
/*jshint eqeqeq:false*/
|
||||
return this.assert(utils.isFalsy(subject), message, {
|
||||
type: "assertFalsy",
|
||||
standard: "Subject is falsy",
|
||||
values: {
|
||||
subject: subject
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Asserts that given text exists in the provided selector.
|
||||
*
|
||||
@@ -447,11 +560,11 @@ Tester.prototype.assertTextExists = Tester.prototype.assertTextExist = function
|
||||
* @param String message Test description
|
||||
* @return Object An assertion result object
|
||||
*/
|
||||
Tester.prototype.assertSelectorHasText = function assertSelectorHasText(selector, text, message) {
|
||||
Tester.prototype.assertSelectorHasText = Tester.prototype.assertSelectorContains = function assertSelectorHasText(selector, text, message) {
|
||||
"use strict";
|
||||
var textFound = this.casper.fetchText(selector).indexOf(text) !== -1;
|
||||
return this.assert(textFound, message, {
|
||||
type: "assertTextInSelector",
|
||||
type: "assertSelectorHasText",
|
||||
standard: f('Found "%s" within the selector "%s"', text, selector),
|
||||
values: {
|
||||
selector: selector,
|
||||
@@ -468,11 +581,11 @@ Tester.prototype.assertSelectorHasText = function assertSelectorHasText(selector
|
||||
* @param String message Test description
|
||||
* @return Object An assertion result object
|
||||
*/
|
||||
Tester.prototype.assertSelectorDoesntHaveText = function assertSelectorDoesntHaveText(selector, text, message) {
|
||||
Tester.prototype.assertSelectorDoesntHaveText = Tester.prototype.assertSelectorDoesntContain = function assertSelectorDoesntHaveText(selector, text, message) {
|
||||
"use strict";
|
||||
var textFound = this.casper.fetchText(selector).indexOf(text) === -1;
|
||||
return this.assert(textFound, message, {
|
||||
type: "assertNoTextInSelector",
|
||||
type: "assertSelectorDoesntHaveText",
|
||||
standard: f('Did not find "%s" within the selector "%s"', text, selector),
|
||||
values: {
|
||||
selector: selector,
|
||||
@@ -510,6 +623,9 @@ Tester.prototype.assertTitle = function assertTitle(expected, message) {
|
||||
*/
|
||||
Tester.prototype.assertTitleMatch = Tester.prototype.assertTitleMatches = function assertTitleMatch(pattern, message) {
|
||||
"use strict";
|
||||
if (utils.betterTypeOf(pattern) !== "regexp") {
|
||||
throw new CasperError('Invalid regexp.');
|
||||
}
|
||||
var currentTitle = this.casper.getTitle();
|
||||
return this.assert(pattern.test(currentTitle), message, {
|
||||
type: "assertTitle",
|
||||
@@ -601,6 +717,19 @@ Tester.prototype.bar = function bar(text, style) {
|
||||
this.casper.echo(text, style, this.options.pad);
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieves the sum of all durations of the tests which were
|
||||
* executed in the current suite
|
||||
*
|
||||
* @return Number duration of all tests executed until now (in the current suite)
|
||||
*/
|
||||
Tester.prototype.calculateSuiteDuration = function calculateSuiteDuration() {
|
||||
"use strict";
|
||||
return this.testResults.passesTime.concat(this.testResults.failuresTime).reduce(function add(a, b) {
|
||||
return a + b;
|
||||
}, 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* Render a colorized output. Basically a proxy method for
|
||||
* Casper.Colorizer#colorize()
|
||||
@@ -635,7 +764,7 @@ Tester.prototype.configure = function configure() {
|
||||
|
||||
// specific timeout callbacks
|
||||
this.casper.options.onStepTimeout = function test_onStepTimeout(timeout, step) {
|
||||
tester.fail(f("Step timeout occured at step %d (%dms)", step, timeout));
|
||||
tester.fail(f("Step timeout occured at step %s (%dms)", step, timeout));
|
||||
};
|
||||
|
||||
this.casper.options.onTimeout = function test_onTimeout(timeout) {
|
||||
@@ -645,29 +774,19 @@ Tester.prototype.configure = function configure() {
|
||||
this.casper.options.onWaitTimeout = function test_onWaitTimeout(timeout) {
|
||||
tester.fail(f("Wait timeout occured (%dms)", timeout));
|
||||
};
|
||||
|
||||
// events
|
||||
this.casper.on('error', function(msg, backtrace) {
|
||||
var line = 0;
|
||||
try {
|
||||
line = backtrace[0].line;
|
||||
} catch (e) {}
|
||||
tester.uncaughtError(msg, tester.currentTestFile, line);
|
||||
tester.done();
|
||||
});
|
||||
|
||||
this.casper.on('step.error', function onStepError(e) {
|
||||
tester.uncaughtError(e, tester.currentTestFile);
|
||||
tester.done();
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Declares the current test suite done.
|
||||
*
|
||||
* @param Number planned Number of planned tests
|
||||
*/
|
||||
Tester.prototype.done = function done() {
|
||||
Tester.prototype.done = function done(planned) {
|
||||
"use strict";
|
||||
if (planned > 0 && planned !== this.executed) {
|
||||
this.fail(f('%s: %d tests planned, %d tests executed',
|
||||
this.currentTestFile, planned, this.executed));
|
||||
}
|
||||
this.emit('test.done');
|
||||
this.running = false;
|
||||
};
|
||||
@@ -784,6 +903,27 @@ Tester.prototype.getPasses = function getPasses() {
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieves the array where all the durations of failed tests are stored
|
||||
*
|
||||
* @return Array durations of failed tests
|
||||
*/
|
||||
Tester.prototype.getFailuresTime = function getFailuresTime() {
|
||||
"use strict";
|
||||
return this.testResults.failuresTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the array where all the durations of passed tests are stored
|
||||
*
|
||||
* @return Array durations of passed tests
|
||||
*/
|
||||
Tester.prototype.getPassesTime = function getPassesTime() {
|
||||
"use strict";
|
||||
return this.testResults.passesTime;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Writes an info-style formatted message to stdout.
|
||||
*
|
||||
@@ -816,21 +956,23 @@ Tester.prototype.pass = function pass(message) {
|
||||
*/
|
||||
Tester.prototype.processAssertionResult = function processAssertionResult(result) {
|
||||
"use strict";
|
||||
var eventName, style, status;
|
||||
if (result.success === true) {
|
||||
eventName = 'success';
|
||||
style = 'INFO';
|
||||
var eventName= 'success',
|
||||
message = result.message || result.standard,
|
||||
style = 'INFO',
|
||||
status = this.options.passText;
|
||||
this.testResults.passed++;
|
||||
} else {
|
||||
if (!result.success) {
|
||||
eventName = 'fail';
|
||||
style = 'RED_BAR';
|
||||
status = this.options.failText;
|
||||
this.testResults.failed++;
|
||||
} else {
|
||||
this.testResults.passed++;
|
||||
}
|
||||
var message = result.message || result.standard;
|
||||
this.casper.echo([this.colorize(status, style), this.formatMessage(message)].join(' '));
|
||||
this.emit(eventName, result);
|
||||
if (this.options.failFast && !result.success) {
|
||||
throw this.SKIP_MESSAGE;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
@@ -852,7 +994,7 @@ Tester.prototype.renderFailureDetails = function renderFailureDetails(failures)
|
||||
message = failure.message;
|
||||
this.casper.echo(f('In %s:%s', failure.file, line));
|
||||
this.casper.echo(f(' %s: %s', type, message || failure.standard || "(no message was entered)"), "COMMENT");
|
||||
});
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -867,8 +1009,8 @@ Tester.prototype.renderResults = function renderResults(exit, status, save) {
|
||||
var total = this.testResults.passed + this.testResults.failed, statusText, style, result;
|
||||
var exitStatus = ~~(status || (this.testResults.failed > 0 ? 1 : 0));
|
||||
if (total === 0) {
|
||||
statusText = this.options.failText;
|
||||
style = 'RED_BAR';
|
||||
statusText = this.options.warnText;
|
||||
style = 'WARN_BAR';
|
||||
result = f("%s Looks like you didn't run any test.", statusText);
|
||||
} else {
|
||||
if (this.testResults.failed > 0) {
|
||||
@@ -878,8 +1020,9 @@ Tester.prototype.renderResults = function renderResults(exit, status, save) {
|
||||
statusText = this.options.passText;
|
||||
style = 'GREEN_BAR';
|
||||
}
|
||||
result = f('%s %s tests executed, %d passed, %d failed.',
|
||||
statusText, total, this.testResults.passed, this.testResults.failed);
|
||||
result = f('%s %s tests executed in %ss, %d passed, %d failed.',
|
||||
statusText, total, utils.ms2seconds(this.calculateSuiteDuration()),
|
||||
this.testResults.passed, this.testResults.failed);
|
||||
}
|
||||
this.casper.echo(result, style, this.options.pad);
|
||||
if (this.testResults.failed > 0) {
|
||||
@@ -931,16 +1074,23 @@ Tester.prototype.runSuites = function runSuites() {
|
||||
this.casper.exit(1);
|
||||
}
|
||||
self.currentSuiteNum = 0;
|
||||
self.currentTestStartTime = new Date();
|
||||
self.lastAssertTime = 0;
|
||||
var interval = setInterval(function _check(self) {
|
||||
if (self.running) {
|
||||
return;
|
||||
}
|
||||
if (self.currentSuiteNum === testFiles.length) {
|
||||
if (self.currentSuiteNum === testFiles.length || self.aborted) {
|
||||
self.emit('tests.complete');
|
||||
clearInterval(interval);
|
||||
self.exporter.setSuiteDuration(self.calculateSuiteDuration());
|
||||
self.aborted = false;
|
||||
} else {
|
||||
self.runTest(testFiles[self.currentSuiteNum]);
|
||||
self.exporter.setSuiteDuration(self.calculateSuiteDuration());
|
||||
self.currentSuiteNum++;
|
||||
self.passesTime = [];
|
||||
self.failuresTime = [];
|
||||
}
|
||||
}, 100, this);
|
||||
};
|
||||
@@ -953,6 +1103,7 @@ Tester.prototype.runTest = function runTest(testFile) {
|
||||
"use strict";
|
||||
this.bar(f('Test file: %s', testFile), 'INFO_BAR');
|
||||
this.running = true; // this.running is set back to false with done()
|
||||
this.executed = 0;
|
||||
this.exec(testFile);
|
||||
};
|
||||
|
||||
|
||||
@@ -34,17 +34,27 @@
|
||||
* Provides a better typeof operator equivalent, able to retrieve the array
|
||||
* type.
|
||||
*
|
||||
* CAVEAT: this function does not necessarilly map to classical js "type" names,
|
||||
* notably a `null` will map to "null" instead of "object".
|
||||
*
|
||||
* @param mixed input
|
||||
* @return String
|
||||
* @see http://javascriptweblog.wordpress.com/2011/08/08/fixing-the-javascript-typeof-operator/
|
||||
*/
|
||||
function betterTypeOf(input) {
|
||||
"use strict";
|
||||
switch (input) {
|
||||
case undefined:
|
||||
return 'undefined';
|
||||
case null:
|
||||
return 'null';
|
||||
default:
|
||||
try {
|
||||
return Object.prototype.toString.call(input).match(/^\[object\s(.*)\]$/)[1].toLowerCase();
|
||||
} catch (e) {
|
||||
return typeof input;
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.betterTypeOf = betterTypeOf;
|
||||
|
||||
@@ -69,6 +79,18 @@ function cleanUrl(url) {
|
||||
}
|
||||
exports.cleanUrl = cleanUrl;
|
||||
|
||||
/**
|
||||
* Clones an object.
|
||||
*
|
||||
* @param Mixed o
|
||||
* @return Mixed
|
||||
*/
|
||||
function clone(o) {
|
||||
"use strict";
|
||||
return JSON.parse(JSON.stringify(o));
|
||||
}
|
||||
exports.clone = clone;
|
||||
|
||||
/**
|
||||
* Dumps a JSON representation of passed value to the console. Used for
|
||||
* debugging purpose only.
|
||||
@@ -264,6 +286,18 @@ function isClipRect(value) {
|
||||
}
|
||||
exports.isClipRect = isClipRect;
|
||||
|
||||
/**
|
||||
* Checks that the subject is falsy.
|
||||
*
|
||||
* @param Mixed subject Test subject
|
||||
* @return Boolean
|
||||
*/
|
||||
function isFalsy(subject) {
|
||||
"use strict";
|
||||
/*jshint eqeqeq:false*/
|
||||
return !subject;
|
||||
}
|
||||
exports.isFalsy = isFalsy;
|
||||
/**
|
||||
* Checks if value is a javascript Function
|
||||
*
|
||||
@@ -337,6 +371,18 @@ function isObject(value) {
|
||||
}
|
||||
exports.isObject = isObject;
|
||||
|
||||
/**
|
||||
* Checks if value is a RegExp
|
||||
*
|
||||
* @param mixed value
|
||||
* @return Boolean
|
||||
*/
|
||||
function isRegExp(value) {
|
||||
"use strict";
|
||||
return isType(value, "regexp");
|
||||
}
|
||||
exports.isRegExp = isRegExp;
|
||||
|
||||
/**
|
||||
* Checks if value is a javascript String
|
||||
*
|
||||
@@ -349,6 +395,19 @@ function isString(value) {
|
||||
}
|
||||
exports.isString = isString;
|
||||
|
||||
/**
|
||||
* Checks that the subject is truthy.
|
||||
*
|
||||
* @param Mixed subject Test subject
|
||||
* @return Boolean
|
||||
*/
|
||||
function isTruthy(subject) {
|
||||
"use strict";
|
||||
/*jshint eqeqeq:false*/
|
||||
return !!subject;
|
||||
}
|
||||
exports.isTruthy = isTruthy;
|
||||
|
||||
/**
|
||||
* Shorthands for checking if a value is of the given type. Can check for
|
||||
* arrays.
|
||||
@@ -433,13 +492,13 @@ exports.isWebPage = isWebPage;
|
||||
function mergeObjects(origin, add) {
|
||||
"use strict";
|
||||
for (var p in add) {
|
||||
try {
|
||||
if (add[p].constructor === Object) {
|
||||
if (add[p] && add[p].constructor === Object) {
|
||||
if (origin[p] && origin[p].constructor === Object) {
|
||||
origin[p] = mergeObjects(origin[p], add[p]);
|
||||
} else {
|
||||
origin[p] = add[p];
|
||||
origin[p] = clone(add[p]);
|
||||
}
|
||||
} catch(e) {
|
||||
} else {
|
||||
origin[p] = add[p];
|
||||
}
|
||||
}
|
||||
@@ -447,6 +506,18 @@ function mergeObjects(origin, add) {
|
||||
}
|
||||
exports.mergeObjects = mergeObjects;
|
||||
|
||||
/**
|
||||
* Converts milliseconds to seconds and rounds the results to 3 digits accuracy.
|
||||
*
|
||||
* @param Number milliseconds
|
||||
* @return Number seconds
|
||||
*/
|
||||
function ms2seconds(milliseconds) {
|
||||
"use strict";
|
||||
return Math.round(milliseconds / 1000 * 1000) / 1000;
|
||||
}
|
||||
exports.ms2seconds = ms2seconds;
|
||||
|
||||
/**
|
||||
* Creates an (SG|X)ML node element.
|
||||
*
|
||||
@@ -467,6 +538,20 @@ function node(name, attributes) {
|
||||
}
|
||||
exports.node = node;
|
||||
|
||||
/**
|
||||
* Maps an object to an array made from its values.
|
||||
*
|
||||
* @param Object obj
|
||||
* @return Array
|
||||
*/
|
||||
function objectValues(obj) {
|
||||
"use strict";
|
||||
return Object.keys(obj).map(function(arg) {
|
||||
return obj[arg];
|
||||
});
|
||||
}
|
||||
exports.objectValues = objectValues;
|
||||
|
||||
/**
|
||||
* Serializes a value using JSON.
|
||||
*
|
||||
@@ -506,3 +591,62 @@ function unique(array) {
|
||||
return r;
|
||||
}
|
||||
exports.unique = unique;
|
||||
|
||||
/**
|
||||
* Compare two version numbers represented as strings.
|
||||
*
|
||||
* @param String a Version a
|
||||
* @param String b Version b
|
||||
* @return Number
|
||||
*/
|
||||
function cmpVersion(a, b) {
|
||||
"use strict";
|
||||
var i, cmp, len, re = /(\.0)+[^\.]*$/;
|
||||
function versionToString(version) {
|
||||
if (isObject(version)) {
|
||||
try {
|
||||
return [version.major, version.minor, version.patch].join('.');
|
||||
} catch (e) {}
|
||||
}
|
||||
return version;
|
||||
}
|
||||
a = versionToString(a);
|
||||
b = versionToString(b);
|
||||
a = (a + '').replace(re, '').split('.');
|
||||
b = (b + '').replace(re, '').split('.');
|
||||
len = Math.min(a.length, b.length);
|
||||
for (i = 0; i < len; i++) {
|
||||
cmp = parseInt(a[i], 10) - parseInt(b[i], 10);
|
||||
if (cmp !== 0) {
|
||||
return cmp;
|
||||
}
|
||||
}
|
||||
return a.length - b.length;
|
||||
}
|
||||
exports.cmpVersion = cmpVersion;
|
||||
|
||||
/**
|
||||
* Checks if a version number string is greater or equals another.
|
||||
*
|
||||
* @param String a Version a
|
||||
* @param String b Version b
|
||||
* @return Boolean
|
||||
*/
|
||||
function gteVersion(a, b) {
|
||||
"use strict";
|
||||
return cmpVersion(a, b) >= 0;
|
||||
}
|
||||
exports.gteVersion = gteVersion;
|
||||
|
||||
/**
|
||||
* Checks if a version number string is less than another.
|
||||
*
|
||||
* @param String a Version a
|
||||
* @param String b Version b
|
||||
* @return Boolean
|
||||
*/
|
||||
function ltVersion(a, b) {
|
||||
"use strict";
|
||||
return cmpVersion(a, b) < 0;
|
||||
}
|
||||
exports.ltVersion = ltVersion;
|
||||
|
||||
@@ -45,7 +45,7 @@ var fs = require('fs');
|
||||
function generateClassName(classname) {
|
||||
"use strict";
|
||||
classname = classname.replace(phantom.casperPath, "").trim();
|
||||
var script = classname || phantom.casperScript;
|
||||
var script = classname || phantom.casperScript || "";
|
||||
if (script.indexOf(fs.workingDirectory) === 0) {
|
||||
script = script.substring(fs.workingDirectory.length + 1);
|
||||
}
|
||||
@@ -55,6 +55,12 @@ function generateClassName(classname) {
|
||||
if (~script.indexOf('.')) {
|
||||
script = script.substring(0, script.lastIndexOf('.'));
|
||||
}
|
||||
|
||||
// If we have trimmed our string down to nothing, default to script name
|
||||
if (!script && phantom.casperScript) {
|
||||
script = phantom.casperScript;
|
||||
}
|
||||
|
||||
return script || "unknown";
|
||||
}
|
||||
|
||||
@@ -86,13 +92,18 @@ exports.XUnitExporter = XUnitExporter;
|
||||
*
|
||||
* @param String classname
|
||||
* @param String name
|
||||
* @param Number duration Test duration in milliseconds
|
||||
*/
|
||||
XUnitExporter.prototype.addSuccess = function addSuccess(classname, name) {
|
||||
XUnitExporter.prototype.addSuccess = function addSuccess(classname, name, duration) {
|
||||
"use strict";
|
||||
this._xml.appendChild(utils.node('testcase', {
|
||||
var snode = utils.node('testcase', {
|
||||
classname: generateClassName(classname),
|
||||
name: name
|
||||
}));
|
||||
});
|
||||
if (duration !== undefined) {
|
||||
snode.setAttribute('time', utils.ms2seconds(duration));
|
||||
}
|
||||
this._xml.appendChild(snode);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -102,13 +113,17 @@ XUnitExporter.prototype.addSuccess = function addSuccess(classname, name) {
|
||||
* @param String name
|
||||
* @param String message
|
||||
* @param String type
|
||||
* @param Number duration Test duration in milliseconds
|
||||
*/
|
||||
XUnitExporter.prototype.addFailure = function addFailure(classname, name, message, type) {
|
||||
XUnitExporter.prototype.addFailure = function addFailure(classname, name, message, type, duration) {
|
||||
"use strict";
|
||||
var fnode = utils.node('testcase', {
|
||||
classname: generateClassName(classname),
|
||||
name: name
|
||||
});
|
||||
if (duration !== undefined) {
|
||||
fnode.setAttribute('time', utils.ms2seconds(duration));
|
||||
}
|
||||
var failure = utils.node('failure', {
|
||||
type: type || "unknown"
|
||||
});
|
||||
@@ -117,6 +132,18 @@ XUnitExporter.prototype.addFailure = function addFailure(classname, name, messag
|
||||
this._xml.appendChild(fnode);
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds test suite duration
|
||||
*
|
||||
* @param Number duration Test duration in milliseconds
|
||||
*/
|
||||
XUnitExporter.prototype.setSuiteDuration = function setSuiteDuration(duration) {
|
||||
"use strict";
|
||||
if (!isNaN(duration)) {
|
||||
this._xml.setAttribute("time", utils.ms2seconds(duration));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieves generated XML object - actually an HTMLElement.
|
||||
*
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "casperjs",
|
||||
"description": "Navigation scripting & testing utility for PhantomJS",
|
||||
"version": "1.0.0-RC4",
|
||||
"version": "1.0.2",
|
||||
"keywords": [
|
||||
"phantomjs",
|
||||
"javascript"
|
||||
@@ -14,7 +14,7 @@
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"http://www.phantomjs.org/": "1.6"
|
||||
"http://www.phantomjs.org/": "1.7"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/n1k0/casperjs/issues"
|
||||
|
||||
203
zephyr/tests/frontend/casperjs/rpm/casperjs.spec
Normal file
203
zephyr/tests/frontend/casperjs/rpm/casperjs.spec
Normal file
@@ -0,0 +1,203 @@
|
||||
%define name casperjs
|
||||
%define version 1.0.0
|
||||
%define release 1_1
|
||||
%define prefix /usr
|
||||
|
||||
%define mybuilddir %{_builddir}/%{name}-%{version}-root
|
||||
|
||||
Summary: open source navigation scripting & testing utility written in Javascript
|
||||
Name: %{name}
|
||||
Version: %{version}
|
||||
License: BSD
|
||||
Release: %{release}
|
||||
Packager: Jan Schaumann <jschauma@etsy.com>
|
||||
Group: Utilities/Misc
|
||||
Source: %{name}-%{version}.tar.gz
|
||||
BuildRoot: /tmp/%{name}-%{version}-root
|
||||
|
||||
Requires: phantomjs
|
||||
|
||||
%description
|
||||
CasperJS is an open source navigation scripting & testing utility written
|
||||
in Javascript and based on PhantomJS. It eases the process of defining a
|
||||
full navigation scenario and provides useful high-level functions, methods
|
||||
& syntactic sugar for doing common tasks
|
||||
|
||||
%prep
|
||||
%setup -q
|
||||
|
||||
%setup
|
||||
mkdir -p %{mybuilddir}%{prefix}/bin
|
||||
mkdir -p %{mybuilddir}%{prefix}/share/%{name}/bin
|
||||
mkdir -p %{mybuilddir}%{prefix}/share/%{name}/modules
|
||||
mkdir -p %{mybuilddir}%{prefix}/share/%{name}/samples
|
||||
mkdir -p %{mybuilddir}%{prefix}/share/%{name}/tests
|
||||
|
||||
%install
|
||||
cp bin/%{name} %{mybuilddir}%{prefix}/share/%{name}/bin/
|
||||
ln -s %{prefix}/share/%{name}/bin/%{name} %{mybuilddir}%{prefix}/bin/%{name}
|
||||
cp bin/bootstrap.js %{mybuilddir}%{prefix}/share/%{name}/bin/
|
||||
# Yes, this tool needs this file in the 'bin' directory.
|
||||
cp bin/usage.txt %{mybuilddir}%{prefix}/share/%{name}/bin/
|
||||
cp CHANGELOG.md %{mybuilddir}%{prefix}/share/%{name}/
|
||||
cp CONTRIBUTING.md %{mybuilddir}%{prefix}/share/%{name}/
|
||||
cp CONTRIBUTORS.md %{mybuilddir}%{prefix}/share/%{name}/
|
||||
cp LICENSE.md %{mybuilddir}%{prefix}/share/%{name}/
|
||||
cp README.md %{mybuilddir}%{prefix}/share/%{name}/
|
||||
cp package.json %{mybuilddir}%{prefix}/share/%{name}/
|
||||
cp -R modules/* %{mybuilddir}%{prefix}/share/%{name}/modules/
|
||||
cp -R samples/* %{mybuilddir}%{prefix}/share/%{name}/samples/
|
||||
cp -R tests/* %{mybuilddir}%{prefix}/share/%{name}/tests/
|
||||
|
||||
%files
|
||||
%defattr(0444,root,root)
|
||||
%attr(0555,root,root)%{prefix}/bin/%{name}
|
||||
%attr(0555,root,root)%{prefix}/share/%{name}/bin/%{name}
|
||||
%attr(0555,root,root)%{prefix}/share/%{name}/bin/bootstrap.js
|
||||
%{prefix}/share/%{name}/bin/usage.txt
|
||||
%{prefix}/share/%{name}/CHANGELOG.md
|
||||
%{prefix}/share/%{name}/CONTRIBUTING.md
|
||||
%{prefix}/share/%{name}/CONTRIBUTORS.md
|
||||
%{prefix}/share/%{name}/LICENSE.md
|
||||
%{prefix}/share/%{name}/README.md
|
||||
%{prefix}/share/%{name}/package.json
|
||||
%{prefix}/share/%{name}/modules/casper.js
|
||||
%{prefix}/share/%{name}/modules/cli.js
|
||||
%{prefix}/share/%{name}/modules/clientutils.js
|
||||
%{prefix}/share/%{name}/modules/colorizer.js
|
||||
%{prefix}/share/%{name}/modules/events.js
|
||||
%{prefix}/share/%{name}/modules/http.js
|
||||
%{prefix}/share/%{name}/modules/mouse.js
|
||||
%{prefix}/share/%{name}/modules/querystring.js
|
||||
%{prefix}/share/%{name}/modules/tester.js
|
||||
%{prefix}/share/%{name}/modules/utils.js
|
||||
%{prefix}/share/%{name}/modules/vendors/coffee-script.js
|
||||
%{prefix}/share/%{name}/modules/xunit.js
|
||||
%{prefix}/share/%{name}/samples/bbcshots.coffee
|
||||
%{prefix}/share/%{name}/samples/bbcshots.js
|
||||
%{prefix}/share/%{name}/samples/cliplay.coffee
|
||||
%{prefix}/share/%{name}/samples/cliplay.js
|
||||
%{prefix}/share/%{name}/samples/customevents.coffee
|
||||
%{prefix}/share/%{name}/samples/customevents.js
|
||||
%{prefix}/share/%{name}/samples/customlogging.coffee
|
||||
%{prefix}/share/%{name}/samples/customlogging.js
|
||||
%{prefix}/share/%{name}/samples/download.coffee
|
||||
%{prefix}/share/%{name}/samples/download.js
|
||||
%{prefix}/share/%{name}/samples/dynamic.coffee
|
||||
%{prefix}/share/%{name}/samples/dynamic.js
|
||||
%{prefix}/share/%{name}/samples/each.coffee
|
||||
%{prefix}/share/%{name}/samples/each.js
|
||||
%{prefix}/share/%{name}/samples/events.coffee
|
||||
%{prefix}/share/%{name}/samples/events.js
|
||||
%{prefix}/share/%{name}/samples/extends.coffee
|
||||
%{prefix}/share/%{name}/samples/extends.js
|
||||
%{prefix}/share/%{name}/samples/googlelinks.coffee
|
||||
%{prefix}/share/%{name}/samples/googlelinks.js
|
||||
%{prefix}/share/%{name}/samples/googlematch.coffee
|
||||
%{prefix}/share/%{name}/samples/googlematch.js
|
||||
%{prefix}/share/%{name}/samples/googlepagination.coffee
|
||||
%{prefix}/share/%{name}/samples/googlepagination.js
|
||||
%{prefix}/share/%{name}/samples/googletesting.coffee
|
||||
%{prefix}/share/%{name}/samples/googletesting.js
|
||||
%{prefix}/share/%{name}/samples/logcolor.coffee
|
||||
%{prefix}/share/%{name}/samples/logcolor.js
|
||||
%{prefix}/share/%{name}/samples/metaextract.coffee
|
||||
%{prefix}/share/%{name}/samples/metaextract.js
|
||||
%{prefix}/share/%{name}/samples/multirun.coffee
|
||||
%{prefix}/share/%{name}/samples/multirun.js
|
||||
%{prefix}/share/%{name}/samples/screenshot.coffee
|
||||
%{prefix}/share/%{name}/samples/screenshot.js
|
||||
%{prefix}/share/%{name}/samples/statushandlers.coffee
|
||||
%{prefix}/share/%{name}/samples/statushandlers.js
|
||||
%{prefix}/share/%{name}/samples/steptimeout.coffee
|
||||
%{prefix}/share/%{name}/samples/steptimeout.js
|
||||
%{prefix}/share/%{name}/samples/timeout.coffee
|
||||
%{prefix}/share/%{name}/samples/timeout.js
|
||||
%{prefix}/share/%{name}/tests/site/field-array.html
|
||||
%{prefix}/share/%{name}/tests/site/images/phantom.png
|
||||
%{prefix}/share/%{name}/tests/site/result.html
|
||||
%{prefix}/share/%{name}/tests/site/multiple-forms.html
|
||||
%{prefix}/share/%{name}/tests/site/global.html
|
||||
%{prefix}/share/%{name}/tests/site/elementattribute.html
|
||||
%{prefix}/share/%{name}/tests/site/urls.html
|
||||
%{prefix}/share/%{name}/tests/site/mouse-events.html
|
||||
%{prefix}/share/%{name}/tests/site/index.html
|
||||
%{prefix}/share/%{name}/tests/site/click.html
|
||||
%{prefix}/share/%{name}/tests/site/page1.html
|
||||
%{prefix}/share/%{name}/tests/site/prompt.html
|
||||
%{prefix}/share/%{name}/tests/site/error.html
|
||||
%{prefix}/share/%{name}/tests/site/dummy.js
|
||||
%{prefix}/share/%{name}/tests/site/page2.html
|
||||
%{prefix}/share/%{name}/tests/site/alert.html
|
||||
%{prefix}/share/%{name}/tests/site/form.html
|
||||
%{prefix}/share/%{name}/tests/site/confirm.html
|
||||
%{prefix}/share/%{name}/tests/site/resources.html
|
||||
%{prefix}/share/%{name}/tests/site/test.html
|
||||
%{prefix}/share/%{name}/tests/site/page3.html
|
||||
%{prefix}/share/%{name}/tests/site/visible.html
|
||||
%{prefix}/share/%{name}/tests/site/waitFor.html
|
||||
%{prefix}/share/%{name}/tests/sample_modules/csmodule.coffee
|
||||
%{prefix}/share/%{name}/tests/sample_modules/jsmodule.js
|
||||
%{prefix}/share/%{name}/tests/testdir/03_a.js
|
||||
%{prefix}/share/%{name}/tests/testdir/02_b/abc.js
|
||||
%{prefix}/share/%{name}/tests/testdir/04/02_do.js
|
||||
%{prefix}/share/%{name}/tests/testdir/04/01_init.js
|
||||
%{prefix}/share/%{name}/tests/testdir/01_a/abc.js
|
||||
%{prefix}/share/%{name}/tests/testdir/01_a/def.js
|
||||
%{prefix}/share/%{name}/tests/testdir/03_b.js
|
||||
%{prefix}/share/%{name}/tests/suites/casper/capture.js
|
||||
%{prefix}/share/%{name}/tests/suites/casper/prompt.js
|
||||
%{prefix}/share/%{name}/tests/suites/casper/resources.coffee
|
||||
%{prefix}/share/%{name}/tests/suites/casper/auth.js
|
||||
%{prefix}/share/%{name}/tests/suites/casper/alert.js
|
||||
%{prefix}/share/%{name}/tests/suites/casper/wait.js
|
||||
%{prefix}/share/%{name}/tests/suites/casper/flow.coffee
|
||||
%{prefix}/share/%{name}/tests/suites/casper/events.js
|
||||
%{prefix}/share/%{name}/tests/suites/casper/evaluate.js
|
||||
%{prefix}/share/%{name}/tests/suites/casper/logging.js
|
||||
%{prefix}/share/%{name}/tests/suites/casper/xpath.js
|
||||
%{prefix}/share/%{name}/tests/suites/casper/elementattribute.js
|
||||
%{prefix}/share/%{name}/tests/suites/casper/viewport.js
|
||||
%{prefix}/share/%{name}/tests/suites/casper/.casper
|
||||
%{prefix}/share/%{name}/tests/suites/casper/steps.js
|
||||
%{prefix}/share/%{name}/tests/suites/casper/exists.js
|
||||
%{prefix}/share/%{name}/tests/suites/casper/click.js
|
||||
%{prefix}/share/%{name}/tests/suites/casper/mouseevents.js
|
||||
%{prefix}/share/%{name}/tests/suites/casper/fetchtext.js
|
||||
%{prefix}/share/%{name}/tests/suites/casper/urls.js
|
||||
%{prefix}/share/%{name}/tests/suites/casper/open.js
|
||||
%{prefix}/share/%{name}/tests/suites/casper/agent.js
|
||||
%{prefix}/share/%{name}/tests/suites/casper/formfill.js
|
||||
%{prefix}/share/%{name}/tests/suites/casper/request.js
|
||||
%{prefix}/share/%{name}/tests/suites/casper/confirm.js
|
||||
%{prefix}/share/%{name}/tests/suites/casper/history.js
|
||||
%{prefix}/share/%{name}/tests/suites/casper/debug.js
|
||||
%{prefix}/share/%{name}/tests/suites/casper/global.js
|
||||
%{prefix}/share/%{name}/tests/suites/casper/encode.js
|
||||
%{prefix}/share/%{name}/tests/suites/casper/onerror.js
|
||||
%{prefix}/share/%{name}/tests/suites/casper/start.js
|
||||
%{prefix}/share/%{name}/tests/suites/casper/hooks.js
|
||||
%{prefix}/share/%{name}/tests/suites/casper/headers.js
|
||||
%{prefix}/share/%{name}/tests/suites/casper/visible.js
|
||||
%{prefix}/share/%{name}/tests/suites/coffee.coffee
|
||||
%{prefix}/share/%{name}/tests/suites/require.js
|
||||
%{prefix}/share/%{name}/tests/suites/cli.js
|
||||
%{prefix}/share/%{name}/tests/suites/fs.js
|
||||
%{prefix}/share/%{name}/tests/suites/.casper
|
||||
%{prefix}/share/%{name}/tests/suites/tester.js
|
||||
%{prefix}/share/%{name}/tests/suites/clientutils.js
|
||||
%{prefix}/share/%{name}/tests/suites/http_status.js
|
||||
%{prefix}/share/%{name}/tests/suites/xunit.js
|
||||
%{prefix}/share/%{name}/tests/suites/utils.js
|
||||
%{prefix}/share/%{name}/tests/selftest.js
|
||||
%{prefix}/share/%{name}/tests/run.js
|
||||
|
||||
%changelog
|
||||
* Mon Dec 24 2012 Nicolas Perriault <nicolas@perriault.net>
|
||||
- removed 'injector.js' module
|
||||
|
||||
* Mon Dec 10 2012 Jan Schaumann <jschauma@etsy.com>
|
||||
- include 'tests'
|
||||
|
||||
* Mon Nov 26 2012 Jan Schaumann <jschauma@etsy.com>
|
||||
- first rpm version
|
||||
25
zephyr/tests/frontend/casperjs/rpm/mkrpm.sh
Executable file
25
zephyr/tests/frontend/casperjs/rpm/mkrpm.sh
Executable file
@@ -0,0 +1,25 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# A silly little helper script to build the RPM.
|
||||
set -e
|
||||
|
||||
name=${1:?"Usage: build <toolname>"}
|
||||
name=${name%.spec}
|
||||
topdir=$(mktemp -d)
|
||||
version=$(awk '/define version/ { print $NF }' ${name}.spec)
|
||||
builddir=${TMPDIR:-/tmp}/${name}-${version}
|
||||
sourcedir="${topdir}/SOURCES"
|
||||
buildroot="${topdir}/BUILD/${name}-${version}-root"
|
||||
mkdir -p ${topdir}/RPMS ${topdir}/SRPMS ${topdir}/SOURCES ${topdir}/BUILD
|
||||
mkdir -p ${buildroot} ${builddir}
|
||||
echo "=> Copying sources..."
|
||||
( cd .. && tar cf - ./[A-Z]* ./package.json ./bin ./samples ./tests ./modules | tar xf - -C ${builddir} )
|
||||
echo "=> Creating source tarball under ${sourcedir}..."
|
||||
( cd ${builddir}/.. && tar zcf ${sourcedir}/${name}-${version}.tar.gz ${name}-${version} )
|
||||
echo "=> Building RPM..."
|
||||
#rpmbuild --define "_topdir ${topdir}" --buildroot ${buildroot} --clean -bb ${name}.spec
|
||||
rpm=$(rpmbuild --define "_topdir ${topdir}" --buildroot ${buildroot} --clean -bb ${name}.spec 2>/dev/null | \
|
||||
awk '/\/RPMS\// { print $2; }')
|
||||
cp ${rpm} ${TMPDIR:-/tmp}/
|
||||
rm -fr ${topdir}
|
||||
echo ${TMPDIR:-/tmp}/${rpm##*/}
|
||||
@@ -59,4 +59,4 @@ if system(CASPER_COMMAND.join(" ")).nil?
|
||||
puts "Fatal: Did you install phantomjs?"
|
||||
end
|
||||
|
||||
exit $?.exitstatus
|
||||
exit $?.exitstatus || 1
|
||||
|
||||
@@ -11,7 +11,7 @@ images = []
|
||||
casper.hide = (selector) ->
|
||||
@evaluate (selector) ->
|
||||
document.querySelector(selector).style.display = "none"
|
||||
, selector: selector
|
||||
, selector
|
||||
|
||||
casper.start "http://www.bbc.co.uk/", ->
|
||||
nbLinks = @evaluate ->
|
||||
@@ -21,7 +21,8 @@ casper.start "http://www.bbc.co.uk/", ->
|
||||
@hide ".nav_left"
|
||||
@hide ".nav_right"
|
||||
@mouse.move "#promo2_carousel"
|
||||
@waitUntilVisible ".autoplay.nav_pause", ->
|
||||
|
||||
casper.waitUntilVisible ".autoplay.nav_pause", ->
|
||||
@echo "Moving over pause button"
|
||||
@mouse.move ".autoplay.nav_pause"
|
||||
@click ".autoplay.nav_pause"
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
/*
|
||||
/*jshint strict:false*/
|
||||
/*global CasperError console phantom require*/
|
||||
|
||||
/**
|
||||
* Create a mosaic image from all headline photos on BBC homepage
|
||||
*/
|
||||
|
||||
var casper = require("casper").create();
|
||||
var nbLinks = 0;
|
||||
var currentLink = 1;
|
||||
@@ -12,9 +14,7 @@ var buildPage, next;
|
||||
casper.hide = function(selector) {
|
||||
this.evaluate(function(selector) {
|
||||
document.querySelector(selector).style.display = "none";
|
||||
}, {
|
||||
selector: selector
|
||||
});
|
||||
}, selector);
|
||||
};
|
||||
|
||||
casper.start("http://www.bbc.co.uk/", function() {
|
||||
@@ -26,7 +26,9 @@ casper.start("http://www.bbc.co.uk/", function() {
|
||||
this.hide(".nav_left");
|
||||
this.hide(".nav_right");
|
||||
this.mouse.move("#promo2_carousel");
|
||||
this.waitUntilVisible(".autoplay.nav_pause", function() {
|
||||
});
|
||||
|
||||
casper.waitUntilVisible(".autoplay.nav_pause", function() {
|
||||
this.echo("Moving over pause button");
|
||||
this.mouse.move(".autoplay.nav_pause");
|
||||
this.click(".autoplay.nav_pause");
|
||||
@@ -36,7 +38,6 @@ casper.start("http://www.bbc.co.uk/", function() {
|
||||
// hide play button
|
||||
this.hide(".autoplay");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Capture carrousel area
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
/*jshint strict:false*/
|
||||
/*global CasperError console phantom require*/
|
||||
|
||||
var casper = require("casper").create();
|
||||
var dump = require("utils").dump;
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
/*jshint strict:false*/
|
||||
/*global CasperError console phantom require*/
|
||||
|
||||
var casper = require("casper").create();
|
||||
|
||||
// listening to a custom event
|
||||
|
||||
@@ -2,15 +2,15 @@
|
||||
A basic custom logging implementation. The idea is to (extremely) verbosely
|
||||
log every received resource.
|
||||
###
|
||||
|
||||
casper = require("casper").create
|
||||
###
|
||||
Every time a resource is received, a new log entry is added to the stack
|
||||
at the 'verbose' level.
|
||||
verbose: true # we want to see the log printed out to the console
|
||||
logLevel: "verbose" # of course we want to see logs to our new level :)
|
||||
|
||||
@param Object resource A phantomjs resource object
|
||||
###
|
||||
onResourceReceived: (self, resource) ->
|
||||
###
|
||||
Every time a resource is received, a new log entry is added to the stack
|
||||
at the 'verbose' level.
|
||||
###
|
||||
casper.on 'resource.received', (resource) ->
|
||||
infos = []
|
||||
props = [
|
||||
"url"
|
||||
@@ -22,8 +22,6 @@ casper = require("casper").create
|
||||
infos.push resource[prop] for prop in props
|
||||
infos.push "[#{header.name}: #{header.value}]" for header in resource.headers
|
||||
@log infos.join(", "), "verbose"
|
||||
verbose: true # we want to see the log printed out to the console
|
||||
logLevel: "verbose" # of course we want to see logs to our new level :)
|
||||
|
||||
# add a new 'verbose' logging level at the lowest priority
|
||||
casper.logLevels = ["verbose"].concat casper.logLevels
|
||||
|
||||
@@ -1,36 +1,35 @@
|
||||
/*
|
||||
/*jshint strict:false*/
|
||||
/*global CasperError console phantom require*/
|
||||
|
||||
/**
|
||||
* A basic custom logging implementation. The idea is to (extremely) verbosely
|
||||
* log every received resource.
|
||||
*/
|
||||
|
||||
var casper = require("casper").create({
|
||||
/*
|
||||
Every time a resource is received, a new log entry is added to the stack at
|
||||
the 'verbose' level.
|
||||
verbose: true,
|
||||
logLevel: "verbose"
|
||||
});
|
||||
|
||||
/**
|
||||
* Every time a resource is received, a new log entry is added to the stack at
|
||||
* the 'verbose' level.
|
||||
*/
|
||||
onResourceReceived: function(self, resource) {
|
||||
var header, infos, prop, props, _i, _j, _len, _len1, _ref;
|
||||
infos = [];
|
||||
props = [
|
||||
casper.on('resource.received', function(resource) {
|
||||
var infos = [];
|
||||
var props = [
|
||||
"url",
|
||||
"status",
|
||||
"statusText",
|
||||
"redirectURL",
|
||||
"bodySize"
|
||||
];
|
||||
for (_i = 0, _len = props.length; _i < _len; _i++) {
|
||||
prop = props[_i];
|
||||
props.forEach(function(prop) {
|
||||
infos.push(resource[prop]);
|
||||
}
|
||||
_ref = resource.headers;
|
||||
for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) {
|
||||
header = _ref[_j];
|
||||
});
|
||||
resource.headers.forEach(function(header) {
|
||||
infos.push("[" + header.name + ": " + header.value + "]");
|
||||
}
|
||||
});
|
||||
this.log(infos.join(", "), "verbose");
|
||||
},
|
||||
verbose: true,
|
||||
logLevel: "verbose"
|
||||
});
|
||||
|
||||
// add a new 'verbose' logging level at the lowest priority
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
/*
|
||||
/*jshint strict:false*/
|
||||
/*global CasperError console phantom require*/
|
||||
|
||||
/**
|
||||
* download the google logo image onto the local filesystem
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
/*jshint strict:false*/
|
||||
/*global CasperError console phantom require*/
|
||||
|
||||
var casper = require("casper").create({
|
||||
verbose: true
|
||||
});
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
/*jshint strict:false*/
|
||||
/*global CasperError console phantom require*/
|
||||
|
||||
var casper = require("casper").create();
|
||||
|
||||
var links = [
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
/*
|
||||
/*jshint strict:false*/
|
||||
/*global CasperError console phantom require*/
|
||||
|
||||
/**
|
||||
* This script will add a custom HTTP status code handler, here for 404 pages.
|
||||
*/
|
||||
|
||||
var casper = require("casper").create();
|
||||
|
||||
casper.on("http.status.200", function(resource) {
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
/*jshint strict:false*/
|
||||
/*global CasperError console phantom require*/
|
||||
|
||||
var casper = require("casper").create({
|
||||
loadImages: false,
|
||||
logLevel: "debug",
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
/*jshint strict:false*/
|
||||
/*global CasperError console phantom require*/
|
||||
var links = [];
|
||||
var casper = require("casper").create();
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ casper = require("casper").create verbose: true
|
||||
|
||||
casper.fetchScore = ->
|
||||
@evaluate ->
|
||||
result = document.querySelector('#resultStats').innerText
|
||||
result = __utils__.findOne('#resultStats').innerText
|
||||
parseInt /Environ ([0-9\s]{1,}).*/.exec(result)[1].replace(/\s/g, '')
|
||||
|
||||
terms = casper.cli.args # terms are passed through command-line arguments
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
/*
|
||||
/*jshint strict:false*/
|
||||
/*global CasperError console phantom require*/
|
||||
|
||||
/**
|
||||
* Takes provided terms passed as arguments and query google for the number of
|
||||
* estimated results each have.
|
||||
*
|
||||
@@ -16,7 +19,7 @@ var casper = require("casper").create({
|
||||
|
||||
casper.fetchScore = function() {
|
||||
return this.evaluate(function() {
|
||||
var result = document.querySelector('#resultStats').innerText;
|
||||
var result = __utils__.findOne('#resultStats').innerText;
|
||||
return parseInt(/Environ ([0-9\s]{1,}).*/.exec(result)[1].replace(/\s/g, ''), 10);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
/*
|
||||
/*jshint strict:false*/
|
||||
/*global CasperError console phantom require*/
|
||||
|
||||
/**
|
||||
* Capture multiple pages of google search results
|
||||
*
|
||||
* Usage: $ casperjs googlepagination.coffee my search terms
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
/*jshint strict:false*/
|
||||
/*global CasperError console phantom require*/
|
||||
|
||||
var casper = require("casper").create({
|
||||
logLevel: "debug"
|
||||
});
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
/*jshint strict:false*/
|
||||
/*global CasperError console phantom require*/
|
||||
|
||||
var casper = require("casper").create({
|
||||
verbose: true,
|
||||
logLevel: "debug"
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
/*jshint strict:false*/
|
||||
/*global CasperError console phantom require*/
|
||||
|
||||
var casper = require("casper").create();
|
||||
var url = casper.cli.get(0);
|
||||
var metas = [];
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
/*jshint strict:false*/
|
||||
/*global CasperError console phantom require*/
|
||||
|
||||
var casper = require("casper").create({
|
||||
verbose: true
|
||||
});
|
||||
|
||||
@@ -16,8 +16,8 @@ if not twitterAccount or not filename or not /\.(png|jpg|pdf)$/i.test filename
|
||||
.echo("Usage: $ casperjs screenshot.coffee <twitter-account> <filename.[jpg|png|pdf]>")
|
||||
.exit(1)
|
||||
|
||||
casper.start "https://twitter.com/#!/#{twitterAccount}", ->
|
||||
@waitForSelector ".tweet-row", (->
|
||||
casper.start "https://twitter.com/#{twitterAccount}", ->
|
||||
@waitForSelector ".stream-container", (->
|
||||
@captureSelector filename, "html"
|
||||
@echo "Saved screenshot of #{@getCurrentUrl()} to #{filename}"
|
||||
), (->
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
/*
|
||||
/*jshint strict:false*/
|
||||
/*global CasperError console phantom require*/
|
||||
|
||||
/**
|
||||
* This script will capture a screenshot of a twitter account page
|
||||
* Usage: $ casperjs screenshot.coffee <twitter-account> <filename.[jpg|png|pdf]>
|
||||
* Usage: $ casperjs screenshot.js <twitter-account> <filename.[jpg|png|pdf]>
|
||||
*/
|
||||
|
||||
var casper = require("casper").create({
|
||||
@@ -15,13 +18,13 @@ var filename = casper.cli.get(1);
|
||||
|
||||
if (!twitterAccount || !filename || !/\.(png|jpg|pdf)$/i.test(filename)) {
|
||||
casper
|
||||
.echo("Usage: $ casperjs screenshot.coffee <twitter-account> <filename.[jpg|png|pdf]>")
|
||||
.echo("Usage: $ casperjs screenshot.js <twitter-account> <filename.[jpg|png|pdf]>")
|
||||
.exit(1)
|
||||
;
|
||||
}
|
||||
|
||||
casper.start("https://twitter.com/#!/" + twitterAccount, function() {
|
||||
this.waitForSelector(".tweet-row", (function() {
|
||||
casper.start("https://twitter.com/" + twitterAccount, function() {
|
||||
this.waitForSelector(".stream-container", (function() {
|
||||
this.captureSelector(filename, "html");
|
||||
this.echo("Saved screenshot of " + (this.getCurrentUrl()) + " to " + filename);
|
||||
}), (function() {
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
/*
|
||||
/*jshint strict:false*/
|
||||
/*global CasperError console phantom require*/
|
||||
|
||||
/**
|
||||
* This script will add a custom HTTP status code handler, here for 404 pages.
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
/*jshint strict:false*/
|
||||
/*global CasperError console phantom require*/
|
||||
|
||||
var failed = [];
|
||||
var start = null;
|
||||
var links = [
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
/*
|
||||
/*jshint strict:false*/
|
||||
/*global CasperError console phantom require*/
|
||||
|
||||
/**
|
||||
* Just a silly game.
|
||||
*
|
||||
* $ casperjs samples/timeout.js 500
|
||||
|
||||
23
zephyr/tests/frontend/casperjs/samples/translate.coffee
Normal file
23
zephyr/tests/frontend/casperjs/samples/translate.coffee
Normal file
@@ -0,0 +1,23 @@
|
||||
###
|
||||
Translation using the Google Translate Service.
|
||||
|
||||
Usage:
|
||||
|
||||
$ casperjs translate.coffee --target=fr "hello world"
|
||||
bonjour tout le monde
|
||||
###
|
||||
system = require("system")
|
||||
casper = require("casper").create()
|
||||
format = require("utils").format
|
||||
source = casper.cli.get("source") or "auto"
|
||||
target = casper.cli.get("target")
|
||||
text = casper.cli.get(0)
|
||||
result = undefined
|
||||
|
||||
casper.warn("The --target option is mandatory.").exit 1 unless target
|
||||
|
||||
casper.start(format("http://translate.google.com/#%s/%s/%s", source, target, text), ->
|
||||
@fill "form#gt-form", text: text
|
||||
).waitForSelector "span.hps", -> @echo @fetchText("#result_box")
|
||||
|
||||
casper.run()
|
||||
30
zephyr/tests/frontend/casperjs/samples/translate.js
Normal file
30
zephyr/tests/frontend/casperjs/samples/translate.js
Normal file
@@ -0,0 +1,30 @@
|
||||
/*jshint strict:false*/
|
||||
/*global CasperError console phantom require*/
|
||||
|
||||
/**
|
||||
* Translation using the Google Translate Service.
|
||||
*
|
||||
* Usage:
|
||||
*
|
||||
* $ casperjs translate.js --target=fr "hello world"
|
||||
* bonjour tout le monde
|
||||
*/
|
||||
var system = require('system'),
|
||||
casper = require('casper').create(),
|
||||
format = require('utils').format,
|
||||
source = casper.cli.get('source') || 'auto',
|
||||
target = casper.cli.get('target'),
|
||||
text = casper.cli.get(0),
|
||||
result;
|
||||
|
||||
if (!target) {
|
||||
casper.warn('The --target option is mandatory.').exit(1);
|
||||
}
|
||||
|
||||
casper.start(format('http://translate.google.com/#%s/%s/%s', source, target, text), function() {
|
||||
this.fill('form#gt-form', {text: text});
|
||||
}).waitForSelector('span.hps', function() {
|
||||
this.echo(this.fetchText("#result_box"));
|
||||
});
|
||||
|
||||
casper.run();
|
||||
14
zephyr/tests/frontend/casperjs/tests/commands/mytest.js
Normal file
14
zephyr/tests/frontend/casperjs/tests/commands/mytest.js
Normal file
@@ -0,0 +1,14 @@
|
||||
/*jshint strict:false*/
|
||||
/*global CasperError casper console phantom require*/
|
||||
casper.start('about:blank', function() {
|
||||
this.test.pass('ok1');
|
||||
});
|
||||
|
||||
casper.then(function() {
|
||||
this.test.pass('ok2');
|
||||
});
|
||||
|
||||
casper.run(function() {
|
||||
this.test.pass('ok3');
|
||||
this.test.done();
|
||||
});
|
||||
3
zephyr/tests/frontend/casperjs/tests/commands/script.js
Normal file
3
zephyr/tests/frontend/casperjs/tests/commands/script.js
Normal file
@@ -0,0 +1,3 @@
|
||||
var casper = require('casper').create();
|
||||
casper.echo('it works');
|
||||
casper.exit();
|
||||
@@ -1,4 +1,4 @@
|
||||
/*global phantom*/
|
||||
/*global phantom CasperError*/
|
||||
|
||||
if (!phantom.casperLoaded) {
|
||||
console.log('This script must be invoked using the casperjs executable');
|
||||
@@ -21,11 +21,9 @@ function checkSelfTest(tests) {
|
||||
var isCasperTest = false;
|
||||
tests.forEach(function(test) {
|
||||
var testDir = fs.absolute(fs.dirname(test));
|
||||
if (fs.isDirectory(testDir)) {
|
||||
if (fs.exists(fs.pathJoin(testDir, '.casper'))) {
|
||||
if (fs.isDirectory(testDir) && fs.exists(fs.pathJoin(testDir, '.casper'))) {
|
||||
isCasperTest = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
return isCasperTest;
|
||||
}
|
||||
@@ -52,35 +50,42 @@ function checkIncludeFile(include) {
|
||||
return absInclude;
|
||||
}
|
||||
|
||||
// parse some options from cli
|
||||
casper.options.verbose = casper.cli.get('direct') || false;
|
||||
casper.options.logLevel = casper.cli.get('log-level') || "error";
|
||||
if (casper.cli.get('no-colors') === true) {
|
||||
function checkArgs() {
|
||||
"use strict";
|
||||
// parse some options from cli
|
||||
casper.options.verbose = casper.cli.get('direct') || false;
|
||||
casper.options.logLevel = casper.cli.get('log-level') || "error";
|
||||
if (casper.cli.get('no-colors') === true) {
|
||||
var cls = 'Dummy';
|
||||
casper.options.colorizerType = cls;
|
||||
casper.colorizer = colorizer.create(cls);
|
||||
}
|
||||
}
|
||||
casper.test.options.failFast = casper.cli.get('fail-fast') || false;
|
||||
|
||||
// test paths are passed as args
|
||||
if (casper.cli.args.length) {
|
||||
// test paths are passed as args
|
||||
if (casper.cli.args.length) {
|
||||
tests = casper.cli.args.filter(function(path) {
|
||||
"use strict";
|
||||
return fs.isFile(path) || fs.isDirectory(path);
|
||||
if (fs.isFile(path) || fs.isDirectory(path)) {
|
||||
return true;
|
||||
}
|
||||
throw new CasperError(f("Invalid test path: %s", path));
|
||||
});
|
||||
} else {
|
||||
} else {
|
||||
casper.echo('No test path passed, exiting.', 'RED_BAR', 80);
|
||||
casper.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// check for casper selftests
|
||||
if (!phantom.casperSelfTest && checkSelfTest(tests)) {
|
||||
// check for casper selftests
|
||||
if (!phantom.casperSelfTest && checkSelfTest(tests)) {
|
||||
casper.warn('To run casper self tests, use the `selftest` command.');
|
||||
casper.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// includes handling
|
||||
this.loadIncludes.forEach(function(include){
|
||||
function initRunner() {
|
||||
"use strict";
|
||||
// includes handling
|
||||
loadIncludes.forEach(function(include){
|
||||
var container;
|
||||
if (casper.cli.has(include)) {
|
||||
container = casper.cli.get(include).split(',').map(function(file) {
|
||||
@@ -88,16 +93,29 @@ this.loadIncludes.forEach(function(include){
|
||||
}).filter(function(file) {
|
||||
return utils.isString(file);
|
||||
});
|
||||
|
||||
casper.test.loadIncludes[include] = utils.unique(container);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// test suites completion listener
|
||||
casper.test.on('tests.complete', function() {
|
||||
"use strict";
|
||||
// test suites completion listener
|
||||
casper.test.on('tests.complete', function() {
|
||||
this.renderResults(true, undefined, casper.cli.get('xunit') || undefined);
|
||||
});
|
||||
if (this.options.failFast && this.testResults.failures.length > 0) {
|
||||
casper.warn('Test suite failed fast, all tests may not have been executed.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// run all the suites
|
||||
casper.test.runSuites.apply(casper.test, tests);
|
||||
var error;
|
||||
try {
|
||||
checkArgs();
|
||||
} catch (e) {
|
||||
error = true;
|
||||
casper.warn(e);
|
||||
casper.exit(1);
|
||||
}
|
||||
|
||||
if (!error) {
|
||||
initRunner();
|
||||
casper.test.runSuites.apply(casper.test, tests);
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
{"ok": true}
|
||||
@@ -1,5 +1 @@
|
||||
try
|
||||
exports.ok = true
|
||||
catch e
|
||||
casper.test.fail('error in coffeescript module code: ' + e)
|
||||
casper.test.done()
|
||||
exports.ok = true
|
||||
|
||||
@@ -1,7 +1 @@
|
||||
/*global casper*/
|
||||
try {
|
||||
exports.ok = true;
|
||||
} catch (e) {
|
||||
casper.test.fail('error in js module code' + e);
|
||||
casper.test.done()
|
||||
}
|
||||
exports.ok = true;
|
||||
|
||||
@@ -28,7 +28,11 @@ service = server.listen(testServerPort, function(request, response) {
|
||||
console.log(utils.format('Test server url not found: %s (file: %s)', request.url, pageFile), "warning");
|
||||
response.write("404 - NOT FOUND");
|
||||
} else {
|
||||
response.statusCode = 200;
|
||||
var headers = {};
|
||||
if (/js$/.test(pageFile)) {
|
||||
headers['Content-Type'] = "application/javascript";
|
||||
}
|
||||
response.writeHead(200, headers);
|
||||
response.write(fs.read(pageFile));
|
||||
}
|
||||
response.close();
|
||||
|
||||
@@ -19,7 +19,8 @@
|
||||
testdown: [],
|
||||
testup: [],
|
||||
testmove: [],
|
||||
testclick: []
|
||||
testclick: [],
|
||||
testdoubleclick: []
|
||||
};
|
||||
document.querySelector('#test4').onclick = function(event) {
|
||||
results.test4 = true;
|
||||
@@ -34,6 +35,9 @@
|
||||
window.onmousemove = function(event) {
|
||||
results.testmove = [event.x, event.y];
|
||||
};
|
||||
window.ondblclick = function(event) {
|
||||
results.testdoubleclick = [event.x, event.y];
|
||||
};
|
||||
})(window);
|
||||
</script>
|
||||
</body>
|
||||
|
||||
14
zephyr/tests/frontend/casperjs/tests/site/field-array.html
Normal file
14
zephyr/tests/frontend/casperjs/tests/site/field-array.html
Normal file
@@ -0,0 +1,14 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<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="foo[bar]">
|
||||
<input type="text" name="foo[baz]">
|
||||
<input type="submit" name="submit" value="submit">
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
10
zephyr/tests/frontend/casperjs/tests/site/frame1.html
Normal file
10
zephyr/tests/frontend/casperjs/tests/site/frame1.html
Normal file
@@ -0,0 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<title>CasperJS frame 1</title>
|
||||
</head>
|
||||
<body id="f1">
|
||||
<h1>This is frame 1.</h1>
|
||||
</body>
|
||||
</html>
|
||||
11
zephyr/tests/frontend/casperjs/tests/site/frame2.html
Normal file
11
zephyr/tests/frontend/casperjs/tests/site/frame2.html
Normal file
@@ -0,0 +1,11 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<title>CasperJS frame 2</title>
|
||||
</head>
|
||||
<body id="f2">
|
||||
<h1>This is frame 2.</h1>
|
||||
<p><a href="frame3.html" target="frame2">frame 3</a></p>
|
||||
</body>
|
||||
</html>
|
||||
11
zephyr/tests/frontend/casperjs/tests/site/frame3.html
Normal file
11
zephyr/tests/frontend/casperjs/tests/site/frame3.html
Normal file
@@ -0,0 +1,11 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<title>CasperJS frame 3</title>
|
||||
</head>
|
||||
<body id="f3">
|
||||
<h1>This is frame 3.</h1>
|
||||
<p><a href="frame2.html">frame 2</a></p>
|
||||
</body>
|
||||
</html>
|
||||
12
zephyr/tests/frontend/casperjs/tests/site/frames.html
Normal file
12
zephyr/tests/frontend/casperjs/tests/site/frames.html
Normal file
@@ -0,0 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<title>CasperJS test frames</title>
|
||||
</head>
|
||||
<frameset cols="50%,50%%">
|
||||
<frame src="frame1.html" name="frame1">
|
||||
<frame src="frame2.html" name="frame2">
|
||||
</frameset>
|
||||
</html>
|
||||
|
||||
@@ -4,6 +4,11 @@
|
||||
<script type="text/javascript">
|
||||
var myGlobal = 'awesome string';
|
||||
var myUnencodableGlobal = document;
|
||||
var myObject = {
|
||||
foo: {
|
||||
bar: 'baz'
|
||||
}
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,6 @@
|
||||
(function() {
|
||||
var elem = document.createElement('div');
|
||||
elem.setAttribute('id', 'include1');
|
||||
elem.appendChild(document.createTextNode('include1'));
|
||||
document.querySelector('body').appendChild(elem);
|
||||
})();
|
||||
@@ -0,0 +1,6 @@
|
||||
(function() {
|
||||
var elem = document.createElement('div');
|
||||
elem.setAttribute('id', 'include2');
|
||||
elem.appendChild(document.createTextNode('include2'));
|
||||
document.querySelector('body').appendChild(elem);
|
||||
})();
|
||||
19
zephyr/tests/frontend/casperjs/tests/site/popup.html
Normal file
19
zephyr/tests/frontend/casperjs/tests/site/popup.html
Normal file
@@ -0,0 +1,19 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<title>CasperJS test popup</title>
|
||||
</head>
|
||||
<a href="." class="close">close</a>
|
||||
<body>
|
||||
<a href="/tests/site/form.html" target="_blank">new window</a>
|
||||
<script>
|
||||
var w = window.open("http://localhost:54321/tests/site/index.html",
|
||||
"popup", "menubar=no, status=no, scrollbars=no, menubar=no, width=400, height=300");
|
||||
document.querySelector('a').onclick = function onclick(evt) {
|
||||
evt.preventDefault();
|
||||
w.close();
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -22,5 +22,5 @@ casper.thenOpen('tests/site/index.html');
|
||||
|
||||
casper.run(function() {
|
||||
this.removeListener('resource.requested', fetchUA);
|
||||
this.test.done();
|
||||
this.test.done(3);
|
||||
});
|
||||
|
||||
14
zephyr/tests/frontend/casperjs/tests/suites/casper/alert.js
Normal file
14
zephyr/tests/frontend/casperjs/tests/suites/casper/alert.js
Normal file
@@ -0,0 +1,14 @@
|
||||
/*global casper*/
|
||||
/*jshint strict:false*/
|
||||
|
||||
var ok = false;
|
||||
|
||||
casper.on('remote.alert', function(message) {
|
||||
ok = message === 'plop';
|
||||
});
|
||||
|
||||
casper.start('tests/site/alert.html').run(function() {
|
||||
this.test.assert(ok, 'alert event has been intercepted');
|
||||
this.removeAllListeners('remote.alert');
|
||||
this.test.done(1);
|
||||
});
|
||||
24
zephyr/tests/frontend/casperjs/tests/suites/casper/auth.js
Normal file
24
zephyr/tests/frontend/casperjs/tests/suites/casper/auth.js
Normal file
@@ -0,0 +1,24 @@
|
||||
/*global casper*/
|
||||
/*jshint strict:false maxstatements:99*/
|
||||
|
||||
casper.start('tests/site/index.html');
|
||||
|
||||
casper.configureHttpAuth('http://localhost/');
|
||||
casper.test.assertEquals(casper.page.settings.userName, undefined);
|
||||
casper.test.assertEquals(casper.page.settings.password, undefined);
|
||||
|
||||
casper.configureHttpAuth('http://niko:plop@localhost/');
|
||||
casper.test.assertEquals(casper.page.settings.userName, 'niko');
|
||||
casper.test.assertEquals(casper.page.settings.password, 'plop');
|
||||
|
||||
casper.configureHttpAuth('http://localhost/', {username: 'john', password: 'doe'});
|
||||
casper.test.assertEquals(casper.page.settings.userName, 'john');
|
||||
casper.test.assertEquals(casper.page.settings.password, 'doe');
|
||||
|
||||
casper.configureHttpAuth('http://niko:plop@localhost/', {username: 'john', password: 'doe'});
|
||||
casper.test.assertEquals(casper.page.settings.userName, 'niko');
|
||||
casper.test.assertEquals(casper.page.settings.password, 'plop');
|
||||
|
||||
casper.run(function() {
|
||||
this.test.done(8);
|
||||
});
|
||||
@@ -13,8 +13,7 @@ casper.start('tests/site/index.html', function() {
|
||||
this.test.assert(fs.isFile(testFile), 'Casper.capture() captured a screenshot');
|
||||
});
|
||||
|
||||
if (phantom.version.major === 1 && phantom.version.minor >= 6) {
|
||||
casper.thenOpen('tests/site/index.html', function() {
|
||||
casper.thenOpen('tests/site/index.html', function() {
|
||||
this.test.comment('Casper.captureBase64()');
|
||||
this.test.assert(this.captureBase64('png').length > 0,
|
||||
'Casper.captureBase64() rendered a page capture as base64');
|
||||
@@ -22,12 +21,11 @@ if (phantom.version.major === 1 && phantom.version.minor >= 6) {
|
||||
'Casper.captureBase64() rendered a capture from a selector as base64');
|
||||
this.test.assert(this.captureBase64('png', {top: 0, left: 0, width: 30, height: 30}).length > 0,
|
||||
'Casper.captureBase64() rendered a capture from a clipRect as base64');
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
casper.run(function() {
|
||||
try {
|
||||
fs.remove(testFile);
|
||||
} catch(e) {}
|
||||
this.test.done();
|
||||
this.test.done(4);
|
||||
});
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
/*global casper*/
|
||||
/*jshint strict:false*/
|
||||
/*jshint strict:false maxstatements: 99*/
|
||||
var utils = require('utils');
|
||||
|
||||
casper.start('tests/site/index.html', function() {
|
||||
this.click('a[href="test.html"]');
|
||||
});
|
||||
@@ -56,8 +58,26 @@ casper.then(function() {
|
||||
this.mouse.move(200, 100);
|
||||
results = this.getGlobal('results');
|
||||
this.test.assertEquals(results.testmove, [200, 100], 'Mouse.move() has moved to the specified position');
|
||||
|
||||
if (utils.gteVersion(phantom.version, '1.8.0')) {
|
||||
this.test.comment('Mouse.doubleclick()');
|
||||
this.mouse.doubleclick(200, 100);
|
||||
results = this.getGlobal('results');
|
||||
this.test.assertEquals(results.testdoubleclick, [200, 100],
|
||||
'Mouse.doubleclick() double-clicked the specified position');
|
||||
} else {
|
||||
this.test.pass("Mouse.doubleclick() requires PhantomJS >= 1.8");
|
||||
}
|
||||
});
|
||||
|
||||
// element focus on click
|
||||
casper.then(function() {
|
||||
this.page.content = '<form><input type="text" name="foo"></form>'
|
||||
this.click('form input[name=foo]')
|
||||
this.page.sendEvent('keypress', 'bar');
|
||||
this.test.assertEquals(this.getFormValues('form')['foo'], 'bar', 'Casper.click() sets the focus on clicked element');
|
||||
});
|
||||
|
||||
casper.run(function() {
|
||||
this.test.done();
|
||||
this.test.done(23);
|
||||
});
|
||||
|
||||
@@ -1,23 +1,29 @@
|
||||
/*global casper*/
|
||||
/*jshint strict:false*/
|
||||
// skip this test for phantom versions < 1.5
|
||||
if (phantom.version.major === 1 && phantom.version.minor < 6) {
|
||||
casper.test.comment('Skipped tests, PhantomJS 1.6 required');
|
||||
casper.test.done();
|
||||
} else {
|
||||
var received;
|
||||
var received;
|
||||
|
||||
casper.setFilter('page.confirm', function(message) {
|
||||
casper.setFilter('page.confirm', function(message) {
|
||||
received = message;
|
||||
return true;
|
||||
});
|
||||
});
|
||||
|
||||
casper.start('tests/site/confirm.html', function() {
|
||||
this.test.assert(this.getGlobal('confirmed'), 'confirmation received');
|
||||
});
|
||||
casper.start('tests/site/confirm.html', function() {
|
||||
this.test.assert(this.getGlobal('confirmed'), 'confirmation dialog accepted');
|
||||
});
|
||||
|
||||
casper.run(function() {
|
||||
casper.then(function() {
|
||||
//remove the page.confirm event filter so we can add a new one
|
||||
casper.removeAllFilters('page.confirm')
|
||||
casper.setFilter('page.confirm', function(message) {
|
||||
return false;
|
||||
});
|
||||
});
|
||||
|
||||
casper.thenOpen('/tests/site/confirm.html', function() {
|
||||
this.test.assertNot(this.getGlobal('confirmed'), 'confirmation dialog canceled');
|
||||
});
|
||||
|
||||
casper.run(function() {
|
||||
this.test.assertEquals(received, 'are you sure?', 'confirmation message is ok');
|
||||
this.test.done();
|
||||
});
|
||||
}
|
||||
this.test.done(3);
|
||||
});
|
||||
|
||||
@@ -6,5 +6,5 @@ casper.start('tests/site/index.html', function() {
|
||||
});
|
||||
|
||||
casper.run(function() {
|
||||
casper.test.done();
|
||||
casper.test.done(2);
|
||||
});
|
||||
|
||||
@@ -6,5 +6,5 @@ casper.start('tests/site/elementattribute.html', function() {
|
||||
});
|
||||
|
||||
casper.run(function() {
|
||||
this.test.done();
|
||||
this.test.done(1);
|
||||
});
|
||||
|
||||
@@ -20,5 +20,5 @@ casper.start('file://' + phantom.casperPath + '/tests/site/index.html', function
|
||||
});
|
||||
|
||||
casper.run(function() {
|
||||
this.test.done();
|
||||
this.test.done(2);
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*global casper*/
|
||||
/*jshint strict:false*/
|
||||
/*jshint strict:false maxparams:99*/
|
||||
casper.test.comment('Casper.evaluate()');
|
||||
|
||||
casper.start();
|
||||
@@ -32,4 +32,56 @@ casper.test.assertEquals(result.toString(),
|
||||
['boolean', 'boolean', 'number', 'number', 'string', 'object', 'object', 'function'].toString(),
|
||||
'Casper.evaluate() handles passed argument context correcly');
|
||||
|
||||
casper.test.done();
|
||||
// no context
|
||||
casper.test.assertEquals(casper.evaluate(function() {
|
||||
return 42;
|
||||
}), 42, 'Casper.evaluate() handles evaluation with no context passed');
|
||||
|
||||
// object context (previous casperjs versions compatibility mode)
|
||||
casper.test.assertEquals(casper.evaluate(function(a) {
|
||||
return [a];
|
||||
}, {a: "foo"}), ["foo"], 'Casper.evaluate() accepts an object as arguments context');
|
||||
casper.test.assertEquals(casper.evaluate(function(a, b) {
|
||||
return [a, b];
|
||||
}, {a: "foo", b: "bar"}), ["foo", "bar"], 'Casper.evaluate() accepts an object as arguments context');
|
||||
casper.test.assertEquals(casper.evaluate(function(a, b, c) {
|
||||
return [a, b, c];
|
||||
}, {a: "foo", b: "bar", c: "baz"}), ["foo", "bar", "baz"], 'Casper.evaluate() accepts an object as arguments context');
|
||||
|
||||
// array context
|
||||
casper.test.assertEquals(casper.evaluate(function(a) {
|
||||
return [a];
|
||||
}, ["foo"]), ["foo"], 'Casper.evaluate() accepts an array as arguments context');
|
||||
casper.test.assertEquals(casper.evaluate(function(a, b) {
|
||||
return [a, b];
|
||||
}, ["foo", "bar"]), ["foo", "bar"], 'Casper.evaluate() accepts an array as arguments context');
|
||||
casper.test.assertEquals(casper.evaluate(function(a, b, c) {
|
||||
return [a, b, c];
|
||||
}, ["foo", "bar", "baz"]), ["foo", "bar", "baz"], 'Casper.evaluate() accepts an array as arguments context');
|
||||
|
||||
// natural arguments context (phantomjs equivalent)
|
||||
casper.test.assertEquals(casper.evaluate(function(a) {
|
||||
return [a];
|
||||
}, "foo"), ["foo"], 'Casper.evaluate() accepts natural arguments context');
|
||||
casper.test.assertEquals(casper.evaluate(function(a, b) {
|
||||
return [a, b];
|
||||
}, "foo", "bar"), ["foo", "bar"], 'Casper.evaluate() accepts natural arguments context');
|
||||
casper.test.assertEquals(casper.evaluate(function(a, b, c) {
|
||||
return [a, b, c];
|
||||
}, "foo", "bar", "baz"), ["foo", "bar", "baz"], 'Casper.evaluate() accepts natural arguments context');
|
||||
|
||||
casper.start().thenEvaluate(function(a, b) {
|
||||
window.a = a
|
||||
window.b = b;
|
||||
}, "foo", "bar");
|
||||
|
||||
casper.then(function() {
|
||||
this.test.comment('Casper.thenEvaluate()');
|
||||
this.test.assertEquals(this.getGlobal('a'), "foo", "Casper.thenEvaluate() sets args");
|
||||
this.test.assertEquals(this.getGlobal('b'), "bar",
|
||||
"Casper.thenEvaluate() sets args the same way evaluate() does");
|
||||
});
|
||||
|
||||
casper.run(function() {
|
||||
this.test.done(13);
|
||||
});
|
||||
|
||||
@@ -37,4 +37,4 @@ casper.test.assertEquals(casper.foo, 42, "filter() applies the correct context")
|
||||
|
||||
delete casper.foo;
|
||||
|
||||
casper.test.done();
|
||||
casper.test.done(5);
|
||||
|
||||
@@ -7,5 +7,5 @@ casper.start('tests/site/index.html', function() {
|
||||
});
|
||||
|
||||
casper.run(function() {
|
||||
this.test.done();
|
||||
this.test.done(1);
|
||||
});
|
||||
|
||||
@@ -7,5 +7,5 @@ casper.start('tests/site/index.html', function() {
|
||||
});
|
||||
|
||||
casper.run(function() {
|
||||
this.test.done();
|
||||
this.test.done(1);
|
||||
});
|
||||
|
||||
@@ -35,4 +35,4 @@ casper.then ->
|
||||
casper.then ->
|
||||
@test.assertEquals ++step, 13, "last step"
|
||||
|
||||
casper.run(-> @test.done())
|
||||
casper.run(-> @test.done(13))
|
||||
|
||||
@@ -41,6 +41,23 @@ casper.start('tests/site/form.html', function() {
|
||||
!document.querySelector('input[name="checklist[]"][value="2"]').checked &&
|
||||
document.querySelector('input[name="checklist[]"][value="3"]').checked);
|
||||
}, true, 'Casper.fill() can fill a list of checkboxes');
|
||||
|
||||
});
|
||||
|
||||
casper.then(function() {
|
||||
this.test.comment('Casper.getFormValues()');
|
||||
this.test.assertEquals(this.getFormValues('form'), {
|
||||
"check": true,
|
||||
"checklist[]": ["1", "3"],
|
||||
"choice": "no",
|
||||
"content": "Am watching thou",
|
||||
"email": "chuck@norris.com",
|
||||
"file": "C:\\fakepath\\README.md",
|
||||
"password": "chuck",
|
||||
"submit": "submit",
|
||||
"topic": "bar"
|
||||
}, 'Casper.getFormValues() retrieves filled values');
|
||||
this.test.comment('submitting form');
|
||||
this.click('input[type="submit"]');
|
||||
});
|
||||
|
||||
@@ -54,6 +71,33 @@ casper.then(function() {
|
||||
this.test.assertUrlMatch(/topic=bar/, 'Casper.fill() select field was submitted');
|
||||
});
|
||||
|
||||
casper.thenOpen('tests/site/form.html', function() {
|
||||
this.fill('form[action="result.html"]', {
|
||||
email: 'chuck@norris.com',
|
||||
password: 'chuck',
|
||||
content: 'Am watching thou',
|
||||
check: true,
|
||||
choice: 'yes',
|
||||
topic: 'bar',
|
||||
file: phantom.libraryPath + '/README.md',
|
||||
'checklist[]': ['1', '3']
|
||||
});
|
||||
});
|
||||
|
||||
casper.then(function() {
|
||||
this.test.assertEquals(this.getFormValues('form'), {
|
||||
"check": true,
|
||||
"checklist[]": ["1", "3"],
|
||||
"choice": "yes",
|
||||
"content": "Am watching thou",
|
||||
"email": "chuck@norris.com",
|
||||
"file": "C:\\fakepath\\README.md",
|
||||
"password": "chuck",
|
||||
"submit": "submit",
|
||||
"topic": "bar"
|
||||
}, 'Casper.getFormValues() correctly retrieves values from radio inputs regardless of order');
|
||||
});
|
||||
|
||||
casper.thenOpen('tests/site/form.html', function() {
|
||||
this.test.comment('Unexistent fields');
|
||||
this.test.assertRaises(this.fill, ['form[action="result.html"]', {
|
||||
@@ -67,12 +111,21 @@ casper.thenOpen('tests/site/multiple-forms.html', function() {
|
||||
this.fill('form[name="f2"]', {
|
||||
yo: "ok"
|
||||
}, true);
|
||||
});
|
||||
|
||||
casper.then(function() {
|
||||
}).then(function() {
|
||||
this.test.assertUrlMatch(/\?f=f2&yo=ok$/, 'Casper.fill() handles multiple forms');
|
||||
});
|
||||
|
||||
casper.run(function() {
|
||||
this.test.done();
|
||||
// issue #267: array syntax field names
|
||||
casper.thenOpen('tests/site/field-array.html', function() {
|
||||
this.test.comment('Field arrays');
|
||||
this.fill('form', {
|
||||
'foo[bar]': "bar",
|
||||
'foo[baz]': "baz"
|
||||
}, true);
|
||||
}).then(function() {
|
||||
this.test.assertUrlMatch('?foo[bar]=bar&foo[baz]=baz', 'Casper.fill() handles array syntax field names');
|
||||
});
|
||||
|
||||
casper.run(function() {
|
||||
this.test.done(20);
|
||||
});
|
||||
|
||||
43
zephyr/tests/frontend/casperjs/tests/suites/casper/frames.js
Normal file
43
zephyr/tests/frontend/casperjs/tests/suites/casper/frames.js
Normal file
@@ -0,0 +1,43 @@
|
||||
/*global casper __utils__*/
|
||||
/*jshint strict:false*/
|
||||
casper.start('tests/site/frames.html');
|
||||
|
||||
casper.withFrame('frame1', function() {
|
||||
this.test.assertTitle('CasperJS frame 1');
|
||||
this.test.assertExists("#f1");
|
||||
this.test.assertDoesntExist("#f2");
|
||||
this.test.assertEval(function() {
|
||||
return '__utils__' in window && 'getBinary' in __utils__;
|
||||
}, '__utils__ object is available in child frame');
|
||||
this.test.assertMatches(this.page.frameContent, /This is frame 1/);
|
||||
this.test.assertMatches(this.getHTML(), /This is frame 1/);
|
||||
});
|
||||
|
||||
casper.withFrame('frame2', function() {
|
||||
this.test.assertTitle('CasperJS frame 2');
|
||||
this.test.assertExists("#f2");
|
||||
this.test.assertDoesntExist("#f1");
|
||||
this.test.assertEval(function() {
|
||||
return '__utils__' in window && 'getBinary' in __utils__;
|
||||
}, '__utils__ object is available in other child frame');
|
||||
this.clickLabel('frame 3');
|
||||
});
|
||||
|
||||
casper.withFrame('frame2', function() {
|
||||
this.test.assertTitle('CasperJS frame 3');
|
||||
});
|
||||
|
||||
casper.withFrame(0, function() {
|
||||
this.test.assertTitle('CasperJS frame 1');
|
||||
this.test.assertExists("#f1");
|
||||
this.test.assertDoesntExist("#f2");
|
||||
});
|
||||
|
||||
casper.withFrame(1, function() {
|
||||
this.test.assertTitle('CasperJS frame 3');
|
||||
});
|
||||
|
||||
casper.run(function() {
|
||||
this.test.assertTitle('CasperJS test frames');
|
||||
this.test.done(16);
|
||||
});
|
||||
@@ -2,10 +2,14 @@
|
||||
/*jshint strict:false*/
|
||||
casper.start('tests/site/global.html', function() {
|
||||
this.test.comment('Casper.getGlobal()');
|
||||
this.test.assertEquals(this.getGlobal('myGlobal'), 'awesome string', 'Casper.getGlobal() can retrieve a remote global variable');
|
||||
this.test.assertRaises(this.getGlobal, ['myUnencodableGlobal'], 'Casper.getGlobal() does not fail trying to encode an unencodable global');
|
||||
this.test.assertEquals(this.getGlobal('myGlobal'), 'awesome string',
|
||||
'Casper.getGlobal() can retrieve a remote global variable');
|
||||
this.test.assertEquals(this.getGlobal('myObject').foo.bar, 'baz',
|
||||
'Casper.getGlobal() can retrieves a serializable object');
|
||||
this.test.assertRaises(this.getGlobal, ['myUnencodableGlobal'],
|
||||
'Casper.getGlobal() does not fail trying to encode an unserializable global');
|
||||
});
|
||||
|
||||
casper.run(function() {
|
||||
this.test.done();
|
||||
this.test.done(3);
|
||||
});
|
||||
|
||||
@@ -37,5 +37,5 @@ casper.thenOpen('http://localhost:8090/', function thenLocalhost(response) {
|
||||
|
||||
casper.run(function() {
|
||||
server.close();
|
||||
this.test.done();
|
||||
this.test.done(4);
|
||||
});
|
||||
|
||||
@@ -19,5 +19,5 @@ casper.then(function() {
|
||||
casper.run(function() {
|
||||
this.test.assert(this.history.length > 0, 'Casper.history contains urls');
|
||||
this.test.assertMatch(this.history[0], /tests\/site\/page1\.html$/, 'Casper.history has the correct first url');
|
||||
this.test.done();
|
||||
this.test.done(4);
|
||||
});
|
||||
|
||||
@@ -39,5 +39,5 @@ casper.then(function() {
|
||||
|
||||
casper.run(function() {
|
||||
this.options.onAlert = null;
|
||||
this.test.done();
|
||||
this.test.done(5);
|
||||
});
|
||||
|
||||
15
zephyr/tests/frontend/casperjs/tests/suites/casper/keys.js
Normal file
15
zephyr/tests/frontend/casperjs/tests/suites/casper/keys.js
Normal file
@@ -0,0 +1,15 @@
|
||||
/*jshint strict:false*/
|
||||
/*global CasperError casper console phantom require*/
|
||||
casper.start('tests/site/form.html', function() {
|
||||
this.sendKeys('input[name="email"]', 'duke@nuk.em');
|
||||
this.sendKeys('textarea', "Damn, I’m looking good.");
|
||||
var values = this.getFormValues('form');
|
||||
this.test.assertEquals(values['email'], 'duke@nuk.em',
|
||||
'Casper.sendKeys() sends keys to given input');
|
||||
this.test.assertEquals(values['content'], "Damn, I’m looking good.",
|
||||
'Casper.sendKeys() sends keys to given textarea');
|
||||
});
|
||||
|
||||
casper.run(function() {
|
||||
this.test.done(2);
|
||||
});
|
||||
@@ -0,0 +1,23 @@
|
||||
/*jshint strict:false*/
|
||||
/*global CasperError casper console phantom require*/
|
||||
var utils = require('utils')
|
||||
|
||||
if (utils.ltVersion(phantom.version, '1.8.0')) {
|
||||
// https://github.com/n1k0/casperjs/issues/101
|
||||
casper.warn('document.location is broken under phantomjs < 1.8');
|
||||
casper.test.done();
|
||||
} else {
|
||||
casper.start('tests/site/index.html', function() {
|
||||
this.evaluate(function() {
|
||||
document.location = '/tests/site/form.html';
|
||||
});
|
||||
});
|
||||
|
||||
casper.then(function() {
|
||||
this.test.assertUrlMatches(/form\.html$/);
|
||||
});
|
||||
|
||||
casper.run(function() {
|
||||
this.test.done();
|
||||
});
|
||||
}
|
||||
@@ -36,5 +36,5 @@ casper.then(function() {
|
||||
|
||||
casper.run(function() {
|
||||
this.test.assertEquals(this.result.log.length, 3, 'Casper.log() logged messages');
|
||||
this.test.done();
|
||||
this.test.done(4);
|
||||
});
|
||||
|
||||
@@ -25,5 +25,5 @@ casper.then(function() {
|
||||
});
|
||||
|
||||
casper.run(function() {
|
||||
this.test.done();
|
||||
this.test.done(16);
|
||||
});
|
||||
|
||||
@@ -17,5 +17,5 @@ casper.thenOpen('tests/site/error.html', function() {
|
||||
});
|
||||
|
||||
casper.run(function() {
|
||||
this.test.done();
|
||||
this.test.done(2);
|
||||
});
|
||||
|
||||
@@ -48,7 +48,7 @@ var t = casper.test, current = 0, tests = [
|
||||
username: 'bob',
|
||||
password: 'sinclar'
|
||||
}, "Casper.thenOpen() used the expected HTTP auth settings");
|
||||
},
|
||||
}
|
||||
];
|
||||
|
||||
casper.start();
|
||||
@@ -131,5 +131,5 @@ casper.thenOpen('tests/site/index.html', {
|
||||
|
||||
casper.run(function() {
|
||||
this.removeAllListeners('open');
|
||||
t.done();
|
||||
t.done(16);
|
||||
});
|
||||
|
||||
86
zephyr/tests/frontend/casperjs/tests/suites/casper/popup.js
Normal file
86
zephyr/tests/frontend/casperjs/tests/suites/casper/popup.js
Normal file
@@ -0,0 +1,86 @@
|
||||
/*jshint strict:false*/
|
||||
/*global CasperError casper console phantom require*/
|
||||
var utils = require('utils');
|
||||
var x = require('casper').selectXPath;
|
||||
|
||||
casper.on('popup.created', function(popup) {
|
||||
this.test.pass('"popup.created" event is fired');
|
||||
this.test.assert(utils.isWebPage(popup),
|
||||
'"popup.created" event callback get a popup page instance');
|
||||
});
|
||||
|
||||
casper.on('popup.loaded', function(popup) {
|
||||
this.test.pass('"popup.loaded" event is fired');
|
||||
this.test.assertEquals(popup.evaluate(function() {
|
||||
return document.title;
|
||||
}), 'CasperJS test index',
|
||||
'"popup.loaded" is triggered when popup content is actually loaded');
|
||||
});
|
||||
|
||||
casper.on('popup.closed', function(popup) {
|
||||
this.test.assertEquals(this.popups.length, 0, '"popup.closed" event is fired');
|
||||
});
|
||||
|
||||
casper.start('tests/site/popup.html');
|
||||
|
||||
casper.waitForPopup('index.html', function() {
|
||||
this.test.pass('Casper.waitForPopup() waits for a popup being created');
|
||||
this.test.assertEquals(this.popups.length, 1, 'A popup has been added');
|
||||
this.test.assert(utils.isWebPage(this.popups[0]), 'A popup is a WebPage');
|
||||
});
|
||||
|
||||
casper.withPopup('index.html', function() {
|
||||
this.test.assertUrlMatches(/index\.html$/,
|
||||
'Casper.withPopup() switched to popup as current active one');
|
||||
this.test.assertEval(function() {
|
||||
return '__utils__' in window;
|
||||
}, 'Casper.withPopup() has client utils injected');
|
||||
this.test.assertExists('h1',
|
||||
'Casper.withPopup() can perform assertions on the DOM');
|
||||
this.test.assertExists(x('//h1'),
|
||||
'Casper.withPopup() can perform assertions on the DOM using XPath');
|
||||
});
|
||||
|
||||
casper.then(function() {
|
||||
this.test.assertUrlMatches(/popup\.html$/,
|
||||
'Casper.withPopup() has reverted to main page after using the popup');
|
||||
});
|
||||
|
||||
casper.thenClick('.close', function() {
|
||||
this.test.assertEquals(this.popups.length, 0, 'Popup is removed when closed');
|
||||
});
|
||||
|
||||
casper.thenOpen('tests/site/popup.html');
|
||||
|
||||
casper.waitForPopup(/index\.html$/, function() {
|
||||
this.test.pass('Casper.waitForPopup() waits for a popup being created');
|
||||
});
|
||||
|
||||
casper.withPopup(/index\.html$/, function() {
|
||||
this.test.assertTitle('CasperJS test index',
|
||||
'Casper.withPopup() can use a regexp to identify popup');
|
||||
});
|
||||
|
||||
casper.thenClick('.close', function() {
|
||||
this.test.assertUrlMatches(/popup\.html$/,
|
||||
'Casper.withPopup() has reverted to main page after using the popup');
|
||||
this.test.assertEquals(this.popups.length, 0, 'Popup is removed when closed');
|
||||
this.removeAllListeners('popup.created');
|
||||
this.removeAllListeners('popup.loaded');
|
||||
this.removeAllListeners('popup.closed');
|
||||
});
|
||||
|
||||
casper.thenClick('a[target="_blank"]');
|
||||
|
||||
casper.waitForPopup('form.html', function() {
|
||||
this.test.pass('Casper.waitForPopup() waits when clicked on a link with target=_blank');
|
||||
});
|
||||
|
||||
casper.withPopup('form.html', function() {
|
||||
this.test.assertTitle('CasperJS test form');
|
||||
});
|
||||
|
||||
casper.run(function() {
|
||||
// removes event listeners as they've now been tested already
|
||||
this.test.done(25);
|
||||
});
|
||||
@@ -1,19 +1,13 @@
|
||||
/*global casper*/
|
||||
/*jshint strict:false*/
|
||||
// skip this test for phantom versions < 1.5
|
||||
if (phantom.version.major === 1 && phantom.version.minor < 6) {
|
||||
casper.test.comment('Skipped tests, PhantomJS 1.6 required');
|
||||
casper.test.done();
|
||||
} else {
|
||||
casper.setFilter('page.prompt', function(message, value) {
|
||||
casper.setFilter('page.prompt', function(message, value) {
|
||||
return 'Chuck ' + value;
|
||||
});
|
||||
});
|
||||
|
||||
casper.start('tests/site/prompt.html', function() {
|
||||
casper.start('tests/site/prompt.html', function() {
|
||||
this.test.assertEquals(this.getGlobal('name'), 'Chuck Norris', 'prompted value has been received');
|
||||
});
|
||||
});
|
||||
|
||||
casper.run(function() {
|
||||
this.test.done();
|
||||
});
|
||||
}
|
||||
casper.run(function() {
|
||||
this.test.done(1);
|
||||
});
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*global casper*/
|
||||
/*jshint strict:false*/
|
||||
function testHeader(header) {
|
||||
return header.name === 'Accept' && header.value === 'application/json';
|
||||
}
|
||||
|
||||
var t = casper.test, current = 0, tests = [
|
||||
function(request) {
|
||||
t.assertNot(request.headers.some(testHeader), "Casper.open() sets no custom header by default");
|
||||
},
|
||||
function(request) {
|
||||
t.assert(request.headers.some(testHeader), "Casper.open() can set a custom header");
|
||||
},
|
||||
function(request) {
|
||||
t.assertNot(request.headers.some(testHeader), "Casper.open() custom headers option is not persistent");
|
||||
}
|
||||
];
|
||||
|
||||
casper.on('page.resource.requested', function(request) {
|
||||
tests[current++](request);
|
||||
});
|
||||
|
||||
casper.start();
|
||||
|
||||
casper.thenOpen('tests/site/index.html');
|
||||
casper.thenOpen('tests/site/index.html', {
|
||||
headers: {
|
||||
Accept: 'application/json'
|
||||
}
|
||||
});
|
||||
casper.thenOpen('tests/site/index.html');
|
||||
|
||||
casper.run(function() {
|
||||
this.removeAllListeners('page.resource.requested');
|
||||
t.done(3);
|
||||
});
|
||||
@@ -21,4 +21,4 @@ casper.start "tests/site/resources.html", ->
|
||||
onTimeout = -> @test.fail "waitForResource timeout occured"
|
||||
@waitForResource "dummy.js", onTime, onTimeout
|
||||
|
||||
casper.run(-> @test.done())
|
||||
casper.run(-> @test.done(5))
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/*global casper*/
|
||||
/*jshint strict:false*/
|
||||
casper.options.remoteScripts = [
|
||||
'includes/include1.js', // local includes are actually served
|
||||
'includes/include2.js', // through the local test webserver
|
||||
'http://code.jquery.com/jquery-1.8.3.min.js'
|
||||
];
|
||||
|
||||
casper.start('tests/site/index.html', function() {
|
||||
this.test.assertSelectorHasText('#include1', 'include1',
|
||||
'Casper.includeRemoteScripts() includes a first remote script on start');
|
||||
this.test.assertSelectorHasText('#include2', 'include2',
|
||||
'Casper.includeRemoteScripts() includes a second remote script on start');
|
||||
this.test.assertEval(function() {
|
||||
return 'jQuery' in window;
|
||||
}, 'Casper.includeRemoteScripts() includes a really remote file on first step');
|
||||
});
|
||||
|
||||
casper.thenOpen('tests/site/form.html', function() {
|
||||
this.test.assertSelectorHasText('#include1', 'include1',
|
||||
'Casper.includeRemoteScripts() includes a first remote script on second step');
|
||||
this.test.assertSelectorHasText('#include2', 'include2',
|
||||
'Casper.includeRemoteScripts() includes a second remote script on second step');
|
||||
this.test.assertEval(function() {
|
||||
return 'jQuery' in window;
|
||||
}, 'Casper.includeRemoteScripts() includes a really remote file on second step');
|
||||
});
|
||||
|
||||
casper.run(function() {
|
||||
this.options.remoteScripts = [];
|
||||
this.test.done(6);
|
||||
});
|
||||
@@ -13,5 +13,5 @@ casper.start('tests/site/index.html', function() {
|
||||
casper.test.assert(casper.started, 'Casper.start() started');
|
||||
|
||||
casper.run(function() {
|
||||
this.test.done();
|
||||
this.test.done(4);
|
||||
});
|
||||
|
||||
@@ -30,5 +30,5 @@ casper.each([1, 2, 3], function(self, item, i) {
|
||||
});
|
||||
|
||||
casper.run(function() {
|
||||
this.test.done();
|
||||
this.test.done(8);
|
||||
});
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user