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,
|
"maxdepth": 3,
|
||||||
"maxstatements": 15,
|
"maxstatements": 15,
|
||||||
"maxcomplexity": 7,
|
"maxcomplexity": 7,
|
||||||
|
"proto": true,
|
||||||
"regexdash": true,
|
"regexdash": true,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"sub": true,
|
"sub": true,
|
||||||
|
|||||||
@@ -1,13 +1,16 @@
|
|||||||
branches:
|
branches:
|
||||||
only:
|
only:
|
||||||
- master
|
- "master"
|
||||||
|
- "1.0"
|
||||||
before_script:
|
before_script:
|
||||||
|
- "npm install -g jshint"
|
||||||
- "phantomjs --version"
|
- "phantomjs --version"
|
||||||
- "export PHANTOMJS_EXECUTABLE='phantomjs --local-to-remote-url-access=yes --ignore-ssl-errors=yes'"
|
- "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:
|
script:
|
||||||
- "DISPLAY=:99.0 ./bin/casperjs selftest"
|
- "./bin/casperjs selftest"
|
||||||
|
- "./bin/casperjs __selfcommandtest"
|
||||||
|
after_script:
|
||||||
|
- "jshint --config=.jshintconfig ."
|
||||||
notifications:
|
notifications:
|
||||||
irc:
|
irc:
|
||||||
channels:
|
channels:
|
||||||
|
|||||||
@@ -1,6 +1,186 @@
|
|||||||
CasperJS Changelog
|
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
|
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).
|
You can check out the [contribution graphs on github](https://github.com/n1k0/casperjs/graphs/contributors).
|
||||||
|
|
||||||
```
|
```
|
||||||
$ git shortlog -s -n
|
$ git shortlog -s -n | cut -c8-
|
||||||
689 Nicolas Perriault
|
Nicolas Perriault
|
||||||
14 oncletom
|
Brikou CARRE
|
||||||
14 Brikou CARRE
|
oncletom
|
||||||
8 hannyu
|
hannyu
|
||||||
6 Chris Lorenzo
|
Chris Lorenzo
|
||||||
4 pborreli
|
Victor Yap
|
||||||
4 nrabinowitz
|
nrabinowitz
|
||||||
3 Andrew Childs
|
pborreli
|
||||||
3 Solomon White
|
Rob Barreca
|
||||||
3 reina.sweet
|
Andrew Childs
|
||||||
2 Reina Sweet
|
Solomon White
|
||||||
2 Jason Funk
|
reina.sweet
|
||||||
2 Michael Geers
|
Dave Lee
|
||||||
2 Julien Moulin
|
Reina Sweet
|
||||||
2 Donovan Hutchinson
|
Elmar Langholz
|
||||||
2 Clochix
|
Jason Funk
|
||||||
1 Marcel Duran
|
Donovan Hutchinson
|
||||||
1 Mathieu Agopian
|
Julien Moulin
|
||||||
1 Mehdi Kabab
|
Michael Geers
|
||||||
1 Mikko Peltonen
|
Jan Schaumann
|
||||||
1 Pascal Borreli
|
Clochix
|
||||||
1 Rafael
|
Raphaël Benitte
|
||||||
1 Rafael Garcia
|
Tim Bunce
|
||||||
1 Raphaël Benitte
|
alfetopito
|
||||||
1 Andrew de Andrade
|
jean-philippe serafin
|
||||||
1 Tim Bunce
|
snkashis
|
||||||
1 Victor Yap
|
Andrew de Andrade
|
||||||
1 alfetopito
|
Ben Lowery
|
||||||
1 Christophe Benz
|
Chris Winters
|
||||||
1 jean-philippe serafin
|
Christophe Benz
|
||||||
1 Chris Winters
|
Harrison Reiser
|
||||||
1 Ben Lowery
|
Jan Pochyla
|
||||||
1 Jan Pochyla
|
Jan-Martin Fruehwacht
|
||||||
1 Harrison Reiser
|
Julian Gruber
|
||||||
1 Julian Gruber
|
Justin Slattery
|
||||||
1 Justine Tunney
|
Justine Tunney
|
||||||
1 KaroDidi
|
KaroDidi
|
||||||
1 Leandro Boscariol
|
Leandro Boscariol
|
||||||
1 Maisons du monde
|
Maisons du monde
|
||||||
|
Marcel Duran
|
||||||
|
Mathieu Agopian
|
||||||
|
Mehdi Kabab
|
||||||
|
Mikko Peltonen
|
||||||
|
Pascal Borreli
|
||||||
|
Rafael
|
||||||
|
Rafael Garcia
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,22 +1,5 @@
|
|||||||
@ECHO OFF
|
@ECHO OFF
|
||||||
set CASPER_PATH=%~dp0..\
|
set CASPER_PATH=%~dp0..
|
||||||
set CASPER_BIN=%CASPER_PATH%bin\
|
set CASPER_BIN=%CASPER_PATH%\bin\
|
||||||
|
set ARGV=%*
|
||||||
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)
|
call phantomjs "%CASPER_BIN%bootstrap.js" --casper-path="%CASPER_PATH%" --cli %ARGV%
|
||||||
|
|
||||||
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%
|
|
||||||
96
zephyr/tests/frontend/casperjs/bin/bootstrap.js
vendored
96
zephyr/tests/frontend/casperjs/bin/bootstrap.js
vendored
@@ -33,14 +33,21 @@
|
|||||||
|
|
||||||
if (!phantom) {
|
if (!phantom) {
|
||||||
console.error('CasperJS needs to be executed in a PhantomJS environment http://phantomjs.org/');
|
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) {
|
if (phantom.version.major === 1 && phantom.version.minor < 7) {
|
||||||
console.error('CasperJS needs at least PhantomJS v1.6.0 or later.');
|
console.error('CasperJS needs at least PhantomJS v1.7 or later.');
|
||||||
phantom.exit(1);
|
phantom.exit(1);
|
||||||
} else {
|
} else {
|
||||||
bootstrap(window);
|
try {
|
||||||
|
bootstrap(window);
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
(e.stackArray || []).forEach(function(entry) {
|
||||||
|
console.error(' In ' + entry.sourceURL + ':' + entry.line);
|
||||||
|
});
|
||||||
|
phantom.exit(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Polyfills
|
// Polyfills
|
||||||
@@ -106,10 +113,13 @@ function patchRequire(require, requireDirs) {
|
|||||||
fileGuesses.push.apply(fileGuesses, [
|
fileGuesses.push.apply(fileGuesses, [
|
||||||
testPath,
|
testPath,
|
||||||
testPath + '.js',
|
testPath + '.js',
|
||||||
|
testPath + '.json',
|
||||||
testPath + '.coffee',
|
testPath + '.coffee',
|
||||||
fs.pathJoin(testPath, 'index.js'),
|
fs.pathJoin(testPath, 'index.js'),
|
||||||
|
fs.pathJoin(testPath, 'index.json'),
|
||||||
fs.pathJoin(testPath, 'index.coffee'),
|
fs.pathJoin(testPath, 'index.coffee'),
|
||||||
fs.pathJoin(testPath, 'lib', fs.basename(testPath) + '.js'),
|
fs.pathJoin(testPath, 'lib', fs.basename(testPath) + '.js'),
|
||||||
|
fs.pathJoin(testPath, 'lib', fs.basename(testPath) + '.json'),
|
||||||
fs.pathJoin(testPath, 'lib', fs.basename(testPath) + '.coffee')
|
fs.pathJoin(testPath, 'lib', fs.basename(testPath) + '.coffee')
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
@@ -120,16 +130,25 @@ function patchRequire(require, requireDirs) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!file) {
|
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) {
|
if (file in requireCache) {
|
||||||
return requireCache[file].exports;
|
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 = (function getScriptCode(file) {
|
||||||
var scriptCode = fs.read(file);
|
var scriptCode = fs.read(file);
|
||||||
if (/\.coffee$/i.test(file)) {
|
if (/\.coffee$/i.test(file)) {
|
||||||
/*global CoffeeScript*/
|
/*global CoffeeScript*/
|
||||||
scriptCode = CoffeeScript.compile(scriptCode);
|
try {
|
||||||
|
scriptCode = CoffeeScript.compile(scriptCode);
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error('Unable to compile coffeescript:' + e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return scriptCode;
|
return scriptCode;
|
||||||
})(file);
|
})(file);
|
||||||
@@ -137,8 +156,14 @@ function patchRequire(require, requireDirs) {
|
|||||||
try {
|
try {
|
||||||
fn(file, _require, module, module.exports);
|
fn(file, _require, module, module.exports);
|
||||||
} catch (e) {
|
} 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.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;
|
throw error;
|
||||||
}
|
}
|
||||||
requireCache[file] = module;
|
requireCache[file] = module;
|
||||||
@@ -150,9 +175,20 @@ function patchRequire(require, requireDirs) {
|
|||||||
|
|
||||||
function bootstrap(global) {
|
function bootstrap(global) {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var phantomArgs = require('system').args;
|
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.
|
* Loads and initialize the CasperJS environment.
|
||||||
*/
|
*/
|
||||||
@@ -230,7 +266,7 @@ function bootstrap(global) {
|
|||||||
throw new global.CasperError('Cannot read package file contents: ' + e);
|
throw new global.CasperError('Cannot read package file contents: ' + e);
|
||||||
}
|
}
|
||||||
parts = pkg.version.trim().split(".");
|
parts = pkg.version.trim().split(".");
|
||||||
if (parts < 3) {
|
if (parts.length < 3) {
|
||||||
throw new global.CasperError("Invalid version number");
|
throw new global.CasperError("Invalid version number");
|
||||||
}
|
}
|
||||||
patchPart = parts[2].split('-');
|
patchPart = parts[2].split('-');
|
||||||
@@ -264,20 +300,21 @@ function bootstrap(global) {
|
|||||||
*/
|
*/
|
||||||
phantom.initCasperCli = function initCasperCli() {
|
phantom.initCasperCli = function initCasperCli() {
|
||||||
var fs = require("fs");
|
var fs = require("fs");
|
||||||
|
var baseTestsPath = fs.pathJoin(phantom.casperPath, 'tests');
|
||||||
|
|
||||||
if (!!phantom.casperArgs.options.version) {
|
if (!!phantom.casperArgs.options.version) {
|
||||||
console.log(phantom.casperVersion.toString());
|
console.log(phantom.casperVersion.toString());
|
||||||
phantom.exit(0);
|
return phantom.exit();
|
||||||
} else if (phantom.casperArgs.get(0) === "test") {
|
} 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.casperTest = true;
|
||||||
phantom.casperArgs.drop("test");
|
phantom.casperArgs.drop("test");
|
||||||
} else if (phantom.casperArgs.get(0) === "selftest") {
|
} else if (phantom.casperArgs.get(0) === "selftest") {
|
||||||
phantom.casperScript = fs.absolute(fs.pathJoin(phantom.casperPath, 'tests', 'run.js'));
|
phantom.casperScript = fs.absolute(fs.pathJoin(baseTestsPath, 'run.js'));
|
||||||
phantom.casperSelfTest = true;
|
phantom.casperSelfTest = phantom.casperTest = true;
|
||||||
phantom.casperArgs.options.includes = fs.pathJoin(phantom.casperPath, 'tests', 'selftest.js');
|
phantom.casperArgs.options.includes = fs.pathJoin(baseTestsPath, 'selftest.js');
|
||||||
if (phantom.casperArgs.args.length <= 1) {
|
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");
|
phantom.casperArgs.drop("selftest");
|
||||||
} else if (phantom.casperArgs.args.length === 0 || !!phantom.casperArgs.options.help) {
|
} else if (phantom.casperArgs.args.length === 0 || !!phantom.casperArgs.options.help) {
|
||||||
@@ -287,25 +324,30 @@ function bootstrap(global) {
|
|||||||
phantom.casperVersion.toString(),
|
phantom.casperVersion.toString(),
|
||||||
phantom.casperPath, phantomVersion));
|
phantom.casperPath, phantomVersion));
|
||||||
console.log(fs.read(fs.pathJoin(phantom.casperPath, 'bin', 'usage.txt')));
|
console.log(fs.read(fs.pathJoin(phantom.casperPath, 'bin', 'usage.txt')));
|
||||||
phantom.exit(0);
|
return phantom.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!phantom.casperScript) {
|
if (!phantom.casperScript) {
|
||||||
phantom.casperScript = phantom.casperArgs.get(0);
|
phantom.casperScript = phantom.casperArgs.get(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (phantom.casperScript) {
|
if (!fs.isFile(phantom.casperScript)) {
|
||||||
if (!fs.isFile(phantom.casperScript)) {
|
console.error('Unable to open file: ' + phantom.casperScript);
|
||||||
console.error('Unable to open file: ' + phantom.casperScript);
|
return phantom.exit(1);
|
||||||
phantom.exit(1);
|
}
|
||||||
} else {
|
|
||||||
// filter out the called script name from casper args
|
|
||||||
phantom.casperArgs.drop(phantom.casperScript);
|
|
||||||
|
|
||||||
// passed casperjs script execution
|
// filter out the called script name from casper args
|
||||||
phantom.injectJs(phantom.casperScript);
|
phantom.casperArgs.drop(phantom.casperScript);
|
||||||
}
|
|
||||||
|
// passed casperjs script execution
|
||||||
|
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
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
import json
|
||||||
import os
|
import os
|
||||||
|
import subprocess
|
||||||
import sys
|
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):
|
def resolve(path):
|
||||||
if os.path.islink(path):
|
if os.path.islink(path):
|
||||||
@@ -32,9 +41,25 @@ PHANTOMJS_NATIVE_ARGS = [
|
|||||||
'web-security',
|
'web-security',
|
||||||
]
|
]
|
||||||
CASPER_ARGS = []
|
CASPER_ARGS = []
|
||||||
|
CASPER_PATH = os.path.abspath(os.path.join(os.path.dirname(resolve(__file__)), '..'))
|
||||||
PHANTOMJS_ARGS = []
|
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
|
found = False
|
||||||
for native in PHANTOMJS_NATIVE_ARGS:
|
for native in PHANTOMJS_NATIVE_ARGS:
|
||||||
if arg.startswith('--%s' % native):
|
if arg.startswith('--%s' % native):
|
||||||
@@ -43,7 +68,6 @@ for arg in sys.argv[1:]:
|
|||||||
if not found:
|
if not found:
|
||||||
CASPER_ARGS.append(arg)
|
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 = os.environ.get('PHANTOMJS_EXECUTABLE', 'phantomjs').split(' ')
|
||||||
CASPER_COMMAND.extend(PHANTOMJS_ARGS)
|
CASPER_COMMAND.extend(PHANTOMJS_ARGS)
|
||||||
CASPER_COMMAND.extend([
|
CASPER_COMMAND.extend([
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
|
|
||||||
Usage: casperjs [options] script.[js|coffee] [script argument [script argument ...]]
|
Usage: casperjs [options] script.[js|coffee] [script argument [script argument ...]]
|
||||||
casperjs [options] test [test path [test path ...]]
|
casperjs [options] test [test path [test path ...]]
|
||||||
|
casperjs [options] selftest
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
|
|
||||||
--help Prints this help
|
--help Prints this help
|
||||||
--version Prints out CasperJS version
|
--version Prints out CasperJS version
|
||||||
|
|
||||||
Read the docs http://casperjs.org/
|
Read the docs http://casperjs.org/
|
||||||
|
|||||||
@@ -19,5 +19,5 @@ high-level functions, methods & syntaxic sugar for doing common tasks."
|
|||||||
s.bindir = "rubybin"
|
s.bindir = "rubybin"
|
||||||
s.executables = [ "casperjs" ]
|
s.executables = [ "casperjs" ]
|
||||||
s.license = "MIT"
|
s.license = "MIT"
|
||||||
s.requirements = [ "PhantomJS v1.6" ]
|
s.requirements = [ "PhantomJS v1.7" ]
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ var events = require('events');
|
|||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
var http = require('http');
|
var http = require('http');
|
||||||
var mouse = require('mouse');
|
var mouse = require('mouse');
|
||||||
|
var pagestack = require('pagestack');
|
||||||
var qs = require('querystring');
|
var qs = require('querystring');
|
||||||
var tester = require('tester');
|
var tester = require('tester');
|
||||||
var utils = require('utils');
|
var utils = require('utils');
|
||||||
@@ -75,7 +76,7 @@ exports.selectXPath = selectXPath;
|
|||||||
*/
|
*/
|
||||||
var Casper = function Casper(options) {
|
var Casper = function Casper(options) {
|
||||||
"use strict";
|
"use strict";
|
||||||
/*jshint maxstatements:30*/
|
/*jshint maxstatements:40*/
|
||||||
// init & checks
|
// init & checks
|
||||||
if (!(this instanceof Casper)) {
|
if (!(this instanceof Casper)) {
|
||||||
return new Casper(options);
|
return new Casper(options);
|
||||||
@@ -110,6 +111,7 @@ var Casper = function Casper(options) {
|
|||||||
localToRemoteUrlAccessEnabled: true,
|
localToRemoteUrlAccessEnabled: true,
|
||||||
userAgent: defaultUserAgent
|
userAgent: defaultUserAgent
|
||||||
},
|
},
|
||||||
|
remoteScripts: [],
|
||||||
stepTimeout: null,
|
stepTimeout: null,
|
||||||
timeout: null,
|
timeout: null,
|
||||||
verbose: false,
|
verbose: false,
|
||||||
@@ -138,6 +140,7 @@ var Casper = function Casper(options) {
|
|||||||
this.mouse = mouse.create(this);
|
this.mouse = mouse.create(this);
|
||||||
this.page = null;
|
this.page = null;
|
||||||
this.pendingWait = false;
|
this.pendingWait = false;
|
||||||
|
this.popups = pagestack.create();
|
||||||
this.requestUrl = 'about:blank';
|
this.requestUrl = 'about:blank';
|
||||||
this.resources = [];
|
this.resources = [];
|
||||||
this.result = {
|
this.result = {
|
||||||
@@ -154,12 +157,14 @@ var Casper = function Casper(options) {
|
|||||||
this.initErrorHandler();
|
this.initErrorHandler();
|
||||||
|
|
||||||
this.on('error', function(msg, backtrace) {
|
this.on('error', function(msg, backtrace) {
|
||||||
|
if (msg === this.test.SKIP_MESSAGE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
var c = this.getColorizer();
|
var c = this.getColorizer();
|
||||||
var match = /^(.*): __mod_error(.*):: (.*)/.exec(msg);
|
var match = /^(.*): __mod_error(.*):: (.*)/.exec(msg);
|
||||||
var notices = [];
|
var notices = [];
|
||||||
if (match && match.length === 4) {
|
if (match && match.length === 4) {
|
||||||
notices.push(' in module ' + match[2]);
|
notices.push(' in module ' + match[2]);
|
||||||
notices.push(' NOTICE: errors within modules cannot be backtraced yet.');
|
|
||||||
msg = match[3];
|
msg = match[3];
|
||||||
}
|
}
|
||||||
console.error(c.colorize(msg, 'RED_BAR', 80));
|
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) {
|
Casper.prototype.base64encode = function base64encode(url, method, data) {
|
||||||
"use strict";
|
"use strict";
|
||||||
return this.evaluate(function _evaluate(url, method, data) {
|
return this.evaluate(function _evaluate(url, method, data) {
|
||||||
return window.__utils__.getBase64(url, method, data);
|
return __utils__.getBase64(url, method, data);
|
||||||
}, { url: url, method: method, data: data });
|
}, url, method, data);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -382,7 +387,14 @@ Casper.prototype.clear = function clear() {
|
|||||||
Casper.prototype.click = function click(selector) {
|
Casper.prototype.click = function click(selector) {
|
||||||
"use strict";
|
"use strict";
|
||||||
this.checkStarted();
|
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);
|
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.
|
* Creates a step definition.
|
||||||
*
|
*
|
||||||
@@ -455,13 +493,13 @@ Casper.prototype.debugPage = function debugPage() {
|
|||||||
*/
|
*/
|
||||||
Casper.prototype.die = function die(message, status) {
|
Casper.prototype.die = function die(message, status) {
|
||||||
"use strict";
|
"use strict";
|
||||||
this.checkStarted();
|
|
||||||
this.result.status = "error";
|
this.result.status = "error";
|
||||||
this.result.time = new Date().getTime() - this.startTime;
|
this.result.time = new Date().getTime() - this.startTime;
|
||||||
if (!utils.isString(message) || !message.length) {
|
if (!utils.isString(message) || !message.length) {
|
||||||
message = "Suite explicitely interrupted without any message given.";
|
message = "Suite explicitely interrupted without any message given.";
|
||||||
}
|
}
|
||||||
this.log(message, "error");
|
this.log(message, "error");
|
||||||
|
this.echo(message, "ERROR");
|
||||||
this.emit('die', message, status);
|
this.emit('die', message, status);
|
||||||
if (utils.isFunction(this.options.onDie)) {
|
if (utils.isFunction(this.options.onDie)) {
|
||||||
this.options.onDie.call(this, this, message, status);
|
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('#username').value = username;
|
||||||
* document.querySelector('#password').value = password;
|
* document.querySelector('#password').value = password;
|
||||||
* document.querySelector('#submit').click();
|
* document.querySelector('#submit').click();
|
||||||
* }, {
|
* }, 'Bazoonga', 'baz00nga');
|
||||||
* username: 'Bazoonga',
|
|
||||||
* password: 'baz00nga'
|
|
||||||
* })
|
|
||||||
*
|
|
||||||
* FIXME: waiting for a patch of PhantomJS to allow direct passing of
|
|
||||||
* arguments to the function.
|
|
||||||
*
|
*
|
||||||
* @param Function fn The function to be evaluated within current page DOM
|
* @param Function fn The function to be evaluated within current page DOM
|
||||||
* @param Object context Object containing the parameters to inject into the function
|
* @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) {
|
Casper.prototype.evaluate = function evaluate(fn, context) {
|
||||||
"use strict";
|
"use strict";
|
||||||
this.checkStarted();
|
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
|
// ensure client utils are always injected
|
||||||
this.injectClientUtils();
|
this.injectClientUtils();
|
||||||
// function context
|
// function context
|
||||||
context = utils.isObject(context) ? context : {};
|
if (arguments.length === 1) {
|
||||||
// the way this works is kept for BC with older casperjs versions
|
return this.page.evaluate(fn);
|
||||||
var args = Object.keys(context).map(function(arg) {
|
} else if (arguments.length === 2) {
|
||||||
return context[arg];
|
// check for closure signature if it matches context
|
||||||
});
|
if (utils.isObject(context) && eval(fn).length === Object.keys(context).length) {
|
||||||
return this.page.evaluate.apply(this.page, [fn].concat(args));
|
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";
|
"use strict";
|
||||||
this.checkStarted();
|
this.checkStarted();
|
||||||
return this.evaluate(function _evaluate(selector) {
|
return this.evaluate(function _evaluate(selector) {
|
||||||
return window.__utils__.exists(selector);
|
return __utils__.exists(selector);
|
||||||
}, { selector: selector });
|
}, selector);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -633,8 +677,8 @@ Casper.prototype.fetchText = function fetchText(selector) {
|
|||||||
"use strict";
|
"use strict";
|
||||||
this.checkStarted();
|
this.checkStarted();
|
||||||
return this.evaluate(function _evaluate(selector) {
|
return this.evaluate(function _evaluate(selector) {
|
||||||
return window.__utils__.fetchText(selector);
|
return __utils__.fetchText(selector);
|
||||||
}, { selector: selector });
|
}, selector);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -653,11 +697,8 @@ Casper.prototype.fill = function fill(selector, vals, submit) {
|
|||||||
}
|
}
|
||||||
this.emit('fill', selector, vals, submit);
|
this.emit('fill', selector, vals, submit);
|
||||||
var fillResults = this.evaluate(function _evaluate(selector, values) {
|
var fillResults = this.evaluate(function _evaluate(selector, values) {
|
||||||
return window.__utils__.fill(selector, values);
|
return __utils__.fill(selector, values);
|
||||||
}, {
|
}, selector, vals);
|
||||||
selector: selector,
|
|
||||||
values: vals
|
|
||||||
});
|
|
||||||
if (!fillResults) {
|
if (!fillResults) {
|
||||||
throw new CasperError("Unable to fill form");
|
throw new CasperError("Unable to fill form");
|
||||||
} else if (fillResults.errors.length > 0) {
|
} else if (fillResults.errors.length > 0) {
|
||||||
@@ -681,17 +722,17 @@ Casper.prototype.fill = function fill(selector, vals, submit) {
|
|||||||
// Form submission?
|
// Form submission?
|
||||||
if (submit) {
|
if (submit) {
|
||||||
this.evaluate(function _evaluate(selector) {
|
this.evaluate(function _evaluate(selector) {
|
||||||
var form = window.__utils__.findOne(selector);
|
var form = __utils__.findOne(selector);
|
||||||
var method = (form.getAttribute('method') || "GET").toUpperCase();
|
var method = (form.getAttribute('method') || "GET").toUpperCase();
|
||||||
var action = form.getAttribute('action') || "unknown";
|
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") {
|
if (typeof form.submit === "function") {
|
||||||
form.submit();
|
form.submit();
|
||||||
} else {
|
} else {
|
||||||
// http://www.spiration.co.uk/post/1232/Submit-is-not-a-function
|
// http://www.spiration.co.uk/post/1232/Submit-is-not-a-function
|
||||||
form.submit.click();
|
form.submit.click();
|
||||||
}
|
}
|
||||||
}, { selector: selector });
|
}, selector);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -732,7 +773,7 @@ Casper.prototype.getPageContent = function getPageContent() {
|
|||||||
this.checkStarted();
|
this.checkStarted();
|
||||||
var contentType = utils.getPropertyPath(this, 'currentResponse.contentType');
|
var contentType = utils.getPropertyPath(this, 'currentResponse.contentType');
|
||||||
if (!utils.isString(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
|
// for some reason webkit/qtwebkit will always enclose body contents within html tags
|
||||||
var sanitizedHtml = this.evaluate(function checkHtml() {
|
var sanitizedHtml = this.evaluate(function checkHtml() {
|
||||||
@@ -742,7 +783,7 @@ Casper.prototype.getPageContent = function getPageContent() {
|
|||||||
return __utils__.findOne('body pre').textContent.trim();
|
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
|
* @param String attribute The attribute name to lookup
|
||||||
* @return String The requested DOM element attribute value
|
* @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";
|
"use strict";
|
||||||
this.checkStarted();
|
this.checkStarted();
|
||||||
return this.evaluate(function _evaluate(selector, attribute) {
|
return this.evaluate(function _evaluate(selector, attribute) {
|
||||||
return document.querySelector(selector).getAttribute(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);
|
throw new CasperError("No element matching selector found: " + selector);
|
||||||
}
|
}
|
||||||
var clipRect = this.evaluate(function _evaluate(selector) {
|
var clipRect = this.evaluate(function _evaluate(selector) {
|
||||||
return window.__utils__.getElementBounds(selector);
|
return __utils__.getElementBounds(selector);
|
||||||
}, { selector: selector });
|
}, selector);
|
||||||
if (!utils.isClipRect(clipRect)) {
|
if (!utils.isClipRect(clipRect)) {
|
||||||
throw new CasperError('Could not fetch boundaries for element matching selector: ' + selector);
|
throw new CasperError('Could not fetch boundaries for element matching selector: ' + selector);
|
||||||
}
|
}
|
||||||
return clipRect;
|
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.
|
* 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);
|
throw new CasperError("No element matching selector found: " + selector);
|
||||||
}
|
}
|
||||||
return this.evaluate(function _evaluate(selector) {
|
return this.evaluate(function _evaluate(selector) {
|
||||||
return window.__utils__.getElementsBounds(selector);
|
return __utils__.getElementsBounds(selector);
|
||||||
}, { selector: 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]);
|
result.value = JSON.stringify(window[name]);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
var message = f("Unable to JSON encode window.%s: %s", name, 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;
|
result.error = message;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}, {'name': name});
|
}, name);
|
||||||
if (typeof result !== "object") {
|
if (!utils.isObject(result)) {
|
||||||
throw new CasperError(f('Could not retrieve global value for "%s"', name));
|
throw new CasperError(f('Could not retrieve global value for "%s"', name));
|
||||||
} else if ('error' in result) {
|
} else if ('error' in result) {
|
||||||
throw new CasperError(result.error);
|
throw new CasperError(result.error);
|
||||||
} else if (utils.isString(result.value)) {
|
} else if (utils.isString(result.value)) {
|
||||||
return JSON.parse(result.value);
|
return JSON.parse(result.value);
|
||||||
} else {
|
|
||||||
return undefined;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -861,7 +935,7 @@ Casper.prototype.getHTML = function getHTML(selector, outer) {
|
|||||||
"use strict";
|
"use strict";
|
||||||
this.checkStarted();
|
this.checkStarted();
|
||||||
if (!selector) {
|
if (!selector) {
|
||||||
return this.page.content;
|
return this.page.frameContent;
|
||||||
}
|
}
|
||||||
if (!this.exists(selector)) {
|
if (!this.exists(selector)) {
|
||||||
throw new CasperError("No element matching selector found: " + 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) {
|
return this.evaluate(function getSelectorHTML(selector, outer) {
|
||||||
var element = __utils__.findOne(selector);
|
var element = __utils__.findOne(selector);
|
||||||
return outer ? element.outerHTML : element.innerHTML;
|
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) {
|
Casper.prototype.handleReceivedResource = function(resource) {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
/*jshint maxstatements:20*/
|
||||||
if (resource.stage !== "end") {
|
if (resource.stage !== "end") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -902,6 +977,7 @@ Casper.prototype.handleReceivedResource = function(resource) {
|
|||||||
this.currentHTTPStatus = null;
|
this.currentHTTPStatus = null;
|
||||||
this.currentResponse = undefined;
|
this.currentResponse = undefined;
|
||||||
if (utils.isHTTPResource(resource)) {
|
if (utils.isHTTPResource(resource)) {
|
||||||
|
this.emit('page.resource.received', resource);
|
||||||
this.currentResponse = resource;
|
this.currentResponse = resource;
|
||||||
this.currentHTTPStatus = resource.status;
|
this.currentHTTPStatus = resource.status;
|
||||||
this.emit('http.status.' + resource.status, resource);
|
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
|
* @return Casper
|
||||||
*/
|
*/
|
||||||
@@ -965,7 +1041,7 @@ Casper.prototype.injectClientUtils = function injectClientUtils() {
|
|||||||
"use strict";
|
"use strict";
|
||||||
this.checkStarted();
|
this.checkStarted();
|
||||||
var clientUtilsInjected = this.page.evaluate(function() {
|
var clientUtilsInjected = this.page.evaluate(function() {
|
||||||
return typeof window.__utils__ === "object";
|
return typeof __utils__ === "object";
|
||||||
});
|
});
|
||||||
if (true === clientUtilsInjected) {
|
if (true === clientUtilsInjected) {
|
||||||
return;
|
return;
|
||||||
@@ -984,6 +1060,32 @@ Casper.prototype.injectClientUtils = function injectClientUtils() {
|
|||||||
}.toString().replace('__options', JSON.stringify(this.options)));
|
}.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.
|
* Logs a message.
|
||||||
*
|
*
|
||||||
@@ -1041,22 +1143,18 @@ Casper.prototype.mouseEvent = function mouseEvent(type, selector) {
|
|||||||
if (!this.exists(selector)) {
|
if (!this.exists(selector)) {
|
||||||
throw new CasperError(f("Cannot dispatch %s event on nonexistent selector: %s", type, 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);
|
return window.__utils__.mouseEvent(type, selector);
|
||||||
}, {
|
}, type, selector)) {
|
||||||
type: type,
|
return true;
|
||||||
selector: selector
|
|
||||||
});
|
|
||||||
if (!eventSuccess) {
|
|
||||||
// fallback onto native QtWebKit mouse events
|
|
||||||
try {
|
|
||||||
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;
|
// fallback onto native QtWebKit mouse events
|
||||||
|
try {
|
||||||
|
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;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1066,7 +1164,7 @@ Casper.prototype.mouseEvent = function mouseEvent(type, selector) {
|
|||||||
*
|
*
|
||||||
* - String method: The HTTP method to use
|
* - String method: The HTTP method to use
|
||||||
* - Object data: The data to use to perform the request, eg. {foo: 'bar'}
|
* - 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 String location The url to open
|
||||||
* @param Object settings The request settings (optional)
|
* @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) {
|
Casper.prototype.open = function open(location, settings) {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
/*jshint maxstatements:30*/
|
||||||
|
var baseCustomHeaders = this.page.customHeaders,
|
||||||
|
customHeaders = settings && settings.headers || {};
|
||||||
this.checkStarted();
|
this.checkStarted();
|
||||||
// settings validation
|
settings = utils.isObject(settings) ? settings : {};
|
||||||
if (!settings) {
|
settings.method = settings.method || "get";
|
||||||
settings = {
|
|
||||||
method: "get"
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if (!utils.isObject(settings)) {
|
|
||||||
throw new CasperError("open(): request settings must be an Object");
|
|
||||||
}
|
|
||||||
// http method
|
// http method
|
||||||
// taken from https://github.com/ariya/phantomjs/blob/master/src/webpage.cpp#L302
|
// taken from https://github.com/ariya/phantomjs/blob/master/src/webpage.cpp#L302
|
||||||
var methods = ["get", "head", "put", "post", "delete"];
|
var methods = ["get", "head", "put", "post", "delete"];
|
||||||
@@ -1101,28 +1195,21 @@ Casper.prototype.open = function open(location, settings) {
|
|||||||
// clean location
|
// clean location
|
||||||
location = utils.cleanUrl(location);
|
location = utils.cleanUrl(location);
|
||||||
// current request url
|
// current request url
|
||||||
|
this.configureHttpAuth(location, settings);
|
||||||
this.requestUrl = this.filter('open.location', location) || location;
|
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.emit('open', this.requestUrl, settings);
|
||||||
this.log(f('opening url: %s, HTTP %s', this.requestUrl, settings.method.toUpperCase()), "debug");
|
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, {
|
this.page.openUrl(this.requestUrl, {
|
||||||
operation: settings.method,
|
operation: settings.method,
|
||||||
data: settings.data,
|
data: settings.data
|
||||||
headers: settings.headers
|
|
||||||
}, this.page.settings);
|
}, this.page.settings);
|
||||||
this.resources = [];
|
// revert base custom headers
|
||||||
|
this.page.customHeaders = baseCustomHeaders;
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1203,8 +1290,7 @@ Casper.prototype.run = function run(onComplete, time) {
|
|||||||
"use strict";
|
"use strict";
|
||||||
this.checkStarted();
|
this.checkStarted();
|
||||||
if (!this.steps || this.steps.length < 1) {
|
if (!this.steps || this.steps.length < 1) {
|
||||||
this.log("No steps defined, aborting", "error");
|
throw new CasperError('No steps defined, aborting');
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
this.log(f("Running suite: %d step%s", this.steps.length, this.steps.length > 1 ? "s" : ""), "info");
|
this.log(f("Running suite: %d step%s", this.steps.length, this.steps.length > 1 ? "s" : ""), "info");
|
||||||
this.emit('run.start');
|
this.emit('run.start');
|
||||||
@@ -1232,7 +1318,7 @@ Casper.prototype.runStep = function runStep(step) {
|
|||||||
if ((self.test.currentSuiteNum + "-" + self.step) === stepNum) {
|
if ((self.test.currentSuiteNum + "-" + self.step) === stepNum) {
|
||||||
self.emit('step.timeout');
|
self.emit('step.timeout');
|
||||||
if (utils.isFunction(self.options.onStepTimeout)) {
|
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);
|
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 selector A DOM CSS3 compatible selector
|
||||||
* @param String password The HTTP_AUTH_PW value
|
* @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
|
* @return Casper
|
||||||
*/
|
*/
|
||||||
Casper.prototype.setHttpAuth = function setHttpAuth(username, password) {
|
Casper.prototype.setHttpAuth = function setHttpAuth(username, password) {
|
||||||
"use strict";
|
"use strict";
|
||||||
this.checkStarted();
|
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.userName = username;
|
||||||
this.page.settings.password = password;
|
this.page.settings.password = password;
|
||||||
this.emit('http.auth', username, password);
|
|
||||||
this.log("Setting HTTP authentication for user " + username, "info");
|
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1279,10 +1396,12 @@ Casper.prototype.setHttpAuth = function setHttpAuth(username, password) {
|
|||||||
*/
|
*/
|
||||||
Casper.prototype.start = function start(location, then) {
|
Casper.prototype.start = function start(location, then) {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
/*jshint maxstatements:30*/
|
||||||
this.emit('starting');
|
this.emit('starting');
|
||||||
this.log('Starting...', "info");
|
this.log('Starting...', "info");
|
||||||
this.startTime = new Date().getTime();
|
this.startTime = new Date().getTime();
|
||||||
this.history = [];
|
this.history = [];
|
||||||
|
this.popups = pagestack.create();
|
||||||
this.steps = [];
|
this.steps = [];
|
||||||
this.step = 0;
|
this.step = 0;
|
||||||
// Option checks
|
// 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.log(f("Unknown log level '%d', defaulting to 'warning'", this.options.logLevel), "warning");
|
||||||
this.options.logLevel = "warning";
|
this.options.logLevel = "warning";
|
||||||
}
|
}
|
||||||
// WebPage
|
|
||||||
if (!utils.isWebPage(this.page)) {
|
if (!utils.isWebPage(this.page)) {
|
||||||
if (utils.isWebPage(this.options.page)) {
|
this.page = this.mainPage = utils.isWebPage(this.options.page) ? this.options.page : createPage(this);
|
||||||
this.page = this.options.page;
|
|
||||||
} else {
|
|
||||||
this.page = createPage(this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
this.page.settings = utils.mergeObjects(this.page.settings, this.options.pageSettings);
|
this.page.settings = utils.mergeObjects(this.page.settings, this.options.pageSettings);
|
||||||
if (utils.isClipRect(this.options.clipRect)) {
|
if (utils.isClipRect(this.options.clipRect)) {
|
||||||
@@ -1305,8 +1419,7 @@ Casper.prototype.start = function start(location, then) {
|
|||||||
if (utils.isObject(this.options.viewportSize)) {
|
if (utils.isObject(this.options.viewportSize)) {
|
||||||
this.page.viewportSize = this.options.viewportSize;
|
this.page.viewportSize = this.options.viewportSize;
|
||||||
}
|
}
|
||||||
this.started = true;
|
// timeout handling
|
||||||
this.emit('started');
|
|
||||||
if (utils.isNumber(this.options.timeout) && this.options.timeout > 0) {
|
if (utils.isNumber(this.options.timeout) && this.options.timeout > 0) {
|
||||||
this.log(f("Execution timeout set to %dms", this.options.timeout), "info");
|
this.log(f("Execution timeout set to %dms", this.options.timeout), "info");
|
||||||
setTimeout(function _check(self) {
|
setTimeout(function _check(self) {
|
||||||
@@ -1316,10 +1429,12 @@ Casper.prototype.start = function start(location, then) {
|
|||||||
}
|
}
|
||||||
}, this.options.timeout, this);
|
}, this.options.timeout, this);
|
||||||
}
|
}
|
||||||
|
this.started = true;
|
||||||
|
this.emit('started');
|
||||||
if (utils.isString(location) && location.length > 0) {
|
if (utils.isString(location) && location.length > 0) {
|
||||||
return this.thenOpen(location, utils.isFunction(then) ? then : this.createStep(function _step() {
|
return this.thenOpen(location, utils.isFunction(then) ? then : this.createStep(function _step() {
|
||||||
this.log("start page is loaded", "debug");
|
this.log("start page is loaded", "debug");
|
||||||
}));
|
}, {skipLog: true}));
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
@@ -1409,8 +1524,9 @@ Casper.prototype.thenClick = function thenClick(selector, then, fallbackToHref)
|
|||||||
Casper.prototype.thenEvaluate = function thenEvaluate(fn, context) {
|
Casper.prototype.thenEvaluate = function thenEvaluate(fn, context) {
|
||||||
"use strict";
|
"use strict";
|
||||||
this.checkStarted();
|
this.checkStarted();
|
||||||
|
var args = [fn].concat([].slice.call(arguments, 1));
|
||||||
return this.then(function _step() {
|
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) {
|
Casper.prototype.userAgent = function userAgent(agent) {
|
||||||
"use strict";
|
"use strict";
|
||||||
this.checkStarted();
|
this.options.pageSettings.userAgent = agent;
|
||||||
this.options.pageSettings.userAgent = this.page.settings.userAgent = agent;
|
if (this.started && this.page) {
|
||||||
|
this.page.settings.userAgent = agent;
|
||||||
|
}
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1510,8 +1628,8 @@ Casper.prototype.visible = function visible(selector) {
|
|||||||
"use strict";
|
"use strict";
|
||||||
this.checkStarted();
|
this.checkStarted();
|
||||||
return this.evaluate(function _evaluate(selector) {
|
return this.evaluate(function _evaluate(selector) {
|
||||||
return window.__utils__.visible(selector);
|
return __utils__.visible(selector);
|
||||||
}, { selector: 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
|
* 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 then The next step to perform (optional)
|
||||||
* @param Function onTimeout A callback function to call on timeout (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)
|
* @param Number timeout The max amount of time to wait, in milliseconds (optional)
|
||||||
* @return Casper
|
* @return Casper
|
||||||
*/
|
*/
|
||||||
Casper.prototype.waitForText = function(text, then, onTimeout, timeout) {
|
Casper.prototype.waitForText = function(pattern, then, onTimeout, timeout) {
|
||||||
"use strict";
|
"use strict";
|
||||||
this.checkStarted();
|
this.checkStarted();
|
||||||
timeout = timeout ? timeout : this.options.waitTimeout;
|
timeout = timeout ? timeout : this.options.waitTimeout;
|
||||||
return this.waitFor(function _check() {
|
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);
|
}, then, onTimeout, timeout);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1730,6 +1874,73 @@ Casper.prototype.waitWhileVisible = function waitWhileVisible(selector, then, on
|
|||||||
}, then, onTimeout, timeout);
|
}, 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.
|
* Changes the current page zoom factor.
|
||||||
*
|
*
|
||||||
@@ -1771,6 +1982,7 @@ exports.Casper = Casper;
|
|||||||
* @return WebPage
|
* @return WebPage
|
||||||
*/
|
*/
|
||||||
function createPage(casper) {
|
function createPage(casper) {
|
||||||
|
/*jshint maxstatements:20*/
|
||||||
"use strict";
|
"use strict";
|
||||||
var page = require('webpage').create();
|
var page = require('webpage').create();
|
||||||
page.onAlert = function onAlert(message) {
|
page.onAlert = function onAlert(message) {
|
||||||
@@ -1781,17 +1993,21 @@ function createPage(casper) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
page.onConfirm = function onConfirm(message) {
|
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) {
|
page.onConsoleMessage = function onConsoleMessage(msg) {
|
||||||
// client utils casper console message
|
// 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) {
|
if (consoleTest && consoleTest.length === 2) {
|
||||||
casper.echo(consoleTest[1]);
|
casper.echo(consoleTest[1]);
|
||||||
return; // don't trigger remote.message event for these
|
return; // don't trigger remote.message event for these
|
||||||
}
|
}
|
||||||
// client utils log messages
|
// 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) {
|
if (logTest && logTest.length === 3) {
|
||||||
logLevel = logTest[1];
|
logLevel = logTest[1];
|
||||||
msg = logTest[2];
|
msg = logTest[2];
|
||||||
@@ -1803,9 +2019,9 @@ function createPage(casper) {
|
|||||||
casper.emit('page.error', msg, trace);
|
casper.emit('page.error', msg, trace);
|
||||||
};
|
};
|
||||||
page.onInitialized = function onInitialized() {
|
page.onInitialized = function onInitialized() {
|
||||||
casper.emit('page.initialized', this);
|
casper.emit('page.initialized', page);
|
||||||
if (utils.isFunction(casper.options.onPageInitialized)) {
|
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);
|
casper.options.onPageInitialized.call(casper, page);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -1814,6 +2030,7 @@ function createPage(casper) {
|
|||||||
casper.emit('load.started');
|
casper.emit('load.started');
|
||||||
};
|
};
|
||||||
page.onLoadFinished = function onLoadFinished(status) {
|
page.onLoadFinished = function onLoadFinished(status) {
|
||||||
|
/*jshint maxstatements:20*/
|
||||||
if (status !== "success") {
|
if (status !== "success") {
|
||||||
casper.emit('load.failed', {
|
casper.emit('load.failed', {
|
||||||
status: status,
|
status: status,
|
||||||
@@ -1831,7 +2048,10 @@ function createPage(casper) {
|
|||||||
casper.options.onLoadError.call(casper, casper, casper.requestUrl, status);
|
casper.options.onLoadError.call(casper, casper, casper.requestUrl, status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// local client scripts
|
||||||
casper.injectClientScripts();
|
casper.injectClientScripts();
|
||||||
|
// remote client scripts
|
||||||
|
casper.includeRemoteScripts();
|
||||||
// Client-side utils injection
|
// Client-side utils injection
|
||||||
casper.injectClientUtils();
|
casper.injectClientUtils();
|
||||||
// history
|
// history
|
||||||
@@ -1847,6 +2067,17 @@ function createPage(casper) {
|
|||||||
}
|
}
|
||||||
casper.emit('navigation.requested', url, navigationType, navigationLocked, isMainFrame);
|
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) {
|
page.onPrompt = function onPrompt(message, value) {
|
||||||
return casper.filter('page.prompt', message, value);
|
return casper.filter('page.prompt', message, value);
|
||||||
};
|
};
|
||||||
@@ -1860,6 +2091,9 @@ function createPage(casper) {
|
|||||||
};
|
};
|
||||||
page.onResourceRequested = function onResourceRequested(request) {
|
page.onResourceRequested = function onResourceRequested(request) {
|
||||||
casper.emit('resource.requested', request);
|
casper.emit('resource.requested', request);
|
||||||
|
if (request.url === casper.requestUrl) {
|
||||||
|
casper.emit('page.resource.requested', request);
|
||||||
|
}
|
||||||
if (utils.isFunction(casper.options.onResourceRequested)) {
|
if (utils.isFunction(casper.options.onResourceRequested)) {
|
||||||
casper.options.onResourceRequested.call(casper, casper, request);
|
casper.options.onResourceRequested.call(casper, casper, request);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
* Casper client-side helpers.
|
* Casper client-side helpers.
|
||||||
*/
|
*/
|
||||||
exports.ClientUtils = function ClientUtils(options) {
|
exports.ClientUtils = function ClientUtils(options) {
|
||||||
|
/*jshint maxstatements:40*/
|
||||||
// private members
|
// private members
|
||||||
var BASE64_ENCODE_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
var BASE64_ENCODE_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||||
var BASE64_DECODE_CHARS = new Array(
|
var BASE64_DECODE_CHARS = new Array(
|
||||||
@@ -200,6 +201,7 @@
|
|||||||
* @return Object An object containing setting result for each field, including file uploads
|
* @return Object An object containing setting result for each field, including file uploads
|
||||||
*/
|
*/
|
||||||
this.fill = function fill(form, vals) {
|
this.fill = function fill(form, vals) {
|
||||||
|
/*jshint maxcomplexity:8*/
|
||||||
var out = {
|
var out = {
|
||||||
errors: [],
|
errors: [],
|
||||||
fields: [],
|
fields: [],
|
||||||
@@ -260,7 +262,7 @@
|
|||||||
try {
|
try {
|
||||||
var pSelector = this.processSelector(selector);
|
var pSelector = this.processSelector(selector);
|
||||||
if (pSelector.type === 'xpath') {
|
if (pSelector.type === 'xpath') {
|
||||||
return this.getElementsByXPath(pSelector.path);
|
return this.getElementsByXPath(pSelector.path, scope);
|
||||||
} else {
|
} else {
|
||||||
return scope.querySelectorAll(pSelector.path);
|
return scope.querySelectorAll(pSelector.path);
|
||||||
}
|
}
|
||||||
@@ -281,7 +283,7 @@
|
|||||||
try {
|
try {
|
||||||
var pSelector = this.processSelector(selector);
|
var pSelector = this.processSelector(selector);
|
||||||
if (pSelector.type === 'xpath') {
|
if (pSelector.type === 'xpath') {
|
||||||
return this.getElementByXPath(pSelector.path);
|
return this.getElementByXPath(pSelector.path, scope);
|
||||||
} else {
|
} else {
|
||||||
return scope.querySelector(pSelector.path);
|
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.
|
* Retrieves a single DOM element matching a given XPath expression.
|
||||||
*
|
*
|
||||||
* @param String expression The XPath expression
|
* @param String expression The XPath expression
|
||||||
|
* @param HTMLElement|null scope Element to search child elements within
|
||||||
* @return HTMLElement or null
|
* @return HTMLElement or null
|
||||||
*/
|
*/
|
||||||
this.getElementByXPath = function getElementByXPath(expression) {
|
this.getElementByXPath = function getElementByXPath(expression, scope) {
|
||||||
var a = document.evaluate(expression, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
|
scope = scope || this.options.scope;
|
||||||
|
var a = document.evaluate(expression, scope, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
|
||||||
if (a.snapshotLength > 0) {
|
if (a.snapshotLength > 0) {
|
||||||
return a.snapshotItem(0);
|
return a.snapshotItem(0);
|
||||||
}
|
}
|
||||||
@@ -406,12 +437,14 @@
|
|||||||
/**
|
/**
|
||||||
* Retrieves all DOM elements matching a given XPath expression.
|
* Retrieves all DOM elements matching a given XPath expression.
|
||||||
*
|
*
|
||||||
* @param String expression The XPath expression
|
* @param String expression The XPath expression
|
||||||
|
* @param HTMLElement|null scope Element to search child elements within
|
||||||
* @return Array
|
* @return Array
|
||||||
*/
|
*/
|
||||||
this.getElementsByXPath = function getElementsByXPath(expression) {
|
this.getElementsByXPath = function getElementsByXPath(expression, scope) {
|
||||||
|
scope = scope || this.options.scope;
|
||||||
var nodes = [];
|
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++) {
|
for (var i = 0; i < a.snapshotLength; i++) {
|
||||||
nodes.push(a.snapshotItem(i));
|
nodes.push(a.snapshotItem(i));
|
||||||
}
|
}
|
||||||
@@ -445,7 +478,7 @@
|
|||||||
if (type === 'radio') {
|
if (type === 'radio') {
|
||||||
var value;
|
var value;
|
||||||
[].forEach.call(inputs, function(radio) {
|
[].forEach.call(inputs, function(radio) {
|
||||||
value = radio.checked ? radio.value : undefined;
|
value = radio.checked ? radio.value : value;
|
||||||
});
|
});
|
||||||
return value;
|
return value;
|
||||||
} else if (type === 'checkbox') {
|
} 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
|
* Logs a message. Will format the message a way CasperJS will be able
|
||||||
* to log phantomjs side.
|
* to log phantomjs side.
|
||||||
@@ -569,24 +621,21 @@
|
|||||||
* Performs an AJAX request.
|
* Performs an AJAX request.
|
||||||
*
|
*
|
||||||
* @param String url Url.
|
* @param String url Url.
|
||||||
* @param String method HTTP method.
|
* @param String method HTTP method (default: GET).
|
||||||
* @param Object data Request parameters.
|
* @param Object data Request parameters.
|
||||||
* @param Boolean async Asynchroneous request? (default: false)
|
* @param Boolean async Asynchroneous request? (default: false)
|
||||||
* @return String Response text.
|
* @return String Response text.
|
||||||
*/
|
*/
|
||||||
this.sendAJAX = function sendAJAX(url, method, data, async) {
|
this.sendAJAX = function sendAJAX(url, method, data, async) {
|
||||||
var xhr = new XMLHttpRequest(), dataString = "";
|
var xhr = new XMLHttpRequest(),
|
||||||
if (typeof method !== "string" || ["GET", "POST"].indexOf(method.toUpperCase()) === -1) {
|
dataString = "",
|
||||||
method = "GET";
|
dataList = [];
|
||||||
} else {
|
method = method && method.toUpperCase() || "GET";
|
||||||
method = method.toUpperCase();
|
|
||||||
}
|
|
||||||
xhr.open(method, url, !!async);
|
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");
|
xhr.overrideMimeType("text/plain; charset=x-user-defined");
|
||||||
if (method === "POST") {
|
if (method === "POST") {
|
||||||
if (typeof data === "object") {
|
if (typeof data === "object") {
|
||||||
var dataList = [];
|
|
||||||
for (var k in data) {
|
for (var k in data) {
|
||||||
dataList.push(encodeURIComponent(k) + "=" + encodeURIComponent(data[k].toString()));
|
dataList.push(encodeURIComponent(k) + "=" + encodeURIComponent(data[k].toString()));
|
||||||
}
|
}
|
||||||
@@ -595,7 +644,7 @@
|
|||||||
} else if (typeof data === "string") {
|
} else if (typeof data === "string") {
|
||||||
dataString = data;
|
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);
|
xhr.send(method === "POST" ? dataString : null);
|
||||||
return xhr.responseText;
|
return xhr.responseText;
|
||||||
@@ -609,6 +658,7 @@
|
|||||||
* @param mixed value The field value to set
|
* @param mixed value The field value to set
|
||||||
*/
|
*/
|
||||||
this.setField = function setField(field, value) {
|
this.setField = function setField(field, value) {
|
||||||
|
/*jshint maxcomplexity:99 */
|
||||||
var logValue, fields, out;
|
var logValue, fields, out;
|
||||||
value = logValue = (value || "");
|
value = logValue = (value || "");
|
||||||
if (field instanceof NodeList) {
|
if (field instanceof NodeList) {
|
||||||
@@ -694,10 +744,14 @@
|
|||||||
out = 'Unsupported field type: ' + nodeName;
|
out = 'Unsupported field type: ' + nodeName;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// firing the `change` event
|
|
||||||
var changeEvent = document.createEvent("HTMLEvents");
|
// firing the `change` and `input` events
|
||||||
changeEvent.initEvent('change', true, true);
|
['change', 'input'].forEach(function(name) {
|
||||||
field.dispatchEvent(changeEvent);
|
var event = document.createEvent("HTMLEvents");
|
||||||
|
event.initEvent(name, true, true);
|
||||||
|
field.dispatchEvent(event);
|
||||||
|
});
|
||||||
|
|
||||||
// blur the field
|
// blur the field
|
||||||
try {
|
try {
|
||||||
field.blur();
|
field.blur();
|
||||||
|
|||||||
@@ -64,7 +64,8 @@ var Colorizer = function Colorizer() {
|
|||||||
'WARNING': { fg: 'red', bold: true },
|
'WARNING': { fg: 'red', bold: true },
|
||||||
'GREEN_BAR': { fg: 'white', bg: 'green', bold: true },
|
'GREEN_BAR': { fg: 'white', bg: 'green', bold: true },
|
||||||
'RED_BAR': { fg: 'white', bg: 'red', 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
|
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
/*global CasperError*/
|
||||||
|
|
||||||
var isArray = Array.isArray;
|
var isArray = Array.isArray;
|
||||||
|
|
||||||
function EventEmitter() {
|
function EventEmitter() {
|
||||||
@@ -230,6 +232,17 @@ EventEmitter.prototype.filter = function() {
|
|||||||
return filter.apply(this, Array.prototype.splice.call(arguments, 1));
|
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) {
|
EventEmitter.prototype.setFilter = function(type, filterFn) {
|
||||||
if (!this._filters) {
|
if (!this._filters) {
|
||||||
this._filters = {};
|
this._filters = {};
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ responseHeaders.prototype.get = function get(name){
|
|||||||
*/
|
*/
|
||||||
exports.augmentResponse = function(response) {
|
exports.augmentResponse = function(response) {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
/*jshint proto:true*/
|
||||||
if (!utils.isHTTPResource(response)) {
|
if (!utils.isHTTPResource(response)) {
|
||||||
return;
|
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');
|
throw new CasperError('Mouse() needs a Casper instance');
|
||||||
}
|
}
|
||||||
|
|
||||||
var slice = Array.prototype.slice;
|
var slice = Array.prototype.slice,
|
||||||
|
nativeEvents = ['mouseup', 'mousedown', 'click', 'mousemove'];
|
||||||
var nativeEvents = ['mouseup', 'mousedown', 'click', 'mousemove'];
|
if (utils.gteVersion(phantom.version, '1.8.0')) {
|
||||||
var emulatedEvents = ['mouseover', 'mouseout'];
|
nativeEvents.push('doubleclick');
|
||||||
var supportedEvents = nativeEvents.concat(emulatedEvents);
|
}
|
||||||
|
var emulatedEvents = ['mouseover', 'mouseout'],
|
||||||
|
supportedEvents = nativeEvents.concat(emulatedEvents);
|
||||||
|
|
||||||
function computeCenter(selector) {
|
function computeCenter(selector) {
|
||||||
var bounds = casper.getElementBounds(selector);
|
var bounds = casper.getElementBounds(selector);
|
||||||
@@ -72,8 +74,7 @@ var Mouse = function Mouse(casper) {
|
|||||||
throw new CasperError('Mouse.processEvent(): Too few arguments');
|
throw new CasperError('Mouse.processEvent(): Too few arguments');
|
||||||
case 1:
|
case 1:
|
||||||
// selector
|
// selector
|
||||||
var selector = args[0];
|
casper.page.sendEvent.apply(casper.page, [type].concat(computeCenter(args[0])));
|
||||||
casper.page.sendEvent.apply(casper.page, [type].concat(computeCenter(selector)));
|
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
// coordinates
|
// coordinates
|
||||||
@@ -95,6 +96,10 @@ var Mouse = function Mouse(casper) {
|
|||||||
processEvent('click', arguments);
|
processEvent('click', arguments);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.doubleclick = function doubleclick() {
|
||||||
|
processEvent('doubleclick', arguments);
|
||||||
|
};
|
||||||
|
|
||||||
this.down = function down() {
|
this.down = function down() {
|
||||||
processEvent('mousedown', arguments);
|
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) {
|
var Tester = function Tester(casper, options) {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
/*jshint maxstatements:30*/
|
||||||
|
|
||||||
if (!utils.isCasperObject(casper)) {
|
if (!utils.isCasperObject(casper)) {
|
||||||
throw new CasperError("Tester needs a Casper instance");
|
throw new CasperError("Tester needs a Casper instance");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
|
||||||
this.casper = casper;
|
this.casper = casper;
|
||||||
|
|
||||||
|
this.SKIP_MESSAGE = '__termination__';
|
||||||
|
|
||||||
|
this.aborted = false;
|
||||||
|
this.executed = 0;
|
||||||
this.currentTestFile = null;
|
this.currentTestFile = null;
|
||||||
this.currentSuiteNum = 0;
|
this.currentSuiteNum = 0;
|
||||||
this.exporter = require('xunit').create();
|
this.exporter = require('xunit').create();
|
||||||
@@ -66,9 +73,11 @@ var Tester = function Tester(casper, options) {
|
|||||||
this.running = false;
|
this.running = false;
|
||||||
this.suites = [];
|
this.suites = [];
|
||||||
this.options = utils.mergeObjects({
|
this.options = utils.mergeObjects({
|
||||||
|
failFast: false, // terminates a suite as soon as a test fails?
|
||||||
failText: "FAIL", // text to use for a successful test
|
failText: "FAIL", // text to use for a successful test
|
||||||
passText: "PASS", // text to use for a failed 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);
|
}, options);
|
||||||
|
|
||||||
// properties
|
// properties
|
||||||
@@ -76,25 +85,39 @@ var Tester = function Tester(casper, options) {
|
|||||||
passed: 0,
|
passed: 0,
|
||||||
failed: 0,
|
failed: 0,
|
||||||
passes: [],
|
passes: [],
|
||||||
failures: []
|
failures: [],
|
||||||
|
passesTime: [],
|
||||||
|
failuresTime: []
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// measuring test duration
|
||||||
|
this.currentTestStartTime = new Date();
|
||||||
|
this.lastAssertTime = 0;
|
||||||
|
|
||||||
this.configure();
|
this.configure();
|
||||||
|
|
||||||
this.on('success', function onSuccess(success) {
|
this.on('success', function onSuccess(success) {
|
||||||
this.testResults.passes.push(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) {
|
this.on('fail', function onFail(failure) {
|
||||||
// export
|
// export
|
||||||
|
var timeElapsed = new Date() - this.currentTestStartTime;
|
||||||
|
this.testResults.failuresTime.push(timeElapsed - this.lastAssertTime);
|
||||||
this.exporter.addFailure(
|
this.exporter.addFailure(
|
||||||
fs.absolute(failure.file),
|
fs.absolute(failure.file),
|
||||||
failure.message || failure.standard,
|
failure.message || failure.standard,
|
||||||
failure.standard || "test failed",
|
failure.standard || "test failed",
|
||||||
failure.type || "unknown"
|
failure.type || "unknown",
|
||||||
|
(timeElapsed - this.lastAssertTime)
|
||||||
);
|
);
|
||||||
|
this.lastAssertTime = timeElapsed;
|
||||||
this.testResults.failures.push(failure);
|
this.testResults.failures.push(failure);
|
||||||
|
|
||||||
// special printing
|
// special printing
|
||||||
if (failure.type) {
|
if (failure.type) {
|
||||||
this.comment(' type: ' + 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
|
// Tester class is an EventEmitter
|
||||||
@@ -138,6 +188,7 @@ exports.Tester = Tester;
|
|||||||
*/
|
*/
|
||||||
Tester.prototype.assert = Tester.prototype.assertTrue = function assert(subject, message, context) {
|
Tester.prototype.assert = Tester.prototype.assertTrue = function assert(subject, message, context) {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
this.executed++;
|
||||||
return this.processAssertionResult(utils.mergeObjects({
|
return this.processAssertionResult(utils.mergeObjects({
|
||||||
success: subject === true,
|
success: subject === true,
|
||||||
type: "assert",
|
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 Function fn A function to be evaluated in remote DOM
|
||||||
* @param String message Test description
|
* @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
|
* @return Object An assertion result object
|
||||||
*/
|
*/
|
||||||
Tester.prototype.assertEval = Tester.prototype.assertEvaluate = function assertEval(fn, message, params) {
|
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";
|
"use strict";
|
||||||
var actual = this.casper.evaluate(function(inputName) {
|
var actual = this.casper.evaluate(function(inputName) {
|
||||||
return __utils__.getFieldValue(inputName);
|
return __utils__.getFieldValue(inputName);
|
||||||
}, { inputName: inputName });
|
}, inputName);
|
||||||
return this.assert(this.testEquals(actual, expected), message, {
|
return this.assert(this.testEquals(actual, expected), message, {
|
||||||
type: 'assertField',
|
type: 'assertField',
|
||||||
standard: f('"%s" input field has the value "%s"', inputName, expected),
|
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
|
* @param String message Test description
|
||||||
* @return Object An assertion result object
|
* @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";
|
"use strict";
|
||||||
return this.assert(this.casper.exists(selector), message, {
|
return this.assert(this.casper.exists(selector), message, {
|
||||||
type: "assertExists",
|
type: "assertExists",
|
||||||
@@ -327,6 +378,9 @@ Tester.prototype.assertHttpStatus = function assertHttpStatus(status, message) {
|
|||||||
*/
|
*/
|
||||||
Tester.prototype.assertMatch = Tester.prototype.assertMatches = function assertMatch(subject, pattern, message) {
|
Tester.prototype.assertMatch = Tester.prototype.assertMatches = function assertMatch(subject, pattern, message) {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
if (utils.betterTypeOf(pattern) !== "regexp") {
|
||||||
|
throw new CasperError('Invalid regexp.');
|
||||||
|
}
|
||||||
return this.assert(pattern.test(subject), message, {
|
return this.assert(pattern.test(subject), message, {
|
||||||
type: "assertMatch",
|
type: "assertMatch",
|
||||||
standard: "Subject matches the provided pattern",
|
standard: "Subject matches the provided pattern",
|
||||||
@@ -344,7 +398,7 @@ Tester.prototype.assertMatch = Tester.prototype.assertMatches = function assertM
|
|||||||
* @param String message Test description
|
* @param String message Test description
|
||||||
* @return Object An assertion result object
|
* @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";
|
"use strict";
|
||||||
return this.assert(!condition, message, {
|
return this.assert(!condition, message, {
|
||||||
type: "assertNot",
|
type: "assertNot",
|
||||||
@@ -382,7 +436,7 @@ Tester.prototype.assertNotVisible = Tester.prototype.assertInvisible = function
|
|||||||
* @param String message Test description
|
* @param String message Test description
|
||||||
* @return Object An assertion result object
|
* @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";
|
"use strict";
|
||||||
var context = {
|
var context = {
|
||||||
type: "assertRaises",
|
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.
|
* 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.
|
* 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
|
* @param String message Test description
|
||||||
* @return Object An assertion result object
|
* @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";
|
"use strict";
|
||||||
var textFound = this.casper.fetchText(selector).indexOf(text) !== -1;
|
var textFound = this.casper.fetchText(selector).indexOf(text) !== -1;
|
||||||
return this.assert(textFound, message, {
|
return this.assert(textFound, message, {
|
||||||
type: "assertTextInSelector",
|
type: "assertSelectorHasText",
|
||||||
standard: f('Found "%s" within the selector "%s"', text, selector),
|
standard: f('Found "%s" within the selector "%s"', text, selector),
|
||||||
values: {
|
values: {
|
||||||
selector: selector,
|
selector: selector,
|
||||||
@@ -468,11 +581,11 @@ Tester.prototype.assertSelectorHasText = function assertSelectorHasText(selector
|
|||||||
* @param String message Test description
|
* @param String message Test description
|
||||||
* @return Object An assertion result object
|
* @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";
|
"use strict";
|
||||||
var textFound = this.casper.fetchText(selector).indexOf(text) === -1;
|
var textFound = this.casper.fetchText(selector).indexOf(text) === -1;
|
||||||
return this.assert(textFound, message, {
|
return this.assert(textFound, message, {
|
||||||
type: "assertNoTextInSelector",
|
type: "assertSelectorDoesntHaveText",
|
||||||
standard: f('Did not find "%s" within the selector "%s"', text, selector),
|
standard: f('Did not find "%s" within the selector "%s"', text, selector),
|
||||||
values: {
|
values: {
|
||||||
selector: selector,
|
selector: selector,
|
||||||
@@ -510,6 +623,9 @@ Tester.prototype.assertTitle = function assertTitle(expected, message) {
|
|||||||
*/
|
*/
|
||||||
Tester.prototype.assertTitleMatch = Tester.prototype.assertTitleMatches = function assertTitleMatch(pattern, message) {
|
Tester.prototype.assertTitleMatch = Tester.prototype.assertTitleMatches = function assertTitleMatch(pattern, message) {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
if (utils.betterTypeOf(pattern) !== "regexp") {
|
||||||
|
throw new CasperError('Invalid regexp.');
|
||||||
|
}
|
||||||
var currentTitle = this.casper.getTitle();
|
var currentTitle = this.casper.getTitle();
|
||||||
return this.assert(pattern.test(currentTitle), message, {
|
return this.assert(pattern.test(currentTitle), message, {
|
||||||
type: "assertTitle",
|
type: "assertTitle",
|
||||||
@@ -601,6 +717,19 @@ Tester.prototype.bar = function bar(text, style) {
|
|||||||
this.casper.echo(text, style, this.options.pad);
|
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
|
* Render a colorized output. Basically a proxy method for
|
||||||
* Casper.Colorizer#colorize()
|
* Casper.Colorizer#colorize()
|
||||||
@@ -635,7 +764,7 @@ Tester.prototype.configure = function configure() {
|
|||||||
|
|
||||||
// specific timeout callbacks
|
// specific timeout callbacks
|
||||||
this.casper.options.onStepTimeout = function test_onStepTimeout(timeout, step) {
|
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) {
|
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) {
|
this.casper.options.onWaitTimeout = function test_onWaitTimeout(timeout) {
|
||||||
tester.fail(f("Wait timeout occured (%dms)", 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.
|
* 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";
|
"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.emit('test.done');
|
||||||
this.running = false;
|
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.
|
* Writes an info-style formatted message to stdout.
|
||||||
*
|
*
|
||||||
@@ -816,21 +956,23 @@ Tester.prototype.pass = function pass(message) {
|
|||||||
*/
|
*/
|
||||||
Tester.prototype.processAssertionResult = function processAssertionResult(result) {
|
Tester.prototype.processAssertionResult = function processAssertionResult(result) {
|
||||||
"use strict";
|
"use strict";
|
||||||
var eventName, style, status;
|
var eventName= 'success',
|
||||||
if (result.success === true) {
|
message = result.message || result.standard,
|
||||||
eventName = 'success';
|
style = 'INFO',
|
||||||
style = 'INFO';
|
|
||||||
status = this.options.passText;
|
status = this.options.passText;
|
||||||
this.testResults.passed++;
|
if (!result.success) {
|
||||||
} else {
|
|
||||||
eventName = 'fail';
|
eventName = 'fail';
|
||||||
style = 'RED_BAR';
|
style = 'RED_BAR';
|
||||||
status = this.options.failText;
|
status = this.options.failText;
|
||||||
this.testResults.failed++;
|
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.casper.echo([this.colorize(status, style), this.formatMessage(message)].join(' '));
|
||||||
this.emit(eventName, result);
|
this.emit(eventName, result);
|
||||||
|
if (this.options.failFast && !result.success) {
|
||||||
|
throw this.SKIP_MESSAGE;
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -852,7 +994,7 @@ Tester.prototype.renderFailureDetails = function renderFailureDetails(failures)
|
|||||||
message = failure.message;
|
message = failure.message;
|
||||||
this.casper.echo(f('In %s:%s', failure.file, line));
|
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");
|
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 total = this.testResults.passed + this.testResults.failed, statusText, style, result;
|
||||||
var exitStatus = ~~(status || (this.testResults.failed > 0 ? 1 : 0));
|
var exitStatus = ~~(status || (this.testResults.failed > 0 ? 1 : 0));
|
||||||
if (total === 0) {
|
if (total === 0) {
|
||||||
statusText = this.options.failText;
|
statusText = this.options.warnText;
|
||||||
style = 'RED_BAR';
|
style = 'WARN_BAR';
|
||||||
result = f("%s Looks like you didn't run any test.", statusText);
|
result = f("%s Looks like you didn't run any test.", statusText);
|
||||||
} else {
|
} else {
|
||||||
if (this.testResults.failed > 0) {
|
if (this.testResults.failed > 0) {
|
||||||
@@ -878,8 +1020,9 @@ Tester.prototype.renderResults = function renderResults(exit, status, save) {
|
|||||||
statusText = this.options.passText;
|
statusText = this.options.passText;
|
||||||
style = 'GREEN_BAR';
|
style = 'GREEN_BAR';
|
||||||
}
|
}
|
||||||
result = f('%s %s tests executed, %d passed, %d failed.',
|
result = f('%s %s tests executed in %ss, %d passed, %d failed.',
|
||||||
statusText, total, this.testResults.passed, this.testResults.failed);
|
statusText, total, utils.ms2seconds(this.calculateSuiteDuration()),
|
||||||
|
this.testResults.passed, this.testResults.failed);
|
||||||
}
|
}
|
||||||
this.casper.echo(result, style, this.options.pad);
|
this.casper.echo(result, style, this.options.pad);
|
||||||
if (this.testResults.failed > 0) {
|
if (this.testResults.failed > 0) {
|
||||||
@@ -931,16 +1074,23 @@ Tester.prototype.runSuites = function runSuites() {
|
|||||||
this.casper.exit(1);
|
this.casper.exit(1);
|
||||||
}
|
}
|
||||||
self.currentSuiteNum = 0;
|
self.currentSuiteNum = 0;
|
||||||
|
self.currentTestStartTime = new Date();
|
||||||
|
self.lastAssertTime = 0;
|
||||||
var interval = setInterval(function _check(self) {
|
var interval = setInterval(function _check(self) {
|
||||||
if (self.running) {
|
if (self.running) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (self.currentSuiteNum === testFiles.length) {
|
if (self.currentSuiteNum === testFiles.length || self.aborted) {
|
||||||
self.emit('tests.complete');
|
self.emit('tests.complete');
|
||||||
clearInterval(interval);
|
clearInterval(interval);
|
||||||
|
self.exporter.setSuiteDuration(self.calculateSuiteDuration());
|
||||||
|
self.aborted = false;
|
||||||
} else {
|
} else {
|
||||||
self.runTest(testFiles[self.currentSuiteNum]);
|
self.runTest(testFiles[self.currentSuiteNum]);
|
||||||
|
self.exporter.setSuiteDuration(self.calculateSuiteDuration());
|
||||||
self.currentSuiteNum++;
|
self.currentSuiteNum++;
|
||||||
|
self.passesTime = [];
|
||||||
|
self.failuresTime = [];
|
||||||
}
|
}
|
||||||
}, 100, this);
|
}, 100, this);
|
||||||
};
|
};
|
||||||
@@ -953,6 +1103,7 @@ Tester.prototype.runTest = function runTest(testFile) {
|
|||||||
"use strict";
|
"use strict";
|
||||||
this.bar(f('Test file: %s', testFile), 'INFO_BAR');
|
this.bar(f('Test file: %s', testFile), 'INFO_BAR');
|
||||||
this.running = true; // this.running is set back to false with done()
|
this.running = true; // this.running is set back to false with done()
|
||||||
|
this.executed = 0;
|
||||||
this.exec(testFile);
|
this.exec(testFile);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -34,16 +34,26 @@
|
|||||||
* Provides a better typeof operator equivalent, able to retrieve the array
|
* Provides a better typeof operator equivalent, able to retrieve the array
|
||||||
* type.
|
* 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
|
* @param mixed input
|
||||||
* @return String
|
* @return String
|
||||||
* @see http://javascriptweblog.wordpress.com/2011/08/08/fixing-the-javascript-typeof-operator/
|
* @see http://javascriptweblog.wordpress.com/2011/08/08/fixing-the-javascript-typeof-operator/
|
||||||
*/
|
*/
|
||||||
function betterTypeOf(input) {
|
function betterTypeOf(input) {
|
||||||
"use strict";
|
"use strict";
|
||||||
try {
|
switch (input) {
|
||||||
return Object.prototype.toString.call(input).match(/^\[object\s(.*)\]$/)[1].toLowerCase();
|
case undefined:
|
||||||
} catch (e) {
|
return 'undefined';
|
||||||
return typeof input;
|
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;
|
exports.betterTypeOf = betterTypeOf;
|
||||||
@@ -69,6 +79,18 @@ function cleanUrl(url) {
|
|||||||
}
|
}
|
||||||
exports.cleanUrl = cleanUrl;
|
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
|
* Dumps a JSON representation of passed value to the console. Used for
|
||||||
* debugging purpose only.
|
* debugging purpose only.
|
||||||
@@ -264,6 +286,18 @@ function isClipRect(value) {
|
|||||||
}
|
}
|
||||||
exports.isClipRect = isClipRect;
|
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
|
* Checks if value is a javascript Function
|
||||||
*
|
*
|
||||||
@@ -337,6 +371,18 @@ function isObject(value) {
|
|||||||
}
|
}
|
||||||
exports.isObject = isObject;
|
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
|
* Checks if value is a javascript String
|
||||||
*
|
*
|
||||||
@@ -349,6 +395,19 @@ function isString(value) {
|
|||||||
}
|
}
|
||||||
exports.isString = isString;
|
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
|
* Shorthands for checking if a value is of the given type. Can check for
|
||||||
* arrays.
|
* arrays.
|
||||||
@@ -433,20 +492,32 @@ exports.isWebPage = isWebPage;
|
|||||||
function mergeObjects(origin, add) {
|
function mergeObjects(origin, add) {
|
||||||
"use strict";
|
"use strict";
|
||||||
for (var p in add) {
|
for (var p in add) {
|
||||||
try {
|
if (add[p] && add[p].constructor === Object) {
|
||||||
if (add[p].constructor === Object) {
|
if (origin[p] && origin[p].constructor === Object) {
|
||||||
origin[p] = mergeObjects(origin[p], add[p]);
|
origin[p] = mergeObjects(origin[p], add[p]);
|
||||||
} else {
|
} else {
|
||||||
origin[p] = add[p];
|
origin[p] = clone(add[p]);
|
||||||
}
|
}
|
||||||
} catch(e) {
|
} else {
|
||||||
origin[p] = add[p];
|
origin[p] = add[p];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return origin;
|
return origin;
|
||||||
}
|
}
|
||||||
exports.mergeObjects = mergeObjects;
|
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.
|
* Creates an (SG|X)ML node element.
|
||||||
*
|
*
|
||||||
@@ -456,7 +527,7 @@ exports.mergeObjects = mergeObjects;
|
|||||||
*/
|
*/
|
||||||
function node(name, attributes) {
|
function node(name, attributes) {
|
||||||
"use strict";
|
"use strict";
|
||||||
var _node = document.createElement(name);
|
var _node = document.createElement(name);
|
||||||
for (var attrName in attributes) {
|
for (var attrName in attributes) {
|
||||||
var value = attributes[attrName];
|
var value = attributes[attrName];
|
||||||
if (attributes.hasOwnProperty(attrName) && isString(attrName)) {
|
if (attributes.hasOwnProperty(attrName) && isString(attrName)) {
|
||||||
@@ -467,6 +538,20 @@ function node(name, attributes) {
|
|||||||
}
|
}
|
||||||
exports.node = node;
|
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.
|
* Serializes a value using JSON.
|
||||||
*
|
*
|
||||||
@@ -506,3 +591,62 @@ function unique(array) {
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
exports.unique = unique;
|
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) {
|
function generateClassName(classname) {
|
||||||
"use strict";
|
"use strict";
|
||||||
classname = classname.replace(phantom.casperPath, "").trim();
|
classname = classname.replace(phantom.casperPath, "").trim();
|
||||||
var script = classname || phantom.casperScript;
|
var script = classname || phantom.casperScript || "";
|
||||||
if (script.indexOf(fs.workingDirectory) === 0) {
|
if (script.indexOf(fs.workingDirectory) === 0) {
|
||||||
script = script.substring(fs.workingDirectory.length + 1);
|
script = script.substring(fs.workingDirectory.length + 1);
|
||||||
}
|
}
|
||||||
@@ -55,6 +55,12 @@ function generateClassName(classname) {
|
|||||||
if (~script.indexOf('.')) {
|
if (~script.indexOf('.')) {
|
||||||
script = script.substring(0, script.lastIndexOf('.'));
|
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";
|
return script || "unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,13 +92,18 @@ exports.XUnitExporter = XUnitExporter;
|
|||||||
*
|
*
|
||||||
* @param String classname
|
* @param String classname
|
||||||
* @param String name
|
* @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";
|
"use strict";
|
||||||
this._xml.appendChild(utils.node('testcase', {
|
var snode = utils.node('testcase', {
|
||||||
classname: generateClassName(classname),
|
classname: generateClassName(classname),
|
||||||
name: name
|
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 name
|
||||||
* @param String message
|
* @param String message
|
||||||
* @param String type
|
* @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";
|
"use strict";
|
||||||
var fnode = utils.node('testcase', {
|
var fnode = utils.node('testcase', {
|
||||||
classname: generateClassName(classname),
|
classname: generateClassName(classname),
|
||||||
name: name
|
name: name
|
||||||
});
|
});
|
||||||
|
if (duration !== undefined) {
|
||||||
|
fnode.setAttribute('time', utils.ms2seconds(duration));
|
||||||
|
}
|
||||||
var failure = utils.node('failure', {
|
var failure = utils.node('failure', {
|
||||||
type: type || "unknown"
|
type: type || "unknown"
|
||||||
});
|
});
|
||||||
@@ -117,6 +132,18 @@ XUnitExporter.prototype.addFailure = function addFailure(classname, name, messag
|
|||||||
this._xml.appendChild(fnode);
|
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.
|
* Retrieves generated XML object - actually an HTMLElement.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "casperjs",
|
"name": "casperjs",
|
||||||
"description": "Navigation scripting & testing utility for PhantomJS",
|
"description": "Navigation scripting & testing utility for PhantomJS",
|
||||||
"version": "1.0.0-RC4",
|
"version": "1.0.2",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"phantomjs",
|
"phantomjs",
|
||||||
"javascript"
|
"javascript"
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"http://www.phantomjs.org/": "1.6"
|
"http://www.phantomjs.org/": "1.7"
|
||||||
},
|
},
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/n1k0/casperjs/issues"
|
"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?"
|
puts "Fatal: Did you install phantomjs?"
|
||||||
end
|
end
|
||||||
|
|
||||||
exit $?.exitstatus
|
exit $?.exitstatus || 1
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ images = []
|
|||||||
casper.hide = (selector) ->
|
casper.hide = (selector) ->
|
||||||
@evaluate (selector) ->
|
@evaluate (selector) ->
|
||||||
document.querySelector(selector).style.display = "none"
|
document.querySelector(selector).style.display = "none"
|
||||||
, selector: selector
|
, selector
|
||||||
|
|
||||||
casper.start "http://www.bbc.co.uk/", ->
|
casper.start "http://www.bbc.co.uk/", ->
|
||||||
nbLinks = @evaluate ->
|
nbLinks = @evaluate ->
|
||||||
@@ -21,15 +21,16 @@ casper.start "http://www.bbc.co.uk/", ->
|
|||||||
@hide ".nav_left"
|
@hide ".nav_left"
|
||||||
@hide ".nav_right"
|
@hide ".nav_right"
|
||||||
@mouse.move "#promo2_carousel"
|
@mouse.move "#promo2_carousel"
|
||||||
@waitUntilVisible ".autoplay.nav_pause", ->
|
|
||||||
@echo "Moving over pause button"
|
casper.waitUntilVisible ".autoplay.nav_pause", ->
|
||||||
@mouse.move ".autoplay.nav_pause"
|
@echo "Moving over pause button"
|
||||||
@click ".autoplay.nav_pause"
|
@mouse.move ".autoplay.nav_pause"
|
||||||
@echo "Clicked on pause button"
|
@click ".autoplay.nav_pause"
|
||||||
@waitUntilVisible ".autoplay.nav_play", ->
|
@echo "Clicked on pause button"
|
||||||
@echo "Carousel has been paused"
|
@waitUntilVisible ".autoplay.nav_play", ->
|
||||||
# hide play button
|
@echo "Carousel has been paused"
|
||||||
@hide ".autoplay"
|
# hide play button
|
||||||
|
@hide ".autoplay"
|
||||||
|
|
||||||
# Capture carrousel area
|
# Capture carrousel area
|
||||||
next = ->
|
next = ->
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
/*
|
/*jshint strict:false*/
|
||||||
|
/*global CasperError console phantom require*/
|
||||||
|
|
||||||
|
/**
|
||||||
* Create a mosaic image from all headline photos on BBC homepage
|
* Create a mosaic image from all headline photos on BBC homepage
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var casper = require("casper").create();
|
var casper = require("casper").create();
|
||||||
var nbLinks = 0;
|
var nbLinks = 0;
|
||||||
var currentLink = 1;
|
var currentLink = 1;
|
||||||
@@ -12,9 +14,7 @@ var buildPage, next;
|
|||||||
casper.hide = function(selector) {
|
casper.hide = function(selector) {
|
||||||
this.evaluate(function(selector) {
|
this.evaluate(function(selector) {
|
||||||
document.querySelector(selector).style.display = "none";
|
document.querySelector(selector).style.display = "none";
|
||||||
}, {
|
}, selector);
|
||||||
selector: selector
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
casper.start("http://www.bbc.co.uk/", function() {
|
casper.start("http://www.bbc.co.uk/", function() {
|
||||||
@@ -26,16 +26,17 @@ casper.start("http://www.bbc.co.uk/", function() {
|
|||||||
this.hide(".nav_left");
|
this.hide(".nav_left");
|
||||||
this.hide(".nav_right");
|
this.hide(".nav_right");
|
||||||
this.mouse.move("#promo2_carousel");
|
this.mouse.move("#promo2_carousel");
|
||||||
this.waitUntilVisible(".autoplay.nav_pause", function() {
|
});
|
||||||
this.echo("Moving over pause button");
|
|
||||||
this.mouse.move(".autoplay.nav_pause");
|
casper.waitUntilVisible(".autoplay.nav_pause", function() {
|
||||||
this.click(".autoplay.nav_pause");
|
this.echo("Moving over pause button");
|
||||||
this.echo("Clicked on pause button");
|
this.mouse.move(".autoplay.nav_pause");
|
||||||
this.waitUntilVisible(".autoplay.nav_play", function() {
|
this.click(".autoplay.nav_pause");
|
||||||
this.echo("Carousel has been paused");
|
this.echo("Clicked on pause button");
|
||||||
// hide play button
|
this.waitUntilVisible(".autoplay.nav_play", function() {
|
||||||
this.hide(".autoplay");
|
this.echo("Carousel has been paused");
|
||||||
});
|
// hide play button
|
||||||
|
this.hide(".autoplay");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
/*jshint strict:false*/
|
||||||
|
/*global CasperError console phantom require*/
|
||||||
|
|
||||||
var casper = require("casper").create();
|
var casper = require("casper").create();
|
||||||
var dump = require("utils").dump;
|
var dump = require("utils").dump;
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
/*jshint strict:false*/
|
||||||
|
/*global CasperError console phantom require*/
|
||||||
|
|
||||||
var casper = require("casper").create();
|
var casper = require("casper").create();
|
||||||
|
|
||||||
// listening to a custom event
|
// listening to a custom event
|
||||||
|
|||||||
@@ -2,29 +2,27 @@
|
|||||||
A basic custom logging implementation. The idea is to (extremely) verbosely
|
A basic custom logging implementation. The idea is to (extremely) verbosely
|
||||||
log every received resource.
|
log every received resource.
|
||||||
###
|
###
|
||||||
|
|
||||||
casper = require("casper").create
|
casper = require("casper").create
|
||||||
###
|
|
||||||
Every time a resource is received, a new log entry is added to the stack
|
|
||||||
at the 'verbose' level.
|
|
||||||
|
|
||||||
@param Object resource A phantomjs resource object
|
|
||||||
###
|
|
||||||
onResourceReceived: (self, resource) ->
|
|
||||||
infos = []
|
|
||||||
props = [
|
|
||||||
"url"
|
|
||||||
"status"
|
|
||||||
"statusText"
|
|
||||||
"redirectURL"
|
|
||||||
"bodySize"
|
|
||||||
]
|
|
||||||
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
|
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 :)
|
logLevel: "verbose" # of course we want to see logs to our new level :)
|
||||||
|
|
||||||
|
###
|
||||||
|
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"
|
||||||
|
"status"
|
||||||
|
"statusText"
|
||||||
|
"redirectURL"
|
||||||
|
"bodySize"
|
||||||
|
]
|
||||||
|
infos.push resource[prop] for prop in props
|
||||||
|
infos.push "[#{header.name}: #{header.value}]" for header in resource.headers
|
||||||
|
@log infos.join(", "), "verbose"
|
||||||
|
|
||||||
# add a new 'verbose' logging level at the lowest priority
|
# add a new 'verbose' logging level at the lowest priority
|
||||||
casper.logLevels = ["verbose"].concat casper.logLevels
|
casper.logLevels = ["verbose"].concat casper.logLevels
|
||||||
|
|
||||||
|
|||||||
@@ -1,38 +1,37 @@
|
|||||||
/*
|
/*jshint strict:false*/
|
||||||
|
/*global CasperError console phantom require*/
|
||||||
|
|
||||||
|
/**
|
||||||
* A basic custom logging implementation. The idea is to (extremely) verbosely
|
* A basic custom logging implementation. The idea is to (extremely) verbosely
|
||||||
* log every received resource.
|
* log every received resource.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var casper = require("casper").create({
|
var casper = require("casper").create({
|
||||||
/*
|
|
||||||
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 = [
|
|
||||||
"url",
|
|
||||||
"status",
|
|
||||||
"statusText",
|
|
||||||
"redirectURL",
|
|
||||||
"bodySize"
|
|
||||||
];
|
|
||||||
for (_i = 0, _len = props.length; _i < _len; _i++) {
|
|
||||||
prop = props[_i];
|
|
||||||
infos.push(resource[prop]);
|
|
||||||
}
|
|
||||||
_ref = resource.headers;
|
|
||||||
for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) {
|
|
||||||
header = _ref[_j];
|
|
||||||
infos.push("[" + header.name + ": " + header.value + "]");
|
|
||||||
}
|
|
||||||
this.log(infos.join(", "), "verbose");
|
|
||||||
},
|
|
||||||
verbose: true,
|
verbose: true,
|
||||||
logLevel: "verbose"
|
logLevel: "verbose"
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Every time a resource is received, a new log entry is added to the stack at
|
||||||
|
* the 'verbose' level.
|
||||||
|
*/
|
||||||
|
casper.on('resource.received', function(resource) {
|
||||||
|
var infos = [];
|
||||||
|
var props = [
|
||||||
|
"url",
|
||||||
|
"status",
|
||||||
|
"statusText",
|
||||||
|
"redirectURL",
|
||||||
|
"bodySize"
|
||||||
|
];
|
||||||
|
props.forEach(function(prop) {
|
||||||
|
infos.push(resource[prop]);
|
||||||
|
});
|
||||||
|
resource.headers.forEach(function(header) {
|
||||||
|
infos.push("[" + header.name + ": " + header.value + "]");
|
||||||
|
});
|
||||||
|
this.log(infos.join(", "), "verbose");
|
||||||
|
});
|
||||||
|
|
||||||
// add a new 'verbose' logging level at the lowest priority
|
// add a new 'verbose' logging level at the lowest priority
|
||||||
casper.logLevels = ["verbose"].concat(casper.logLevels);
|
casper.logLevels = ["verbose"].concat(casper.logLevels);
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
/*
|
/*jshint strict:false*/
|
||||||
|
/*global CasperError console phantom require*/
|
||||||
|
|
||||||
|
/**
|
||||||
* download the google logo image onto the local filesystem
|
* 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({
|
var casper = require("casper").create({
|
||||||
verbose: true
|
verbose: true
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
/*jshint strict:false*/
|
||||||
|
/*global CasperError console phantom require*/
|
||||||
|
|
||||||
var casper = require("casper").create();
|
var casper = require("casper").create();
|
||||||
|
|
||||||
var links = [
|
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.
|
* This script will add a custom HTTP status code handler, here for 404 pages.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var casper = require("casper").create();
|
var casper = require("casper").create();
|
||||||
|
|
||||||
casper.on("http.status.200", function(resource) {
|
casper.on("http.status.200", function(resource) {
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
/*jshint strict:false*/
|
||||||
|
/*global CasperError console phantom require*/
|
||||||
|
|
||||||
var casper = require("casper").create({
|
var casper = require("casper").create({
|
||||||
loadImages: false,
|
loadImages: false,
|
||||||
logLevel: "debug",
|
logLevel: "debug",
|
||||||
@@ -34,4 +37,4 @@ Object.keys(links).forEach(function(url) {
|
|||||||
fantomas.run(function() {
|
fantomas.run(function() {
|
||||||
this.renderJSON(links);
|
this.renderJSON(links);
|
||||||
this.exit();
|
this.exit();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
/*jshint strict:false*/
|
||||||
|
/*global CasperError console phantom require*/
|
||||||
var links = [];
|
var links = [];
|
||||||
var casper = require("casper").create();
|
var casper = require("casper").create();
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ casper = require("casper").create verbose: true
|
|||||||
|
|
||||||
casper.fetchScore = ->
|
casper.fetchScore = ->
|
||||||
@evaluate ->
|
@evaluate ->
|
||||||
result = document.querySelector('#resultStats').innerText
|
result = __utils__.findOne('#resultStats').innerText
|
||||||
parseInt /Environ ([0-9\s]{1,}).*/.exec(result)[1].replace(/\s/g, '')
|
parseInt /Environ ([0-9\s]{1,}).*/.exec(result)[1].replace(/\s/g, '')
|
||||||
|
|
||||||
terms = casper.cli.args # terms are passed through command-line arguments
|
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
|
* Takes provided terms passed as arguments and query google for the number of
|
||||||
* estimated results each have.
|
* estimated results each have.
|
||||||
*
|
*
|
||||||
@@ -16,7 +19,7 @@ var casper = require("casper").create({
|
|||||||
|
|
||||||
casper.fetchScore = function() {
|
casper.fetchScore = function() {
|
||||||
return this.evaluate(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);
|
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
|
* Capture multiple pages of google search results
|
||||||
*
|
*
|
||||||
* Usage: $ casperjs googlepagination.coffee my search terms
|
* Usage: $ casperjs googlepagination.coffee my search terms
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
/*jshint strict:false*/
|
||||||
|
/*global CasperError console phantom require*/
|
||||||
|
|
||||||
var casper = require("casper").create({
|
var casper = require("casper").create({
|
||||||
logLevel: "debug"
|
logLevel: "debug"
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
/*jshint strict:false*/
|
||||||
|
/*global CasperError console phantom require*/
|
||||||
|
|
||||||
var casper = require("casper").create({
|
var casper = require("casper").create({
|
||||||
verbose: true,
|
verbose: true,
|
||||||
logLevel: "debug"
|
logLevel: "debug"
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
/*jshint strict:false*/
|
||||||
|
/*global CasperError console phantom require*/
|
||||||
|
|
||||||
var casper = require("casper").create();
|
var casper = require("casper").create();
|
||||||
var url = casper.cli.get(0);
|
var url = casper.cli.get(0);
|
||||||
var metas = [];
|
var metas = [];
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
/*jshint strict:false*/
|
||||||
|
/*global CasperError console phantom require*/
|
||||||
|
|
||||||
var casper = require("casper").create({
|
var casper = require("casper").create({
|
||||||
verbose: true
|
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]>")
|
.echo("Usage: $ casperjs screenshot.coffee <twitter-account> <filename.[jpg|png|pdf]>")
|
||||||
.exit(1)
|
.exit(1)
|
||||||
|
|
||||||
casper.start "https://twitter.com/#!/#{twitterAccount}", ->
|
casper.start "https://twitter.com/#{twitterAccount}", ->
|
||||||
@waitForSelector ".tweet-row", (->
|
@waitForSelector ".stream-container", (->
|
||||||
@captureSelector filename, "html"
|
@captureSelector filename, "html"
|
||||||
@echo "Saved screenshot of #{@getCurrentUrl()} to #{filename}"
|
@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
|
* 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({
|
var casper = require("casper").create({
|
||||||
@@ -15,13 +18,13 @@ var filename = casper.cli.get(1);
|
|||||||
|
|
||||||
if (!twitterAccount || !filename || !/\.(png|jpg|pdf)$/i.test(filename)) {
|
if (!twitterAccount || !filename || !/\.(png|jpg|pdf)$/i.test(filename)) {
|
||||||
casper
|
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)
|
.exit(1)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
casper.start("https://twitter.com/#!/" + twitterAccount, function() {
|
casper.start("https://twitter.com/" + twitterAccount, function() {
|
||||||
this.waitForSelector(".tweet-row", (function() {
|
this.waitForSelector(".stream-container", (function() {
|
||||||
this.captureSelector(filename, "html");
|
this.captureSelector(filename, "html");
|
||||||
this.echo("Saved screenshot of " + (this.getCurrentUrl()) + " to " + filename);
|
this.echo("Saved screenshot of " + (this.getCurrentUrl()) + " to " + filename);
|
||||||
}), (function() {
|
}), (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.
|
* 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 failed = [];
|
||||||
var start = null;
|
var start = null;
|
||||||
var links = [
|
var links = [
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
/*
|
/*jshint strict:false*/
|
||||||
|
/*global CasperError console phantom require*/
|
||||||
|
|
||||||
|
/**
|
||||||
* Just a silly game.
|
* Just a silly game.
|
||||||
*
|
*
|
||||||
* $ casperjs samples/timeout.js 500
|
* $ 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) {
|
if (!phantom.casperLoaded) {
|
||||||
console.log('This script must be invoked using the casperjs executable');
|
console.log('This script must be invoked using the casperjs executable');
|
||||||
@@ -21,10 +21,8 @@ function checkSelfTest(tests) {
|
|||||||
var isCasperTest = false;
|
var isCasperTest = false;
|
||||||
tests.forEach(function(test) {
|
tests.forEach(function(test) {
|
||||||
var testDir = fs.absolute(fs.dirname(test));
|
var testDir = fs.absolute(fs.dirname(test));
|
||||||
if (fs.isDirectory(testDir)) {
|
if (fs.isDirectory(testDir) && fs.exists(fs.pathJoin(testDir, '.casper'))) {
|
||||||
if (fs.exists(fs.pathJoin(testDir, '.casper'))) {
|
isCasperTest = true;
|
||||||
isCasperTest = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return isCasperTest;
|
return isCasperTest;
|
||||||
@@ -52,52 +50,72 @@ function checkIncludeFile(include) {
|
|||||||
return absInclude;
|
return absInclude;
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse some options from cli
|
function checkArgs() {
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
casper.echo('No test path passed, exiting.', 'RED_BAR', 80);
|
|
||||||
casper.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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){
|
|
||||||
"use strict";
|
"use strict";
|
||||||
var container;
|
// parse some options from cli
|
||||||
if (casper.cli.has(include)) {
|
casper.options.verbose = casper.cli.get('direct') || false;
|
||||||
container = casper.cli.get(include).split(',').map(function(file) {
|
casper.options.logLevel = casper.cli.get('log-level') || "error";
|
||||||
return checkIncludeFile(file);
|
if (casper.cli.get('no-colors') === true) {
|
||||||
}).filter(function(file) {
|
var cls = 'Dummy';
|
||||||
return utils.isString(file);
|
casper.options.colorizerType = cls;
|
||||||
});
|
casper.colorizer = colorizer.create(cls);
|
||||||
|
|
||||||
casper.test.loadIncludes[include] = utils.unique(container);
|
|
||||||
}
|
}
|
||||||
});
|
casper.test.options.failFast = casper.cli.get('fail-fast') || false;
|
||||||
|
|
||||||
// test suites completion listener
|
// test paths are passed as args
|
||||||
casper.test.on('tests.complete', function() {
|
if (casper.cli.args.length) {
|
||||||
|
tests = casper.cli.args.filter(function(path) {
|
||||||
|
if (fs.isFile(path) || fs.isDirectory(path)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
throw new CasperError(f("Invalid test path: %s", path));
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
casper.echo('No test path passed, exiting.', 'RED_BAR', 80);
|
||||||
|
casper.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for casper selftests
|
||||||
|
if (!phantom.casperSelfTest && checkSelfTest(tests)) {
|
||||||
|
casper.warn('To run casper self tests, use the `selftest` command.');
|
||||||
|
casper.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function initRunner() {
|
||||||
"use strict";
|
"use strict";
|
||||||
this.renderResults(true, undefined, casper.cli.get('xunit') || undefined);
|
// includes handling
|
||||||
});
|
loadIncludes.forEach(function(include){
|
||||||
|
var container;
|
||||||
|
if (casper.cli.has(include)) {
|
||||||
|
container = casper.cli.get(include).split(',').map(function(file) {
|
||||||
|
return checkIncludeFile(file);
|
||||||
|
}).filter(function(file) {
|
||||||
|
return utils.isString(file);
|
||||||
|
});
|
||||||
|
casper.test.loadIncludes[include] = utils.unique(container);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// run all the suites
|
// test suites completion listener
|
||||||
casper.test.runSuites.apply(casper.test, tests);
|
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.');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
exports.ok = true
|
|
||||||
catch e
|
|
||||||
casper.test.fail('error in coffeescript module code: ' + e)
|
|
||||||
casper.test.done()
|
|
||||||
|
|||||||
@@ -1,7 +1 @@
|
|||||||
/*global casper*/
|
exports.ok = true;
|
||||||
try {
|
|
||||||
exports.ok = true;
|
|
||||||
} catch (e) {
|
|
||||||
casper.test.fail('error in js module code' + e);
|
|
||||||
casper.test.done()
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -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");
|
console.log(utils.format('Test server url not found: %s (file: %s)', request.url, pageFile), "warning");
|
||||||
response.write("404 - NOT FOUND");
|
response.write("404 - NOT FOUND");
|
||||||
} else {
|
} 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.write(fs.read(pageFile));
|
||||||
}
|
}
|
||||||
response.close();
|
response.close();
|
||||||
|
|||||||
@@ -16,10 +16,11 @@
|
|||||||
test2: false,
|
test2: false,
|
||||||
test3: false,
|
test3: false,
|
||||||
test4: false,
|
test4: false,
|
||||||
testdown: [],
|
testdown: [],
|
||||||
testup: [],
|
testup: [],
|
||||||
testmove: [],
|
testmove: [],
|
||||||
testclick: []
|
testclick: [],
|
||||||
|
testdoubleclick: []
|
||||||
};
|
};
|
||||||
document.querySelector('#test4').onclick = function(event) {
|
document.querySelector('#test4').onclick = function(event) {
|
||||||
results.test4 = true;
|
results.test4 = true;
|
||||||
@@ -34,6 +35,9 @@
|
|||||||
window.onmousemove = function(event) {
|
window.onmousemove = function(event) {
|
||||||
results.testmove = [event.x, event.y];
|
results.testmove = [event.x, event.y];
|
||||||
};
|
};
|
||||||
|
window.ondblclick = function(event) {
|
||||||
|
results.testdoubleclick = [event.x, event.y];
|
||||||
|
};
|
||||||
})(window);
|
})(window);
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</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">
|
<script type="text/javascript">
|
||||||
var myGlobal = 'awesome string';
|
var myGlobal = 'awesome string';
|
||||||
var myUnencodableGlobal = document;
|
var myUnencodableGlobal = document;
|
||||||
|
var myObject = {
|
||||||
|
foo: {
|
||||||
|
bar: 'baz'
|
||||||
|
}
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</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() {
|
casper.run(function() {
|
||||||
this.removeListener('resource.requested', fetchUA);
|
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,21 +13,19 @@ casper.start('tests/site/index.html', function() {
|
|||||||
this.test.assert(fs.isFile(testFile), 'Casper.capture() captured a screenshot');
|
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.comment('Casper.captureBase64()');
|
this.test.assert(this.captureBase64('png').length > 0,
|
||||||
this.test.assert(this.captureBase64('png').length > 0,
|
'Casper.captureBase64() rendered a page capture as base64');
|
||||||
'Casper.captureBase64() rendered a page capture as base64');
|
this.test.assert(this.captureBase64('png', 'ul').length > 0,
|
||||||
this.test.assert(this.captureBase64('png', 'ul').length > 0,
|
'Casper.captureBase64() rendered a capture from a selector as base64');
|
||||||
'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,
|
||||||
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.captureBase64() rendered a capture from a clipRect as base64');
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
casper.run(function() {
|
casper.run(function() {
|
||||||
try {
|
try {
|
||||||
fs.remove(testFile);
|
fs.remove(testFile);
|
||||||
} catch(e) {}
|
} catch(e) {}
|
||||||
this.test.done();
|
this.test.done(4);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
/*global casper*/
|
/*global casper*/
|
||||||
/*jshint strict:false*/
|
/*jshint strict:false maxstatements: 99*/
|
||||||
|
var utils = require('utils');
|
||||||
|
|
||||||
casper.start('tests/site/index.html', function() {
|
casper.start('tests/site/index.html', function() {
|
||||||
this.click('a[href="test.html"]');
|
this.click('a[href="test.html"]');
|
||||||
});
|
});
|
||||||
@@ -56,8 +58,26 @@ casper.then(function() {
|
|||||||
this.mouse.move(200, 100);
|
this.mouse.move(200, 100);
|
||||||
results = this.getGlobal('results');
|
results = this.getGlobal('results');
|
||||||
this.test.assertEquals(results.testmove, [200, 100], 'Mouse.move() has moved to the specified position');
|
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() {
|
casper.run(function() {
|
||||||
this.test.done();
|
this.test.done(23);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,23 +1,29 @@
|
|||||||
/*global casper*/
|
/*global casper*/
|
||||||
/*jshint strict:false*/
|
/*jshint strict:false*/
|
||||||
// skip this test for phantom versions < 1.5
|
var received;
|
||||||
if (phantom.version.major === 1 && phantom.version.minor < 6) {
|
|
||||||
casper.test.comment('Skipped tests, PhantomJS 1.6 required');
|
|
||||||
casper.test.done();
|
|
||||||
} else {
|
|
||||||
var received;
|
|
||||||
|
|
||||||
|
casper.setFilter('page.confirm', function(message) {
|
||||||
|
received = message;
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
casper.start('tests/site/confirm.html', function() {
|
||||||
|
this.test.assert(this.getGlobal('confirmed'), 'confirmation dialog accepted');
|
||||||
|
});
|
||||||
|
|
||||||
|
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) {
|
casper.setFilter('page.confirm', function(message) {
|
||||||
received = message;
|
return false;
|
||||||
return true;
|
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
casper.start('tests/site/confirm.html', function() {
|
casper.thenOpen('/tests/site/confirm.html', function() {
|
||||||
this.test.assert(this.getGlobal('confirmed'), 'confirmation received');
|
this.test.assertNot(this.getGlobal('confirmed'), 'confirmation dialog canceled');
|
||||||
});
|
});
|
||||||
|
|
||||||
casper.run(function() {
|
casper.run(function() {
|
||||||
this.test.assertEquals(received, 'are you sure?', 'confirmation message is ok');
|
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.run(function() {
|
||||||
casper.test.done();
|
casper.test.done(2);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -6,5 +6,5 @@ casper.start('tests/site/elementattribute.html', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
casper.run(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() {
|
casper.run(function() {
|
||||||
this.test.done();
|
this.test.done(2);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*global casper*/
|
/*global casper*/
|
||||||
/*jshint strict:false*/
|
/*jshint strict:false maxparams:99*/
|
||||||
casper.test.comment('Casper.evaluate()');
|
casper.test.comment('Casper.evaluate()');
|
||||||
|
|
||||||
casper.start();
|
casper.start();
|
||||||
@@ -32,4 +32,56 @@ casper.test.assertEquals(result.toString(),
|
|||||||
['boolean', 'boolean', 'number', 'number', 'string', 'object', 'object', 'function'].toString(),
|
['boolean', 'boolean', 'number', 'number', 'string', 'object', 'object', 'function'].toString(),
|
||||||
'Casper.evaluate() handles passed argument context correcly');
|
'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;
|
delete casper.foo;
|
||||||
|
|
||||||
casper.test.done();
|
casper.test.done(5);
|
||||||
|
|||||||
@@ -7,5 +7,5 @@ casper.start('tests/site/index.html', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
casper.run(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() {
|
casper.run(function() {
|
||||||
this.test.done();
|
this.test.done(1);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -35,4 +35,4 @@ casper.then ->
|
|||||||
casper.then ->
|
casper.then ->
|
||||||
@test.assertEquals ++step, 13, "last step"
|
@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="2"]').checked &&
|
||||||
document.querySelector('input[name="checklist[]"][value="3"]').checked);
|
document.querySelector('input[name="checklist[]"][value="3"]').checked);
|
||||||
}, true, 'Casper.fill() can fill a list of checkboxes');
|
}, 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"]');
|
this.click('input[type="submit"]');
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -54,6 +71,33 @@ casper.then(function() {
|
|||||||
this.test.assertUrlMatch(/topic=bar/, 'Casper.fill() select field was submitted');
|
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() {
|
casper.thenOpen('tests/site/form.html', function() {
|
||||||
this.test.comment('Unexistent fields');
|
this.test.comment('Unexistent fields');
|
||||||
this.test.assertRaises(this.fill, ['form[action="result.html"]', {
|
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"]', {
|
this.fill('form[name="f2"]', {
|
||||||
yo: "ok"
|
yo: "ok"
|
||||||
}, true);
|
}, true);
|
||||||
});
|
}).then(function() {
|
||||||
|
|
||||||
casper.then(function() {
|
|
||||||
this.test.assertUrlMatch(/\?f=f2&yo=ok$/, 'Casper.fill() handles multiple forms');
|
this.test.assertUrlMatch(/\?f=f2&yo=ok$/, 'Casper.fill() handles multiple forms');
|
||||||
});
|
});
|
||||||
|
|
||||||
casper.run(function() {
|
// issue #267: array syntax field names
|
||||||
this.test.done();
|
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*/
|
/*jshint strict:false*/
|
||||||
casper.start('tests/site/global.html', function() {
|
casper.start('tests/site/global.html', function() {
|
||||||
this.test.comment('Casper.getGlobal()');
|
this.test.comment('Casper.getGlobal()');
|
||||||
this.test.assertEquals(this.getGlobal('myGlobal'), 'awesome string', 'Casper.getGlobal() can retrieve a remote global variable');
|
this.test.assertEquals(this.getGlobal('myGlobal'), 'awesome string',
|
||||||
this.test.assertRaises(this.getGlobal, ['myUnencodableGlobal'], 'Casper.getGlobal() does not fail trying to encode an unencodable global');
|
'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() {
|
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() {
|
casper.run(function() {
|
||||||
server.close();
|
server.close();
|
||||||
this.test.done();
|
this.test.done(4);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -19,5 +19,5 @@ casper.then(function() {
|
|||||||
casper.run(function() {
|
casper.run(function() {
|
||||||
this.test.assert(this.history.length > 0, 'Casper.history contains urls');
|
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.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() {
|
casper.run(function() {
|
||||||
this.options.onAlert = null;
|
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() {
|
casper.run(function() {
|
||||||
this.test.assertEquals(this.result.log.length, 3, 'Casper.log() logged messages');
|
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() {
|
casper.run(function() {
|
||||||
this.test.done();
|
this.test.done(16);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -17,5 +17,5 @@ casper.thenOpen('tests/site/error.html', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
casper.run(function() {
|
casper.run(function() {
|
||||||
this.test.done();
|
this.test.done(2);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ var t = casper.test, current = 0, tests = [
|
|||||||
username: 'bob',
|
username: 'bob',
|
||||||
password: 'sinclar'
|
password: 'sinclar'
|
||||||
}, "Casper.thenOpen() used the expected HTTP auth settings");
|
}, "Casper.thenOpen() used the expected HTTP auth settings");
|
||||||
},
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
casper.start();
|
casper.start();
|
||||||
@@ -131,5 +131,5 @@ casper.thenOpen('tests/site/index.html', {
|
|||||||
|
|
||||||
casper.run(function() {
|
casper.run(function() {
|
||||||
this.removeAllListeners('open');
|
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*/
|
/*global casper*/
|
||||||
/*jshint strict:false*/
|
/*jshint strict:false*/
|
||||||
// skip this test for phantom versions < 1.5
|
casper.setFilter('page.prompt', function(message, value) {
|
||||||
if (phantom.version.major === 1 && phantom.version.minor < 6) {
|
return 'Chuck ' + value;
|
||||||
casper.test.comment('Skipped tests, PhantomJS 1.6 required');
|
});
|
||||||
casper.test.done();
|
|
||||||
} else {
|
|
||||||
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');
|
this.test.assertEquals(this.getGlobal('name'), 'Chuck Norris', 'prompted value has been received');
|
||||||
});
|
});
|
||||||
|
|
||||||
casper.run(function() {
|
casper.run(function() {
|
||||||
this.test.done();
|
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"
|
onTimeout = -> @test.fail "waitForResource timeout occured"
|
||||||
@waitForResource "dummy.js", onTime, onTimeout
|
@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.test.assert(casper.started, 'Casper.start() started');
|
||||||
|
|
||||||
casper.run(function() {
|
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() {
|
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