Merge pull request #2312 from tschaub/test-deps
Move test dependencies out of the repo.
This commit is contained in:
@@ -21,12 +21,17 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"closure-util": "0.19.0",
|
||||
"expect.js": "~0.3.1",
|
||||
"fs-extra": "~0.8.1",
|
||||
"graceful-fs": "~3.0.2",
|
||||
"jquery": "~2.1.1",
|
||||
"jsdoc": "~3.3.0-alpha7",
|
||||
"jshint": "~2.5.1",
|
||||
"mocha": "~1.20.1",
|
||||
"mocha-phantomjs": "~3.5.0",
|
||||
"nomnom": "~1.6.2",
|
||||
"phantomjs": "~1.9.7-5",
|
||||
"sinon": "~1.10.2",
|
||||
"taffydb": "~2.7.0",
|
||||
"temp": "~0.7.0",
|
||||
"underscore": "~1.6.0",
|
||||
|
||||
@@ -55,7 +55,8 @@ serve.createServer(function(err, server) {
|
||||
var address = server.address();
|
||||
var url = 'http://' + address.address + ':' + address.port;
|
||||
var args = [
|
||||
path.join(__dirname, '..', 'test', 'mocha-phantomjs.js'),
|
||||
path.join(__dirname,
|
||||
'../node_modules/mocha-phantomjs/lib/mocha-phantomjs.coffee'),
|
||||
url + '/test/index.html'
|
||||
];
|
||||
|
||||
|
||||
@@ -1,41 +1,33 @@
|
||||
Included in this directory
|
||||
--------------------------
|
||||
## Included in this directory
|
||||
|
||||
- ol.html - the web page used to run the test suite.
|
||||
- index.html - the web page used to run the test suite.
|
||||
|
||||
- spec - includes the OpenLayers test/spec files.
|
||||
|
||||
- expect-0.2.0 - Minimalistic BDD-style assertion framework.
|
||||
https://github.com/LearnBoost/expect.js/
|
||||
|
||||
- jquery-1.9.1 - The Write Less, Do More, JavaScript Library.
|
||||
http://jquery.com/
|
||||
|
||||
- mocha-1.8.1 - the fun, simple, flexible JavaScript test framework.
|
||||
http://visionmedia.github.com/mocha/
|
||||
|
||||
- sinon-1.6.0 - Standalone test spies, stubs and mocks for JavaScript.
|
||||
http://sinonjs.org/
|
||||
|
||||
- test-extensions.js - includes OpenLayers-specific extensions to the
|
||||
testing frameworks.
|
||||
|
||||
- mocha-phantom - a PhantomJS script for headless testing with mocha.
|
||||
http://metaskills.net/mocha-phantomjs/
|
||||
|
||||
Run the test suite with PhantomJS
|
||||
---------------------------------
|
||||
## Run the test suite
|
||||
|
||||
With PhantomJS installed, and assuming phantomjs is in the PATH:
|
||||
Install the test dependencies (from the root of the repository):
|
||||
|
||||
$ phantomjs mocha-phantom.coffee ol.html
|
||||
npm install
|
||||
|
||||
(Works with PhantomJS 1.6.1, untested with other versions.)
|
||||
Run the tests once with PhantomJS:
|
||||
|
||||
This command can also be run by doing `./build.py test` at the root of ol3.
|
||||
./build.py test
|
||||
|
||||
Make sure that the polvr web server is running (`./build.py serve`), otherwise
|
||||
you will most likely see something like `0 specs, 0 failures in 0.001s.`.
|
||||
(Note that for `npm` users, this can also be run as `npm test`.)
|
||||
|
||||
Run the tests in a browser:
|
||||
|
||||
./build.py serve
|
||||
|
||||
(Again for `npm` users, this is `npm start`.)
|
||||
|
||||
Now visit http://localhost:3000/test/ in your browser. The tests will re-run
|
||||
any time one of the source or spec files changes.
|
||||
|
||||
Tip for TDD'ers: to make PhantomJS run the test suite continuously each time
|
||||
a spec file is changed you can use nosier (http://pypi.python.org/pypi/nosier)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -3,17 +3,16 @@
|
||||
<head>
|
||||
<title>OL Spec Runner</title>
|
||||
<meta charset="utf-8">
|
||||
<link rel="stylesheet" type="text/css" href="mocha-1.8.1/mocha.css">
|
||||
<link rel="stylesheet" type="text/css" href="../node_modules/mocha/mocha.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="mocha"></div>
|
||||
|
||||
<script type="text/javascript" src="jquery-1.9.1/jquery.min.js"></script>
|
||||
<!-- Extended expect.js w/ various methods, see #374 for the differences to 0.2.0 -->
|
||||
<script type="text/javascript" src="expect-0.2.0-ol3/expect.js"></script>
|
||||
<script type="text/javascript" src="sinon-1.6.0/sinon.js"></script>
|
||||
<script type="text/javascript" src="mocha-1.8.1/mocha.js"></script>
|
||||
<script type="text/javascript" src="../node_modules/jquery/dist/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="../node_modules/expect.js/index.js"></script>
|
||||
<script type="text/javascript" src="../node_modules/sinon/pkg/sinon.js"></script>
|
||||
<script type="text/javascript" src="../node_modules/mocha/mocha.js"></script>
|
||||
<script type="text/javascript" src="test-extensions.js"></script>
|
||||
<script>
|
||||
mocha.setup({
|
||||
|
||||
5
test/jquery-1.9.1/jquery.min.js
vendored
5
test/jquery-1.9.1/jquery.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -1,22 +0,0 @@
|
||||
(The MIT License)
|
||||
|
||||
Copyright (c) 2011-2013 TJ Holowaychuk <tj@vision-media.ca>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
'Software'), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
@@ -1,231 +0,0 @@
|
||||
@charset "utf-8";
|
||||
|
||||
body {
|
||||
font: 20px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
padding: 60px 50px;
|
||||
}
|
||||
|
||||
#mocha ul, #mocha li {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#mocha ul {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
#mocha h1, #mocha h2 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#mocha h1 {
|
||||
margin-top: 15px;
|
||||
font-size: 1em;
|
||||
font-weight: 200;
|
||||
}
|
||||
|
||||
#mocha h1 a {
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
#mocha h1 a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
#mocha .suite .suite h1 {
|
||||
margin-top: 0;
|
||||
font-size: .8em;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#mocha h2 {
|
||||
font-size: 12px;
|
||||
font-weight: normal;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#mocha .suite {
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
#mocha .test {
|
||||
margin-left: 15px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#mocha .test.pending:hover h2::after {
|
||||
content: '(pending)';
|
||||
font-family: arial;
|
||||
}
|
||||
|
||||
#mocha .test.pass.medium .duration {
|
||||
background: #C09853;
|
||||
}
|
||||
|
||||
#mocha .test.pass.slow .duration {
|
||||
background: #B94A48;
|
||||
}
|
||||
|
||||
#mocha .test.pass::before {
|
||||
content: '✓';
|
||||
font-size: 12px;
|
||||
display: block;
|
||||
float: left;
|
||||
margin-right: 5px;
|
||||
color: #00d6b2;
|
||||
}
|
||||
|
||||
#mocha .test.pass .duration {
|
||||
font-size: 9px;
|
||||
margin-left: 5px;
|
||||
padding: 2px 5px;
|
||||
color: white;
|
||||
-webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
|
||||
-moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
|
||||
box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
|
||||
-webkit-border-radius: 5px;
|
||||
-moz-border-radius: 5px;
|
||||
-ms-border-radius: 5px;
|
||||
-o-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
#mocha .test.pass.fast .duration {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#mocha .test.pending {
|
||||
color: #0b97c4;
|
||||
}
|
||||
|
||||
#mocha .test.pending::before {
|
||||
content: '◦';
|
||||
color: #0b97c4;
|
||||
}
|
||||
|
||||
#mocha .test.fail {
|
||||
color: #c00;
|
||||
}
|
||||
|
||||
#mocha .test.fail pre {
|
||||
color: black;
|
||||
}
|
||||
|
||||
#mocha .test.fail::before {
|
||||
content: '✖';
|
||||
font-size: 12px;
|
||||
display: block;
|
||||
float: left;
|
||||
margin-right: 5px;
|
||||
color: #c00;
|
||||
}
|
||||
|
||||
#mocha .test pre.error {
|
||||
color: #c00;
|
||||
max-height: 300px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
#mocha .test pre {
|
||||
display: block;
|
||||
float: left;
|
||||
clear: left;
|
||||
font: 12px/1.5 monaco, monospace;
|
||||
margin: 5px;
|
||||
padding: 15px;
|
||||
border: 1px solid #eee;
|
||||
border-bottom-color: #ddd;
|
||||
-webkit-border-radius: 3px;
|
||||
-webkit-box-shadow: 0 1px 3px #eee;
|
||||
-moz-border-radius: 3px;
|
||||
-moz-box-shadow: 0 1px 3px #eee;
|
||||
}
|
||||
|
||||
#mocha .test h2 {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#mocha .test a.replay {
|
||||
position: absolute;
|
||||
top: 3px;
|
||||
right: 0;
|
||||
text-decoration: none;
|
||||
vertical-align: middle;
|
||||
display: block;
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
line-height: 15px;
|
||||
text-align: center;
|
||||
background: #eee;
|
||||
font-size: 15px;
|
||||
-moz-border-radius: 15px;
|
||||
border-radius: 15px;
|
||||
-webkit-transition: opacity 200ms;
|
||||
-moz-transition: opacity 200ms;
|
||||
transition: opacity 200ms;
|
||||
opacity: 0.3;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
#mocha .test:hover a.replay {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
#mocha-report.pass .test.fail {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#mocha-report.fail .test.pass {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#mocha-error {
|
||||
color: #c00;
|
||||
font-size: 1.5 em;
|
||||
font-weight: 100;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
#mocha-stats {
|
||||
position: fixed;
|
||||
top: 15px;
|
||||
right: 10px;
|
||||
font-size: 12px;
|
||||
margin: 0;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
#mocha-stats .progress {
|
||||
float: right;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
#mocha-stats em {
|
||||
color: black;
|
||||
}
|
||||
|
||||
#mocha-stats a {
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
#mocha-stats a:hover {
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
#mocha-stats li {
|
||||
display: inline-block;
|
||||
margin: 0 5px;
|
||||
list-style: none;
|
||||
padding-top: 11px;
|
||||
}
|
||||
|
||||
code .comment { color: #ddd }
|
||||
code .init { color: #2F6FAD }
|
||||
code .string { color: #5890AD }
|
||||
code .keyword { color: #8A6343 }
|
||||
code .number { color: #2F6FAD }
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,261 +0,0 @@
|
||||
system = require 'system'
|
||||
webpage = require 'webpage'
|
||||
|
||||
USAGE = """
|
||||
Usage: phantomjs mocha-phantomjs.coffee URL REPORTER [CONFIG]
|
||||
"""
|
||||
|
||||
class Reporter
|
||||
|
||||
constructor: (@reporter, @config) ->
|
||||
@url = system.args[1]
|
||||
@columns = parseInt(system.env.COLUMNS or 75) * .75 | 0
|
||||
@mochaStarted = false
|
||||
@mochaStartWait = @config.timeout || 6000
|
||||
@startTime = Date.now()
|
||||
@fail(USAGE) unless @url
|
||||
|
||||
run: ->
|
||||
@initPage()
|
||||
@loadPage()
|
||||
|
||||
# Subclass Hooks
|
||||
|
||||
customizeRunner: (options) ->
|
||||
undefined
|
||||
|
||||
customizeProcessStdout: (options) ->
|
||||
undefined
|
||||
|
||||
customizeConsole: (options) ->
|
||||
undefined
|
||||
|
||||
customizeOptions: ->
|
||||
columns: @columns
|
||||
|
||||
# Private
|
||||
|
||||
fail: (msg, errno) ->
|
||||
console.log msg if msg
|
||||
phantom.exit errno || 1
|
||||
|
||||
finish: ->
|
||||
phantom.exit @page.evaluate -> mochaPhantomJS.failures
|
||||
|
||||
initPage: ->
|
||||
@page = webpage.create
|
||||
settings: @config.settings
|
||||
@page.customHeaders = @config.headers if @config.headers
|
||||
for name, value of @config.cookies
|
||||
@page.addCookie
|
||||
name: name
|
||||
value: value
|
||||
@page.viewportSize = @config.viewportSize if @config.viewportSize
|
||||
@page.onConsoleMessage = (msg) -> console.log msg
|
||||
@page.onInitialized = =>
|
||||
@page.evaluate ->
|
||||
window.mochaPhantomJS =
|
||||
failures: 0
|
||||
ended: false
|
||||
started: false
|
||||
run: ->
|
||||
mochaPhantomJS.started = true
|
||||
window.callPhantom 'mochaPhantomJS.run'
|
||||
|
||||
loadPage: ->
|
||||
@page.open @url
|
||||
@page.onLoadFinished = (status) =>
|
||||
@page.onLoadFinished = ->
|
||||
@onLoadFailed() if status isnt 'success'
|
||||
@waitForInitMocha()
|
||||
@page.onCallback = (data) =>
|
||||
if data is 'mochaPhantomJS.run'
|
||||
@waitForRunMocha() if @injectJS()
|
||||
|
||||
onLoadFailed: ->
|
||||
@fail "Failed to load the page. Check the url: #{@url}"
|
||||
|
||||
injectJS: ->
|
||||
if @page.evaluate(-> window.mocha?)
|
||||
@page.injectJs 'mocha-phantomjs/core_extensions.js'
|
||||
@page.evaluate @customizeProcessStdout, @customizeOptions()
|
||||
@page.evaluate @customizeConsole, @customizeOptions()
|
||||
true
|
||||
else
|
||||
@fail "Failed to find mocha on the page."
|
||||
false
|
||||
|
||||
runMocha: ->
|
||||
if @config.useColors is false then @page.evaluate -> Mocha.reporters.Base.useColors = false
|
||||
@page.evaluate @runner, @reporter
|
||||
@mochaStarted = @page.evaluate -> mochaPhantomJS.runner or false
|
||||
if @mochaStarted
|
||||
@mochaRunAt = new Date().getTime()
|
||||
@page.evaluate @customizeRunner, @customizeOptions()
|
||||
@waitForMocha()
|
||||
else
|
||||
@fail "Failed to start mocha."
|
||||
|
||||
waitForMocha: =>
|
||||
ended = @page.evaluate -> mochaPhantomJS.ended
|
||||
if ended then @finish() else setTimeout @waitForMocha, 100
|
||||
|
||||
waitForInitMocha: =>
|
||||
setTimeout @waitForInitMocha, 100 unless @checkStarted()
|
||||
|
||||
waitForRunMocha: =>
|
||||
if @checkStarted() then @runMocha() else setTimeout @waitForRunMocha, 100
|
||||
|
||||
checkStarted: =>
|
||||
started = @page.evaluate -> mochaPhantomJS.started
|
||||
if !started && @mochaStartWait && @startTime + @mochaStartWait < Date.now()
|
||||
@fail "Failed to start mocha: Init timeout", 255
|
||||
started
|
||||
|
||||
runner: (reporter) ->
|
||||
try
|
||||
mocha.setup reporter: reporter
|
||||
mochaPhantomJS.runner = mocha.run()
|
||||
if mochaPhantomJS.runner
|
||||
cleanup = ->
|
||||
mochaPhantomJS.failures = mochaPhantomJS.runner.failures
|
||||
mochaPhantomJS.ended = true
|
||||
if mochaPhantomJS.runner?.stats?.end
|
||||
cleanup()
|
||||
else
|
||||
mochaPhantomJS.runner.on 'end', cleanup
|
||||
catch error
|
||||
false
|
||||
|
||||
class Spec extends Reporter
|
||||
|
||||
constructor: (config) ->
|
||||
super 'spec', config
|
||||
|
||||
customizeProcessStdout: (options) ->
|
||||
process.stdout.write = (string) ->
|
||||
return if string is process.cursor.deleteLine or string is process.cursor.beginningOfLine
|
||||
console.log string
|
||||
|
||||
customizeConsole: (options) ->
|
||||
process.cursor.CRMatcher = /\s+◦\s\S/
|
||||
process.cursor.CRCleaner = process.cursor.up + process.cursor.deleteLine
|
||||
origLog = console.log
|
||||
console.log = ->
|
||||
string = console.format.apply(console, arguments)
|
||||
if string.match(process.cursor.CRMatcher)
|
||||
process.cursor.CRCleanup = true
|
||||
else if process.cursor.CRCleanup
|
||||
string = process.cursor.CRCleaner + string
|
||||
process.cursor.CRCleanup = false
|
||||
origLog.call console, string
|
||||
|
||||
class Dot extends Reporter
|
||||
|
||||
constructor: (config) ->
|
||||
super 'dot', config
|
||||
|
||||
customizeProcessStdout: (options) ->
|
||||
process.cursor.margin = 2
|
||||
process.cursor.CRMatcher = /\u001b\[\d\dm\․\u001b\[0m/
|
||||
process.stdout.columns = options.columns
|
||||
process.stdout.allowedFirstNewLine = false
|
||||
process.stdout.write = (string) ->
|
||||
if string is '\n '
|
||||
unless process.stdout.allowedFirstNewLine
|
||||
process.stdout.allowedFirstNewLine = true
|
||||
else
|
||||
return
|
||||
else if string.match(process.cursor.CRMatcher)
|
||||
if process.cursor.count is process.stdout.columns
|
||||
process.cursor.count = 0
|
||||
forward = process.cursor.margin
|
||||
string = process.cursor.forwardN(forward) + string
|
||||
else
|
||||
forward = process.cursor.margin + process.cursor.count
|
||||
string = process.cursor.up + process.cursor.forwardN(forward) + string
|
||||
++process.cursor.count
|
||||
console.log string
|
||||
|
||||
class Tap extends Reporter
|
||||
|
||||
constructor: (config) ->
|
||||
super 'tap', config
|
||||
|
||||
class List extends Reporter
|
||||
|
||||
constructor: (config) ->
|
||||
super 'list', config
|
||||
|
||||
customizeProcessStdout: (options) ->
|
||||
process.stdout.write = (string) ->
|
||||
return if string is process.cursor.deleteLine or string is process.cursor.beginningOfLine
|
||||
console.log string
|
||||
|
||||
customizeProcessStdout: (options) ->
|
||||
process.cursor.CRMatcher = /\u001b\[90m.*:\s\u001b\[0m/
|
||||
process.cursor.CRCleaner = (string) -> process.cursor.up + process.cursor.deleteLine + string + process.cursor.up + process.cursor.up
|
||||
origLog = console.log
|
||||
console.log = ->
|
||||
string = console.format.apply(console, arguments)
|
||||
if string.match /\u001b\[32m\s\s-\u001b\[0m/
|
||||
string = string
|
||||
process.cursor.CRCleanup = false
|
||||
if string.match(process.cursor.CRMatcher)
|
||||
process.cursor.CRCleanup = true
|
||||
else if process.cursor.CRCleanup
|
||||
string = process.cursor.CRCleaner(string)
|
||||
process.cursor.CRCleanup = false
|
||||
origLog.call console, string
|
||||
|
||||
class Min extends Reporter
|
||||
|
||||
constructor: (config) ->
|
||||
super 'min', config
|
||||
|
||||
class Doc extends Reporter
|
||||
|
||||
constructor: (config) ->
|
||||
super 'doc', config
|
||||
|
||||
class Teamcity extends Reporter
|
||||
|
||||
constructor: (config) ->
|
||||
super 'teamcity', config
|
||||
|
||||
class Xunit extends Reporter
|
||||
|
||||
constructor: (config) ->
|
||||
super 'xunit', config
|
||||
|
||||
class Json extends Reporter
|
||||
|
||||
constructor: (config) ->
|
||||
super 'json', config
|
||||
|
||||
class JsonCov extends Reporter
|
||||
|
||||
constructor: (config) ->
|
||||
super 'json-cov', config
|
||||
|
||||
class HtmlCov extends Reporter
|
||||
|
||||
constructor: (config) ->
|
||||
super 'html-cov', config
|
||||
|
||||
|
||||
reporterString = system.args[2] || 'spec'
|
||||
reporterString = ("#{s.charAt(0).toUpperCase()}#{s.slice(1)}" for s in reporterString.split('-')).join('')
|
||||
reporterKlass = try
|
||||
eval(reporterString)
|
||||
catch error
|
||||
undefined
|
||||
|
||||
config = JSON.parse(system.args[3] || '{}')
|
||||
|
||||
if reporterKlass
|
||||
reporter = new reporterKlass config
|
||||
reporter.run()
|
||||
else
|
||||
console.log "Reporter class not implemented: #{reporterString}"
|
||||
phantom.exit 1
|
||||
@@ -1,468 +0,0 @@
|
||||
// Generated by CoffeeScript 1.6.3
|
||||
(function() {
|
||||
var Doc, Dot, HtmlCov, Json, JsonCov, List, Min, Reporter, Spec, Tap, Teamcity, USAGE, Xunit, config, error, reporter, reporterKlass, reporterString, s, system, webpage,
|
||||
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
|
||||
__hasProp = {}.hasOwnProperty,
|
||||
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
||||
|
||||
system = require('system');
|
||||
|
||||
webpage = require('webpage');
|
||||
|
||||
USAGE = "Usage: phantomjs mocha-phantomjs.coffee URL REPORTER [CONFIG]";
|
||||
|
||||
Reporter = (function() {
|
||||
function Reporter(reporter, config) {
|
||||
this.reporter = reporter;
|
||||
this.config = config;
|
||||
this.checkStarted = __bind(this.checkStarted, this);
|
||||
this.waitForRunMocha = __bind(this.waitForRunMocha, this);
|
||||
this.waitForInitMocha = __bind(this.waitForInitMocha, this);
|
||||
this.waitForMocha = __bind(this.waitForMocha, this);
|
||||
this.url = system.args[1];
|
||||
this.columns = parseInt(system.env.COLUMNS || 75) * .75 | 0;
|
||||
this.mochaStarted = false;
|
||||
this.mochaStartWait = this.config.timeout || 6000;
|
||||
this.startTime = Date.now();
|
||||
if (!this.url) {
|
||||
this.fail(USAGE);
|
||||
}
|
||||
}
|
||||
|
||||
Reporter.prototype.run = function() {
|
||||
this.initPage();
|
||||
return this.loadPage();
|
||||
};
|
||||
|
||||
Reporter.prototype.customizeRunner = function(options) {
|
||||
return void 0;
|
||||
};
|
||||
|
||||
Reporter.prototype.customizeProcessStdout = function(options) {
|
||||
return void 0;
|
||||
};
|
||||
|
||||
Reporter.prototype.customizeConsole = function(options) {
|
||||
return void 0;
|
||||
};
|
||||
|
||||
Reporter.prototype.customizeOptions = function() {
|
||||
return {
|
||||
columns: this.columns
|
||||
};
|
||||
};
|
||||
|
||||
Reporter.prototype.fail = function(msg, errno) {
|
||||
if (msg) {
|
||||
console.log(msg);
|
||||
}
|
||||
return phantom.exit(errno || 1);
|
||||
};
|
||||
|
||||
Reporter.prototype.finish = function() {
|
||||
return phantom.exit(this.page.evaluate(function() {
|
||||
return mochaPhantomJS.failures;
|
||||
}));
|
||||
};
|
||||
|
||||
Reporter.prototype.initPage = function() {
|
||||
var name, value, _ref,
|
||||
_this = this;
|
||||
this.page = webpage.create({
|
||||
settings: this.config.settings
|
||||
});
|
||||
if (this.config.headers) {
|
||||
this.page.customHeaders = this.config.headers;
|
||||
}
|
||||
_ref = this.config.cookies;
|
||||
for (name in _ref) {
|
||||
value = _ref[name];
|
||||
this.page.addCookie({
|
||||
name: name,
|
||||
value: value
|
||||
});
|
||||
}
|
||||
if (this.config.viewportSize) {
|
||||
this.page.viewportSize = this.config.viewportSize;
|
||||
}
|
||||
this.page.onConsoleMessage = function(msg) {
|
||||
return console.log(msg);
|
||||
};
|
||||
return this.page.onInitialized = function() {
|
||||
return _this.page.evaluate(function() {
|
||||
return window.mochaPhantomJS = {
|
||||
failures: 0,
|
||||
ended: false,
|
||||
started: false,
|
||||
run: function() {
|
||||
mochaPhantomJS.started = true;
|
||||
return window.callPhantom('mochaPhantomJS.run');
|
||||
}
|
||||
};
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
Reporter.prototype.loadPage = function() {
|
||||
var _this = this;
|
||||
this.page.open(this.url);
|
||||
this.page.onLoadFinished = function(status) {
|
||||
_this.page.onLoadFinished = function() {};
|
||||
if (status !== 'success') {
|
||||
_this.onLoadFailed();
|
||||
}
|
||||
return _this.waitForInitMocha();
|
||||
};
|
||||
return this.page.onCallback = function(data) {
|
||||
if (data === 'mochaPhantomJS.run') {
|
||||
if (_this.injectJS()) {
|
||||
return _this.waitForRunMocha();
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
Reporter.prototype.onLoadFailed = function() {
|
||||
return this.fail("Failed to load the page. Check the url: " + this.url);
|
||||
};
|
||||
|
||||
Reporter.prototype.injectJS = function() {
|
||||
if (this.page.evaluate(function() {
|
||||
return window.mocha != null;
|
||||
})) {
|
||||
this.page.injectJs('mocha-phantomjs/core_extensions.js');
|
||||
this.page.evaluate(this.customizeProcessStdout, this.customizeOptions());
|
||||
this.page.evaluate(this.customizeConsole, this.customizeOptions());
|
||||
return true;
|
||||
} else {
|
||||
this.fail("Failed to find mocha on the page.");
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
Reporter.prototype.runMocha = function() {
|
||||
if (this.config.useColors === false) {
|
||||
this.page.evaluate(function() {
|
||||
return Mocha.reporters.Base.useColors = false;
|
||||
});
|
||||
}
|
||||
this.page.evaluate(this.runner, this.reporter);
|
||||
this.mochaStarted = this.page.evaluate(function() {
|
||||
return mochaPhantomJS.runner || false;
|
||||
});
|
||||
if (this.mochaStarted) {
|
||||
this.mochaRunAt = new Date().getTime();
|
||||
this.page.evaluate(this.customizeRunner, this.customizeOptions());
|
||||
return this.waitForMocha();
|
||||
} else {
|
||||
return this.fail("Failed to start mocha.");
|
||||
}
|
||||
};
|
||||
|
||||
Reporter.prototype.waitForMocha = function() {
|
||||
var ended;
|
||||
ended = this.page.evaluate(function() {
|
||||
return mochaPhantomJS.ended;
|
||||
});
|
||||
if (ended) {
|
||||
return this.finish();
|
||||
} else {
|
||||
return setTimeout(this.waitForMocha, 100);
|
||||
}
|
||||
};
|
||||
|
||||
Reporter.prototype.waitForInitMocha = function() {
|
||||
if (!this.checkStarted()) {
|
||||
return setTimeout(this.waitForInitMocha, 100);
|
||||
}
|
||||
};
|
||||
|
||||
Reporter.prototype.waitForRunMocha = function() {
|
||||
if (this.checkStarted()) {
|
||||
return this.runMocha();
|
||||
} else {
|
||||
return setTimeout(this.waitForRunMocha, 100);
|
||||
}
|
||||
};
|
||||
|
||||
Reporter.prototype.checkStarted = function() {
|
||||
var started;
|
||||
started = this.page.evaluate(function() {
|
||||
return mochaPhantomJS.started;
|
||||
});
|
||||
if (!started && this.mochaStartWait && this.startTime + this.mochaStartWait < Date.now()) {
|
||||
this.fail("Failed to start mocha: Init timeout", 255);
|
||||
}
|
||||
return started;
|
||||
};
|
||||
|
||||
Reporter.prototype.runner = function(reporter) {
|
||||
var cleanup, error, _ref, _ref1;
|
||||
try {
|
||||
mocha.setup({
|
||||
reporter: reporter
|
||||
});
|
||||
mochaPhantomJS.runner = mocha.run();
|
||||
if (mochaPhantomJS.runner) {
|
||||
cleanup = function() {
|
||||
mochaPhantomJS.failures = mochaPhantomJS.runner.failures;
|
||||
return mochaPhantomJS.ended = true;
|
||||
};
|
||||
if ((_ref = mochaPhantomJS.runner) != null ? (_ref1 = _ref.stats) != null ? _ref1.end : void 0 : void 0) {
|
||||
return cleanup();
|
||||
} else {
|
||||
return mochaPhantomJS.runner.on('end', cleanup);
|
||||
}
|
||||
}
|
||||
} catch (_error) {
|
||||
error = _error;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
return Reporter;
|
||||
|
||||
})();
|
||||
|
||||
Spec = (function(_super) {
|
||||
__extends(Spec, _super);
|
||||
|
||||
function Spec(config) {
|
||||
Spec.__super__.constructor.call(this, 'spec', config);
|
||||
}
|
||||
|
||||
Spec.prototype.customizeProcessStdout = function(options) {
|
||||
return process.stdout.write = function(string) {
|
||||
if (string === process.cursor.deleteLine || string === process.cursor.beginningOfLine) {
|
||||
return;
|
||||
}
|
||||
return console.log(string);
|
||||
};
|
||||
};
|
||||
|
||||
Spec.prototype.customizeConsole = function(options) {
|
||||
var origLog;
|
||||
process.cursor.CRMatcher = /\s+◦\s\S/;
|
||||
process.cursor.CRCleaner = process.cursor.up + process.cursor.deleteLine;
|
||||
origLog = console.log;
|
||||
return console.log = function() {
|
||||
var string;
|
||||
string = console.format.apply(console, arguments);
|
||||
if (string.match(process.cursor.CRMatcher)) {
|
||||
process.cursor.CRCleanup = true;
|
||||
} else if (process.cursor.CRCleanup) {
|
||||
string = process.cursor.CRCleaner + string;
|
||||
process.cursor.CRCleanup = false;
|
||||
}
|
||||
return origLog.call(console, string);
|
||||
};
|
||||
};
|
||||
|
||||
return Spec;
|
||||
|
||||
})(Reporter);
|
||||
|
||||
Dot = (function(_super) {
|
||||
__extends(Dot, _super);
|
||||
|
||||
function Dot(config) {
|
||||
Dot.__super__.constructor.call(this, 'dot', config);
|
||||
}
|
||||
|
||||
Dot.prototype.customizeProcessStdout = function(options) {
|
||||
process.cursor.margin = 2;
|
||||
process.cursor.CRMatcher = /\u001b\[\d\dm\․\u001b\[0m/;
|
||||
process.stdout.columns = options.columns;
|
||||
process.stdout.allowedFirstNewLine = false;
|
||||
return process.stdout.write = function(string) {
|
||||
var forward;
|
||||
if (string === '\n ') {
|
||||
if (!process.stdout.allowedFirstNewLine) {
|
||||
process.stdout.allowedFirstNewLine = true;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else if (string.match(process.cursor.CRMatcher)) {
|
||||
if (process.cursor.count === process.stdout.columns) {
|
||||
process.cursor.count = 0;
|
||||
forward = process.cursor.margin;
|
||||
string = process.cursor.forwardN(forward) + string;
|
||||
} else {
|
||||
forward = process.cursor.margin + process.cursor.count;
|
||||
string = process.cursor.up + process.cursor.forwardN(forward) + string;
|
||||
}
|
||||
++process.cursor.count;
|
||||
}
|
||||
return console.log(string);
|
||||
};
|
||||
};
|
||||
|
||||
return Dot;
|
||||
|
||||
})(Reporter);
|
||||
|
||||
Tap = (function(_super) {
|
||||
__extends(Tap, _super);
|
||||
|
||||
function Tap(config) {
|
||||
Tap.__super__.constructor.call(this, 'tap', config);
|
||||
}
|
||||
|
||||
return Tap;
|
||||
|
||||
})(Reporter);
|
||||
|
||||
List = (function(_super) {
|
||||
__extends(List, _super);
|
||||
|
||||
function List(config) {
|
||||
List.__super__.constructor.call(this, 'list', config);
|
||||
}
|
||||
|
||||
List.prototype.customizeProcessStdout = function(options) {
|
||||
return process.stdout.write = function(string) {
|
||||
if (string === process.cursor.deleteLine || string === process.cursor.beginningOfLine) {
|
||||
return;
|
||||
}
|
||||
return console.log(string);
|
||||
};
|
||||
};
|
||||
|
||||
List.prototype.customizeProcessStdout = function(options) {
|
||||
var origLog;
|
||||
process.cursor.CRMatcher = /\u001b\[90m.*:\s\u001b\[0m/;
|
||||
process.cursor.CRCleaner = function(string) {
|
||||
return process.cursor.up + process.cursor.deleteLine + string + process.cursor.up + process.cursor.up;
|
||||
};
|
||||
origLog = console.log;
|
||||
return console.log = function() {
|
||||
var string;
|
||||
string = console.format.apply(console, arguments);
|
||||
if (string.match(/\u001b\[32m\s\s-\u001b\[0m/)) {
|
||||
string = string;
|
||||
process.cursor.CRCleanup = false;
|
||||
}
|
||||
if (string.match(process.cursor.CRMatcher)) {
|
||||
process.cursor.CRCleanup = true;
|
||||
} else if (process.cursor.CRCleanup) {
|
||||
string = process.cursor.CRCleaner(string);
|
||||
process.cursor.CRCleanup = false;
|
||||
}
|
||||
return origLog.call(console, string);
|
||||
};
|
||||
};
|
||||
|
||||
return List;
|
||||
|
||||
})(Reporter);
|
||||
|
||||
Min = (function(_super) {
|
||||
__extends(Min, _super);
|
||||
|
||||
function Min(config) {
|
||||
Min.__super__.constructor.call(this, 'min', config);
|
||||
}
|
||||
|
||||
return Min;
|
||||
|
||||
})(Reporter);
|
||||
|
||||
Doc = (function(_super) {
|
||||
__extends(Doc, _super);
|
||||
|
||||
function Doc(config) {
|
||||
Doc.__super__.constructor.call(this, 'doc', config);
|
||||
}
|
||||
|
||||
return Doc;
|
||||
|
||||
})(Reporter);
|
||||
|
||||
Teamcity = (function(_super) {
|
||||
__extends(Teamcity, _super);
|
||||
|
||||
function Teamcity(config) {
|
||||
Teamcity.__super__.constructor.call(this, 'teamcity', config);
|
||||
}
|
||||
|
||||
return Teamcity;
|
||||
|
||||
})(Reporter);
|
||||
|
||||
Xunit = (function(_super) {
|
||||
__extends(Xunit, _super);
|
||||
|
||||
function Xunit(config) {
|
||||
Xunit.__super__.constructor.call(this, 'xunit', config);
|
||||
}
|
||||
|
||||
return Xunit;
|
||||
|
||||
})(Reporter);
|
||||
|
||||
Json = (function(_super) {
|
||||
__extends(Json, _super);
|
||||
|
||||
function Json(config) {
|
||||
Json.__super__.constructor.call(this, 'json', config);
|
||||
}
|
||||
|
||||
return Json;
|
||||
|
||||
})(Reporter);
|
||||
|
||||
JsonCov = (function(_super) {
|
||||
__extends(JsonCov, _super);
|
||||
|
||||
function JsonCov(config) {
|
||||
JsonCov.__super__.constructor.call(this, 'json-cov', config);
|
||||
}
|
||||
|
||||
return JsonCov;
|
||||
|
||||
})(Reporter);
|
||||
|
||||
HtmlCov = (function(_super) {
|
||||
__extends(HtmlCov, _super);
|
||||
|
||||
function HtmlCov(config) {
|
||||
HtmlCov.__super__.constructor.call(this, 'html-cov', config);
|
||||
}
|
||||
|
||||
return HtmlCov;
|
||||
|
||||
})(Reporter);
|
||||
|
||||
reporterString = system.args[2] || 'spec';
|
||||
|
||||
reporterString = ((function() {
|
||||
var _i, _len, _ref, _results;
|
||||
_ref = reporterString.split('-');
|
||||
_results = [];
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
s = _ref[_i];
|
||||
_results.push("" + (s.charAt(0).toUpperCase()) + (s.slice(1)));
|
||||
}
|
||||
return _results;
|
||||
})()).join('');
|
||||
|
||||
reporterKlass = (function() {
|
||||
try {
|
||||
return eval(reporterString);
|
||||
} catch (_error) {
|
||||
error = _error;
|
||||
return void 0;
|
||||
}
|
||||
})();
|
||||
|
||||
config = JSON.parse(system.args[3] || '{}');
|
||||
|
||||
if (reporterKlass) {
|
||||
reporter = new reporterKlass(config);
|
||||
reporter.run();
|
||||
} else {
|
||||
console.log("Reporter class not implemented: " + reporterString);
|
||||
phantom.exit(1);
|
||||
}
|
||||
|
||||
}).call(this);
|
||||
@@ -1,86 +0,0 @@
|
||||
(function(){
|
||||
|
||||
// A shim for non ES5 supporting browsers, like PhantomJS. Lovingly inspired by:
|
||||
// http://www.angrycoding.com/2011/09/to-bind-or-not-to-bind-that-is-in.html
|
||||
if (!('bind' in Function.prototype)) {
|
||||
Function.prototype.bind = function() {
|
||||
var funcObj = this;
|
||||
var extraArgs = Array.prototype.slice.call(arguments);
|
||||
var thisObj = extraArgs.shift();
|
||||
return function() {
|
||||
return funcObj.apply(thisObj, extraArgs.concat(Array.prototype.slice.call(arguments)));
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
// Mocha needs process.stdout.write in order to change the cursor position. However,
|
||||
// PhantomJS console.log always puts a new line character when logging and no STDOUT or
|
||||
// stream access is available, outside writing to /dev/stdout, etc. To work around
|
||||
// this, runner classes typically override `process.stdout.write` as needed to simulate
|
||||
// write to standard out using cursor commands.
|
||||
process.cursor = {
|
||||
count: 0,
|
||||
margin: 0,
|
||||
buffer: '',
|
||||
CRCleanup: false,
|
||||
CRMatcher: undefined,
|
||||
CRCleaner: undefined,
|
||||
hide: '\u001b[?25l',
|
||||
show: '\u001b[?25h',
|
||||
deleteLine: '\u001b[2K',
|
||||
beginningOfLine: '\u001b[0G',
|
||||
up: '\u001b[A',
|
||||
down: '\u001b[B',
|
||||
forward: '\u001b[C',
|
||||
forwardN: function(n){ return '\u001b[' + n + 'C'; },
|
||||
backward: '\u001b[D',
|
||||
nextLine: '\u001b[E',
|
||||
previousLine: '\u001b[F'
|
||||
}
|
||||
process.stdout.columns = 0;
|
||||
process.stdout.write = function(string) { console.log(string); }
|
||||
|
||||
// Mocha needs the formating feature of console.log so copy node's format function and
|
||||
// monkey-patch it into place. This code is copied from node's, links copyright applies.
|
||||
// https://github.com/joyent/node/blob/master/lib/util.js
|
||||
console.format = function(f) {
|
||||
if (typeof f !== 'string') {
|
||||
var objects = [];
|
||||
for (var i = 0; i < arguments.length; i++) {
|
||||
objects.push(JSON.stringify(arguments[i]));
|
||||
}
|
||||
return objects.join(' ');
|
||||
}
|
||||
var i = 1;
|
||||
var args = arguments;
|
||||
var len = args.length;
|
||||
var str = String(f).replace(/%[sdj%]/g, function(x) {
|
||||
if (x === '%%') return '%';
|
||||
if (i >= len) return x;
|
||||
switch (x) {
|
||||
case '%s': return String(args[i++]);
|
||||
case '%d': return Number(args[i++]);
|
||||
case '%j': return JSON.stringify(args[i++]);
|
||||
default:
|
||||
return x;
|
||||
}
|
||||
});
|
||||
for (var x = args[i]; i < len; x = args[++i]) {
|
||||
if (x === null || typeof x !== 'object') {
|
||||
str += ' ' + x;
|
||||
} else {
|
||||
str += ' ' + JSON.stringify(x);
|
||||
}
|
||||
}
|
||||
return str;
|
||||
};
|
||||
var origError = console.error;
|
||||
console.error = function(){ origError.call(console, console.format.apply(console, arguments)); };
|
||||
var origLog = console.log;
|
||||
console.log = function(){ origLog.call(console, console.format.apply(console, arguments)); };
|
||||
|
||||
})();
|
||||
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -3,6 +3,21 @@ goog.provide('ol.test.expect.js');
|
||||
|
||||
describe('expect.js', function() {
|
||||
|
||||
describe('arreqlNaN', function() {
|
||||
|
||||
it('considers NaN in array to be equal', function() {
|
||||
expect([1, NaN, 2]).to.arreqlNaN([1, NaN, 2]);
|
||||
expect([1, NaN, 2]).not.to.arreqlNaN([1, 1.5, 2]);
|
||||
});
|
||||
|
||||
it('allows a mix of number and string', function() {
|
||||
expect([1, NaN, 'foo']).to.arreqlNaN([1, NaN, 'foo']);
|
||||
expect([1, NaN, 'foo']).not.to.arreqlNaN([1, NaN, 'bar']);
|
||||
expect([1, NaN]).not.to.arreqlNaN([1, 'foo']);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('roughlyEqual', function() {
|
||||
|
||||
it('can tell the difference between 1 and 3', function() {
|
||||
@@ -15,31 +30,19 @@ describe('expect.js', function() {
|
||||
}).to.throwException();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('kindaEqual', function() {
|
||||
|
||||
it('thinks that 1 ain\'t so different from 2', function() {
|
||||
expect(1).to.kindaEqual(2, 1);
|
||||
expect(1).to.roughlyEqual(2, 1);
|
||||
});
|
||||
|
||||
it('knows that, like, 1 and 2 would, like, totally dig each other',
|
||||
function() {
|
||||
expect(function() {
|
||||
expect(1).to.kindaEqual(2, 1);
|
||||
expect(1).to.roughlyEqual(2, 1);
|
||||
}).not.to.throwException();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('roughlyEqual and kindaEqual', function() {
|
||||
|
||||
it('it\'s like they\'re soul mates', function() {
|
||||
expect(expect(0).to.roughlyEqual).to.be(expect(1).to.kindaEqual);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('called', function() {
|
||||
|
||||
var telephone;
|
||||
@@ -57,38 +60,21 @@ describe('expect.js', function() {
|
||||
expect(telephone).not.to.be.called();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('totallyWantsToSpeakToYou', function() {
|
||||
|
||||
var callMeMaybe;
|
||||
beforeEach(function() {
|
||||
callMeMaybe = sinon.spy();
|
||||
});
|
||||
|
||||
it('reminds you that you forgot', function() {
|
||||
expect(function() {
|
||||
expect(callMeMaybe).to.be.called();
|
||||
expect(telephone).to.be.called();
|
||||
}).to.throwException();
|
||||
});
|
||||
|
||||
it('gets moody all too quickly', function() {
|
||||
callMeMaybe();
|
||||
telephone();
|
||||
expect(function() {
|
||||
expect(callMeMaybe).not.to.be.called();
|
||||
expect(telephone).not.to.be.called();
|
||||
}).to.throwException();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('called and totallyWantsToSpeakToYou', function() {
|
||||
|
||||
it('are best friends forever \u2665', function() {
|
||||
expect(expect(0).to.called).to.be(expect(1).to.totallyWantsToSpeakToYou);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('Test equality of XML documents - xmleql', function() {
|
||||
|
||||
it('Test XML document with single root, different prefix', function() {
|
||||
|
||||
@@ -260,31 +260,31 @@ describe('ol.structs.Buffer', function() {
|
||||
it('allows multiple adds and removes', function() {
|
||||
var b = new ol.structs.Buffer(new Array(8), 0);
|
||||
expect(b.add([0, 1])).to.be(0);
|
||||
expect(b.getArray()).to.eql([0, 1, NaN, NaN, NaN, NaN, NaN, NaN]);
|
||||
expect(b.getArray()).to.arreqlNaN([0, 1, NaN, NaN, NaN, NaN, NaN, NaN]);
|
||||
expect(b.getCount()).to.be(2);
|
||||
expect(b.add([2, 3, 4, 5])).to.be(2);
|
||||
expect(b.getArray()).to.eql([0, 1, 2, 3, 4, 5, NaN, NaN]);
|
||||
expect(b.getArray()).to.arreqlNaN([0, 1, 2, 3, 4, 5, NaN, NaN]);
|
||||
expect(b.getCount()).to.be(6);
|
||||
expect(b.add([6, 7])).to.be(6);
|
||||
expect(b.getArray()).to.eql([0, 1, 2, 3, 4, 5, 6, 7]);
|
||||
expect(b.getCount()).to.be(8);
|
||||
b.remove(2, 2);
|
||||
expect(b.getArray()).to.eql([0, 1, NaN, NaN, 4, 5, 6, 7]);
|
||||
expect(b.getArray()).to.arreqlNaN([0, 1, NaN, NaN, 4, 5, 6, 7]);
|
||||
expect(b.getCount()).to.be(6);
|
||||
expect(b.add([8, 9])).to.be(2);
|
||||
expect(b.getArray()).to.eql([0, 1, 8, 9, 4, 5, 6, 7]);
|
||||
expect(b.getCount()).to.be(8);
|
||||
b.remove(1, 1);
|
||||
expect(b.getArray()).to.eql([0, NaN, 8, 9, 4, 5, 6, 7]);
|
||||
expect(b.getArray()).to.arreqlNaN([0, NaN, 8, 9, 4, 5, 6, 7]);
|
||||
expect(b.getCount()).to.be(7);
|
||||
b.remove(4, 4);
|
||||
expect(b.getArray()).to.eql([0, NaN, 8, 9, NaN, NaN, NaN, NaN]);
|
||||
expect(b.getArray()).to.arreqlNaN([0, NaN, 8, 9, NaN, NaN, NaN, NaN]);
|
||||
expect(b.getCount()).to.be(3);
|
||||
expect(b.add([10, 11, 12])).to.be(4);
|
||||
expect(b.getArray()).to.eql([0, NaN, 8, 9, 10, 11, 12, NaN]);
|
||||
expect(b.getArray()).to.arreqlNaN([0, NaN, 8, 9, 10, 11, 12, NaN]);
|
||||
expect(b.getCount()).to.be(6);
|
||||
expect(b.add([13])).to.be(1);
|
||||
expect(b.getArray()).to.eql([0, 13, 8, 9, 10, 11, 12, NaN]);
|
||||
expect(b.getArray()).to.arreqlNaN([0, 13, 8, 9, 10, 11, 12, NaN]);
|
||||
expect(b.getCount()).to.be(7);
|
||||
});
|
||||
|
||||
|
||||
@@ -50,4 +50,274 @@
|
||||
afterLoad('xml', path, next);
|
||||
};
|
||||
|
||||
|
||||
// extensions to expect.js
|
||||
var expect = global.expect;
|
||||
|
||||
|
||||
/**
|
||||
* Assert value is within some tolerance of a number.
|
||||
* @param {Number} n Number.
|
||||
* @param {Number} tol Tolerance.
|
||||
*/
|
||||
expect.Assertion.prototype.roughlyEqual = function(n, tol) {
|
||||
this.assert(
|
||||
Math.abs(this.obj - n) <= tol,
|
||||
function() {
|
||||
return 'expected ' + expect.stringify(this.obj) + ' to be within ' +
|
||||
tol + ' of ' + n;
|
||||
},
|
||||
function() {
|
||||
return 'expected ' + expect.stringify(this.obj) +
|
||||
' not to be within ' + tol + ' of ' + n;
|
||||
});
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Assert that a sinon spy was called.
|
||||
*/
|
||||
expect.Assertion.prototype.called = function() {
|
||||
this.assert(
|
||||
this.obj.called,
|
||||
function() {
|
||||
return 'expected ' + expect.stringify(this.obj) + ' to be called';
|
||||
},
|
||||
function() {
|
||||
return 'expected ' + expect.stringify(this.obj) + ' not to be called';
|
||||
});
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
function getChildNodes(node, options) {
|
||||
// check whitespace
|
||||
if (options && options.includeWhiteSpace) {
|
||||
return node.childNodes;
|
||||
} else {
|
||||
var nodes = [];
|
||||
for (var i = 0, ii=node.childNodes.length; i < ii; i++ ) {
|
||||
var child = node.childNodes[i];
|
||||
if (child.nodeType == 1) {
|
||||
// element node, add it
|
||||
nodes.push(child);
|
||||
} else if (child.nodeType == 3) {
|
||||
// text node, add if non empty
|
||||
if (child.nodeValue &&
|
||||
child.nodeValue.replace(/^\s*(.*?)\s*$/, '$1') !== '') {
|
||||
nodes.push(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
return nodes;
|
||||
}
|
||||
}
|
||||
|
||||
function assertElementNodesEqual(node1, node2, options, errors) {
|
||||
var testPrefix = (options && options.prefix === true);
|
||||
try {
|
||||
expect(node1.nodeType).to.equal(node2.nodeType);
|
||||
} catch(e) {
|
||||
errors.push('nodeType test failed for: ' + node1.nodeName + ' | ' +
|
||||
node2.nodeName + ' | ' + e.message);
|
||||
}
|
||||
if (testPrefix) {
|
||||
try {
|
||||
expect(node1.nodeName).to.equal(node2.nodeName);
|
||||
} catch(e) {
|
||||
errors.push('nodeName test failed for: ' + node1.nodeName + ' | ' +
|
||||
node2.nodeName + ' | ' + e.message);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
expect(node1.nodeName.split(':').pop()).to.equal(
|
||||
node2.nodeName.split(':').pop());
|
||||
} catch(e) {
|
||||
errors.push('nodeName test failed for: ' + node1.nodeName + ' | ' +
|
||||
node2.nodeName + ' | ' + e.message);
|
||||
}
|
||||
}
|
||||
// for text nodes compare value
|
||||
if (node1.nodeType === 3) {
|
||||
try {
|
||||
// TODO should we make this optional?
|
||||
expect(node1.nodeValue.replace(/\s/g, '')).to.equal(
|
||||
node2.nodeValue.replace(/\s/g, ''));
|
||||
} catch(e) {
|
||||
errors.push('nodeValue test failed | ' + e.message);
|
||||
}
|
||||
}
|
||||
// for element type nodes compare namespace, attributes, and children
|
||||
else if (node1.nodeType === 1) {
|
||||
// test namespace alias and uri
|
||||
if (node1.prefix || node2.prefix) {
|
||||
if (testPrefix) {
|
||||
try {
|
||||
expect(node1.prefix).to.equal(node2.prefix);
|
||||
} catch(e) {
|
||||
errors.push('Prefix test failed for: ' + node1.nodeName + ' | ' +
|
||||
e.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (node1.namespaceURI || node2.namespaceURI) {
|
||||
try {
|
||||
expect(node1.namespaceURI).to.equal(node2.namespaceURI);
|
||||
} catch(e) {
|
||||
errors.push('namespaceURI test failed for: ' + node1.nodeName +
|
||||
' | ' + e.message);
|
||||
}
|
||||
}
|
||||
// compare attributes - disregard xmlns given namespace handling above
|
||||
var node1AttrLen = 0;
|
||||
var node1Attr = {};
|
||||
var node2AttrLen = 0;
|
||||
var node2Attr = {};
|
||||
var ga, ea, gn, en;
|
||||
var i, ii;
|
||||
if (node1.attributes) {
|
||||
for (i=0, ii=node1.attributes.length; i<ii; ++i) {
|
||||
ga = node1.attributes[i];
|
||||
if (ga.specified === undefined || ga.specified === true) {
|
||||
if (ga.name.split(':').shift() != 'xmlns') {
|
||||
gn = testPrefix ? ga.name : ga.name.split(':').pop();
|
||||
node1Attr[gn] = ga;
|
||||
++node1AttrLen;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (node2.attributes) {
|
||||
for (i=0, ii=node2.attributes.length; i<ii; ++i) {
|
||||
ea = node2.attributes[i];
|
||||
if (ea.specified === undefined || ea.specified === true) {
|
||||
if (ea.name.split(':').shift() != 'xmlns') {
|
||||
en = testPrefix ? ea.name : ea.name.split(':').pop();
|
||||
node2Attr[en] = ea;
|
||||
++node2AttrLen;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
expect(node1AttrLen).to.equal(node2AttrLen);
|
||||
} catch(e) {
|
||||
errors.push('Number of attributes test failed for: ' + node1.nodeName +
|
||||
' | ' + e.message);
|
||||
}
|
||||
var gv, ev;
|
||||
for (var name in node1Attr) {
|
||||
if (node2Attr[name] === undefined) {
|
||||
errors.push('Attribute name ' + node1Attr[name].name +
|
||||
' expected for element ' + node1.nodeName);
|
||||
}
|
||||
// test attribute namespace
|
||||
try {
|
||||
// we do not care about the difference between an empty string and
|
||||
// null for namespaceURI some tests will fail in IE9 otherwise
|
||||
// see also
|
||||
// http://msdn.microsoft.com/en-us/library/ff460650(v=vs.85).aspx
|
||||
expect(node1Attr[name].namespaceURI || null).to.be(
|
||||
node2Attr[name].namespaceURI || null);
|
||||
} catch(e) {
|
||||
errors.push('namespaceURI attribute test failed for: ' +
|
||||
node1.nodeName + ' | ' + e.message);
|
||||
}
|
||||
try {
|
||||
expect(node1Attr[name].value).to.equal(node2Attr[name].value);
|
||||
} catch(e) {
|
||||
errors.push('Attribute value test failed for: ' + node1.nodeName +
|
||||
' | ' + e.message);
|
||||
}
|
||||
}
|
||||
// compare children
|
||||
var node1ChildNodes = getChildNodes(node1, options);
|
||||
var node2ChildNodes = getChildNodes(node2, options);
|
||||
try {
|
||||
expect(node1ChildNodes.length).to.equal(node2ChildNodes.length);
|
||||
} catch(e) {
|
||||
errors.push('Number of childNodes test failed for: ' + node1.nodeName +
|
||||
' | ' + e.message);
|
||||
}
|
||||
// only compare if they are equal
|
||||
if (node1ChildNodes.length === node2ChildNodes.length) {
|
||||
for (var j=0, jj=node1ChildNodes.length; j<jj; ++j) {
|
||||
assertElementNodesEqual(
|
||||
node1ChildNodes[j], node2ChildNodes[j], options, errors);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the XML document sort of equals another XML document.
|
||||
*/
|
||||
expect.Assertion.prototype.xmleql = function(obj, options) {
|
||||
if (obj && obj.nodeType == 9) {
|
||||
obj = obj.documentElement;
|
||||
}
|
||||
if (this.obj && this.obj.nodeType == 9) {
|
||||
this.obj = this.obj.documentElement;
|
||||
}
|
||||
var errors = [];
|
||||
assertElementNodesEqual(obj, this.obj, options, errors);
|
||||
var result = (errors.length === 0);
|
||||
this.assert(
|
||||
!!result,
|
||||
function() {
|
||||
return 'expected ' + expect.stringify(this.obj) +
|
||||
' to sort of equal ' + expect.stringify(obj) + '\n' +
|
||||
errors.join('\n');
|
||||
},
|
||||
function() {
|
||||
return 'expected ' + expect.stringify(this.obj) +
|
||||
' to sort of not equal ' + expect.stringify(obj) + '\n' +
|
||||
errors.join('\n');
|
||||
});
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the array sort of equals another array.
|
||||
*/
|
||||
expect.Assertion.prototype.arreql = function (obj) {
|
||||
this.assert(
|
||||
goog.array.equals(this.obj, obj),
|
||||
function() {
|
||||
return 'expected ' + expect.stringify(this.obj) +
|
||||
' to sort of equal ' + expect.stringify(obj);
|
||||
},
|
||||
function() {
|
||||
return 'expected ' + expect.stringify(this.obj) +
|
||||
' to sort of not equal ' + expect.stringify(obj);
|
||||
});
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the array sort of equals another array (allows NaNs to be equal).
|
||||
*/
|
||||
expect.Assertion.prototype.arreqlNaN = function (obj) {
|
||||
function compare(a, b) {
|
||||
return a === b || (typeof a === 'number' && typeof b === 'number' &&
|
||||
isNaN(a) && isNaN(b));
|
||||
}
|
||||
this.assert(
|
||||
goog.array.equals(this.obj, obj, compare),
|
||||
function() {
|
||||
return 'expected ' + expect.stringify(this.obj) +
|
||||
' to sort of equal ' + expect.stringify(obj);
|
||||
},
|
||||
function() {
|
||||
return 'expected ' + expect.stringify(this.obj) +
|
||||
' to sort of not equal ' + expect.stringify(obj);
|
||||
});
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
})(this);
|
||||
|
||||
Reference in New Issue
Block a user