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
0d0e9621
...
0d0e962148663dd34fc54a8b27d1b481bc3d4c62
authored
2012-01-02 19:06:16 +0100
by
Nicolas Perriault
Browse Files
Options
Browse Files
Tag
Download
Email Patches
Plain Diff
added events where applicable in Casper methods
1 parent
582f1f9a
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
321 additions
and
215 deletions
bin/casperjs
modules/casper.js
modules/utils.js
bin/casperjs
View file @
0d0e962
...
...
@@ -11,7 +11,7 @@ def resolve(path):
return
path
CASPER_PATH
=
os
.
path
.
abspath
(
os
.
path
.
join
(
os
.
path
.
dirname
(
resolve
(
__file__
)),
'..'
))
CASPER_ARGS
=
[
'phantomjs'
,
os
.
path
.
join
(
CASPER_PATH
,
'bin'
,
'bootstrap.js'
),
'--casper-path=
%
s'
%
CASPER_PATH
,
'--cli'
]
CASPER_ARGS
=
[
'phantomjs
14
'
,
os
.
path
.
join
(
CASPER_PATH
,
'bin'
,
'bootstrap.js'
),
'--casper-path=
%
s'
%
CASPER_PATH
,
'--cli'
]
CASPER_ARGS
.
extend
(
sys
.
argv
[
1
:])
try
:
...
...
modules/casper.js
View file @
0d0e962
...
...
@@ -26,6 +26,7 @@
*
*/
var
events
=
require
(
'events'
);
var
fs
=
require
(
'fs'
);
var
utils
=
require
(
'utils'
);
...
...
@@ -104,24 +105,24 @@ var Casper = function(options) {
this
.
test
=
require
(
'tester'
).
create
(
this
);
};
utils
.
inherits
(
Casper
,
events
.
EventEmitter
);
/**
* Casper prototype
*/
Casper
.
prototype
=
{
/**
* Go a step back in browser's history
*
* @return Casper
*/
back
:
function
()
{
return
this
.
then
(
function
(
self
)
{
self
.
evaluate
(
function
()
{
Casper
.
prototype
.
back
=
function
()
{
return
this
.
then
(
function
()
{
this
.
emit
(
'casper.back'
);
this
.
evaluate
(
function
()
{
history
.
back
();
});
});
},
};
/**
/**
* Encodes a resource using the base64 algorithm synchroneously using
* client-side XMLHttpRequest.
*
...
...
@@ -132,13 +133,13 @@ Casper.prototype = {
* @param String data The data to send, optional
* @return string Base64 encoded result
*/
base64encode
:
function
(
url
,
method
,
data
)
{
Casper
.
prototype
.
base64encode
=
function
(
url
,
method
,
data
)
{
return
this
.
evaluate
(
function
(
url
,
method
,
data
)
{
return
__utils__
.
getBase64
(
url
,
method
,
data
);
},
{
url
:
url
,
method
:
method
,
data
:
data
});
},
};
/**
/**
* Proxy method for WebPage#render. Adds a clipRect parameter for
* automatically set page clipRect setting values and sets it back once
* done. If the cliprect parameter is omitted, the full page viewport
...
...
@@ -148,7 +149,7 @@ Casper.prototype = {
* @param mixed clipRect An optional clipRect object (optional)
* @return Casper
*/
capture
:
function
(
targetFile
,
clipRect
)
{
Casper
.
prototype
.
capture
=
function
(
targetFile
,
clipRect
)
{
var
previousClipRect
;
targetFile
=
fs
.
absolute
(
targetFile
);
if
(
clipRect
)
{
...
...
@@ -168,38 +169,38 @@ Casper.prototype = {
this
.
page
.
clipRect
=
previousClipRect
;
}
return
this
;
},
};
/**
/**
* Captures the page area containing the provided selector.
*
* @param String targetFile Target destination file path.
* @param String selector CSS3 selector
* @return Casper
*/
captureSelector
:
function
(
targetFile
,
selector
)
{
Casper
.
prototype
.
captureSelector
=
function
(
targetFile
,
selector
)
{
return
this
.
capture
(
targetFile
,
this
.
getElementBounds
(
selector
));
},
};
/**
/**
* Checks for any further navigation step to process.
*
* @param Casper self A self reference
* @param function onComplete An options callback to apply on completion
*/
checkStep
:
function
(
self
,
onComplete
)
{
Casper
.
prototype
.
checkStep
=
function
(
self
,
onComplete
)
{
if
(
self
.
pendingWait
||
self
.
loadInProgress
)
{
return
;
}
var
step
=
self
.
steps
[
self
.
step
++
];
if
(
utils
.
isType
(
step
,
"function"
))
{
if
(
utils
.
isFunction
(
step
))
{
self
.
runStep
(
step
);
}
else
{
self
.
result
.
time
=
new
Date
().
getTime
()
-
self
.
startTime
;
self
.
log
(
"Done "
+
self
.
steps
.
length
+
" steps in "
+
self
.
result
.
time
+
'ms.'
,
"info"
);
self
.
page
.
content
=
''
;
// avoid having previously loaded DOM contents being still active (refs #34)
clearInterval
(
self
.
checker
);
if
(
utils
.
isType
(
onComplete
,
"function"
))
{
if
(
utils
.
isFunction
(
onComplete
))
{
try
{
onComplete
.
call
(
self
,
self
);
}
catch
(
err
)
{
...
...
@@ -210,9 +211,9 @@ Casper.prototype = {
self
.
exit
();
}
}
},
};
/**
/**
* Emulates a click on the element from the provided selector, if
* possible. In case of success, `true` is returned.
*
...
...
@@ -220,82 +221,85 @@ Casper.prototype = {
* @param Boolean fallbackToHref Whether to try to relocate to the value of any href attribute (default: true)
* @return Boolean
*/
click
:
function
(
selector
,
fallbackToHref
)
{
Casper
.
prototype
.
click
=
function
(
selector
,
fallbackToHref
)
{
fallbackToHref
=
utils
.
isType
(
fallbackToHref
,
"undefined"
)
?
true
:
!!
fallbackToHref
;
this
.
log
(
"Click on selector: "
+
selector
,
"debug"
);
this
.
emit
(
'casper.click'
,
selector
,
fallbackToHref
);
return
this
.
evaluate
(
function
(
selector
,
fallbackToHref
)
{
return
__utils__
.
click
(
selector
,
fallbackToHref
);
},
{
selector
:
selector
,
fallbackToHref
:
fallbackToHref
});
},
};
/**
/**
* Creates a step definition.
*
* @param Function fn The step function to call
* @param Object options Step options
* @return Function The final step function
*/
createStep
:
function
(
fn
,
options
)
{
if
(
!
utils
.
isType
(
fn
,
"function"
))
{
Casper
.
prototype
.
createStep
=
function
(
fn
,
options
)
{
if
(
!
utils
.
isFunction
(
fn
))
{
throw
new
Error
(
"createStep(): a step definition must be a function"
);
}
fn
.
options
=
utils
.
isType
(
options
,
"object"
)
?
options
:
{};
fn
.
options
=
utils
.
isObject
(
options
)
?
options
:
{};
this
.
emit
(
'casper.step.created'
,
fn
);
return
fn
;
},
};
/**
/**
* Logs the HTML code of the current page.
*
* @return Casper
*/
debugHTML
:
function
()
{
Casper
.
prototype
.
debugHTML
=
function
()
{
this
.
echo
(
this
.
evaluate
(
function
()
{
return
document
.
body
.
innerHTML
;
}));
return
this
;
},
};
/**
/**
* Logs the textual contents of the current page.
*
* @return Casper
*/
debugPage
:
function
()
{
Casper
.
prototype
.
debugPage
=
function
()
{
this
.
echo
(
this
.
evaluate
(
function
()
{
return
document
.
body
.
innerText
;
}));
return
this
;
},
};
/**
/**
* Exit phantom on failure, with a logged error message.
*
* @param String message An optional error message
* @param Number status An optional exit status code (must be > 0)
* @return Casper
*/
die
:
function
(
message
,
status
)
{
this
.
result
.
status
=
'error'
;
Casper
.
prototype
.
die
=
function
(
message
,
status
)
{
this
.
result
.
status
=
"error"
;
this
.
result
.
time
=
new
Date
().
getTime
()
-
this
.
startTime
;
message
=
utils
.
isType
(
message
,
"string"
)
&&
message
.
length
>
0
?
message
:
DEFAULT_DIE_MESSAGE
;
message
=
utils
.
isString
(
message
)
&&
message
.
length
>
0
?
message
:
DEFAULT_DIE_MESSAGE
;
this
.
log
(
message
,
"error"
);
if
(
utils
.
isType
(
this
.
options
.
onDie
,
"function"
))
{
this
.
emit
(
'casper.die'
,
message
,
status
);
if
(
utils
.
isFunction
(
this
.
options
.
onDie
))
{
this
.
options
.
onDie
.
call
(
this
,
this
,
message
,
status
);
}
return
this
.
exit
(
Number
(
status
)
>
0
?
Number
(
status
)
:
1
);
},
return
this
.
exit
(
~~
status
>
0
?
~~
status
:
1
);
};
/**
/**
* Downloads a resource and saves it on the filesystem.
*
* @param String url The url of the resource to download
* @param String targetPath The destination file path
* @return Casper
*/
download
:
function
(
url
,
targetPath
)
{
Casper
.
prototype
.
download
=
function
(
url
,
targetPath
)
{
var
cu
=
require
(
'clientutils'
).
create
();
try
{
fs
.
write
(
targetPath
,
cu
.
decode
(
this
.
base64encode
(
url
)),
'w'
);
...
...
@@ -303,18 +307,18 @@ Casper.prototype = {
this
.
log
(
"Error while downloading "
+
url
+
" to "
+
targetPath
+
": "
+
e
,
"error"
);
}
return
this
;
},
};
/**
/**
* Iterates over the values of a provided array and execute a callback
* for each
item.
* for @
item.
*
* @param Array array
* @param Function fn Callback: function(self, item, index)
* @return Casper
*/
each
:
function
(
array
,
fn
)
{
if
(
!
utils
.
isType
(
array
,
"array"
))
{
Casper
.
prototype
.
each
=
function
(
array
,
fn
)
{
if
(
!
utils
.
isArray
(
array
))
{
this
.
log
(
"each() only works with arrays"
,
"error"
);
return
this
;
}
...
...
@@ -324,20 +328,20 @@ Casper.prototype = {
});
})(
this
);
return
this
;
},
};
/**
/**
* Prints something to stdout.
*
* @param String text A string to echo to stdout
* @return Casper
*/
echo
:
function
(
text
,
style
)
{
Casper
.
prototype
.
echo
=
function
(
text
,
style
)
{
console
.
log
(
style
?
this
.
colorizer
.
colorize
(
text
,
style
)
:
text
);
return
this
;
},
};
/**
/**
* Evaluates an expression in the page context, a bit like what
* WebPage#evaluate does, but the passed function can also accept
* parameters if a context Object is also passed:
...
...
@@ -360,13 +364,13 @@ Casper.prototype = {
* @return mixed
* @see WebPage#evaluate
*/
evaluate
:
function
(
fn
,
context
)
{
context
=
utils
.
isType
(
context
,
"object"
)
?
context
:
{};
Casper
.
prototype
.
evaluate
=
function
(
fn
,
context
)
{
context
=
utils
.
isObject
(
context
)
?
context
:
{};
var
newFn
=
require
(
'injector'
).
create
(
fn
).
process
(
context
);
return
this
.
page
.
evaluate
(
newFn
);
},
};
/**
/**
* Evaluates an expression within the current page DOM and die() if it
* returns false.
*
...
...
@@ -374,27 +378,27 @@ Casper.prototype = {
* @param String message The error message to log
* @return Casper
*/
evaluateOrDie
:
function
(
fn
,
message
)
{
Casper
.
prototype
.
evaluateOrDie
=
function
(
fn
,
message
)
{
if
(
!
this
.
evaluate
(
fn
))
{
return
this
.
die
(
message
);
}
return
this
;
},
};
/**
/**
* Checks if an element matching the provided CSS3 selector exists in
* current page DOM.
*
* @param String selector A CSS3 selector
* @return Boolean
*/
exists
:
function
(
selector
)
{
Casper
.
prototype
.
exists
=
function
(
selector
)
{
return
this
.
evaluate
(
function
(
selector
)
{
return
__utils__
.
exists
(
selector
);
},
{
selector
:
selector
});
},
};
/**
/**
* Checks if an element matching the provided CSS3 selector is visible
* current page DOM by checking that offsetWidth and offsetHeight are
* both non-zero.
...
...
@@ -402,51 +406,53 @@ Casper.prototype = {
* @param String selector A CSS3 selector
* @return Boolean
*/
visible
:
function
(
selector
)
{
Casper
.
prototype
.
visible
=
function
(
selector
)
{
return
this
.
evaluate
(
function
(
selector
)
{
return
__utils__
.
visible
(
selector
);
},
{
selector
:
selector
});
},
};
/**
/**
* Exits phantom.
*
* @param Number status Status
* @return Casper
*/
exit
:
function
(
status
)
{
Casper
.
prototype
.
exit
=
function
(
status
)
{
this
.
emit
(
'casper.exit'
,
status
);
phantom
.
exit
(
status
);
return
this
;
},
};
/**
/**
* Fetches innerText within the element(s) matching a given CSS3
* selector.
*
* @param String selector A CSS3 selector
* @return String
*/
fetchText
:
function
(
selector
)
{
Casper
.
prototype
.
fetchText
=
function
(
selector
)
{
return
this
.
evaluate
(
function
(
selector
)
{
return
__utils__
.
fetchText
(
selector
);
},
{
selector
:
selector
});
},
};
/**
/**
* Fills a form with provided field values.
*
* @param String selector A CSS3 selector to the target form to fill
* @param Object vals Field values
* @param Boolean submit Submit the form?
*/
fill
:
function
(
selector
,
vals
,
submit
)
{
Casper
.
prototype
.
fill
=
function
(
selector
,
vals
,
submit
)
{
submit
=
submit
===
true
?
submit
:
false
;
if
(
!
utils
.
isType
(
selector
,
"string"
)
||
!
selector
.
length
)
{
if
(
!
utils
.
isString
(
selector
)
||
!
selector
.
length
)
{
throw
new
Error
(
"Form selector must be a non-empty string"
);
}
if
(
!
utils
.
isType
(
vals
,
"object"
))
{
if
(
!
utils
.
isObject
(
vals
))
{
throw
new
Error
(
"Form values must be provided as an object"
);
}
this
.
emit
(
'casper.fill'
,
selector
,
vals
,
submit
);
var
fillResults
=
this
.
evaluate
(
function
(
selector
,
values
)
{
return
__utils__
.
fill
(
selector
,
values
);
},
{
...
...
@@ -485,39 +491,40 @@ Casper.prototype = {
form
.
submit
();
},
{
selector
:
selector
});
}
},
};
/**
/**
* Go a step forward in browser's history
*
* @return Casper
*/
forward
:
function
(
then
)
{
return
this
.
then
(
function
(
self
)
{
self
.
evaluate
(
function
()
{
Casper
.
prototype
.
forward
=
function
(
then
)
{
return
this
.
then
(
function
()
{
this
.
emit
(
'casper.forward'
);
this
.
evaluate
(
function
()
{
history
.
forward
();
});
});
},
};
/**
/**
* Retrieves current document url.
*
* @return String
*/
getCurrentUrl
:
function
()
{
Casper
.
prototype
.
getCurrentUrl
=
function
()
{
return
decodeURIComponent
(
this
.
evaluate
(
function
()
{
return
document
.
location
.
href
;
}));
},
};
/**
/**
* Retrieves boundaries for a DOM element matching the provided CSS3 selector.
*
* @param String selector A CSS3 selector
* @return Object
*/
getElementBounds
:
function
(
selector
)
{
Casper
.
prototype
.
getElementBounds
=
function
(
selector
)
{
if
(
!
this
.
exists
(
selector
))
{
throw
new
Error
(
"No element matching selector found: "
+
selector
);
}
...
...
@@ -528,15 +535,15 @@ Casper.prototype = {
throw
new
Error
(
'Could not fetch boundaries for element matching selector: '
+
selector
);
}
return
clipRect
;
},
};
/**
/**
* Retrieves global variable.
*
* @param String name The name of the global variable to retrieve
* @return mixed
*/
getGlobal
:
function
(
name
)
{
Casper
.
prototype
.
getGlobal
=
function
(
name
)
{
var
result
=
this
.
evaluate
(
function
(
name
)
{
var
result
=
{};
try
{
...
...
@@ -550,25 +557,25 @@ Casper.prototype = {
},
{
'name'
:
name
});
if
(
'error'
in
result
)
{
throw
new
Error
(
result
.
error
);
}
else
if
(
utils
.
isType
(
result
.
value
,
"string"
))
{
}
else
if
(
utils
.
isString
(
result
.
value
))
{
return
JSON
.
parse
(
result
.
value
);
}
else
{
return
undefined
;
}
},
};
/**
/**
* Retrieves current page title, if any.
*
* @return String
*/
getTitle
:
function
()
{
Casper
.
prototype
.
getTitle
=
function
()
{
return
this
.
evaluate
(
function
()
{
return
document
.
title
;
});
},
};
/**
/**
* Logs a message.
*
* @param String message The message to log
...
...
@@ -576,10 +583,10 @@ Casper.prototype = {
* @param String space Space from where the logged event occured (default: "phantom")
* @return Casper
*/
log
:
function
(
message
,
level
,
space
)
{
Casper
.
prototype
.
log
=
function
(
message
,
level
,
space
)
{
level
=
level
&&
this
.
logLevels
.
indexOf
(
level
)
>
-
1
?
level
:
"debug"
;
space
=
space
?
space
:
"phantom"
;
if
(
level
===
"error"
&&
utils
.
isType
(
this
.
options
.
onError
,
"function"
))
{
if
(
level
===
"error"
&&
utils
.
isFunction
(
this
.
options
.
onError
))
{
this
.
options
.
onError
.
call
(
this
,
this
,
message
,
space
);
}
if
(
this
.
logLevels
.
indexOf
(
level
)
<
this
.
logLevels
.
indexOf
(
this
.
options
.
logLevel
))
{
...
...
@@ -591,7 +598,7 @@ Casper.prototype = {
message
:
message
,
date
:
new
Date
().
toString
()
};
if
(
level
in
this
.
logFormats
&&
utils
.
isType
(
this
.
logFormats
[
level
],
"function"
))
{
if
(
level
in
this
.
logFormats
&&
utils
.
isFunction
(
this
.
logFormats
[
level
]
))
{
message
=
this
.
logFormats
[
level
](
message
,
level
,
space
);
}
else
{
var
levelStr
=
this
.
colorizer
.
colorize
(
'['
+
level
+
']'
,
this
.
logStyles
[
level
]);
...
...
@@ -601,22 +608,23 @@ Casper.prototype = {
this
.
echo
(
message
);
// direct output
}
this
.
result
.
log
.
push
(
entry
);
this
.
emit
(
'casper.log'
,
entry
);
return
this
;
},
};
/**
/**
* Emulates a click on an HTML element matching a given CSS3 selector,
* using the mouse pointer.
*
* @param String selector A DOM CSS3 compatible selector
* @return Casper
*/
mouseClick
:
function
(
selector
)
{
Casper
.
prototype
.
mouseClick
=
function
(
selector
)
{
this
.
mouse
.
click
(
selector
);
return
this
;
},
};
/**
/**
* Opens a page. Takes only one argument, the url to open (using the
* callback argument would defeat the whole purpose of Casper
* actually).
...
...
@@ -624,19 +632,25 @@ Casper.prototype = {
* @param String location The url to open
* @return Casper
*/
open
:
function
(
location
,
options
)
{
options
=
utils
.
isType
(
options
,
"object"
)
?
options
:
{};
Casper
.
prototype
.
open
=
function
(
location
,
options
)
{
options
=
utils
.
isObject
(
options
)
?
options
:
{};
this
.
requestUrl
=
location
;
// http auth
var
httpAuthMatch
=
location
.
match
(
/^https
?
:
\/\/(
.+
)
:
(
.+
)
@/i
);
if
(
httpAuthMatch
)
{
this
.
setHttpAuth
(
httpAuthMatch
[
1
],
httpAuthMatch
[
2
]);
var
httpAuth
=
{
username
:
httpAuthMatch
[
1
],
password
:
httpAuthMatch
[
2
]
};
this
.
emit
(
'casper.http.auth'
,
httpAuth
);
this
.
setHttpAuth
(
httpAuth
.
username
,
httpAuth
.
password
);
}
this
.
emit
(
'casper.open'
,
location
);
this
.
page
.
open
(
location
);
return
this
;
},
};
/**
/**
* Repeats a step a given number of times.
*
* @param Number times Number of times to repeat step
...
...
@@ -644,22 +658,22 @@ Casper.prototype = {
* @return Casper
* @see Casper#then
*/
repeat
:
function
(
times
,
then
)
{
Casper
.
prototype
.
repeat
=
function
(
times
,
then
)
{
for
(
var
i
=
0
;
i
<
times
;
i
++
)
{
this
.
then
(
then
);
}
return
this
;
},
};
/**
/**
* Checks if a given resource was loaded by the remote page.
*
* @param Function/String test A test function or string. In case a string is passed, url matching will be tested.
* @return Boolean
*/
resourceExists
:
function
(
test
)
{
Casper
.
prototype
.
resourceExists
=
function
(
test
)
{
var
testFn
;
if
(
utils
.
isType
(
test
,
"string"
))
{
if
(
utils
.
isString
(
test
))
{
testFn
=
function
(
res
)
{
return
res
.
url
.
search
(
test
)
!==
-
1
;
};
...
...
@@ -667,42 +681,44 @@ Casper.prototype = {
testFn
=
test
;
}
return
this
.
resources
.
some
(
testFn
);
},
};
/**
/**
* Runs the whole suite of steps.
*
* @param function onComplete an optional callback
* @param Number time an optional amount of milliseconds for interval checking
* @return Casper
*/
run
:
function
(
onComplete
,
time
)
{
Casper
.
prototype
.
run
=
function
(
onComplete
,
time
)
{
if
(
!
this
.
steps
||
this
.
steps
.
length
<
1
)
{
this
.
log
(
"No steps defined, aborting"
,
"error"
);
return
this
;
}
this
.
log
(
"Running suite: "
+
this
.
steps
.
length
+
" step"
+
(
this
.
steps
.
length
>
1
?
"s"
:
""
),
"info"
);
this
.
emit
(
'casper.run'
);
this
.
checker
=
setInterval
(
this
.
checkStep
,
(
time
?
time
:
250
),
this
,
onComplete
);
return
this
;
},
};
/**
/**
* Runs a step.
*
* @param Function step
*/
runStep
:
function
(
step
)
{
var
skipLog
=
utils
.
isType
(
step
.
options
,
"object"
)
&&
step
.
options
.
skipLog
===
true
;
Casper
.
prototype
.
runStep
=
function
(
step
)
{
var
skipLog
=
utils
.
isObject
(
step
.
options
)
&&
step
.
options
.
skipLog
===
true
;
var
stepInfo
=
"Step "
+
(
this
.
step
)
+
"/"
+
this
.
steps
.
length
;
var
stepResult
;
if
(
!
skipLog
)
{
this
.
log
(
stepInfo
+
' '
+
this
.
getCurrentUrl
()
+
' (HTTP '
+
this
.
currentHTTPStatus
+
')'
,
"info"
);
}
if
(
utils
.
isType
(
this
.
options
.
stepTimeout
,
"number"
)
&&
this
.
options
.
stepTimeout
>
0
)
{
if
(
utils
.
isNumber
(
this
.
options
.
stepTimeout
)
&&
this
.
options
.
stepTimeout
>
0
)
{
var
stepTimeoutCheckInterval
=
setInterval
(
function
(
self
,
start
,
stepNum
)
{
if
(
new
Date
().
getTime
()
-
start
>
self
.
options
.
stepTimeout
)
{
if
(
self
.
step
==
stepNum
)
{
if
(
utils
.
isType
(
self
.
options
.
onStepTimeout
,
"function"
))
{
self
.
emit
(
'casper.step.timeout'
);
if
(
utils
.
isFunction
(
self
.
options
.
onStepTimeout
))
{
self
.
options
.
onStepTimeout
.
call
(
self
,
self
);
}
else
{
self
.
die
(
"Maximum step execution timeout exceeded for step "
+
stepNum
,
"error"
);
...
...
@@ -712,6 +728,7 @@ Casper.prototype = {
}
},
this
.
options
.
stepTimeout
,
this
,
new
Date
().
getTime
(),
this
.
step
);
}
this
.
emit
(
'casper.step.start'
,
step
);
try
{
stepResult
=
step
.
call
(
this
,
this
);
}
catch
(
e
)
{
...
...
@@ -721,42 +738,44 @@ Casper.prototype = {
throw
e
;
}
}
if
(
utils
.
isType
(
this
.
options
.
onStepComplete
,
"function"
))
{
if
(
utils
.
isFunction
(
this
.
options
.
onStepComplete
))
{
this
.
options
.
onStepComplete
.
call
(
this
,
this
,
stepResult
);
}
if
(
!
skipLog
)
{
this
.
emit
(
'casper.step.complete'
,
stepResult
);
this
.
log
(
stepInfo
+
": done in "
+
(
new
Date
().
getTime
()
-
this
.
startTime
)
+
"ms."
,
"info"
);
}
},
};
/**
/**
* Sets HTTP authentication parameters.
*
* @param String username The HTTP_AUTH_USER value
* @param String password The HTTP_AUTH_PW value
* @return Casper
*/
setHttpAuth
:
function
(
username
,
password
)
{
Casper
.
prototype
.
setHttpAuth
=
function
(
username
,
password
)
{
if
(
!
this
.
started
)
{
throw
new
Error
(
"Casper must be started in order to use the setHttpAuth() method"
);
}
if
(
!
utils
.
isType
(
username
,
"string"
)
||
!
utils
.
isType
(
password
,
"string"
))
{
if
(
!
utils
.
isString
(
username
)
||
!
utils
.
isString
(
password
))
{
throw
new
Error
(
"Both username and password must be strings"
);
}
this
.
page
.
settings
.
userName
=
username
;
this
.
page
.
settings
.
password
=
password
;
this
.
log
(
"Setting HTTP authentication for user "
+
username
,
"info"
);
return
this
;
},
};
/**
/**
* Configures and starts Casper.
*
* @param String location An optional location to open on start
* @param function then Next step function to execute on page loaded (optional)
* @return Casper
*/
start
:
function
(
location
,
then
)
{
Casper
.
prototype
.
start
=
function
(
location
,
then
)
{
this
.
emit
(
'casper.starting'
);
this
.
log
(
'Starting...'
,
"info"
);
this
.
startTime
=
new
Date
().
getTime
();
this
.
history
=
[];
...
...
@@ -776,46 +795,49 @@ Casper.prototype = {
}
}
this
.
page
.
settings
=
utils
.
mergeObjects
(
this
.
page
.
settings
,
this
.
options
.
pageSettings
);
if
(
utils
.
isType
(
this
.
options
.
clipRect
,
"object"
))
{
if
(
utils
.
isClipRect
(
this
.
options
.
clipRect
))
{
this
.
page
.
clipRect
=
this
.
options
.
clipRect
;
}
if
(
utils
.
isType
(
this
.
options
.
viewportSize
,
"object"
))
{
if
(
utils
.
isObject
(
this
.
options
.
viewportSize
))
{
this
.
page
.
viewportSize
=
this
.
options
.
viewportSize
;
}
this
.
started
=
true
;
if
(
utils
.
isType
(
this
.
options
.
timeout
,
"number"
)
&&
this
.
options
.
timeout
>
0
)
{
this
.
emit
(
'casper.started'
);
if
(
utils
.
isNumber
(
this
.
options
.
timeout
)
&&
this
.
options
.
timeout
>
0
)
{
this
.
log
(
"Execution timeout set to "
+
this
.
options
.
timeout
+
'ms'
,
"info"
);
setTimeout
(
function
(
self
)
{
if
(
utils
.
isType
(
self
.
options
.
onTimeout
,
"function"
))
{
self
.
emit
(
'casper.timeout'
);
if
(
utils
.
isFunction
(
self
.
options
.
onTimeout
))
{
self
.
options
.
onTimeout
.
call
(
self
,
self
);
}
else
{
self
.
die
(
"Timeout of "
+
self
.
options
.
timeout
+
"ms exceeded, exiting."
);
}
},
this
.
options
.
timeout
,
this
);
}
if
(
utils
.
isType
(
this
.
options
.
onPageInitialized
,
"function"
))
{
casper
.
emit
(
'casper.page.initialized'
);
if
(
utils
.
isFunction
(
this
.
options
.
onPageInitialized
))
{
this
.
log
(
"Post-configuring WebPage instance"
,
"debug"
);
this
.
options
.
onPageInitialized
.
call
(
this
,
this
.
page
);
}
if
(
utils
.
isType
(
location
,
"string"
)
&&
location
.
length
>
0
)
{
return
this
.
thenOpen
(
location
,
utils
.
isType
(
then
,
"function"
)
?
then
:
this
.
createStep
(
function
(
self
)
{
if
(
utils
.
isString
(
location
)
&&
location
.
length
>
0
)
{
return
this
.
thenOpen
(
location
,
utils
.
isFunction
(
then
)
?
then
:
this
.
createStep
(
function
(
self
)
{
self
.
log
(
"start page is loaded"
,
"debug"
);
}));
}
return
this
;
},
};
/**
/**
* Schedules the next step in the navigation process.
*
* @param function step A function to be called as a step
* @return Casper
*/
then
:
function
(
step
)
{
Casper
.
prototype
.
then
=
function
(
step
)
{
if
(
!
this
.
started
)
{
throw
new
Error
(
"Casper not started; please use Casper#start"
);
}
if
(
!
utils
.
isType
(
step
,
"function"
))
{
if
(
!
utils
.
isFunction
(
step
))
{
throw
new
Error
(
"You can only define a step as a function"
);
}
// check if casper is running
...
...
@@ -836,10 +858,11 @@ Casper.prototype = {
}
this
.
steps
.
splice
(
insertIndex
,
0
,
step
);
}
this
.
emit
(
'casper.step.added'
,
step
);
return
this
;
},
};
/**
/**
* Adds a new navigation step for clicking on a provided link selector
* and execute an optional next step.
*
...
...
@@ -850,14 +873,14 @@ Casper.prototype = {
* @see Casper#click
* @see Casper#then
*/
thenClick
:
function
(
selector
,
then
,
fallbackToHref
)
{
Casper
.
prototype
.
thenClick
=
function
(
selector
,
then
,
fallbackToHref
)
{
this
.
then
(
function
(
self
)
{
self
.
click
(
selector
,
fallbackToHref
);
});
return
utils
.
isType
(
then
,
"function"
)
?
this
.
then
(
then
)
:
this
;
},
return
utils
.
isFunction
(
then
)
?
this
.
then
(
then
)
:
this
;
};
/**
/**
* Adds a new navigation step to perform code evaluation within the
* current retrieved page DOM.
*
...
...
@@ -866,13 +889,13 @@ Casper.prototype = {
* @return Casper
* @see Casper#evaluate
*/
thenEvaluate
:
function
(
fn
,
context
)
{
Casper
.
prototype
.
thenEvaluate
=
function
(
fn
,
context
)
{
return
this
.
then
(
function
(
self
)
{
self
.
evaluate
(
fn
,
context
);
});
},
};
/**
/**
* Adds a new navigation step for opening the provided location.
*
* @param String location The URL to load
...
...
@@ -880,16 +903,16 @@ Casper.prototype = {
* @return Casper
* @see Casper#open
*/
thenOpen
:
function
(
location
,
then
)
{
Casper
.
prototype
.
thenOpen
=
function
(
location
,
then
)
{
this
.
then
(
this
.
createStep
(
function
(
self
)
{
self
.
open
(
location
);
},
{
skipLog
:
true
}));
return
utils
.
isType
(
then
,
"function"
)
?
this
.
then
(
then
)
:
this
;
},
return
utils
.
isFunction
(
then
)
?
this
.
then
(
then
)
:
this
;
};
/**
/**
* Adds a new navigation step for opening and evaluate an expression
* against the DOM retrieved from the provided location.
*
...
...
@@ -900,32 +923,33 @@ Casper.prototype = {
* @see Casper#evaluate
* @see Casper#open
*/
thenOpenAndEvaluate
:
function
(
location
,
fn
,
context
)
{
Casper
.
prototype
.
thenOpenAndEvaluate
=
function
(
location
,
fn
,
context
)
{
return
this
.
thenOpen
(
location
).
thenEvaluate
(
fn
,
context
);
},
};
/**
/**
* Changes the current viewport size.
*
* @param Number width The viewport width, in pixels
* @param Number height The viewport height, in pixels
* @return Casper
*/
viewport
:
function
(
width
,
height
)
{
Casper
.
prototype
.
viewport
=
function
(
width
,
height
)
{
if
(
!
this
.
started
)
{
throw
new
Error
(
"Casper must be started in order to set viewport at runtime"
);
}
if
(
!
utils
.
isType
(
width
,
"number"
)
||
!
utils
.
isType
(
height
,
"number"
)
||
width
<=
0
||
height
<=
0
)
{
if
(
!
utils
.
isNumber
(
width
)
||
!
utils
.
isNumber
(
height
)
||
width
<=
0
||
height
<=
0
)
{
throw
new
Error
(
"Invalid viewport width/height set: "
+
width
+
'x'
+
height
);
}
this
.
page
.
viewportSize
=
{
width
:
width
,
height
:
height
};
this
.
emit
(
'casper.viewport.changed'
,
[
width
,
height
]);
return
this
;
},
};
/**
/**
* Adds a new step that will wait for a given amount of time (expressed
* in milliseconds) before processing an optional next one.
*
...
...
@@ -933,12 +957,12 @@ Casper.prototype = {
* @param Function then Next step to process (optional)
* @return Casper
*/
wait
:
function
(
timeout
,
then
)
{
Casper
.
prototype
.
wait
=
function
(
timeout
,
then
)
{
timeout
=
Number
(
timeout
,
10
);
if
(
!
utils
.
isType
(
timeout
,
"number"
)
||
timeout
<
1
)
{
if
(
!
utils
.
isNumber
(
timeout
)
||
timeout
<
1
)
{
this
.
die
(
"wait() only accepts a positive integer > 0 as a timeout value"
);
}
if
(
then
&&
!
utils
.
isType
(
then
,
"function"
))
{
if
(
then
&&
!
utils
.
isFunction
(
then
))
{
this
.
die
(
"wait() a step definition must be a function"
);
}
return
this
.
then
(
function
(
self
)
{
...
...
@@ -951,17 +975,19 @@ Casper.prototype = {
self
.
waitDone
();
},
timeout
);
});
},
};
waitStart
:
function
()
{
Casper
.
prototype
.
waitStart
=
function
()
{
this
.
emit
(
'casper.wait.start'
);
this
.
pendingWait
=
true
;
},
};
waitDone
:
function
()
{
Casper
.
prototype
.
waitDone
=
function
()
{
this
.
emit
(
'casper.wait.done'
);
this
.
pendingWait
=
false
;
},
};
/**
/**
* Waits until a function returns true to process a next step.
*
* @param Function testFx A function to be evaluated for returning condition satisfecit
...
...
@@ -970,12 +996,12 @@ Casper.prototype = {
* @param Number timeout The max amount of time to wait, in milliseconds (optional)
* @return Casper
*/
waitFor
:
function
(
testFx
,
then
,
onTimeout
,
timeout
)
{
Casper
.
prototype
.
waitFor
=
function
(
testFx
,
then
,
onTimeout
,
timeout
)
{
timeout
=
timeout
?
timeout
:
this
.
defaultWaitTimeout
;
if
(
!
utils
.
isType
(
testFx
,
"function"
))
{
if
(
!
utils
.
isFunction
(
testFx
))
{
this
.
die
(
"waitFor() needs a test function"
);
}
if
(
then
&&
!
utils
.
isType
(
then
,
"function"
))
{
if
(
then
&&
!
utils
.
isFunction
(
then
))
{
this
.
die
(
"waitFor() next step definition must be a function"
);
}
return
this
.
then
(
function
(
self
)
{
...
...
@@ -989,7 +1015,8 @@ Casper.prototype = {
self
.
waitDone
();
if
(
!
condition
)
{
self
.
log
(
"Casper.waitFor() timeout"
,
"warning"
);
if
(
utils
.
isType
(
onTimeout
,
"function"
))
{
self
.
emit
(
'casper.waitFor.timeout'
);
if
(
utils
.
isFunction
(
onTimeout
))
{
onTimeout
.
call
(
self
,
self
);
}
else
{
self
.
die
(
"Timeout of "
+
timeout
+
"ms expired, exiting."
,
"error"
);
...
...
@@ -1005,9 +1032,9 @@ Casper.prototype = {
}
},
100
,
self
,
testFx
,
timeout
,
onTimeout
);
});
},
};
/**
/**
* Waits until a given resource is loaded
*
* @param String/Function test A function to test if the resource exists. A string will be matched against the resources url.
...
...
@@ -1016,14 +1043,14 @@ Casper.prototype = {
* @param Number timeout The max amount of time to wait, in milliseconds (optional)
* @return Casper
*/
waitForResource
:
function
(
test
,
then
,
onTimeout
,
timeout
)
{
Casper
.
prototype
.
waitForResource
=
function
(
test
,
then
,
onTimeout
,
timeout
)
{
timeout
=
timeout
?
timeout
:
this
.
defaultWaitTimeout
;
return
this
.
waitFor
(
function
(
self
)
{
return
self
.
resourceExists
(
test
);
},
then
,
onTimeout
,
timeout
);
},
};
/**
/**
* Waits until an element matching the provided CSS3 selector exists in
* remote DOM to process a next step.
*
...
...
@@ -1033,14 +1060,14 @@ Casper.prototype = {
* @param Number timeout The max amount of time to wait, in milliseconds (optional)
* @return Casper
*/
waitForSelector
:
function
(
selector
,
then
,
onTimeout
,
timeout
)
{
Casper
.
prototype
.
waitForSelector
=
function
(
selector
,
then
,
onTimeout
,
timeout
)
{
timeout
=
timeout
?
timeout
:
this
.
defaultWaitTimeout
;
return
this
.
waitFor
(
function
(
self
)
{
return
self
.
exists
(
selector
);
},
then
,
onTimeout
,
timeout
);
},
};
/**
/**
* Waits until an element matching the provided CSS3 selector does not
* exist in the remote DOM to process a next step.
*
...
...
@@ -1050,14 +1077,14 @@ Casper.prototype = {
* @param Number timeout The max amount of time to wait, in milliseconds (optional)
* @return Casper
*/
waitWhileSelector
:
function
(
selector
,
then
,
onTimeout
,
timeout
)
{
Casper
.
prototype
.
waitWhileSelector
=
function
(
selector
,
then
,
onTimeout
,
timeout
)
{
timeout
=
timeout
?
timeout
:
this
.
defaultWaitTimeout
;
return
this
.
waitFor
(
function
(
self
)
{
return
!
self
.
exists
(
selector
);
},
then
,
onTimeout
,
timeout
);
},
};
/**
/**
* Waits until an element matching the provided CSS3 selector is
* visible in the remote DOM to process a next step.
*
...
...
@@ -1067,14 +1094,14 @@ Casper.prototype = {
* @param Number timeout The max amount of time to wait, in milliseconds (optional)
* @return Casper
*/
waitUntilVisible
:
function
(
selector
,
then
,
onTimeout
,
timeout
)
{
Casper
.
prototype
.
waitUntilVisible
=
function
(
selector
,
then
,
onTimeout
,
timeout
)
{
timeout
=
timeout
?
timeout
:
this
.
defaultWaitTimeout
;
return
this
.
waitFor
(
function
(
self
)
{
return
self
.
visible
(
selector
);
},
then
,
onTimeout
,
timeout
);
},
};
/**
/**
* Waits until an element matching the provided CSS3 selector is no
* longer visible in remote DOM to process a next step.
*
...
...
@@ -1084,12 +1111,11 @@ Casper.prototype = {
* @param Number timeout The max amount of time to wait, in milliseconds (optional)
* @return Casper
*/
waitWhileVisible
:
function
(
selector
,
then
,
onTimeout
,
timeout
)
{
Casper
.
prototype
.
waitWhileVisible
=
function
(
selector
,
then
,
onTimeout
,
timeout
)
{
timeout
=
timeout
?
timeout
:
this
.
defaultWaitTimeout
;
return
this
.
waitFor
(
function
(
self
)
{
return
!
self
.
visible
(
selector
);
},
then
,
onTimeout
,
timeout
);
}
};
/**
...
...
@@ -1098,7 +1124,7 @@ Casper.prototype = {
* @param Object proto Prototype methods to add to Casper
*/
Casper
.
extend
=
function
(
proto
)
{
if
(
!
utils
.
is
Type
(
proto
,
"object"
))
{
if
(
!
utils
.
is
Object
(
proto
))
{
throw
new
Error
(
"extends() only accept objects as prototypes"
);
}
utils
.
mergeObjects
(
Casper
.
prototype
,
proto
);
...
...
@@ -1114,14 +1140,15 @@ exports.Casper = Casper;
*/
function
createPage
(
casper
)
{
var
page
;
if
(
phantom
.
version
.
major
<=
1
&&
phantom
.
version
.
minor
<
3
&&
utils
.
is
Type
(
require
,
"function"
))
{
if
(
phantom
.
version
.
major
<=
1
&&
phantom
.
version
.
minor
<
3
&&
utils
.
is
Function
(
require
))
{
page
=
new
WebPage
();
}
else
{
page
=
require
(
'webpage'
).
create
();
}
page
.
onAlert
=
function
(
message
)
{
casper
.
log
(
'[alert] '
+
message
,
"info"
,
"remote"
);
if
(
utils
.
isType
(
casper
.
options
.
onAlert
,
"function"
))
{
casper
.
emit
(
'casper.remote.alert'
,
message
);
if
(
utils
.
isFunction
(
casper
.
options
.
onAlert
))
{
casper
.
options
.
onAlert
.
call
(
casper
,
casper
,
message
);
}
};
...
...
@@ -1132,25 +1159,32 @@ function createPage(casper) {
msg
=
test
[
2
];
}
casper
.
log
(
msg
,
level
,
"remote"
);
casper
.
emit
(
'casper.remote.message'
,
msg
);
};
page
.
onLoadStarted
=
function
()
{
casper
.
resources
=
[];
casper
.
loadInProgress
=
true
;
casper
.
resources
=
[];
casper
.
emit
(
'casper.load.started'
);
};
page
.
onLoadFinished
=
function
(
status
)
{
if
(
status
!==
"success"
)
{
casper
.
emit
(
'casper.load.failed'
,
{
status
:
status
,
http_status
:
casper
.
currentHTTPStatus
,
url
:
casper
.
requestUrl
});
var
message
=
'Loading resource failed with status='
+
status
;
if
(
casper
.
currentHTTPStatus
)
{
message
+=
' (HTTP '
+
casper
.
currentHTTPStatus
+
')'
;
}
message
+=
': '
+
casper
.
requestUrl
;
casper
.
log
(
message
,
"warning"
);
if
(
utils
.
is
Type
(
casper
.
options
.
onLoadError
,
"function"
))
{
if
(
utils
.
is
Function
(
casper
.
options
.
onLoadError
))
{
casper
.
options
.
onLoadError
.
call
(
casper
,
casper
,
casper
.
requestUrl
,
status
);
}
}
if
(
casper
.
options
.
clientScripts
)
{
if
(
!
utils
.
is
Type
(
casper
.
options
.
clientScripts
,
"array"
))
{
if
(
!
utils
.
is
Array
(
casper
.
options
.
clientScripts
))
{
casper
.
log
(
"The clientScripts option must be an array"
,
"error"
);
}
else
{
for
(
var
i
=
0
;
i
<
casper
.
options
.
clientScripts
.
length
;
i
++
)
{
...
...
@@ -1172,10 +1206,12 @@ function createPage(casper) {
}
// history
casper
.
history
.
push
(
casper
.
getCurrentUrl
());
casper
.
emit
(
'casper.load.finished'
,
status
);
casper
.
loadInProgress
=
false
;
};
page
.
onResourceReceived
=
function
(
resource
)
{
if
(
utils
.
isType
(
casper
.
options
.
onResourceReceived
,
"function"
))
{
casper
.
emit
(
'casper.resource.received'
,
resource
);
if
(
utils
.
isFunction
(
casper
.
options
.
onResourceReceived
))
{
casper
.
options
.
onResourceReceived
.
call
(
casper
,
casper
,
resource
);
}
if
(
resource
.
stage
===
"end"
)
{
...
...
@@ -1183,18 +1219,21 @@ function createPage(casper) {
}
if
(
resource
.
url
===
casper
.
requestUrl
&&
resource
.
stage
===
"start"
)
{
casper
.
currentHTTPStatus
=
resource
.
status
;
if
(
utils
.
isType
(
casper
.
options
.
httpStatusHandlers
,
"object"
)
&&
casper
.
emit
(
'casper.http.status.'
+
resource
.
status
,
resource
);
if
(
utils
.
isObject
(
casper
.
options
.
httpStatusHandlers
)
&&
resource
.
status
in
casper
.
options
.
httpStatusHandlers
&&
utils
.
is
Type
(
casper
.
options
.
httpStatusHandlers
[
resource
.
status
],
"function"
))
{
utils
.
is
Function
(
casper
.
options
.
httpStatusHandlers
[
resource
.
status
]
))
{
casper
.
options
.
httpStatusHandlers
[
resource
.
status
].
call
(
casper
,
casper
,
resource
);
}
casper
.
currentUrl
=
resource
.
url
;
}
};
page
.
onResourceRequested
=
function
(
request
)
{
if
(
utils
.
isType
(
casper
.
options
.
onResourceRequested
,
"function"
))
{
casper
.
emit
(
'casper.resource.requested'
,
request
);
if
(
utils
.
isFunction
(
casper
.
options
.
onResourceRequested
))
{
casper
.
options
.
onResourceRequested
.
call
(
casper
,
casper
,
request
);
}
};
casper
.
emit
(
'casper.page.created'
,
page
);
return
page
;
}
...
...
modules/utils.js
View file @
0d0e962
...
...
@@ -70,7 +70,7 @@ function fileExt(file) {
exports
.
fileExt
=
fileExt
;
/**
* Takes a string and append blank until the pad value is reached.
* Takes a string and append blank
s
until the pad value is reached.
*
* @param String text
* @param Number pad Pad value (optional; default: 80)
...
...
@@ -85,8 +85,14 @@ function fillBlanks(text, pad) {
}
exports
.
fillBlanks
=
fillBlanks
;
/**
* Checks if value is a javascript Array
*
* @param mixed value
* @return Boolean
*/
function
isArray
(
value
)
{
return
isType
(
value
,
"array"
);
return
Array
.
isArray
(
value
)
||
isType
(
value
,
"array"
);
}
exports
.
isArray
=
isArray
;
...
...
@@ -101,17 +107,27 @@ function isCasperObject(value) {
}
exports
.
isCasperObject
=
isCasperObject
;
/**
* Checks if value is a phantomjs clipRect-compatible object
*
* @param mixed value
* @return Boolean
*/
function
isClipRect
(
value
)
{
return
isType
(
value
,
"cliprect"
)
||
(
isType
(
value
,
"object"
)
&&
isType
(
value
.
top
,
"number"
)
&&
isType
(
value
.
left
,
"number"
)
&&
isType
(
value
.
width
,
"number"
)
&&
isType
(
value
.
height
,
"number"
)
isObject
(
value
)
&&
isNumber
(
value
.
top
)
&&
isNumber
(
value
.
left
)
&&
isNumber
(
value
.
width
)
&&
isNumber
(
value
.
height
)
);
}
exports
.
isClipRect
=
isClipRect
;
/**
* Checks if value is a javascript Function
*
* @param mixed value
* @return Boolean
*/
function
isFunction
(
value
)
{
return
isType
(
value
,
"function"
);
}
...
...
@@ -125,15 +141,38 @@ exports.isFunction = isFunction;
*/
function
isJsFile
(
file
)
{
var
ext
=
fileExt
(
file
);
return
is
Type
(
ext
,
"string"
)
&&
[
'js'
,
'coffee'
].
indexOf
(
ext
)
!==
-
1
;
return
is
String
(
ext
,
"string"
)
&&
[
'js'
,
'coffee'
].
indexOf
(
ext
)
!==
-
1
;
}
exports
.
isJsFile
=
isJsFile
;
/**
* Checks if value is a javascript Number
*
* @param mixed value
* @return Boolean
*/
function
isNumber
(
value
)
{
return
isType
(
value
,
"number"
);
}
exports
.
isNumber
=
isNumber
;
/**
* Checks if value is a javascript Object
*
* @param mixed value
* @return Boolean
*/
function
isObject
(
value
)
{
return
isType
(
value
,
"object"
);
}
exports
.
isObject
=
isObject
;
/**
* Checks if value is a javascript String
*
* @param mixed value
* @return Boolean
*/
function
isString
(
value
)
{
return
isType
(
value
,
"string"
);
}
...
...
@@ -148,7 +187,10 @@ exports.isString = isString;
* @return Boolean
*/
function
isType
(
what
,
typeName
)
{
return
betterTypeOf
(
what
)
===
typeName
;
if
(
typeof
typeName
!==
"string"
||
!
typeName
)
{
throw
new
Error
(
"You must pass isType() a typeName string"
);
}
return
betterTypeOf
(
what
).
toLowerCase
()
===
typeName
.
toLowerCase
();
}
exports
.
isType
=
isType
;
...
...
@@ -159,10 +201,10 @@ exports.isType = isType;
* @return Boolean
*/
function
isWebPage
(
what
)
{
if
(
!
what
||
!
is
Type
(
what
,
"object"
))
{
if
(
!
what
||
!
is
Object
(
what
))
{
return
false
;
}
if
(
phantom
.
version
.
major
<=
1
&&
phantom
.
version
.
minor
<
3
&&
is
Type
(
require
,
"function"
))
{
if
(
phantom
.
version
.
major
<=
1
&&
phantom
.
version
.
minor
<
3
&&
is
Function
(
require
))
{
return
what
instanceof
WebPage
;
}
else
{
return
what
.
toString
().
indexOf
(
'WebPage('
)
===
0
;
...
...
@@ -202,9 +244,34 @@ exports.mergeObjects = mergeObjects;
function
serialize
(
value
)
{
if
(
isType
(
value
,
"array"
))
{
value
=
value
.
map
(
function
(
prop
)
{
return
is
Type
(
prop
,
"function"
)
?
prop
.
toString
().
replace
(
/
\s{2,}
/
,
''
)
:
prop
;
return
is
Function
(
prop
)
?
prop
.
toString
().
replace
(
/
\s{2,}
/
,
''
)
:
prop
;
});
}
return
JSON
.
stringify
(
value
,
null
,
4
);
}
exports
.
serialize
=
serialize
;
/**
* Inherit the prototype methods from one constructor into another.
*
* The Function.prototype.inherits from lang.js rewritten as a standalone
* function (not on Function.prototype). NOTE: If this file is to be loaded
* during bootstrapping this function needs to be revritten using some native
* functions as prototype setup using normal JavaScript does not work as
* expected during bootstrapping (see mirror.js in r114903).
*
* @param {function} ctor Constructor function which needs to inherit the
* prototype.
* @param {function} superCtor Constructor function to inherit prototype from.
*/
exports
.
inherits
=
function
(
ctor
,
superCtor
)
{
ctor
.
super_
=
superCtor
;
ctor
.
prototype
=
Object
.
create
(
superCtor
.
prototype
,
{
constructor
:
{
value
:
ctor
,
enumerable
:
false
,
writable
:
true
,
configurable
:
true
}
});
};
...
...
Please
register
or
sign in
to post a comment