Skip to content
Toggle navigation
Toggle navigation
This project
Loading...
Sign in
John McEleney
/
casperjs
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Network
Create a new issue
Builds
Commits
Issue Boards
Files
Commits
Network
Compare
Branches
Tags
Commit
93dcfbd4
...
93dcfbd4ef31e52e86ba4a0bd164ec295f027f23
authored
2012-10-20 16:39:08 +0200
by
Nicolas Perriault
Browse Files
Options
Browse Files
Tag
Download
Email Patches
Plain Diff
jshint configuration, code cleaning
1 parent
bcaf4e30
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
599 additions
and
434 deletions
.jshintconfig
.jshintignore
bin/bootstrap.js
modules/casper.js
modules/clientutils.js
modules/http.js
modules/tester.js
modules/utils.js
modules/xunit.js
tests/run.js
tests/selftest.js
.jshintconfig
0 → 100644
View file @
93dcfbd
{
"asi": true,
"browser": true,
"debug": true,
"devel": true,
"eqeqeq": true,
"evil": true,
"maxparams": 5,
"maxdepth": 3,
"maxstatements": 15,
"maxcomplexity": 7,
"regexdash": true,
"strict": true,
"sub": true,
"trailing": true,
"undef": true,
"predef" : [
"exports",
"phantom",
"require",
"window"
]
}
.jshintignore
0 → 100644
View file @
93dcfbd
docs
modules/vendors
modules/events.js
modules/querystring.js
samples
tests/site
tests/testdir
tests/suites
bin/bootstrap.js
View file @
93dcfbd
...
...
@@ -208,12 +208,6 @@ function bootstrap(global) {
// custom global CasperError
global
.
CasperError
=
function
CasperError
(
msg
)
{
Error
.
call
(
this
);
try
{
// let's get where this error has been thrown from, if we can
this
.
_from
=
arguments
.
callee
.
caller
.
name
;
}
catch
(
e
)
{
this
.
_from
=
"anonymous"
;
}
this
.
message
=
msg
;
this
.
name
=
'CasperError'
;
};
...
...
modules/casper.js
View file @
93dcfbd
...
...
@@ -33,6 +33,7 @@
var
colorizer
=
require
(
'colorizer'
);
var
events
=
require
(
'events'
);
var
fs
=
require
(
'fs'
);
var
http
=
require
(
'http'
);
var
mouse
=
require
(
'mouse'
);
var
qs
=
require
(
'querystring'
);
var
tester
=
require
(
'tester'
);
...
...
@@ -192,6 +193,7 @@ utils.inherits(Casper, events.EventEmitter);
*/
Casper
.
prototype
.
back
=
function
back
()
{
"use strict"
;
this
.
checkStarted
();
return
this
.
then
(
function
_step
()
{
this
.
emit
(
'back'
);
this
.
evaluate
(
function
_evaluate
()
{
...
...
@@ -230,9 +232,8 @@ Casper.prototype.base64encode = function base64encode(url, method, data) {
*/
Casper
.
prototype
.
capture
=
function
capture
(
targetFile
,
clipRect
)
{
"use strict"
;
if
(
!
this
.
started
)
{
throw
new
CasperError
(
"Casper not started, can't capture()"
);
}
/*jshint maxstatements:20*/
this
.
checkStarted
();
var
previousClipRect
;
targetFile
=
fs
.
absolute
(
targetFile
);
if
(
clipRect
)
{
...
...
@@ -270,16 +271,9 @@ Casper.prototype.capture = function capture(targetFile, clipRect) {
*/
Casper
.
prototype
.
captureBase64
=
function
captureBase64
(
format
,
area
)
{
"use strict"
;
if
(
!
this
.
started
)
{
throw
new
CasperError
(
"Casper not started, can't captureBase64()"
);
}
if
(
!
(
'renderBase64'
in
this
.
page
))
{
this
.
warn
(
'captureBase64() requires PhantomJS >= 1.6'
);
return
;
}
var
base64
;
var
previousClipRect
;
var
formats
=
[
'bmp'
,
'jpg'
,
'jpeg'
,
'png'
,
'ppm'
,
'tiff'
,
'xbm'
,
'xpm'
];
/*jshint maxstatements:20*/
this
.
checkStarted
();
var
base64
,
previousClipRect
,
formats
=
[
'bmp'
,
'jpg'
,
'jpeg'
,
'png'
,
'ppm'
,
'tiff'
,
'xbm'
,
'xpm'
];
if
(
formats
.
indexOf
(
format
.
toLowerCase
())
===
-
1
)
{
throw
new
CasperError
(
f
(
'Unsupported format "%s"'
,
format
));
}
...
...
@@ -346,6 +340,20 @@ Casper.prototype.checkStep = function checkStep(self, onComplete) {
};
/**
* Checks if this instance is started.
*
* @return Boolean
* @throws CasperError
*/
Casper
.
prototype
.
checkStarted
=
function
checkStarted
()
{
"use strict"
;
if
(
!
this
.
started
)
{
throw
new
CasperError
(
f
(
"Casper is not started, can't execute `%s()`"
,
checkStarted
.
caller
.
name
));
}
};
/**
* Clears the current page execution environment context. Useful to avoid
* having previously loaded DOM contents being still active (refs #34).
*
...
...
@@ -356,6 +364,7 @@ Casper.prototype.checkStep = function checkStep(self, onComplete) {
*/
Casper
.
prototype
.
clear
=
function
clear
()
{
"use strict"
;
this
.
checkStarted
();
this
.
page
.
content
=
''
;
return
this
;
};
...
...
@@ -371,6 +380,7 @@ Casper.prototype.clear = function clear() {
*/
Casper
.
prototype
.
click
=
function
click
(
selector
)
{
"use strict"
;
this
.
checkStarted
();
return
this
.
mouseEvent
(
'click'
,
selector
);
};
...
...
@@ -384,6 +394,7 @@ Casper.prototype.click = function click(selector) {
*/
Casper
.
prototype
.
clickLabel
=
function
clickLabel
(
label
,
tag
)
{
"use strict"
;
this
.
checkStarted
();
tag
=
tag
||
"*"
;
var
escapedLabel
=
label
.
toString
().
replace
(
/"/g
,
'\\"'
);
var
selector
=
selectXPath
(
f
(
'//%s[text()="%s"]'
,
tag
,
escapedLabel
));
...
...
@@ -416,6 +427,7 @@ Casper.prototype.createStep = function createStep(fn, options) {
*/
Casper
.
prototype
.
debugHTML
=
function
debugHTML
(
selector
,
outer
)
{
"use strict"
;
this
.
checkStarted
();
return
this
.
echo
(
this
.
getHTML
(
selector
,
outer
));
};
...
...
@@ -426,6 +438,7 @@ Casper.prototype.debugHTML = function debugHTML(selector, outer) {
*/
Casper
.
prototype
.
debugPage
=
function
debugPage
()
{
"use strict"
;
this
.
checkStarted
();
this
.
echo
(
this
.
evaluate
(
function
_evaluate
()
{
return
document
.
body
.
textContent
||
document
.
body
.
innerText
;
}));
...
...
@@ -441,6 +454,7 @@ Casper.prototype.debugPage = function debugPage() {
*/
Casper
.
prototype
.
die
=
function
die
(
message
,
status
)
{
"use strict"
;
this
.
checkStarted
();
this
.
result
.
status
=
"error"
;
this
.
result
.
time
=
new
Date
().
getTime
()
-
this
.
startTime
;
if
(
!
utils
.
isString
(
message
)
||
!
message
.
length
)
{
...
...
@@ -465,6 +479,7 @@ Casper.prototype.die = function die(message, status) {
*/
Casper
.
prototype
.
download
=
function
download
(
url
,
targetPath
,
method
,
data
)
{
"use strict"
;
this
.
checkStarted
();
var
cu
=
require
(
'clientutils'
).
create
(
utils
.
mergeObjects
({},
this
.
options
));
try
{
fs
.
write
(
targetPath
,
cu
.
decode
(
this
.
base64encode
(
url
,
method
,
data
)),
'wb'
);
...
...
@@ -548,6 +563,7 @@ Casper.prototype.echo = function echo(text, style, pad) {
*/
Casper
.
prototype
.
evaluate
=
function
evaluate
(
fn
,
context
)
{
"use strict"
;
this
.
checkStarted
();
// ensure client utils are always injected
this
.
injectClientUtils
();
// function context
...
...
@@ -571,6 +587,7 @@ Casper.prototype.evaluate = function evaluate(fn, context) {
*/
Casper
.
prototype
.
evaluateOrDie
=
function
evaluateOrDie
(
fn
,
message
,
status
)
{
"use strict"
;
this
.
checkStarted
();
if
(
!
this
.
evaluate
(
fn
))
{
return
this
.
die
(
message
,
status
);
}
...
...
@@ -586,6 +603,7 @@ Casper.prototype.evaluateOrDie = function evaluateOrDie(fn, message, status) {
*/
Casper
.
prototype
.
exists
=
function
exists
(
selector
)
{
"use strict"
;
this
.
checkStarted
();
return
this
.
evaluate
(
function
_evaluate
(
selector
)
{
return
window
.
__utils__
.
exists
(
selector
);
},
{
selector
:
selector
});
...
...
@@ -612,9 +630,7 @@ Casper.prototype.exit = function exit(status) {
*/
Casper
.
prototype
.
fetchText
=
function
fetchText
(
selector
)
{
"use strict"
;
if
(
!
this
.
started
)
{
throw
new
CasperError
(
"Casper not started, can't fetchText()"
);
}
this
.
checkStarted
();
return
this
.
evaluate
(
function
_evaluate
(
selector
)
{
return
window
.
__utils__
.
fetchText
(
selector
);
},
{
selector
:
selector
});
...
...
@@ -629,6 +645,7 @@ Casper.prototype.fetchText = function fetchText(selector) {
*/
Casper
.
prototype
.
fill
=
function
fill
(
selector
,
vals
,
submit
)
{
"use strict"
;
this
.
checkStarted
();
submit
=
submit
===
true
?
submit
:
false
;
if
(
!
utils
.
isObject
(
vals
))
{
throw
new
CasperError
(
"Form values must be provided as an object"
);
...
...
@@ -643,15 +660,8 @@ Casper.prototype.fill = function fill(selector, vals, submit) {
if
(
!
fillResults
)
{
throw
new
CasperError
(
"Unable to fill form"
);
}
else
if
(
fillResults
.
errors
.
length
>
0
)
{
(
function
_each
(
self
){
fillResults
.
errors
.
forEach
(
function
_forEach
(
error
)
{
throw
new
CasperError
(
error
);
});
})(
this
);
if
(
submit
)
{
this
.
warn
(
"Errors encountered while filling form; submission aborted"
);
submit
=
false
;
}
throw
new
CasperError
(
f
(
'Errors encountered while filling form: %s'
,
fillResults
.
errors
.
join
(
'; '
)));
}
// File uploads
if
(
fillResults
.
files
&&
fillResults
.
files
.
length
>
0
)
{
...
...
@@ -691,6 +701,7 @@ Casper.prototype.fill = function fill(selector, vals, submit) {
*/
Casper
.
prototype
.
forward
=
function
forward
(
then
)
{
"use strict"
;
this
.
checkStarted
();
return
this
.
then
(
function
_step
()
{
this
.
emit
(
'forward'
);
this
.
evaluate
(
function
_evaluate
()
{
...
...
@@ -717,9 +728,7 @@ Casper.prototype.getColorizer = function getColorizer() {
*/
Casper
.
prototype
.
getPageContent
=
function
getPageContent
()
{
"use strict"
;
if
(
!
this
.
started
)
{
throw
new
CasperError
(
"Casper not started, can't getPageContent()"
);
}
this
.
checkStarted
();
var
contentType
=
utils
.
getPropertyPath
(
this
,
'currentResponse.contentType'
);
if
(
!
utils
.
isString
(
contentType
))
{
return
this
.
page
.
content
;
...
...
@@ -742,6 +751,7 @@ Casper.prototype.getPageContent = function getPageContent() {
*/
Casper
.
prototype
.
getCurrentUrl
=
function
getCurrentUrl
()
{
"use strict"
;
this
.
checkStarted
();
var
url
=
this
.
evaluate
(
function
_evaluate
()
{
return
document
.
location
.
href
;
});
...
...
@@ -762,6 +772,7 @@ Casper.prototype.getCurrentUrl = function getCurrentUrl() {
*/
Casper
.
prototype
.
getElementAttribute
=
Casper
.
prototype
.
getElementAttr
=
function
getElementAttr
(
selector
,
attribute
)
{
"use strict"
;
this
.
checkStarted
();
return
this
.
evaluate
(
function
_evaluate
(
selector
,
attribute
)
{
return
document
.
querySelector
(
selector
).
getAttribute
(
attribute
);
},
{
selector
:
selector
,
attribute
:
attribute
});
...
...
@@ -775,6 +786,7 @@ Casper.prototype.getElementAttribute = Casper.prototype.getElementAttr = functio
*/
Casper
.
prototype
.
getElementBounds
=
function
getElementBounds
(
selector
)
{
"use strict"
;
this
.
checkStarted
();
if
(
!
this
.
exists
(
selector
))
{
throw
new
CasperError
(
"No element matching selector found: "
+
selector
);
}
...
...
@@ -795,6 +807,7 @@ Casper.prototype.getElementBounds = function getElementBounds(selector) {
*/
Casper
.
prototype
.
getElementsBounds
=
function
getElementBounds
(
selector
)
{
"use strict"
;
this
.
checkStarted
();
if
(
!
this
.
exists
(
selector
))
{
throw
new
CasperError
(
"No element matching selector found: "
+
selector
);
}
...
...
@@ -811,6 +824,7 @@ Casper.prototype.getElementsBounds = function getElementBounds(selector) {
*/
Casper
.
prototype
.
getGlobal
=
function
getGlobal
(
name
)
{
"use strict"
;
this
.
checkStarted
();
var
result
=
this
.
evaluate
(
function
_evaluate
(
name
)
{
var
result
=
{};
try
{
...
...
@@ -843,9 +857,7 @@ Casper.prototype.getGlobal = function getGlobal(name) {
*/
Casper
.
prototype
.
getHTML
=
function
getHTML
(
selector
,
outer
)
{
"use strict"
;
if
(
!
this
.
started
)
{
throw
new
CasperError
(
"Casper not started, can't getHTML()"
);
}
this
.
checkStarted
();
if
(
!
selector
)
{
return
this
.
page
.
content
;
}
...
...
@@ -865,12 +877,43 @@ Casper.prototype.getHTML = function getHTML(selector, outer) {
*/
Casper
.
prototype
.
getTitle
=
function
getTitle
()
{
"use strict"
;
this
.
checkStarted
();
return
this
.
evaluate
(
function
_evaluate
()
{
return
document
.
title
;
});
};
/**
* Handles received HTTP resource.
*
* @param Object resource PhantomJS HTTP resource
*/
Casper
.
prototype
.
handleReceivedResource
=
function
(
resource
)
{
"use strict"
;
if
(
resource
.
stage
!==
"end"
)
{
return
;
}
this
.
resources
.
push
(
resource
);
if
(
resource
.
url
!==
this
.
requestUrl
)
{
return
;
}
this
.
currentHTTPStatus
=
null
;
this
.
currentResponse
=
undefined
;
if
(
utils
.
isHTTPResource
(
resource
))
{
this
.
currentResponse
=
resource
;
this
.
currentHTTPStatus
=
resource
.
status
;
this
.
emit
(
'http.status.'
+
resource
.
status
,
resource
);
if
(
utils
.
isObject
(
this
.
options
.
httpStatusHandlers
)
&&
resource
.
status
in
this
.
options
.
httpStatusHandlers
&&
utils
.
isFunction
(
this
.
options
.
httpStatusHandlers
[
resource
.
status
]))
{
this
.
options
.
httpStatusHandlers
[
resource
.
status
].
call
(
this
,
this
,
resource
);
}
}
this
.
currentUrl
=
resource
.
url
;
this
.
emit
(
'location.changed'
,
resource
.
url
);
};
/**
* Initializes PhantomJS error handler.
*
*/
...
...
@@ -886,11 +929,39 @@ Casper.prototype.initErrorHandler = function initErrorHandler() {
};
/**
* Injects configured client scripts.
*
* @return Casper
*/
Casper
.
prototype
.
injectClientScripts
=
function
injectClientScripts
()
{
"use strict"
;
this
.
checkStarted
();
if
(
!
this
.
options
.
clientScripts
)
{
return
;
}
if
(
utils
.
isString
(
this
.
options
.
clientScripts
))
{
this
.
options
.
clientScripts
=
[
this
.
options
.
clientScripts
];
}
if
(
!
utils
.
isArray
(
this
.
options
.
clientScripts
))
{
throw
new
CasperError
(
"The clientScripts option must be an array"
);
}
this
.
options
.
clientScripts
.
forEach
(
function
_forEach
(
script
)
{
if
(
this
.
page
.
injectJs
(
script
))
{
this
.
log
(
f
(
'Automatically injected %s client side'
,
script
),
"debug"
);
}
else
{
this
.
warn
(
'Failed injecting %s client side'
,
script
);
}
});
return
this
;
};
/**
* Injects Client-side utilities in current page context.
*
*/
Casper
.
prototype
.
injectClientUtils
=
function
injectClientUtils
()
{
"use strict"
;
this
.
checkStarted
();
var
clientUtilsInjected
=
this
.
page
.
evaluate
(
function
()
{
return
typeof
window
.
__utils__
===
"object"
;
});
...
...
@@ -938,8 +1009,10 @@ Casper.prototype.log = function log(message, level, space) {
if
(
level
in
this
.
logFormats
&&
utils
.
isFunction
(
this
.
logFormats
[
level
]))
{
message
=
this
.
logFormats
[
level
](
message
,
level
,
space
);
}
else
{
var
levelStr
=
this
.
colorizer
.
colorize
(
f
(
'[%s]'
,
level
),
this
.
logStyles
[
level
]);
message
=
f
(
'%s [%s] %s'
,
levelStr
,
space
,
message
);
message
=
f
(
'%s [%s] %s'
,
this
.
colorizer
.
colorize
(
f
(
'[%s]'
,
level
),
this
.
logStyles
[
level
]),
space
,
message
);
}
if
(
this
.
options
.
verbose
)
{
this
.
echo
(
this
.
filter
(
'log.message'
,
message
)
||
message
);
// direct output
...
...
@@ -961,6 +1034,7 @@ Casper.prototype.log = function log(message, level, space) {
*/
Casper
.
prototype
.
mouseEvent
=
function
mouseEvent
(
type
,
selector
)
{
"use strict"
;
this
.
checkStarted
();
this
.
log
(
"Mouse event '"
+
type
+
"' on selector: "
+
selector
,
"debug"
);
if
(
!
this
.
exists
(
selector
))
{
throw
new
CasperError
(
f
(
"Cannot dispatch %s event on nonexistent selector: %s"
,
type
,
selector
));
...
...
@@ -998,6 +1072,7 @@ Casper.prototype.mouseEvent = function mouseEvent(type, selector) {
*/
Casper
.
prototype
.
open
=
function
open
(
location
,
settings
)
{
"use strict"
;
this
.
checkStarted
();
// settings validation
if
(
!
settings
)
{
settings
=
{
...
...
@@ -1040,9 +1115,6 @@ Casper.prototype.open = function open(location, settings) {
}
this
.
emit
(
'open'
,
this
.
requestUrl
,
settings
);
this
.
log
(
f
(
'opening url: %s, HTTP %s'
,
this
.
requestUrl
,
settings
.
method
.
toUpperCase
()),
"debug"
);
if
(
'headers'
in
settings
&&
phantom
.
version
.
minor
<
6
)
{
this
.
warn
(
'Custom headers in outgoing requests are supported in PhantomJS >= 1.6'
);
}
this
.
page
.
openUrl
(
this
.
requestUrl
,
{
operation
:
settings
.
method
,
data
:
settings
.
data
,
...
...
@@ -1060,9 +1132,7 @@ Casper.prototype.open = function open(location, settings) {
*/
Casper
.
prototype
.
reload
=
function
reload
(
then
)
{
"use strict"
;
if
(
!
this
.
started
)
{
throw
new
CasperError
(
"Casper not started, can't reload()"
);
}
this
.
checkStarted
();
this
.
evaluate
(
function
()
{
window
.
location
.
reload
();
});
...
...
@@ -1097,6 +1167,7 @@ Casper.prototype.repeat = function repeat(times, then) {
*/
Casper
.
prototype
.
resourceExists
=
function
resourceExists
(
test
)
{
"use strict"
;
this
.
checkStarted
();
var
testFn
;
switch
(
utils
.
betterTypeOf
(
test
))
{
case
"string"
:
...
...
@@ -1128,6 +1199,7 @@ Casper.prototype.resourceExists = function resourceExists(test) {
*/
Casper
.
prototype
.
run
=
function
run
(
onComplete
,
time
)
{
"use strict"
;
this
.
checkStarted
();
if
(
!
this
.
steps
||
this
.
steps
.
length
<
1
)
{
this
.
log
(
"No steps defined, aborting"
,
"error"
);
return
this
;
...
...
@@ -1145,6 +1217,7 @@ Casper.prototype.run = function run(onComplete, time) {
*/
Casper
.
prototype
.
runStep
=
function
runStep
(
step
)
{
"use strict"
;
this
.
checkStarted
();
var
skipLog
=
utils
.
isObject
(
step
.
options
)
&&
step
.
options
.
skipLog
===
true
;
var
stepInfo
=
f
(
"Step %d/%d"
,
this
.
step
,
this
.
steps
.
length
);
var
stepResult
;
...
...
@@ -1184,9 +1257,7 @@ Casper.prototype.runStep = function runStep(step) {
*/
Casper
.
prototype
.
setHttpAuth
=
function
setHttpAuth
(
username
,
password
)
{
"use strict"
;
if
(
!
this
.
started
)
{
throw
new
CasperError
(
"Casper must be started in order to use the setHttpAuth() method"
);
}
this
.
checkStarted
();
if
(
!
utils
.
isString
(
username
)
||
!
utils
.
isString
(
password
))
{
throw
new
CasperError
(
"Both username and password must be strings"
);
}
...
...
@@ -1258,6 +1329,7 @@ Casper.prototype.start = function start(location, then) {
* @return Object
*/
Casper
.
prototype
.
status
=
function
status
(
asString
)
{
"use strict"
;
var
properties
=
[
'currentHTTPStatus'
,
'loadInProgress'
,
'navigationRequested'
,
'options'
,
'pendingWait'
,
'requestUrl'
,
'started'
,
'step'
,
'url'
];
var
currentStatus
=
{};
...
...
@@ -1275,9 +1347,7 @@ Casper.prototype.status = function status(asString) {
*/
Casper
.
prototype
.
then
=
function
then
(
step
)
{
"use strict"
;
if
(
!
this
.
started
)
{
throw
new
CasperError
(
"Casper not started; please use Casper#start"
);
}
this
.
checkStarted
();
if
(
!
utils
.
isFunction
(
step
))
{
throw
new
CasperError
(
"You can only define a step as a function"
);
}
...
...
@@ -1315,6 +1385,7 @@ Casper.prototype.then = function then(step) {
*/
Casper
.
prototype
.
thenClick
=
function
thenClick
(
selector
,
then
,
fallbackToHref
)
{
"use strict"
;
this
.
checkStarted
();
if
(
arguments
.
length
>
2
)
{
this
.
emit
(
"deprecated"
,
"The thenClick() method does not process the fallbackToHref argument since 0.6"
);
}
...
...
@@ -1335,6 +1406,7 @@ Casper.prototype.thenClick = function thenClick(selector, then, fallbackToHref)
*/
Casper
.
prototype
.
thenEvaluate
=
function
thenEvaluate
(
fn
,
context
)
{
"use strict"
;
this
.
checkStarted
();
return
this
.
then
(
function
_step
()
{
this
.
evaluate
(
fn
,
context
);
});
...
...
@@ -1350,6 +1422,7 @@ Casper.prototype.thenEvaluate = function thenEvaluate(fn, context) {
*/
Casper
.
prototype
.
thenOpen
=
function
thenOpen
(
location
,
settings
,
then
)
{
"use strict"
;
this
.
checkStarted
();
if
(
!
(
settings
&&
!
utils
.
isFunction
(
settings
)))
{
then
=
settings
;
settings
=
null
;
...
...
@@ -1375,6 +1448,7 @@ Casper.prototype.thenOpen = function thenOpen(location, settings, then) {
*/
Casper
.
prototype
.
thenOpenAndEvaluate
=
function
thenOpenAndEvaluate
(
location
,
fn
,
context
)
{
"use strict"
;
this
.
checkStarted
();
return
this
.
thenOpen
(
location
).
thenEvaluate
(
fn
,
context
);
};
...
...
@@ -1384,6 +1458,7 @@ Casper.prototype.thenOpenAndEvaluate = function thenOpenAndEvaluate(location, fn
* @return String
*/
Casper
.
prototype
.
toString
=
function
toString
()
{
"use strict"
;
return
'[object Casper], currently at '
+
this
.
getCurrentUrl
();
};
...
...
@@ -1395,9 +1470,7 @@ Casper.prototype.toString = function toString() {
*/
Casper
.
prototype
.
userAgent
=
function
userAgent
(
agent
)
{
"use strict"
;
if
(
!
this
.
started
)
{
throw
new
CasperError
(
"Casper not started, can't set userAgent"
);
}
this
.
checkStarted
();
this
.
options
.
pageSettings
.
userAgent
=
this
.
page
.
settings
.
userAgent
=
agent
;
return
this
;
};
...
...
@@ -1411,9 +1484,7 @@ Casper.prototype.userAgent = function userAgent(agent) {
*/
Casper
.
prototype
.
viewport
=
function
viewport
(
width
,
height
)
{
"use strict"
;
if
(
!
this
.
started
)
{
throw
new
CasperError
(
"Casper must be started in order to set viewport at runtime"
);
}
this
.
checkStarted
();
if
(
!
utils
.
isNumber
(
width
)
||
!
utils
.
isNumber
(
height
)
||
width
<=
0
||
height
<=
0
)
{
throw
new
CasperError
(
f
(
"Invalid viewport: %dx%d"
,
width
,
height
));
}
...
...
@@ -1435,6 +1506,7 @@ Casper.prototype.viewport = function viewport(width, height) {
*/
Casper
.
prototype
.
visible
=
function
visible
(
selector
)
{
"use strict"
;
this
.
checkStarted
();
return
this
.
evaluate
(
function
_evaluate
(
selector
)
{
return
window
.
__utils__
.
visible
(
selector
);
},
{
selector
:
selector
});
...
...
@@ -1463,6 +1535,7 @@ Casper.prototype.warn = function warn(message) {
*/
Casper
.
prototype
.
wait
=
function
wait
(
timeout
,
then
)
{
"use strict"
;
this
.
checkStarted
();
timeout
=
~~
timeout
;
if
(
timeout
<
1
)
{
this
.
die
(
"wait() only accepts a positive integer > 0 as a timeout value"
);
...
...
@@ -1505,6 +1578,7 @@ Casper.prototype.waitDone = function waitDone() {
*/
Casper
.
prototype
.
waitFor
=
function
waitFor
(
testFx
,
then
,
onTimeout
,
timeout
)
{
"use strict"
;
this
.
checkStarted
();
timeout
=
timeout
?
timeout
:
this
.
options
.
waitTimeout
;
if
(
!
utils
.
isFunction
(
testFx
))
{
this
.
die
(
"waitFor() needs a test function"
);
...
...
@@ -1553,6 +1627,7 @@ Casper.prototype.waitFor = function waitFor(testFx, then, onTimeout, timeout) {
*/
Casper
.
prototype
.
waitForResource
=
function
waitForResource
(
test
,
then
,
onTimeout
,
timeout
)
{
"use strict"
;
this
.
checkStarted
();
timeout
=
timeout
?
timeout
:
this
.
options
.
waitTimeout
;
return
this
.
waitFor
(
function
_check
()
{
return
this
.
resourceExists
(
test
);
...
...
@@ -1571,6 +1646,7 @@ Casper.prototype.waitForResource = function waitForResource(test, then, onTimeou
*/
Casper
.
prototype
.
waitForSelector
=
function
waitForSelector
(
selector
,
then
,
onTimeout
,
timeout
)
{
"use strict"
;
this
.
checkStarted
();
timeout
=
timeout
?
timeout
:
this
.
options
.
waitTimeout
;
return
this
.
waitFor
(
function
_check
()
{
return
this
.
exists
(
selector
);
...
...
@@ -1589,6 +1665,7 @@ Casper.prototype.waitForSelector = function waitForSelector(selector, then, onTi
*/
Casper
.
prototype
.
waitWhileSelector
=
function
waitWhileSelector
(
selector
,
then
,
onTimeout
,
timeout
)
{
"use strict"
;
this
.
checkStarted
();
timeout
=
timeout
?
timeout
:
this
.
options
.
waitTimeout
;
return
this
.
waitFor
(
function
_check
()
{
return
!
this
.
exists
(
selector
);
...
...
@@ -1607,6 +1684,7 @@ Casper.prototype.waitWhileSelector = function waitWhileSelector(selector, then,
*/
Casper
.
prototype
.
waitUntilVisible
=
function
waitUntilVisible
(
selector
,
then
,
onTimeout
,
timeout
)
{
"use strict"
;
this
.
checkStarted
();
timeout
=
timeout
?
timeout
:
this
.
options
.
waitTimeout
;
return
this
.
waitFor
(
function
_check
()
{
return
this
.
visible
(
selector
);
...
...
@@ -1625,6 +1703,7 @@ Casper.prototype.waitUntilVisible = function waitUntilVisible(selector, then, on
*/
Casper
.
prototype
.
waitWhileVisible
=
function
waitWhileVisible
(
selector
,
then
,
onTimeout
,
timeout
)
{
"use strict"
;
this
.
checkStarted
();
timeout
=
timeout
?
timeout
:
this
.
options
.
waitTimeout
;
return
this
.
waitFor
(
function
_check
()
{
return
!
this
.
visible
(
selector
);
...
...
@@ -1639,17 +1718,11 @@ Casper.prototype.waitWhileVisible = function waitWhileVisible(selector, then, on
*/
Casper
.
prototype
.
zoom
=
function
zoom
(
factor
)
{
"use strict"
;
if
(
!
this
.
started
)
{
throw
new
CasperError
(
"Casper has not been started, can't set zoom factor"
);
}
this
.
checkStarted
();
if
(
!
utils
.
isNumber
(
factor
)
||
factor
<=
0
)
{
throw
new
CasperError
(
"Invalid zoom factor: "
+
factor
);
}
if
(
'zoomFactor'
in
this
.
page
)
{
this
.
page
.
zoomFactor
=
factor
;
}
else
{
this
.
warn
(
"zoom() requires PhantomJS >= 1.6"
);
}
return
this
;
};
...
...
@@ -1662,7 +1735,7 @@ Casper.prototype.zoom = function zoom(factor) {
*/
Casper
.
extend
=
function
(
proto
)
{
"use strict"
;
this
.
warn
(
'Casper.extend() has been deprecated since 0.6; check the docs'
);
this
.
emit
(
"deprecated"
,
"Casper.extend() has been deprecated since 0.6; check the docs"
)
if
(
!
utils
.
isObject
(
proto
))
{
throw
new
CasperError
(
"extends() only accept objects as prototypes"
);
}
...
...
@@ -1731,21 +1804,7 @@ function createPage(casper) {
casper
.
options
.
onLoadError
.
call
(
casper
,
casper
,
casper
.
requestUrl
,
status
);
}
}
if
(
casper
.
options
.
clientScripts
)
{
if
(
utils
.
isString
(
casper
.
options
.
clientScripts
))
{
casper
.
options
.
clientScripts
=
[
casper
.
options
.
clientScripts
];
}
if
(
!
utils
.
isArray
(
casper
.
options
.
clientScripts
))
{
throw
new
CasperError
(
"The clientScripts option must be an array"
);
}
casper
.
options
.
clientScripts
.
forEach
(
function
_forEach
(
script
)
{
if
(
casper
.
page
.
injectJs
(
script
))
{
casper
.
log
(
f
(
'Automatically injected %s client side'
,
script
),
"debug"
);
}
else
{
casper
.
warn
(
'Failed injecting %s client side'
,
script
);
}
});
}
casper
.
injectClientScripts
();
// Client-side utils injection
casper
.
injectClientUtils
();
// history
...
...
@@ -1765,34 +1824,12 @@ function createPage(casper) {
return
casper
.
filter
(
'page.prompt'
,
message
,
value
);
};
page
.
onResourceReceived
=
function
onResourceReceived
(
resource
)
{
if
(
utils
.
isHTTPResource
(
resource
))
{
require
(
'http'
).
augmentResponse
(
resource
);
}
else
{
casper
.
log
(
f
(
'Non-HTTP resource received from %s'
,
resource
.
url
),
"debug"
);
}
http
.
augmentResponse
(
resource
);
casper
.
emit
(
'resource.received'
,
resource
);
if
(
utils
.
isFunction
(
casper
.
options
.
onResourceReceived
))
{
casper
.
options
.
onResourceReceived
.
call
(
casper
,
casper
,
resource
);
}
if
(
resource
.
stage
===
"end"
)
{
casper
.
resources
.
push
(
resource
);
}
if
(
resource
.
url
===
casper
.
requestUrl
&&
resource
.
stage
===
"end"
)
{
casper
.
currentHTTPStatus
=
null
;
casper
.
currentResponse
=
undefined
;
if
(
utils
.
isHTTPResource
(
resource
))
{
casper
.
currentResponse
=
resource
;
casper
.
currentHTTPStatus
=
resource
.
status
;
casper
.
emit
(
'http.status.'
+
resource
.
status
,
resource
);
if
(
utils
.
isObject
(
casper
.
options
.
httpStatusHandlers
)
&&
resource
.
status
in
casper
.
options
.
httpStatusHandlers
&&
utils
.
isFunction
(
casper
.
options
.
httpStatusHandlers
[
resource
.
status
]))
{
casper
.
options
.
httpStatusHandlers
[
resource
.
status
].
call
(
casper
,
casper
,
resource
);
}
}
casper
.
currentUrl
=
resource
.
url
;
casper
.
emit
(
'location.changed'
,
resource
.
url
);
}
casper
.
handleReceivedResource
(
resource
);
};
page
.
onResourceRequested
=
function
onResourceRequested
(
request
)
{
casper
.
emit
(
'resource.requested'
,
request
);
...
...
modules/clientutils.js
View file @
93dcfbd
...
...
@@ -75,6 +75,7 @@
* @return string
*/
this
.
decode
=
function
decode
(
str
)
{
/*jshint maxstatements:30 maxcomplexity:30 */
var
c1
,
c2
,
c3
,
c4
,
i
=
0
,
len
=
str
.
length
,
out
=
""
;
while
(
i
<
len
)
{
do
{
...
...
@@ -123,6 +124,7 @@
* @return string
*/
this
.
encode
=
function
encode
(
str
)
{
/*jshint maxstatements:30 */
var
out
=
""
,
i
=
0
,
len
=
str
.
length
,
c1
,
c2
,
c3
;
while
(
i
<
len
)
{
c1
=
str
.
charCodeAt
(
i
++
)
&
0xff
;
...
...
@@ -295,37 +297,14 @@
* Retrieves string contents from a binary file behind an url. Silently
* fails but log errors.
*
* @param
String url
* @param
String method
* @param
Object data
* @return
s
tring
* @param
String url Url.
* @param
String method HTTP method.
* @param
Object data Request parameters.
* @return
S
tring
*/
this
.
getBinary
=
function
getBinary
(
url
,
method
,
data
)
{
try
{
var
xhr
=
new
XMLHttpRequest
(),
dataString
=
""
;
if
(
typeof
method
!==
"string"
||
[
"GET"
,
"POST"
].
indexOf
(
method
.
toUpperCase
())
===
-
1
)
{
method
=
"GET"
;
}
else
{
method
=
method
.
toUpperCase
();
}
xhr
.
open
(
method
,
url
,
false
);
this
.
log
(
"getBinary(): Using HTTP method: '"
+
method
+
"'"
,
"debug"
);
xhr
.
overrideMimeType
(
"text/plain; charset=x-user-defined"
);
if
(
method
===
"POST"
)
{
if
(
typeof
data
===
"object"
)
{
var
dataList
=
[];
for
(
var
k
in
data
)
{
dataList
.
push
(
encodeURIComponent
(
k
)
+
"="
+
encodeURIComponent
(
data
[
k
].
toString
()));
}
dataString
=
dataList
.
join
(
'&'
);
this
.
log
(
"getBinary(): Using request data: '"
+
dataString
+
"'"
,
"debug"
);
}
else
if
(
typeof
data
===
"string"
)
{
dataString
=
data
;
}
xhr
.
setRequestHeader
(
"Content-type"
,
"application/x-www-form-urlencoded"
);
}
xhr
.
send
(
method
===
"POST"
?
dataString
:
null
);
return
xhr
.
responseText
;
return
this
.
sendAJAX
(
url
,
method
,
data
,
false
);
}
catch
(
e
)
{
if
(
e
.
name
===
"NETWORK_ERR"
&&
e
.
code
===
101
)
{
this
.
log
(
"getBinary(): Unfortunately, casperjs cannot make cross domain ajax requests"
,
"warning"
);
...
...
@@ -529,6 +508,42 @@
};
/**
* Performs an AJAX request.
*
* @param String url Url.
* @param String method HTTP method.
* @param Object data Request parameters.
* @param Boolean async Asynchroneous request? (default: false)
* @return String Response text.
*/
this
.
sendAJAX
=
function
sendAJAX
(
url
,
method
,
data
,
async
)
{
var
xhr
=
new
XMLHttpRequest
(),
dataString
=
""
;
if
(
typeof
method
!==
"string"
||
[
"GET"
,
"POST"
].
indexOf
(
method
.
toUpperCase
())
===
-
1
)
{
method
=
"GET"
;
}
else
{
method
=
method
.
toUpperCase
();
}
xhr
.
open
(
method
,
url
,
!!
async
);
this
.
log
(
"getBinary(): Using HTTP method: '"
+
method
+
"'"
,
"debug"
);
xhr
.
overrideMimeType
(
"text/plain; charset=x-user-defined"
);
if
(
method
===
"POST"
)
{
if
(
typeof
data
===
"object"
)
{
var
dataList
=
[];
for
(
var
k
in
data
)
{
dataList
.
push
(
encodeURIComponent
(
k
)
+
"="
+
encodeURIComponent
(
data
[
k
].
toString
()));
}
dataString
=
dataList
.
join
(
'&'
);
this
.
log
(
"sendAJAX(): Using request data: '"
+
dataString
+
"'"
,
"debug"
);
}
else
if
(
typeof
data
===
"string"
)
{
dataString
=
data
;
}
xhr
.
setRequestHeader
(
"Content-type"
,
"application/x-www-form-urlencoded"
);
}
xhr
.
send
(
method
===
"POST"
?
dataString
:
null
);
return
xhr
.
responseText
;
};
/**
* Sets a field (or a set of fields) value. Fails silently, but log
* error messages.
*
...
...
modules/http.js
View file @
93dcfbd
...
...
@@ -28,6 +28,8 @@
*
*/
var
utils
=
require
(
'utils'
);
/*
* Building an Array subclass
*/
...
...
@@ -59,7 +61,8 @@ responseHeaders.prototype.get = function get(name){
* @param mixed response Phantom response or undefined (generally with local files)
*/
exports
.
augmentResponse
=
function
(
response
)
{
if
(
response
===
undefined
)
{
"use strict"
;
if
(
!
utils
.
isHTTPResource
(
response
))
{
return
;
}
response
.
headers
.
__proto__
=
responseHeaders
.
prototype
;
...
...
modules/tester.js
View file @
93dcfbd
...
...
@@ -53,6 +53,8 @@ var Tester = function Tester(casper, options) {
throw
new
CasperError
(
"Tester needs a Casper instance"
);
}
this
.
casper
=
casper
;
this
.
currentTestFile
=
null
;
this
.
currentSuiteNum
=
0
;
this
.
exporter
=
require
(
'xunit'
).
create
();
...
...
@@ -132,7 +134,7 @@ var Tester = function Tester(casper, options) {
}
catch
(
e
)
{
try
{
comment
+=
utils
.
serialize
(
failure
.
values
[
name
].
toString
());
}
catch
(
e
)
{
}
catch
(
e
2
)
{
comment
+=
'(unserializable value)'
;
}
}
...
...
@@ -140,9 +142,13 @@ var Tester = function Tester(casper, options) {
}
}
});
};
// Tester class is an EventEmitter
utils
.
inherits
(
Tester
,
events
.
EventEmitter
);
exports
.
Tester
=
Tester
;
// methods
/**
/**
* Asserts that a condition strictly resolves to true. Also returns an
* "assertion object" containing useful informations about the test case
* results.
...
...
@@ -156,7 +162,8 @@ var Tester = function Tester(casper, options) {
* @param Object|null context Assertion context object (Optional)
* @return Object An assertion result object
*/
this
.
assert
=
this
.
assertTrue
=
function
assert
(
subject
,
message
,
context
)
{
Tester
.
prototype
.
assert
=
Tester
.
prototype
.
assertTrue
=
function
assert
(
subject
,
message
,
context
)
{
"use strict"
;
return
this
.
processAssertionResult
(
utils
.
mergeObjects
({
success
:
subject
===
true
,
type
:
"assert"
,
...
...
@@ -167,9 +174,9 @@ var Tester = function Tester(casper, options) {
subject
:
utils
.
getPropertyPath
(
context
,
'values.subject'
)
||
subject
}
},
context
||
{}));
};
};
/**
/**
* Asserts that two values are strictly equals.
*
* @param Mixed subject The value to test
...
...
@@ -177,7 +184,8 @@ var Tester = function Tester(casper, options) {
* @param String message Test description (Optional)
* @return Object An assertion result object
*/
this
.
assertEquals
=
this
.
assertEqual
=
function
assertEquals
(
subject
,
expected
,
message
)
{
Tester
.
prototype
.
assertEquals
=
Tester
.
prototype
.
assertEqual
=
function
assertEquals
(
subject
,
expected
,
message
)
{
"use strict"
;
return
this
.
assert
(
this
.
testEquals
(
subject
,
expected
),
message
,
{
type
:
"assertEquals"
,
standard
:
"Subject equals the expected value"
,
...
...
@@ -186,9 +194,9 @@ var Tester = function Tester(casper, options) {
expected
:
expected
}
});
};
};
/**
/**
* Asserts that two values are strictly not equals.
*
* @param Mixed subject The value to test
...
...
@@ -196,7 +204,8 @@ var Tester = function Tester(casper, options) {
* @param String|null message Test description (Optional)
* @return Object An assertion result object
*/
this
.
assertNotEquals
=
function
assertNotEquals
(
subject
,
shouldnt
,
message
)
{
Tester
.
prototype
.
assertNotEquals
=
function
assertNotEquals
(
subject
,
shouldnt
,
message
)
{
"use strict"
;
return
this
.
assert
(
!
this
.
testEquals
(
subject
,
shouldnt
),
message
,
{
type
:
"assertNotEquals"
,
standard
:
"Subject doesn't equal what it shouldn't be"
,
...
...
@@ -205,9 +214,9 @@ var Tester = function Tester(casper, options) {
shouldnt
:
shouldnt
}
});
};
};
/**
/**
* Asserts that a code evaluation in remote DOM resolves to true.
*
* @param Function fn A function to be evaluated in remote DOM
...
...
@@ -215,8 +224,9 @@ var Tester = function Tester(casper, options) {
* @param Object params Object containing the parameters to inject into the function (optional)
* @return Object An assertion result object
*/
this
.
assertEval
=
this
.
assertEvaluate
=
function
assertEval
(
fn
,
message
,
params
)
{
return
this
.
assert
(
casper
.
evaluate
(
fn
,
params
),
message
,
{
Tester
.
prototype
.
assertEval
=
Tester
.
prototype
.
assertEvaluate
=
function
assertEval
(
fn
,
message
,
params
)
{
"use strict"
;
return
this
.
assert
(
this
.
casper
.
evaluate
(
fn
,
params
),
message
,
{
type
:
"assertEval"
,
standard
:
"Evaluated function returns true"
,
values
:
{
...
...
@@ -224,9 +234,9 @@ var Tester = function Tester(casper, options) {
params
:
params
}
});
};
};
/**
/**
* Asserts that the result of a code evaluation in remote DOM equals
* an expected value.
*
...
...
@@ -236,8 +246,9 @@ var Tester = function Tester(casper, options) {
* @param Object|null params Object containing the parameters to inject into the function (optional)
* @return Object An assertion result object
*/
this
.
assertEvalEquals
=
this
.
assertEvalEqual
=
function
assertEvalEquals
(
fn
,
expected
,
message
,
params
)
{
var
subject
=
casper
.
evaluate
(
fn
,
params
);
Tester
.
prototype
.
assertEvalEquals
=
Tester
.
prototype
.
assertEvalEqual
=
function
assertEvalEquals
(
fn
,
expected
,
message
,
params
)
{
"use strict"
;
var
subject
=
this
.
casper
.
evaluate
(
fn
,
params
);
return
this
.
assert
(
this
.
testEquals
(
subject
,
expected
),
message
,
{
type
:
"assertEvalEquals"
,
standard
:
"Evaluated function returns the expected value"
,
...
...
@@ -248,9 +259,9 @@ var Tester = function Tester(casper, options) {
expected
:
expected
}
});
};
};
/**
/**
* Asserts that a given input field has the provided value.
*
* @param String input_name The name attribute of the input element
...
...
@@ -258,8 +269,9 @@ var Tester = function Tester(casper, options) {
* @param String message Test description
* @return Object An assertion result object
*/
this
.
assertField
=
function
assertField
(
input_name
,
expected_value
,
message
)
{
var
actual_value
=
casper
.
evaluate
(
function
(
input_name
)
{
Tester
.
prototype
.
assertField
=
function
assertField
(
input_name
,
expected_value
,
message
)
{
"use strict"
;
var
actual_value
=
this
.
casper
.
evaluate
(
function
(
input_name
)
{
var
input
=
document
.
querySelector
(
'input[name="'
+
input_name
+
'"]'
);
return
input
?
input
.
value
:
null
;
},
{
input_name
:
input_name
});
...
...
@@ -272,9 +284,9 @@ var Tester = function Tester(casper, options) {
expected_value
:
expected_value
}
});
};
};
/**
/**
* Asserts that an element matching the provided selector expression exists in
* remote DOM.
*
...
...
@@ -282,17 +294,18 @@ var Tester = function Tester(casper, options) {
* @param String message Test description
* @return Object An assertion result object
*/
this
.
assertExists
=
this
.
assertExist
=
this
.
assertSelectorExists
=
this
.
assertSelectorExist
=
function
assertExists
(
selector
,
message
)
{
return
this
.
assert
(
casper
.
exists
(
selector
),
message
,
{
Tester
.
prototype
.
assertExists
=
Tester
.
prototype
.
assertExist
=
this
.
assertSelectorExists
=
Tester
.
prototype
.
assertSelectorExist
=
function
assertExists
(
selector
,
message
)
{
"use strict"
;
return
this
.
assert
(
this
.
casper
.
exists
(
selector
),
message
,
{
type
:
"assertExists"
,
standard
:
f
(
"Found an element matching: %s"
,
selector
),
values
:
{
selector
:
selector
}
});
};
};
/**
/**
* Asserts that an element matching the provided selector expression does not
* exists in remote DOM.
*
...
...
@@ -300,26 +313,28 @@ var Tester = function Tester(casper, options) {
* @param String message Test description
* @return Object An assertion result object
*/
this
.
assertDoesntExist
=
this
.
assertNotExists
=
function
assertDoesntExist
(
selector
,
message
)
{
return
this
.
assert
(
!
casper
.
exists
(
selector
),
message
,
{
Tester
.
prototype
.
assertDoesntExist
=
Tester
.
prototype
.
assertNotExists
=
function
assertDoesntExist
(
selector
,
message
)
{
"use strict"
;
return
this
.
assert
(
!
this
.
casper
.
exists
(
selector
),
message
,
{
type
:
"assertDoesntExist"
,
standard
:
f
(
"No element found matching selector: %s"
,
selector
),
values
:
{
selector
:
selector
}
});
};
};
/**
/**
* Asserts that current HTTP status is the one passed as argument.
*
* @param Number status HTTP status code
* @param String message Test description
* @return Object An assertion result object
*/
this
.
assertHttpStatus
=
function
assertHttpStatus
(
status
,
message
)
{
var
currentHTTPStatus
=
casper
.
currentHTTPStatus
;
return
this
.
assert
(
this
.
testEquals
(
casper
.
currentHTTPStatus
,
status
),
message
,
{
Tester
.
prototype
.
assertHttpStatus
=
function
assertHttpStatus
(
status
,
message
)
{
"use strict"
;
var
currentHTTPStatus
=
this
.
casper
.
currentHTTPStatus
;
return
this
.
assert
(
this
.
testEquals
(
this
.
casper
.
currentHTTPStatus
,
status
),
message
,
{
type
:
"assertHttpStatus"
,
standard
:
f
(
"HTTP status code is: %s"
,
status
),
values
:
{
...
...
@@ -327,9 +342,9 @@ var Tester = function Tester(casper, options) {
expected
:
status
}
});
};
};
/**
/**
* Asserts that a provided string matches a provided RegExp pattern.
*
* @param String subject The string to test
...
...
@@ -337,7 +352,8 @@ var Tester = function Tester(casper, options) {
* @param String message Test description
* @return Object An assertion result object
*/
this
.
assertMatch
=
this
.
assertMatches
=
function
assertMatch
(
subject
,
pattern
,
message
)
{
Tester
.
prototype
.
assertMatch
=
Tester
.
prototype
.
assertMatches
=
function
assertMatch
(
subject
,
pattern
,
message
)
{
"use strict"
;
return
this
.
assert
(
pattern
.
test
(
subject
),
message
,
{
type
:
"assertMatch"
,
standard
:
"Subject matches the provided pattern"
,
...
...
@@ -346,16 +362,17 @@ var Tester = function Tester(casper, options) {
pattern
:
pattern
.
toString
()
}
});
};
};
/**
/**
* Asserts a condition resolves to false.
*
* @param Boolean condition The condition to test
* @param String message Test description
* @return Object An assertion result object
*/
this
.
assertNot
=
function
assertNot
(
condition
,
message
)
{
Tester
.
prototype
.
assertNot
=
function
assertNot
(
condition
,
message
)
{
"use strict"
;
return
this
.
assert
(
!
condition
,
message
,
{
type
:
"assertNot"
,
standard
:
"Subject is falsy"
,
...
...
@@ -363,26 +380,27 @@ var Tester = function Tester(casper, options) {
condition
:
condition
}
});
};
};
/**
/**
* Asserts that a selector expression is not currently visible.
*
* @param String expected selector expression
* @param String message Test description
* @return Object An assertion result object
*/
this
.
assertNotVisible
=
this
.
assertInvisible
=
function
assertNotVisible
(
selector
,
message
)
{
return
this
.
assert
(
!
casper
.
visible
(
selector
),
message
,
{
Tester
.
prototype
.
assertNotVisible
=
Tester
.
prototype
.
assertInvisible
=
function
assertNotVisible
(
selector
,
message
)
{
"use strict"
;
return
this
.
assert
(
!
this
.
casper
.
visible
(
selector
),
message
,
{
type
:
"assertVisible"
,
standard
:
"Selector is not visible"
,
values
:
{
selector
:
selector
}
});
};
};
/**
/**
* Asserts that the provided function called with the given parameters
* will raise an exception.
*
...
...
@@ -391,7 +409,8 @@ var Tester = function Tester(casper, options) {
* @param String message Test description
* @return Object An assertion result object
*/
this
.
assertRaises
=
this
.
assertRaise
=
this
.
assertThrows
=
function
assertRaises
(
fn
,
args
,
message
)
{
Tester
.
prototype
.
assertRaises
=
Tester
.
prototype
.
assertRaise
=
this
.
assertThrows
=
function
assertRaises
(
fn
,
args
,
message
)
{
"use strict"
;
var
context
=
{
type
:
"assertRaises"
,
standard
:
"Function raises an error"
...
...
@@ -406,34 +425,36 @@ var Tester = function Tester(casper, options) {
}
}));
}
};
};
/**
/**
* Asserts that the current page has a resource that matches the provided test
*
* @param Function/String test A test function that is called with every response
* @param String message Test description
* @return Object An assertion result object
*/
this
.
assertResourceExists
=
this
.
assertResourceExist
=
function
assertResourceExists
(
test
,
message
)
{
return
this
.
assert
(
casper
.
resourceExists
(
test
),
message
,
{
Tester
.
prototype
.
assertResourceExists
=
Tester
.
prototype
.
assertResourceExist
=
function
assertResourceExists
(
test
,
message
)
{
"use strict"
;
return
this
.
assert
(
this
.
casper
.
resourceExists
(
test
),
message
,
{
type
:
"assertResourceExists"
,
standard
:
"Expected resource has been found"
,
values
:
{
test
:
test
}
});
};
};
/**
/**
* Asserts that given text exists in the document body.
*
* @param String text Text to be found
* @param String message Test description
* @return Object An assertion result object
*/
this
.
assertTextExists
=
this
.
assertTextExist
=
function
assertTextExists
(
text
,
message
)
{
var
textFound
=
(
casper
.
evaluate
(
function
_evaluate
()
{
Tester
.
prototype
.
assertTextExists
=
Tester
.
prototype
.
assertTextExist
=
function
assertTextExists
(
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
,
{
...
...
@@ -443,9 +464,9 @@ var Tester = function Tester(casper, options) {
text
:
text
}
});
};
};
/**
/**
* Asserts that given text exists in the provided selector.
*
* @param String selector Selector expression
...
...
@@ -453,8 +474,9 @@ var Tester = function Tester(casper, options) {
* @param String message Test description
* @return Object An assertion result object
*/
this
.
assertSelectorHasText
=
function
assertSelectorHasText
(
selector
,
text
,
message
)
{
var
textFound
=
casper
.
fetchText
(
selector
).
indexOf
(
text
)
!==
-
1
;
Tester
.
prototype
.
assertSelectorHasText
=
function
assertSelectorHasText
(
selector
,
text
,
message
)
{
"use strict"
;
var
textFound
=
this
.
casper
.
fetchText
(
selector
).
indexOf
(
text
)
!==
-
1
;
return
this
.
assert
(
textFound
,
message
,
{
type
:
"assertTextInSelector"
,
standard
:
f
(
'Found "%s" within the selector "%s"'
,
text
,
selector
),
...
...
@@ -463,9 +485,9 @@ var Tester = function Tester(casper, options) {
text
:
text
}
});
};
};
/**
/**
* Asserts that given text does not exist in the provided selector.
*
* @param String selector Selector expression
...
...
@@ -473,8 +495,9 @@ var Tester = function Tester(casper, options) {
* @param String message Test description
* @return Object An assertion result object
*/
this
.
assertSelectorDoesntHaveText
=
function
assertSelectorDoesntHaveText
(
selector
,
text
,
message
)
{
var
textFound
=
casper
.
fetchText
(
selector
).
indexOf
(
text
)
===
-
1
;
Tester
.
prototype
.
assertSelectorDoesntHaveText
=
function
assertSelectorDoesntHaveText
(
selector
,
text
,
message
)
{
"use strict"
;
var
textFound
=
this
.
casper
.
fetchText
(
selector
).
indexOf
(
text
)
===
-
1
;
return
this
.
assert
(
textFound
,
message
,
{
type
:
"assertNoTextInSelector"
,
standard
:
f
(
'Did not find "%s" within the selector "%s"'
,
text
,
selector
),
...
...
@@ -483,17 +506,18 @@ var Tester = function Tester(casper, options) {
text
:
text
}
});
};
};
/**
/**
* Asserts that title of the remote page equals to the expected one.
*
* @param String expected The expected title string
* @param String message Test description
* @return Object An assertion result object
*/
this
.
assertTitle
=
function
assertTitle
(
expected
,
message
)
{
var
currentTitle
=
casper
.
getTitle
();
Tester
.
prototype
.
assertTitle
=
function
assertTitle
(
expected
,
message
)
{
"use strict"
;
var
currentTitle
=
this
.
casper
.
getTitle
();
return
this
.
assert
(
this
.
testEquals
(
currentTitle
,
expected
),
message
,
{
type
:
"assertTitle"
,
standard
:
f
(
'Page title is: "%s"'
,
expected
),
...
...
@@ -502,17 +526,18 @@ var Tester = function Tester(casper, options) {
expected
:
expected
}
});
};
};
/**
/**
* Asserts that title of the remote page matched the provided pattern.
*
* @param RegExp pattern The pattern to test the title against
* @param String message Test description
* @return Object An assertion result object
*/
this
.
assertTitleMatch
=
this
.
assertTitleMatches
=
function
assertTitleMatch
(
pattern
,
message
)
{
var
currentTitle
=
casper
.
getTitle
();
Tester
.
prototype
.
assertTitleMatch
=
Tester
.
prototype
.
assertTitleMatches
=
function
assertTitleMatch
(
pattern
,
message
)
{
"use strict"
;
var
currentTitle
=
this
.
casper
.
getTitle
();
return
this
.
assert
(
pattern
.
test
(
currentTitle
),
message
,
{
type
:
"assertTitle"
,
details
:
"Page title does not match the provided pattern"
,
...
...
@@ -521,9 +546,9 @@ var Tester = function Tester(casper, options) {
pattern
:
pattern
.
toString
()
}
});
};
};
/**
/**
* Asserts that the provided subject is of the given type.
*
* @param mixed subject The value to test
...
...
@@ -531,7 +556,8 @@ var Tester = function Tester(casper, options) {
* @param String message Test description
* @return Object An assertion result object
*/
this
.
assertType
=
function
assertType
(
subject
,
type
,
message
)
{
Tester
.
prototype
.
assertType
=
function
assertType
(
subject
,
type
,
message
)
{
"use strict"
;
var
actual
=
utils
.
betterTypeOf
(
subject
);
return
this
.
assert
(
this
.
testEquals
(
actual
,
type
),
message
,
{
type
:
"assertType"
,
...
...
@@ -542,9 +568,9 @@ var Tester = function Tester(casper, options) {
actual
:
actual
}
});
};
};
/**
/**
* Asserts that a the current page url matches the provided RegExp
* pattern.
*
...
...
@@ -552,8 +578,9 @@ var Tester = function Tester(casper, options) {
* @param String message Test description
* @return Object An assertion result object
*/
this
.
assertUrlMatch
=
this
.
assertUrlMatches
=
function
assertUrlMatch
(
pattern
,
message
)
{
var
currentUrl
=
casper
.
getCurrentUrl
();
Tester
.
prototype
.
assertUrlMatch
=
Tester
.
prototype
.
assertUrlMatches
=
function
assertUrlMatch
(
pattern
,
message
)
{
"use strict"
;
var
currentUrl
=
this
.
casper
.
getCurrentUrl
();
return
this
.
assert
(
pattern
.
test
(
currentUrl
),
message
,
{
type
:
"assertUrlMatch"
,
standard
:
"Current url matches the provided pattern"
,
...
...
@@ -562,75 +589,82 @@ var Tester = function Tester(casper, options) {
pattern
:
pattern
.
toString
()
}
});
};
};
/**
/**
* Asserts that a selector expression is currently visible.
*
* @param String expected selector expression
* @param String message Test description
* @return Object An assertion result object
*/
this
.
assertVisible
=
function
assertVisible
(
selector
,
message
)
{
return
this
.
assert
(
casper
.
visible
(
selector
),
message
,
{
Tester
.
prototype
.
assertVisible
=
function
assertVisible
(
selector
,
message
)
{
"use strict"
;
return
this
.
assert
(
this
.
casper
.
visible
(
selector
),
message
,
{
type
:
"assertVisible"
,
standard
:
"Selector is visible"
,
values
:
{
selector
:
selector
}
});
};
};
/**
/**
* Prints out a colored bar onto the console.
*
*/
this
.
bar
=
function
bar
(
text
,
style
)
{
casper
.
echo
(
text
,
style
,
this
.
options
.
pad
);
};
Tester
.
prototype
.
bar
=
function
bar
(
text
,
style
)
{
"use strict"
;
this
.
casper
.
echo
(
text
,
style
,
this
.
options
.
pad
);
};
/**
/**
* Render a colorized output. Basically a proxy method for
* Casper.Colorizer#colorize()
*/
this
.
colorize
=
function
colorize
(
message
,
style
)
{
return
casper
.
getColorizer
().
colorize
(
message
,
style
);
};
Tester
.
prototype
.
colorize
=
function
colorize
(
message
,
style
)
{
"use strict"
;
return
this
.
casper
.
getColorizer
().
colorize
(
message
,
style
);
};
/**
/**
* Writes a comment-style formatted message to stdout.
*
* @param String message
*/
this
.
comment
=
function
comment
(
message
)
{
casper
.
echo
(
'# '
+
message
,
'COMMENT'
);
};
Tester
.
prototype
.
comment
=
function
comment
(
message
)
{
"use strict"
;
this
.
casper
.
echo
(
'# '
+
message
,
'COMMENT'
);
};
/**
/**
* Declares the current test suite done.
*
*/
this
.
done
=
function
done
()
{
Tester
.
prototype
.
done
=
function
done
()
{
"use strict"
;
this
.
emit
(
'test.done'
);
this
.
running
=
false
;
};
};
/**
/**
* Writes an error-style formatted message to stdout.
*
* @param String message
*/
this
.
error
=
function
error
(
message
)
{
casper
.
echo
(
message
,
'ERROR'
);
};
Tester
.
prototype
.
error
=
function
error
(
message
)
{
"use strict"
;
this
.
casper
.
echo
(
message
,
'ERROR'
);
};
/**
/**
* Executes a file, wraping and evaluating its code in an isolated
* environment where only the current `casper` instance is passed.
*
* @param String file Absolute path to some js/coffee file
*/
this
.
exec
=
function
exec
(
file
)
{
Tester
.
prototype
.
exec
=
function
exec
(
file
)
{
"use strict"
;
file
=
this
.
filter
(
'exec.file'
,
file
)
||
file
;
if
(
!
fs
.
isFile
(
file
)
||
!
utils
.
isJsFile
(
file
))
{
var
e
=
new
CasperError
(
f
(
"Cannot exec %s: can only exec() files with .js or .coffee extensions"
,
file
));
...
...
@@ -639,26 +673,28 @@ var Tester = function Tester(casper, options) {
}
this
.
currentTestFile
=
file
;
phantom
.
injectJs
(
file
);
};
};
/**
/**
* Adds a failed test entry to the stack.
*
* @param String message
*/
this
.
fail
=
function
fail
(
message
)
{
Tester
.
prototype
.
fail
=
function
fail
(
message
)
{
"use strict"
;
return
this
.
assert
(
false
,
message
,
{
type
:
"fail"
,
standard
:
"explicit call to fail()"
});
};
};
/**
/**
* Recursively finds all test files contained in a given directory.
*
* @param String dir Path to some directory to scan
*/
this
.
findTestFiles
=
function
findTestFiles
(
dir
)
{
Tester
.
prototype
.
findTestFiles
=
function
findTestFiles
(
dir
)
{
"use strict"
;
var
self
=
this
;
if
(
!
fs
.
isDirectory
(
dir
))
{
return
[];
...
...
@@ -676,79 +712,85 @@ var Tester = function Tester(casper, options) {
return
entries
.
filter
(
function
_filter
(
entry
)
{
return
utils
.
isJsFile
(
fs
.
absolute
(
fs
.
pathJoin
(
dir
,
entry
)));
}).
sort
();
};
};
/**
/**
* Formats a message to highlight some parts of it.
*
* @param String message
* @param String style
*/
this
.
formatMessage
=
function
formatMessage
(
message
,
style
)
{
Tester
.
prototype
.
formatMessage
=
function
formatMessage
(
message
,
style
)
{
"use strict"
;
var
parts
=
/^
([
a-z0-9_
\.]
+
\(\))(
.*
)
/i
.
exec
(
message
);
if
(
!
parts
)
{
return
message
;
}
return
this
.
colorize
(
parts
[
1
],
'PARAMETER'
)
+
this
.
colorize
(
parts
[
2
],
style
);
};
};
/**
/**
* Retrieves current failure data and all failed cases.
*
* @return Object casedata An object containg information about cases
* @return Number casedata.length The number of failed cases
* @return Array casedata.cases An array of all the failed case objects
*/
this
.
getFailures
=
function
getFailures
()
{
Tester
.
prototype
.
getFailures
=
function
getFailures
()
{
"use strict"
;
return
{
length
:
this
.
testResults
.
failed
,
cases
:
this
.
testResults
.
failures
};
};
};
/**
/**
* Retrieves current passed data and all passed cases.
*
* @return Object casedata An object containg information about cases
* @return Number casedata.length The number of passed cases
* @return Array casedata.cases An array of all the passed case objects
*/
this
.
getPasses
=
function
getPasses
()
{
Tester
.
prototype
.
getPasses
=
function
getPasses
()
{
"use strict"
;
return
{
length
:
this
.
testResults
.
passed
,
cases
:
this
.
testResults
.
passes
};
};
};
/**
/**
* Writes an info-style formatted message to stdout.
*
* @param String message
*/
this
.
info
=
function
info
(
message
)
{
casper
.
echo
(
message
,
'PARAMETER'
);
};
Tester
.
prototype
.
info
=
function
info
(
message
)
{
"use strict"
;
this
.
casper
.
echo
(
message
,
'PARAMETER'
);
};
/**
/**
* Adds a successful test entry to the stack.
*
* @param String message
*/
this
.
pass
=
function
pass
(
message
)
{
Tester
.
prototype
.
pass
=
function
pass
(
message
)
{
"use strict"
;
return
this
.
assert
(
true
,
message
,
{
type
:
"pass"
,
standard
:
"explicit call to pass()"
});
};
};
/**
/**
* Processes an assertion result by emitting the appropriate event and
* printing result onto the console.
*
* @param Object result An assertion result object
* @return Object The passed assertion result Object
*/
this
.
processAssertionResult
=
function
processAssertionResult
(
result
)
{
Tester
.
prototype
.
processAssertionResult
=
function
processAssertionResult
(
result
)
{
"use strict"
;
var
eventName
,
style
,
status
;
if
(
result
.
success
===
true
)
{
eventName
=
'success'
;
...
...
@@ -762,37 +804,39 @@ var Tester = function Tester(casper, options) {
this
.
testResults
.
failed
++
;
}
var
message
=
result
.
message
||
result
.
standard
;
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
);
return
result
;
};
};
/**
/**
* Renders a detailed report for each failed test.
*
* @param Array failures
*/
this
.
renderFailureDetails
=
function
renderFailureDetails
(
failures
)
{
Tester
.
prototype
.
renderFailureDetails
=
function
renderFailureDetails
(
failures
)
{
"use strict"
;
if
(
failures
.
length
===
0
)
{
return
;
}
casper
.
echo
(
f
(
"\nDetails for the %d failed test%s:\n"
,
failures
.
length
,
failures
.
length
>
1
?
"s"
:
""
),
"PARAMETER"
);
this
.
casper
.
echo
(
f
(
"\nDetails for the %d failed test%s:\n"
,
failures
.
length
,
failures
.
length
>
1
?
"s"
:
""
),
"PARAMETER"
);
failures
.
forEach
(
function
_forEach
(
failure
)
{
var
type
,
message
,
line
;
type
=
failure
.
type
||
"unknown"
;
line
=
~~
failure
.
line
;
message
=
failure
.
message
;
casper
.
echo
(
f
(
'In %s:%s'
,
failure
.
file
,
line
));
casper
.
echo
(
f
(
' %s: %s'
,
type
,
message
||
failure
.
standard
||
"(no message was entered)"
),
"COMMENT"
);
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"
);
});
};
};
/**
/**
* Render tests results, an optionally exit phantomjs.
*
* @param Boolean exit
*/
this
.
renderResults
=
function
renderResults
(
exit
,
status
,
save
)
{
Tester
.
prototype
.
renderResults
=
function
renderResults
(
exit
,
status
,
save
)
{
"use strict"
;
save
=
utils
.
isString
(
save
)
?
save
:
this
.
options
.
save
;
var
total
=
this
.
testResults
.
passed
+
this
.
testResults
.
failed
,
statusText
,
style
,
result
;
var
exitStatus
=
~~
(
status
||
(
this
.
testResults
.
failed
>
0
?
1
:
0
));
...
...
@@ -811,28 +855,29 @@ var Tester = function Tester(casper, options) {
result
=
f
(
'%s %s tests executed, %d passed, %d failed.'
,
statusText
,
total
,
this
.
testResults
.
passed
,
this
.
testResults
.
failed
);
}
casper
.
echo
(
result
,
style
,
this
.
options
.
pad
);
this
.
casper
.
echo
(
result
,
style
,
this
.
options
.
pad
);
if
(
this
.
testResults
.
failed
>
0
)
{
this
.
renderFailureDetails
(
this
.
testResults
.
failures
);
}
if
(
save
&&
utils
.
isFunction
(
require
))
{
try
{
fs
.
write
(
save
,
this
.
exporter
.
getXML
(),
'w'
);
casper
.
echo
(
f
(
'Result log stored in %s'
,
save
),
'INFO'
,
80
);
this
.
casper
.
echo
(
f
(
'Result log stored in %s'
,
save
),
'INFO'
,
80
);
}
catch
(
e
)
{
casper
.
echo
(
f
(
'Unable to write results to %s: %s'
,
save
,
e
),
'ERROR'
,
80
);
this
.
casper
.
echo
(
f
(
'Unable to write results to %s: %s'
,
save
,
e
),
'ERROR'
,
80
);
}
}
if
(
exit
===
true
)
{
casper
.
exit
(
exitStatus
);
this
.
casper
.
exit
(
exitStatus
);
}
};
};
/**
/**
* Runs al suites contained in the paths passed as arguments.
*
*/
this
.
runSuites
=
function
runSuites
()
{
Tester
.
prototype
.
runSuites
=
function
runSuites
()
{
"use strict"
;
var
testFiles
=
[],
self
=
this
;
if
(
arguments
.
length
===
0
)
{
throw
new
CasperError
(
"runSuites() needs at least one path argument"
);
...
...
@@ -862,7 +907,7 @@ var Tester = function Tester(casper, options) {
if
(
testFiles
.
length
===
0
)
{
this
.
bar
(
f
(
"No test file found in %s, aborting."
,
Array
.
prototype
.
slice
.
call
(
arguments
)),
"RED_BAR"
);
casper
.
exit
(
1
);
this
.
casper
.
exit
(
1
);
}
self
.
currentSuiteNum
=
0
;
var
interval
=
setInterval
(
function
_check
(
self
)
{
...
...
@@ -877,30 +922,32 @@ var Tester = function Tester(casper, options) {
self
.
currentSuiteNum
++
;
}
},
100
,
this
);
};
};
/**
/**
* Runs a test file
*
*/
this
.
runTest
=
function
runTest
(
testFile
)
{
Tester
.
prototype
.
runTest
=
function
runTest
(
testFile
)
{
"use strict"
;
this
.
bar
(
f
(
'Test file: %s'
,
testFile
),
'INFO_BAR'
);
this
.
running
=
true
;
// this.running is set back to false with done()
this
.
exec
(
testFile
);
};
};
/**
/**
* Tests equality between the two passed arguments.
*
* @param Mixed v1
* @param Mixed v2
* @param Boolean
*/
this
.
testEquals
=
this
.
testEqual
=
function
testEquals
(
v1
,
v2
)
{
Tester
.
prototype
.
testEquals
=
Tester
.
prototype
.
testEqual
=
function
testEquals
(
v1
,
v2
)
{
"use strict"
;
return
utils
.
equals
(
v1
,
v2
);
};
};
/**
/**
* Processes an error caught while running tests contained in a given test
* file.
*
...
...
@@ -908,7 +955,8 @@ var Tester = function Tester(casper, options) {
* @param String file Test file where the error occurred
* @param Number line Line number (optional)
*/
this
.
uncaughtError
=
function
uncaughtError
(
error
,
file
,
line
)
{
Tester
.
prototype
.
uncaughtError
=
function
uncaughtError
(
error
,
file
,
line
)
{
"use strict"
;
return
this
.
processAssertionResult
({
success
:
false
,
type
:
"uncaughtError"
,
...
...
@@ -919,10 +967,4 @@ var Tester = function Tester(casper, options) {
error
:
error
}
});
};
};
// Tester class is an EventEmitter
utils
.
inherits
(
Tester
,
events
.
EventEmitter
);
exports
.
Tester
=
Tester
;
...
...
modules/utils.js
View file @
93dcfbd
...
...
@@ -30,10 +30,7 @@
/*global CasperError console exports phantom require*/
(
function
(
exports
)
{
"use strict"
;
/**
/**
* Provides a better typeof operator equivalent, able to retrieve the array
* type.
*
...
...
@@ -41,22 +38,24 @@
* @return String
* @see http://javascriptweblog.wordpress.com/2011/08/08/fixing-the-javascript-typeof-operator/
*/
function
betterTypeOf
(
input
)
{
function
betterTypeOf
(
input
)
{
"use strict"
;
try
{
return
Object
.
prototype
.
toString
.
call
(
input
).
match
(
/^
\[
object
\s(
.*
)\]
$/
)[
1
].
toLowerCase
();
}
catch
(
e
)
{
return
typeof
input
;
}
}
exports
.
betterTypeOf
=
betterTypeOf
;
}
exports
.
betterTypeOf
=
betterTypeOf
;
/**
/**
* Cleans a passed URL if it lacks a slash at the end when a sole domain is used.
*
* @param String url An HTTP URL
* @return String
*/
function
cleanUrl
(
url
)
{
function
cleanUrl
(
url
)
{
"use strict"
;
var
parts
=
/
(
https
?)
:
\/\/(
.*
)
/i
.
exec
(
url
);
if
(
!
parts
)
{
return
url
;
...
...
@@ -67,28 +66,30 @@
return
format
(
"%s://%s/"
,
protocol
,
subparts
[
0
]);
}
return
url
;
}
exports
.
cleanUrl
=
cleanUrl
;
}
exports
.
cleanUrl
=
cleanUrl
;
/**
/**
* Dumps a JSON representation of passed value to the console. Used for
* debugging purpose only.
*
* @param Mixed value
*/
function
dump
(
value
)
{
function
dump
(
value
)
{
"use strict"
;
console
.
log
(
serialize
(
value
,
4
));
}
exports
.
dump
=
dump
;
}
exports
.
dump
=
dump
;
/**
/**
* Tests equality between the two passed arguments.
*
* @param Mixed v1
* @param Mixed v2
* @param Boolean
*/
function
equals
(
v1
,
v2
)
{
function
equals
(
v1
,
v2
)
{
"use strict"
;
if
(
betterTypeOf
(
v1
)
!==
betterTypeOf
(
v2
))
{
return
false
;
}
...
...
@@ -107,46 +108,49 @@
return
true
;
}
return
v1
===
v2
;
}
exports
.
equals
=
equals
;
}
exports
.
equals
=
equals
;
/**
/**
* Returns the file extension in lower case.
*
* @param String file File path
* @return string
*/
function
fileExt
(
file
)
{
function
fileExt
(
file
)
{
"use strict"
;
try
{
return
file
.
split
(
'.'
).
pop
().
toLowerCase
().
trim
();
}
catch
(
e
)
{
return
''
;
}
}
exports
.
fileExt
=
fileExt
;
}
exports
.
fileExt
=
fileExt
;
/**
/**
* Takes a string and append blanks until the pad value is reached.
*
* @param String text
* @param Number pad Pad value (optional; default: 80)
* @return String
*/
function
fillBlanks
(
text
,
pad
)
{
function
fillBlanks
(
text
,
pad
)
{
"use strict"
;
pad
=
pad
||
80
;
if
(
text
.
length
<
pad
)
{
text
+=
new
Array
(
pad
-
text
.
length
+
1
).
join
(
' '
);
}
return
text
;
}
exports
.
fillBlanks
=
fillBlanks
;
}
exports
.
fillBlanks
=
fillBlanks
;
/**
/**
* Formats a string with passed parameters. Ported from nodejs `util.format()`.
*
* @return String
*/
function
format
(
f
)
{
function
format
(
f
)
{
"use strict"
;
var
i
=
1
;
var
args
=
arguments
;
var
len
=
args
.
length
;
...
...
@@ -173,10 +177,10 @@
}
}
return
str
;
}
exports
.
format
=
format
;
}
exports
.
format
=
format
;
/**
/**
* Retrieves the value of an Object foreign property using a dot-separated
* path string.
*
...
...
@@ -185,7 +189,8 @@
* @param Object obj The source object
* @param String path Dot separated path, eg. "x.y.z"
*/
function
getPropertyPath
(
obj
,
path
)
{
function
getPropertyPath
(
obj
,
path
)
{
"use strict"
;
if
(
!
isObject
(
obj
)
||
!
isString
(
path
))
{
return
undefined
;
}
...
...
@@ -198,17 +203,18 @@
}
});
return
value
;
}
exports
.
getPropertyPath
=
getPropertyPath
;
}
exports
.
getPropertyPath
=
getPropertyPath
;
/**
/**
* Inherit the prototype methods from one constructor into another.
*
* @param {function} ctor Constructor function which needs to inherit the
* prototype.
* @param {function} superCtor Constructor function to inherit prototype from.
*/
function
inherits
(
ctor
,
superCtor
)
{
function
inherits
(
ctor
,
superCtor
)
{
"use strict"
;
ctor
.
super_
=
ctor
.
__super__
=
superCtor
;
ctor
.
prototype
=
Object
.
create
(
superCtor
.
prototype
,
{
constructor
:
{
...
...
@@ -218,125 +224,135 @@
configurable
:
true
}
});
}
exports
.
inherits
=
inherits
;
}
exports
.
inherits
=
inherits
;
/**
/**
* Checks if value is a javascript Array
*
* @param mixed value
* @return Boolean
*/
function
isArray
(
value
)
{
function
isArray
(
value
)
{
"use strict"
;
return
Array
.
isArray
(
value
)
||
isType
(
value
,
"array"
);
}
exports
.
isArray
=
isArray
;
}
exports
.
isArray
=
isArray
;
/**
/**
* Checks if passed argument is an instance of Capser object.
*
* @param mixed value
* @return Boolean
*/
function
isCasperObject
(
value
)
{
function
isCasperObject
(
value
)
{
"use strict"
;
return
value
instanceof
require
(
'casper'
).
Casper
;
}
exports
.
isCasperObject
=
isCasperObject
;
}
exports
.
isCasperObject
=
isCasperObject
;
/**
/**
* Checks if value is a phantomjs clipRect-compatible object
*
* @param mixed value
* @return Boolean
*/
function
isClipRect
(
value
)
{
function
isClipRect
(
value
)
{
"use strict"
;
return
isType
(
value
,
"cliprect"
)
||
(
isObject
(
value
)
&&
isNumber
(
value
.
top
)
&&
isNumber
(
value
.
left
)
&&
isNumber
(
value
.
width
)
&&
isNumber
(
value
.
height
)
);
}
exports
.
isClipRect
=
isClipRect
;
}
exports
.
isClipRect
=
isClipRect
;
/**
/**
* Checks if value is a javascript Function
*
* @param mixed value
* @return Boolean
*/
function
isFunction
(
value
)
{
function
isFunction
(
value
)
{
"use strict"
;
return
isType
(
value
,
"function"
);
}
exports
.
isFunction
=
isFunction
;
}
exports
.
isFunction
=
isFunction
;
/**
/**
* Checks if passed resource involves an HTTP url.
*
* @param Object resource The PhantomJS HTTP resource object
* @return Boolean
*/
function
isHTTPResource
(
resource
)
{
function
isHTTPResource
(
resource
)
{
"use strict"
;
return
isObject
(
resource
)
&&
/^http/i
.
test
(
resource
.
url
);
}
exports
.
isHTTPResource
=
isHTTPResource
;
}
exports
.
isHTTPResource
=
isHTTPResource
;
/**
/**
* Checks if a file is apparently javascript compatible (.js or .coffee).
*
* @param String file Path to the file to test
* @return Boolean
*/
function
isJsFile
(
file
)
{
function
isJsFile
(
file
)
{
"use strict"
;
var
ext
=
fileExt
(
file
);
return
isString
(
ext
,
"string"
)
&&
[
'js'
,
'coffee'
].
indexOf
(
ext
)
!==
-
1
;
}
exports
.
isJsFile
=
isJsFile
;
}
exports
.
isJsFile
=
isJsFile
;
/**
/**
* Checks if the provided value is null
*
* @return Boolean
*/
function
isNull
(
value
)
{
function
isNull
(
value
)
{
"use strict"
;
return
isType
(
value
,
"null"
);
}
exports
.
isNull
=
isNull
;
}
exports
.
isNull
=
isNull
;
/**
/**
* Checks if value is a javascript Number
*
* @param mixed value
* @return Boolean
*/
function
isNumber
(
value
)
{
function
isNumber
(
value
)
{
"use strict"
;
return
isType
(
value
,
"number"
);
}
exports
.
isNumber
=
isNumber
;
}
exports
.
isNumber
=
isNumber
;
/**
/**
* Checks if value is a javascript Object
*
* @param mixed value
* @return Boolean
*/
function
isObject
(
value
)
{
function
isObject
(
value
)
{
"use strict"
;
var
objectTypes
=
[
"array"
,
"object"
,
"qtruntimeobject"
];
return
objectTypes
.
indexOf
(
betterTypeOf
(
value
))
>=
0
;
}
exports
.
isObject
=
isObject
;
}
exports
.
isObject
=
isObject
;
/**
/**
* Checks if value is a javascript String
*
* @param mixed value
* @return Boolean
*/
function
isString
(
value
)
{
function
isString
(
value
)
{
"use strict"
;
return
isType
(
value
,
"string"
);
}
exports
.
isString
=
isString
;
}
exports
.
isString
=
isString
;
/**
/**
* Shorthands for checking if a value is of the given type. Can check for
* arrays.
*
...
...
@@ -344,31 +360,34 @@
* @param String typeName The type name ("string", "number", "function", etc.)
* @return Boolean
*/
function
isType
(
what
,
typeName
)
{
function
isType
(
what
,
typeName
)
{
"use strict"
;
if
(
typeof
typeName
!==
"string"
||
!
typeName
)
{
throw
new
CasperError
(
"You must pass isType() a typeName string"
);
}
return
betterTypeOf
(
what
).
toLowerCase
()
===
typeName
.
toLowerCase
();
}
exports
.
isType
=
isType
;
}
exports
.
isType
=
isType
;
/**
/**
* Checks if the provided value is undefined
*
* @return Boolean
*/
function
isUndefined
(
value
)
{
function
isUndefined
(
value
)
{
"use strict"
;
return
isType
(
value
,
"undefined"
);
}
exports
.
isUndefined
=
isUndefined
;
}
exports
.
isUndefined
=
isUndefined
;
/**
/**
* Checks if value is a valid selector Object.
*
* @param mixed value
* @return Boolean
*/
function
isValidSelector
(
value
)
{
function
isValidSelector
(
value
)
{
"use strict"
;
if
(
isString
(
value
))
{
try
{
// phantomjs env has a working document object, let's use it
...
...
@@ -392,28 +411,30 @@
return
true
;
}
return
false
;
}
exports
.
isValidSelector
=
isValidSelector
;
}
exports
.
isValidSelector
=
isValidSelector
;
/**
/**
* Checks if the provided var is a WebPage instance
*
* @param mixed what
* @return Boolean
*/
function
isWebPage
(
what
)
{
function
isWebPage
(
what
)
{
"use strict"
;
return
betterTypeOf
(
what
)
===
"qtruntimeobject"
&&
what
.
objectName
===
'WebPage'
;
}
exports
.
isWebPage
=
isWebPage
;
}
exports
.
isWebPage
=
isWebPage
;
/**
/**
* Object recursive merging utility.
*
* @param Object origin the origin object
* @param Object add the object to merge data into origin
* @return Object
*/
function
mergeObjects
(
origin
,
add
)
{
function
mergeObjects
(
origin
,
add
)
{
"use strict"
;
for
(
var
p
in
add
)
{
try
{
if
(
add
[
p
].
constructor
===
Object
)
{
...
...
@@ -426,17 +447,18 @@
}
}
return
origin
;
}
exports
.
mergeObjects
=
mergeObjects
;
}
exports
.
mergeObjects
=
mergeObjects
;
/**
/**
* Creates an (SG|X)ML node element.
*
* @param String name The node name
* @param Object attributes Optional attributes
* @return HTMLElement
*/
function
node
(
name
,
attributes
)
{
function
node
(
name
,
attributes
)
{
"use strict"
;
var
_node
=
document
.
createElement
(
name
);
for
(
var
attrName
in
attributes
)
{
var
value
=
attributes
[
attrName
];
...
...
@@ -445,26 +467,27 @@
}
}
return
_node
;
}
exports
.
node
=
node
;
}
exports
.
node
=
node
;
/**
/**
* Serializes a value using JSON.
*
* @param Mixed value
* @return String
*/
function
serialize
(
value
,
indent
)
{
function
serialize
(
value
,
indent
)
{
"use strict"
;
if
(
isArray
(
value
))
{
value
=
value
.
map
(
function
_map
(
prop
)
{
return
isFunction
(
prop
)
?
prop
.
toString
().
replace
(
/
\s{2,}
/
,
''
)
:
prop
;
});
}
return
JSON
.
stringify
(
value
,
null
,
indent
);
}
exports
.
serialize
=
serialize
;
}
exports
.
serialize
=
serialize
;
/**
/**
* Returns unique values from an array.
*
* Note: ugly code is ugly, but efficient: http://jsperf.com/array-unique2/8
...
...
@@ -472,7 +495,8 @@
* @param Array array
* @return Array
*/
function
unique
(
array
)
{
function
unique
(
array
)
{
"use strict"
;
var
o
=
{},
r
=
[];
for
(
var
i
=
0
,
len
=
array
.
length
;
i
!==
len
;
i
++
)
{
...
...
@@ -483,6 +507,5 @@
}
}
return
r
;
}
exports
.
unique
=
unique
;
})(
exports
);
}
exports
.
unique
=
unique
;
...
...
modules/xunit.js
View file @
93dcfbd
...
...
@@ -33,6 +33,36 @@
var
utils
=
require
(
'utils'
);
var
fs
=
require
(
'fs'
);
/**
* Generates a value for 'classname' attribute of the JUnit XML report.
*
* Uses the (relative) file name of the current casper script without file
* extension as classname.
*
* @param String classname
* @return String
*/
function
generateClassName
(
classname
)
{
"use strict"
;
classname
=
classname
.
replace
(
phantom
.
casperPath
,
""
).
trim
();
var
script
=
classname
||
phantom
.
casperScript
;
if
(
script
.
indexOf
(
fs
.
workingDirectory
)
===
0
)
{
script
=
script
.
substring
(
fs
.
workingDirectory
.
length
+
1
);
}
if
(
script
.
indexOf
(
'/'
)
===
0
)
{
script
=
script
.
substring
(
1
,
script
.
length
);
}
if
(
~
script
.
indexOf
(
'.'
))
{
script
=
script
.
substring
(
0
,
script
.
lastIndexOf
(
'.'
));
}
return
script
||
"unknown"
;
}
/**
* Creates a XUnit instance
*
* @return XUnit
*/
exports
.
create
=
function
create
()
{
"use strict"
;
return
new
XUnitExporter
();
...
...
@@ -88,31 +118,6 @@ XUnitExporter.prototype.addFailure = function addFailure(classname, name, messag
};
/**
* Generates a value for 'classname' attribute of the JUnit XML report.
*
* Uses the (relative) file name of the current casper script without file
* extension as classname.
*
* @param String classname
* @return String
*/
function
generateClassName
(
classname
)
{
"use strict"
;
classname
=
classname
.
replace
(
phantom
.
casperPath
,
""
).
trim
();
var
script
=
classname
||
phantom
.
casperScript
;
if
(
script
.
indexOf
(
fs
.
workingDirectory
)
===
0
)
{
script
=
script
.
substring
(
fs
.
workingDirectory
.
length
+
1
);
}
if
(
script
.
indexOf
(
'/'
)
===
0
)
{
script
=
script
.
substring
(
1
,
script
.
length
);
}
if
(
~
script
.
indexOf
(
'.'
))
{
script
=
script
.
substring
(
0
,
script
.
lastIndexOf
(
'.'
));
}
return
script
||
"unknown"
;
}
/**
* Retrieves generated XML object - actually an HTMLElement.
*
* @return HTMLElement
...
...
tests/run.js
View file @
93dcfbd
/*global phantom*/
if
(
!
phantom
.
casperLoaded
)
{
console
.
log
(
'This script must be invoked using the casperjs executable'
);
phantom
.
exit
(
1
);
...
...
@@ -15,6 +17,7 @@ var casper = require('casper').create({
// local utils
function
checkSelfTest
(
tests
)
{
"use strict"
;
var
isCasperTest
=
false
;
tests
.
forEach
(
function
(
test
)
{
var
testDir
=
fs
.
absolute
(
fs
.
dirname
(
test
));
...
...
@@ -28,6 +31,7 @@ function checkSelfTest(tests) {
}
function
checkIncludeFile
(
include
)
{
"use strict"
;
var
absInclude
=
fs
.
absolute
(
include
.
trim
());
if
(
!
fs
.
exists
(
absInclude
))
{
casper
.
warn
(
"%s file not found, can't be included"
,
absInclude
);
...
...
@@ -60,6 +64,7 @@ if (casper.cli.get('no-colors') === true) {
// 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
{
...
...
@@ -75,6 +80,7 @@ if (!phantom.casperSelfTest && checkSelfTest(tests)) {
// includes handling
this
.
loadIncludes
.
forEach
(
function
(
include
){
"use strict"
;
var
container
;
if
(
casper
.
cli
.
has
(
include
))
{
container
=
casper
.
cli
.
get
(
include
).
split
(
','
).
map
(
function
(
file
)
{
...
...
@@ -89,6 +95,7 @@ this.loadIncludes.forEach(function(include){
// test suites completion listener
casper
.
test
.
on
(
'tests.complete'
,
function
()
{
"use strict"
;
this
.
renderResults
(
true
,
undefined
,
casper
.
cli
.
get
(
'xunit'
)
||
undefined
);
});
...
...
tests/selftest.js
View file @
93dcfbd
/**
* CasperJS local HTTP test server
*/
/*global phantom casper require*/
var
colorizer
=
require
(
'colorizer'
).
create
(
'Colorizer'
);
var
fs
=
require
(
'fs'
);
var
utils
=
require
(
'utils'
);
...
...
@@ -9,10 +12,12 @@ var service;
var
testServerPort
=
54321
;
function
info
(
message
)
{
"use strict"
;
console
.
log
(
colorizer
.
colorize
(
'INFO'
,
'INFO_BAR'
)
+
' '
+
message
);
}
service
=
server
.
listen
(
testServerPort
,
function
(
request
,
response
)
{
"use strict"
;
var
pageFile
=
fs
.
pathJoin
(
phantom
.
casperPath
,
request
.
url
);
if
(
!
fs
.
exists
(
pageFile
)
||
!
fs
.
isFile
(
pageFile
))
{
response
.
statusCode
=
404
;
...
...
@@ -26,16 +31,18 @@ service = server.listen(testServerPort, function(request, response) {
// overriding Casper.open to prefix all test urls
casper
.
setFilter
(
'open.location'
,
function
(
location
)
{
"use strict"
;
if
(
/^file/
.
test
(
location
))
{
return
location
;
}
if
(
!
/^http/
.
test
(
location
))
{
return
f
(
'http://localhost:%d/%s'
,
testServerPort
,
location
);
return
utils
.
format
(
'http://localhost:%d/%s'
,
testServerPort
,
location
);
}
return
location
;
});
// test suites completion listener
casper
.
test
.
on
(
'tests.complete'
,
function
()
{
"use strict"
;
server
.
close
();
});
...
...
Please
register
or
sign in
to post a comment