mirror of
https://github.com/Hopiu/angular.js.git
synced 2026-05-04 21:24:42 +00:00
JSTD adapter for running e2e tests
Couple of changes into angular.scenario runner: - add autotest config (runs tests when document ready) - update ObjectModel (forwards events) - use only one ObjectModel instance for all outputters - expose error msg and line number in ObjectModel.Spec and ObjectModel.Step - fix generating spec.ids - fix 'html' output so that it does not mutate ObjectModel Couple of changes into docs / generator: - rename copy -> copyTpl - move docs/static into docs/examples (to avoid conflict with jstd proxy) Running all docs e2e tests: ======================================================== 1/ compile angular-scenario, jstd-scenario-adapter >> rake compile 2/ build docs >> rake docs 3/ start jstd server >> ./server-scenario.sh 4/ capture some browser 5/ run node server to serve static content >> node ../lib/nodeserver/server.js 6/ run tests >> ./test-scenario.sh
This commit is contained in:
parent
9f56af9c15
commit
1abdc097b2
35 changed files with 1034 additions and 121 deletions
|
|
@ -1,8 +1,13 @@
|
||||||
<a name="0.9.16"><a/>
|
<a name="0.9.16"><a/>
|
||||||
# <angular/> 0.9.16 weather-control (in-progress) #
|
# <angular/> 0.9.16 weather-control (in-progress) #
|
||||||
|
|
||||||
|
### Features
|
||||||
|
- we can run scenario tests with jstd (from command line and in multiple browsers)
|
||||||
|
|
||||||
|
|
||||||
|
### Breaking changes
|
||||||
|
- html scenario runner requires ng:autotest option to start tests automatically
|
||||||
|
|
||||||
|
|
||||||
<a name="0.9.15"><a/>
|
<a name="0.9.15"><a/>
|
||||||
# <angular/> 0.9.15 lethal-stutter (2011-04-11) #
|
# <angular/> 0.9.15 lethal-stutter (2011-04-11) #
|
||||||
|
|
|
||||||
32
Rakefile
32
Rakefile
|
|
@ -53,7 +53,7 @@ ANGULAR_SCENARIO = [
|
||||||
'src/scenario/output/Html.js',
|
'src/scenario/output/Html.js',
|
||||||
'src/scenario/output/Json.js',
|
'src/scenario/output/Json.js',
|
||||||
'src/scenario/output/Xml.js',
|
'src/scenario/output/Xml.js',
|
||||||
'src/scenario/output/Object.js',
|
'src/scenario/output/Object.js'
|
||||||
]
|
]
|
||||||
|
|
||||||
BUILD_DIR = 'build'
|
BUILD_DIR = 'build'
|
||||||
|
|
@ -94,6 +94,30 @@ task :compile_scenario => :init do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
desc 'Compile JSTD Scenario Adapter'
|
||||||
|
task :compile_jstd_scenario_adapter => :init do
|
||||||
|
|
||||||
|
deps = [
|
||||||
|
'src/jstd-scenario-adapter/angular.prefix',
|
||||||
|
'src/jstd-scenario-adapter/Adapter.js',
|
||||||
|
'src/jstd-scenario-adapter/angular.suffix',
|
||||||
|
]
|
||||||
|
|
||||||
|
concat = 'cat ' + deps.flatten.join(' ')
|
||||||
|
|
||||||
|
File.open(path_to('jstd-scenario-adapter.js'), 'w') do |f|
|
||||||
|
f.write(%x{#{concat}})
|
||||||
|
end
|
||||||
|
|
||||||
|
# TODO(vojta) use jstd configuration when implemented
|
||||||
|
# (instead of including jstd-adapter-config.js)
|
||||||
|
File.open(path_to('jstd-scenario-adapter-config.js'), 'w') do |f|
|
||||||
|
f.write("/**\r\n" +
|
||||||
|
" * Configuration for jstd scenario adapter \n */\n" +
|
||||||
|
"var jstdScenarioAdapter = {\n relativeUrlPrefix: '/build/docs/'\n};\n")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
desc 'Generate IE css js patch'
|
desc 'Generate IE css js patch'
|
||||||
task :generate_ie_compat => :init do
|
task :generate_ie_compat => :init do
|
||||||
|
|
@ -152,7 +176,7 @@ end
|
||||||
|
|
||||||
|
|
||||||
desc 'Compile JavaScript'
|
desc 'Compile JavaScript'
|
||||||
task :compile => [:init, :compile_scenario, :generate_ie_compat] do
|
task :compile => [:init, :compile_scenario, :compile_jstd_scenario_adapter, :generate_ie_compat] do
|
||||||
|
|
||||||
deps = [
|
deps = [
|
||||||
'src/angular.prefix',
|
'src/angular.prefix',
|
||||||
|
|
@ -195,7 +219,9 @@ task :package => [:clean, :compile, :docs] do
|
||||||
path_to('angular.js'),
|
path_to('angular.js'),
|
||||||
path_to('angular.min.js'),
|
path_to('angular.min.js'),
|
||||||
path_to('angular-ie-compat.js'),
|
path_to('angular-ie-compat.js'),
|
||||||
path_to('angular-scenario.js')
|
path_to('angular-scenario.js'),
|
||||||
|
path_to('jstd-scenario-adapter.js'),
|
||||||
|
path_to('jstd-scenario-adapter-config.js'),
|
||||||
].each do |src|
|
].each do |src|
|
||||||
dest = src.gsub(/^[^\/]+\//, '').gsub(/((\.min)?\.js)$/, "-#{version}\\1")
|
dest = src.gsub(/^[^\/]+\//, '').gsub(/((\.min)?\.js)$/, "-#{version}\\1")
|
||||||
FileUtils.cp(src, pkg_dir + '/' + dest)
|
FileUtils.cp(src, pkg_dir + '/' + dest)
|
||||||
|
|
|
||||||
|
|
@ -34,8 +34,8 @@ In this example we have a simple app which consist of two screens:
|
||||||
|
|
||||||
The two partials are defined in the following URLs:
|
The two partials are defined in the following URLs:
|
||||||
|
|
||||||
* {@link ./static/settings.html}
|
* {@link ./examples/settings.html}
|
||||||
* {@link ./static/welcome.html}
|
* {@link ./examples/welcome.html}
|
||||||
|
|
||||||
|
|
||||||
<doc:example>
|
<doc:example>
|
||||||
|
|
@ -44,8 +44,8 @@ The two partials are defined in the following URLs:
|
||||||
AppCntl.$inject = ['$route']
|
AppCntl.$inject = ['$route']
|
||||||
function AppCntl($route) {
|
function AppCntl($route) {
|
||||||
// define routes
|
// define routes
|
||||||
$route.when("", {template:'./static/welcome.html', controller:WelcomeCntl});
|
$route.when("", {template:'./examples/welcome.html', controller:WelcomeCntl});
|
||||||
$route.when("/settings", {template:'./static/settings.html', controller:SettingsCntl});
|
$route.when("/settings", {template:'./examples/settings.html', controller:SettingsCntl});
|
||||||
$route.parent(this);
|
$route.parent(this);
|
||||||
|
|
||||||
// initialize the model to something useful
|
// initialize the model to something useful
|
||||||
|
|
|
||||||
|
|
@ -25,22 +25,22 @@ var writes = callback.chain(function(){
|
||||||
var metadata = ngdoc.metadata(docs);
|
var metadata = ngdoc.metadata(docs);
|
||||||
writer.output('docs-keywords.js', ['NG_PAGES=', JSON.stringify(metadata).replace(/{/g, '\n{'), ';'], writes.waitFor());
|
writer.output('docs-keywords.js', ['NG_PAGES=', JSON.stringify(metadata).replace(/{/g, '\n{'), ';'], writes.waitFor());
|
||||||
writer.copyDir('img', writes.waitFor());
|
writer.copyDir('img', writes.waitFor());
|
||||||
writer.copyDir('static', writes.waitFor());
|
writer.copyDir('examples', writes.waitFor());
|
||||||
writer.copy('index.html', writes.waitFor());
|
writer.copyTpl('index.html', writes.waitFor());
|
||||||
writer.copy('docs.js', writes.waitFor());
|
writer.copyTpl('docs.js', writes.waitFor());
|
||||||
writer.copy('docs.css', writes.waitFor());
|
writer.copyTpl('docs.css', writes.waitFor());
|
||||||
writer.copy('doc_widgets.js', writes.waitFor());
|
writer.copyTpl('doc_widgets.js', writes.waitFor());
|
||||||
writer.copy('doc_widgets.css', writes.waitFor());
|
writer.copyTpl('doc_widgets.css', writes.waitFor());
|
||||||
writer.copy('docs-scenario.html', writes.waitFor());
|
writer.copyTpl('docs-scenario.html', writes.waitFor());
|
||||||
writer.output('docs-scenario.js', ngdoc.scenarios(docs), writes.waitFor());
|
writer.output('docs-scenario.js', ngdoc.scenarios(docs), writes.waitFor());
|
||||||
writer.output('sitemap.xml', new SiteMap(docs).render(), writes.waitFor());
|
writer.output('sitemap.xml', new SiteMap(docs).render(), writes.waitFor());
|
||||||
writer.output('robots.txt', 'Sitemap: http://docs.angularjs.org/sitemap.xml\n', writes.waitFor());
|
writer.output('robots.txt', 'Sitemap: http://docs.angularjs.org/sitemap.xml\n', writes.waitFor());
|
||||||
writer.copy('syntaxhighlighter/shBrushJScript.js', writes.waitFor());
|
writer.copyTpl('syntaxhighlighter/shBrushJScript.js', writes.waitFor());
|
||||||
writer.copy('syntaxhighlighter/shBrushXml.js', writes.waitFor());
|
writer.copyTpl('syntaxhighlighter/shBrushXml.js', writes.waitFor());
|
||||||
writer.copy('syntaxhighlighter/shCore.css', writes.waitFor());
|
writer.copyTpl('syntaxhighlighter/shCore.css', writes.waitFor());
|
||||||
writer.copy('syntaxhighlighter/shCore.js', writes.waitFor());
|
writer.copyTpl('syntaxhighlighter/shCore.js', writes.waitFor());
|
||||||
writer.copy('syntaxhighlighter/shThemeDefault.css', writes.waitFor());
|
writer.copyTpl('syntaxhighlighter/shThemeDefault.css', writes.waitFor());
|
||||||
writer.copy('jquery.min.js', writes.waitFor());
|
writer.copyTpl('jquery.min.js', writes.waitFor());
|
||||||
});
|
});
|
||||||
writes.onDone(function(){
|
writes.onDone(function(){
|
||||||
console.log('DONE. Generated ' + docs.length + ' pages in ' +
|
console.log('DONE. Generated ' + docs.length + ' pages in ' +
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
<html xmlns:ng="http://angularjs.org" wiki:ng="http://angularjs.org">
|
<html xmlns:ng="http://angularjs.org" wiki:ng="http://angularjs.org">
|
||||||
<head>
|
<head>
|
||||||
<title><angular/> Docs Scenario Runner</title>
|
<title><angular/> Docs Scenario Runner</title>
|
||||||
<script type="text/javascript" src="../angular-scenario.js" ng:autobind></script>
|
<script type="text/javascript" src="../angular-scenario.js" ng:autotest></script>
|
||||||
<script type="text/javascript" src="docs-scenario.js"></script>
|
<script type="text/javascript" src="docs-scenario.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ exports.makeDir = function (path, callback) {
|
||||||
})();
|
})();
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.copy = function(filename, callback){
|
exports.copyTpl = function(filename, callback) {
|
||||||
copy('docs/src/templates/' + filename, OUTPUT_DIR + filename, callback);
|
copy('docs/src/templates/' + filename, OUTPUT_DIR + filename, callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||||
<head>
|
<head>
|
||||||
<title>Personal Log Scenario Runner</title>
|
<title>Personal Log Scenario Runner</title>
|
||||||
<script type="text/javascript" src="../../../src/scenario/angular-bootstrap.js"></script>
|
<script type="text/javascript" src="../../../src/scenario/angular-bootstrap.js" ng:autotest></script>
|
||||||
<script type="text/javascript" src="personalLogScenario.js"></script>
|
<script type="text/javascript" src="personalLogScenario.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
|
||||||
10
jsTestDriver-scenario.conf
Normal file
10
jsTestDriver-scenario.conf
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
server: http://localhost:9877
|
||||||
|
|
||||||
|
load:
|
||||||
|
- build/angular-scenario.js
|
||||||
|
- build/jstd-scenario-adapter-config.js
|
||||||
|
- build/jstd-scenario-adapter.js
|
||||||
|
- build/docs/docs-scenario.js
|
||||||
|
|
||||||
|
proxy:
|
||||||
|
- {matcher: "*", server: "http://localhost:8000"}
|
||||||
|
|
@ -13,11 +13,13 @@ load:
|
||||||
- test/testabilityPatch.js
|
- test/testabilityPatch.js
|
||||||
- src/scenario/Scenario.js
|
- src/scenario/Scenario.js
|
||||||
- src/scenario/output/*.js
|
- src/scenario/output/*.js
|
||||||
|
- src/jstd-scenario-adapter/*.js
|
||||||
- src/scenario/*.js
|
- src/scenario/*.js
|
||||||
- src/angular-mocks.js
|
- src/angular-mocks.js
|
||||||
- test/mocks.js
|
- test/mocks.js
|
||||||
- test/scenario/*.js
|
- test/scenario/*.js
|
||||||
- test/scenario/output/*.js
|
- test/scenario/output/*.js
|
||||||
|
- test/jstd-scenario-adapter/*.js
|
||||||
- test/*.js
|
- test/*.js
|
||||||
- test/service/*.js
|
- test/service/*.js
|
||||||
- example/personalLog/test/*.js
|
- example/personalLog/test/*.js
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||||
<head>
|
<head>
|
||||||
<script type="text/javascript" src="../build/angular-scenario.js"></script>
|
<script type="text/javascript" src="../build/angular-scenario.js" ng:autotest></script>
|
||||||
<script type="text/javascript" src="widgets-scenario.js"></script>
|
<script type="text/javascript" src="widgets-scenario.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||||
<head>
|
<head>
|
||||||
<script type="text/javascript" src="../src/scenario/angular-bootstrap.js"></script>
|
<script type="text/javascript" src="../src/scenario/angular-bootstrap.js" ng:autotest></script>
|
||||||
<script type="text/javascript" src="widgets-scenario.js"></script>
|
<script type="text/javascript" src="widgets-scenario.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
|
||||||
3
server-scenario.sh
Executable file
3
server-scenario.sh
Executable file
|
|
@ -0,0 +1,3 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
java -jar lib/jstestdriver/JsTestDriver.jar --port 9877 --browserTimeout 90000 --config jsTestDriver-scenario.conf
|
||||||
175
src/jstd-scenario-adapter/Adapter.js
Normal file
175
src/jstd-scenario-adapter/Adapter.js
Normal file
|
|
@ -0,0 +1,175 @@
|
||||||
|
/**
|
||||||
|
* JSTestDriver adapter for angular scenario tests
|
||||||
|
*
|
||||||
|
* Example of jsTestDriver.conf for running scenario tests with JSTD:
|
||||||
|
<pre>
|
||||||
|
server: http://localhost:9877
|
||||||
|
|
||||||
|
load:
|
||||||
|
- lib/angular-scenario.js
|
||||||
|
- lib/jstd-scenario-adapter-config.js
|
||||||
|
- lib/jstd-scenario-adapter.js
|
||||||
|
# your test files go here #
|
||||||
|
|
||||||
|
proxy:
|
||||||
|
- {matcher: "/your-prefix/*", server: "http://localhost:8000/"}
|
||||||
|
</pre>
|
||||||
|
*
|
||||||
|
* For more information on how to configure jstd proxy, see {@link http://code.google.com/p/js-test-driver/wiki/Proxy}
|
||||||
|
* Note the order of files - it's important !
|
||||||
|
*
|
||||||
|
* Example of jstd-scenario-adapter-config.js
|
||||||
|
<pre>
|
||||||
|
var jstdScenarioAdapter = {
|
||||||
|
relativeUrlPrefix: '/your-prefix/'
|
||||||
|
};
|
||||||
|
</pre>
|
||||||
|
*
|
||||||
|
* Whenever you use <code>browser().navigateTo('relativeUrl')</code> in your scenario test, the relativeUrlPrefix will be prepended.
|
||||||
|
* You have to configure this to work together with JSTD proxy.
|
||||||
|
*
|
||||||
|
* Let's assume you are using the above configuration (jsTestDriver.conf and jstd-scenario-adapter-config.js):
|
||||||
|
* Now, when you call <code>browser().navigateTo('index.html')</code> in your scenario test, the browser will open /your-prefix/index.html.
|
||||||
|
* That matches the proxy, so JSTD will proxy this request to http://localhost:8000/index.html.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom type of test case
|
||||||
|
*
|
||||||
|
* @const
|
||||||
|
* @see jstestdriver.TestCaseInfo
|
||||||
|
*/
|
||||||
|
var SCENARIO_TYPE = 'scenario';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plugin for JSTestDriver
|
||||||
|
* Connection point between scenario's jstd output and jstestdriver.
|
||||||
|
*
|
||||||
|
* @see jstestdriver.PluginRegistrar
|
||||||
|
*/
|
||||||
|
function JstdPlugin() {
|
||||||
|
var nop = function() {};
|
||||||
|
|
||||||
|
this.reportResult = nop;
|
||||||
|
this.reportEnd = nop;
|
||||||
|
this.runScenario = nop;
|
||||||
|
|
||||||
|
this.name = 'Angular Scenario Adapter';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called for each JSTD TestCase
|
||||||
|
*
|
||||||
|
* Handles only SCENARIO_TYPE test cases. There should be only one fake TestCase.
|
||||||
|
* Runs all scenario tests (under one fake TestCase) and report all results to JSTD.
|
||||||
|
*
|
||||||
|
* @param {jstestdriver.TestRunConfiguration} configuration
|
||||||
|
* @param {Function} onTestDone
|
||||||
|
* @param {Function} onAllTestsComplete
|
||||||
|
* @returns {boolean} True if this type of test is handled by this plugin, false otherwise
|
||||||
|
*/
|
||||||
|
this.runTestConfiguration = function(configuration, onTestDone, onAllTestsComplete) {
|
||||||
|
if (configuration.getTestCaseInfo().getType() != SCENARIO_TYPE) return false;
|
||||||
|
|
||||||
|
this.reportResult = onTestDone;
|
||||||
|
this.reportEnd = onAllTestsComplete;
|
||||||
|
this.runScenario();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.getTestRunsConfigurationFor = function(testCaseInfos, expressions, testRunsConfiguration) {
|
||||||
|
testRunsConfiguration.push(
|
||||||
|
new jstestdriver.TestRunConfiguration(
|
||||||
|
new jstestdriver.TestCaseInfo(
|
||||||
|
'Angular Scenario Tests', function() {}, SCENARIO_TYPE), []));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Singleton instance of the plugin
|
||||||
|
* Accessed using closure by:
|
||||||
|
* - jstd output (reports to this plugin)
|
||||||
|
* - initScenarioAdapter (register the plugin to jstd)
|
||||||
|
*/
|
||||||
|
var plugin = new JstdPlugin();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialise scenario jstd-adapter
|
||||||
|
* (only if jstestdriver is defined)
|
||||||
|
*
|
||||||
|
* @param {Object} jstestdriver Undefined when run from browser (without jstd)
|
||||||
|
* @param {Function} initScenarioAndRun Function that inits scenario and runs all the tests
|
||||||
|
* @param {Object=} config Configuration object, supported properties:
|
||||||
|
* - relativeUrlPrefix: prefix for all relative links when navigateTo()
|
||||||
|
*/
|
||||||
|
function initScenarioAdapter(jstestdriver, initScenarioAndRun, config) {
|
||||||
|
if (jstestdriver) {
|
||||||
|
// create and register ScenarioPlugin
|
||||||
|
jstestdriver.pluginRegistrar.register(plugin);
|
||||||
|
plugin.runScenario = initScenarioAndRun;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HACK (angular.scenario.Application.navigateTo)
|
||||||
|
*
|
||||||
|
* We need to navigate to relative urls when running from browser (without JSTD),
|
||||||
|
* because we want to allow running scenario tests without creating its own virtual host.
|
||||||
|
* For example: http://angular.local/build/docs/docs-scenario.html
|
||||||
|
*
|
||||||
|
* On the other hand, when running with JSTD, we need to navigate to absolute urls,
|
||||||
|
* because of JSTD proxy. (proxy, because of same domain policy)
|
||||||
|
*
|
||||||
|
* So this hack is applied only if running with JSTD and change all relative urls to absolute.
|
||||||
|
*/
|
||||||
|
var appProto = angular.scenario.Application.prototype,
|
||||||
|
navigateTo = appProto.navigateTo,
|
||||||
|
relativeUrlPrefix = config && config.relativeUrlPrefix || '/';
|
||||||
|
|
||||||
|
appProto.navigateTo = function(url, loadFn, errorFn) {
|
||||||
|
if (url.charAt(0) != '/' && url.charAt(0) != '#' &&
|
||||||
|
url != 'about:blank' && !url.match(/^https?/)) {
|
||||||
|
url = relativeUrlPrefix + url;
|
||||||
|
}
|
||||||
|
|
||||||
|
return navigateTo.call(this, url, loadFn, errorFn);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds proper TestResult object from given model spec
|
||||||
|
*
|
||||||
|
* TODO(vojta) report error details
|
||||||
|
*
|
||||||
|
* @param {angular.scenario.ObjectModel.Spec} spec
|
||||||
|
* @returns {jstestdriver.TestResult}
|
||||||
|
*/
|
||||||
|
function createTestResultFromSpec(spec) {
|
||||||
|
var map = {
|
||||||
|
success: 'PASSED',
|
||||||
|
error: 'ERROR',
|
||||||
|
failure: 'FAILED'
|
||||||
|
};
|
||||||
|
|
||||||
|
return new jstestdriver.TestResult(
|
||||||
|
spec.fullDefinitionName,
|
||||||
|
spec.name,
|
||||||
|
jstestdriver.TestResult.RESULT[map[spec.status]],
|
||||||
|
spec.error || '',
|
||||||
|
spec.line || '',
|
||||||
|
spec.duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates JSTD output (jstestdriver.TestResult)
|
||||||
|
*/
|
||||||
|
angular.scenario.output('jstd', function(context, runner, model) {
|
||||||
|
model.on('SpecEnd', function(spec) {
|
||||||
|
plugin.reportResult(createTestResultFromSpec(spec));
|
||||||
|
});
|
||||||
|
|
||||||
|
model.on('RunnerEnd', function() {
|
||||||
|
plugin.reportEnd();
|
||||||
|
});
|
||||||
|
});
|
||||||
24
src/jstd-scenario-adapter/angular.prefix
Normal file
24
src/jstd-scenario-adapter/angular.prefix
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
/**
|
||||||
|
* The MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010 Adam Abrons and Misko Hevery http://getangular.com
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
(function(window) {
|
||||||
2
src/jstd-scenario-adapter/angular.suffix
Normal file
2
src/jstd-scenario-adapter/angular.suffix
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
initScenarioAdapter(window.jstestdriver, angular.scenario.setUpAndRun, window.jstdScenarioAdapter);
|
||||||
|
})(window);
|
||||||
|
|
@ -37,6 +37,9 @@ angular.scenario.Describe = function(descName, parent) {
|
||||||
// Shared Unique ID generator for every describe block
|
// Shared Unique ID generator for every describe block
|
||||||
angular.scenario.Describe.id = 0;
|
angular.scenario.Describe.id = 0;
|
||||||
|
|
||||||
|
// Shared Unique ID generator for every it (spec)
|
||||||
|
angular.scenario.Describe.specId = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines a block to execute before each it or nested describe.
|
* Defines a block to execute before each it or nested describe.
|
||||||
*
|
*
|
||||||
|
|
@ -93,6 +96,7 @@ angular.scenario.Describe.prototype.xdescribe = angular.noop;
|
||||||
*/
|
*/
|
||||||
angular.scenario.Describe.prototype.it = function(name, body) {
|
angular.scenario.Describe.prototype.it = function(name, body) {
|
||||||
this.its.push({
|
this.its.push({
|
||||||
|
id: angular.scenario.Describe.specId++,
|
||||||
definition: this,
|
definition: this,
|
||||||
only: this.only,
|
only: this.only,
|
||||||
name: name,
|
name: name,
|
||||||
|
|
|
||||||
|
|
@ -4,21 +4,26 @@
|
||||||
* @param {Object} runner The scenario Runner instance to connect to.
|
* @param {Object} runner The scenario Runner instance to connect to.
|
||||||
*
|
*
|
||||||
* TODO(esprehn): Every output type creates one of these, but we probably
|
* TODO(esprehn): Every output type creates one of these, but we probably
|
||||||
* want one glonal shared instance. Need to handle events better too
|
* want one global shared instance. Need to handle events better too
|
||||||
* so the HTML output doesn't need to do spec model.getSpec(spec.id)
|
* so the HTML output doesn't need to do spec model.getSpec(spec.id)
|
||||||
* silliness.
|
* silliness.
|
||||||
|
*
|
||||||
|
* TODO(vojta) refactor on, emit methods (from all objects) - use inheritance
|
||||||
*/
|
*/
|
||||||
angular.scenario.ObjectModel = function(runner) {
|
angular.scenario.ObjectModel = function(runner) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
this.specMap = {};
|
this.specMap = {};
|
||||||
|
this.listeners = [];
|
||||||
this.value = {
|
this.value = {
|
||||||
name: '',
|
name: '',
|
||||||
children: {}
|
children: {}
|
||||||
};
|
};
|
||||||
|
|
||||||
runner.on('SpecBegin', function(spec) {
|
runner.on('SpecBegin', function(spec) {
|
||||||
var block = self.value;
|
var block = self.value,
|
||||||
|
definitions = [];
|
||||||
|
|
||||||
angular.forEach(self.getDefinitionPath(spec), function(def) {
|
angular.forEach(self.getDefinitionPath(spec), function(def) {
|
||||||
if (!block.children[def.name]) {
|
if (!block.children[def.name]) {
|
||||||
block.children[def.name] = {
|
block.children[def.name] = {
|
||||||
|
|
@ -29,49 +34,78 @@ angular.scenario.ObjectModel = function(runner) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
block = block.children[def.name];
|
block = block.children[def.name];
|
||||||
|
definitions.push(def.name);
|
||||||
});
|
});
|
||||||
self.specMap[spec.id] = block.specs[spec.name] =
|
|
||||||
new angular.scenario.ObjectModel.Spec(spec.id, spec.name);
|
var it = self.specMap[spec.id] =
|
||||||
|
block.specs[spec.name] =
|
||||||
|
new angular.scenario.ObjectModel.Spec(spec.id, spec.name, definitions);
|
||||||
|
|
||||||
|
// forward the event
|
||||||
|
self.emit('SpecBegin', it);
|
||||||
});
|
});
|
||||||
|
|
||||||
runner.on('SpecError', function(spec, error) {
|
runner.on('SpecError', function(spec, error) {
|
||||||
var it = self.getSpec(spec.id);
|
var it = self.getSpec(spec.id);
|
||||||
it.status = 'error';
|
it.status = 'error';
|
||||||
it.error = error;
|
it.error = error;
|
||||||
|
|
||||||
|
// forward the event
|
||||||
|
self.emit('SpecError', it, error);
|
||||||
});
|
});
|
||||||
|
|
||||||
runner.on('SpecEnd', function(spec) {
|
runner.on('SpecEnd', function(spec) {
|
||||||
var it = self.getSpec(spec.id);
|
var it = self.getSpec(spec.id);
|
||||||
complete(it);
|
complete(it);
|
||||||
|
|
||||||
|
// forward the event
|
||||||
|
self.emit('SpecEnd', it);
|
||||||
});
|
});
|
||||||
|
|
||||||
runner.on('StepBegin', function(spec, step) {
|
runner.on('StepBegin', function(spec, step) {
|
||||||
var it = self.getSpec(spec.id);
|
var it = self.getSpec(spec.id);
|
||||||
it.steps.push(new angular.scenario.ObjectModel.Step(step.name));
|
var step = new angular.scenario.ObjectModel.Step(step.name);
|
||||||
|
it.steps.push(step);
|
||||||
|
|
||||||
|
// forward the event
|
||||||
|
self.emit('StepBegin', it, step);
|
||||||
});
|
});
|
||||||
|
|
||||||
runner.on('StepEnd', function(spec, step) {
|
runner.on('StepEnd', function(spec, step) {
|
||||||
var it = self.getSpec(spec.id);
|
var it = self.getSpec(spec.id);
|
||||||
if (it.getLastStep().name !== step.name)
|
var step = it.getLastStep();
|
||||||
throw 'Events fired in the wrong order. Step names don\' match.';
|
if (step.name !== step.name)
|
||||||
complete(it.getLastStep());
|
throw 'Events fired in the wrong order. Step names don\'t match.';
|
||||||
|
complete(step);
|
||||||
|
|
||||||
|
// forward the event
|
||||||
|
self.emit('StepEnd', it, step);
|
||||||
});
|
});
|
||||||
|
|
||||||
runner.on('StepFailure', function(spec, step, error) {
|
runner.on('StepFailure', function(spec, step, error) {
|
||||||
var it = self.getSpec(spec.id);
|
var it = self.getSpec(spec.id),
|
||||||
var item = it.getLastStep();
|
modelStep = it.getLastStep();
|
||||||
item.error = error;
|
|
||||||
if (!it.status) {
|
modelStep.setErrorStatus('failure', error, step.line());
|
||||||
it.status = item.status = 'failure';
|
it.setStatusFromStep(modelStep);
|
||||||
}
|
|
||||||
|
// forward the event
|
||||||
|
self.emit('StepFailure', it, modelStep, error);
|
||||||
});
|
});
|
||||||
|
|
||||||
runner.on('StepError', function(spec, step, error) {
|
runner.on('StepError', function(spec, step, error) {
|
||||||
var it = self.getSpec(spec.id);
|
var it = self.getSpec(spec.id),
|
||||||
var item = it.getLastStep();
|
modelStep = it.getLastStep();
|
||||||
it.status = 'error';
|
|
||||||
item.status = 'error';
|
modelStep.setErrorStatus('error', error, step.line());
|
||||||
item.error = error;
|
it.setStatusFromStep(modelStep);
|
||||||
|
|
||||||
|
// forward the event
|
||||||
|
self.emit('StepError', it, modelStep, error);
|
||||||
|
});
|
||||||
|
|
||||||
|
runner.on('RunnerEnd', function() {
|
||||||
|
self.emit('RunnerEnd');
|
||||||
});
|
});
|
||||||
|
|
||||||
function complete(item) {
|
function complete(item) {
|
||||||
|
|
@ -81,6 +115,36 @@ angular.scenario.ObjectModel = function(runner) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a listener for an event.
|
||||||
|
*
|
||||||
|
* @param {string} eventName Name of the event to add a handler for
|
||||||
|
* @param {Function} listener Function that will be called when event is fired
|
||||||
|
*/
|
||||||
|
angular.scenario.ObjectModel.prototype.on = function(eventName, listener) {
|
||||||
|
eventName = eventName.toLowerCase();
|
||||||
|
this.listeners[eventName] = this.listeners[eventName] || [];
|
||||||
|
this.listeners[eventName].push(listener);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emits an event which notifies listeners and passes extra
|
||||||
|
* arguments.
|
||||||
|
*
|
||||||
|
* @param {string} eventName Name of the event to fire.
|
||||||
|
*/
|
||||||
|
angular.scenario.ObjectModel.prototype.emit = function(eventName) {
|
||||||
|
var self = this,
|
||||||
|
args = Array.prototype.slice.call(arguments, 1),
|
||||||
|
eventName = eventName.toLowerCase();
|
||||||
|
|
||||||
|
if (this.listeners[eventName]) {
|
||||||
|
angular.forEach(this.listeners[eventName], function(listener) {
|
||||||
|
listener.apply(self, args);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Computes the path of definition describe blocks that wrap around
|
* Computes the path of definition describe blocks that wrap around
|
||||||
* this spec.
|
* this spec.
|
||||||
|
|
@ -113,12 +177,14 @@ angular.scenario.ObjectModel.prototype.getSpec = function(id) {
|
||||||
*
|
*
|
||||||
* @param {string} id Id of the spec
|
* @param {string} id Id of the spec
|
||||||
* @param {string} name Name of the spec
|
* @param {string} name Name of the spec
|
||||||
|
* @param {Array<string>=} definitionNames List of all describe block names that wrap this spec
|
||||||
*/
|
*/
|
||||||
angular.scenario.ObjectModel.Spec = function(id, name) {
|
angular.scenario.ObjectModel.Spec = function(id, name, definitionNames) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.startTime = new Date().getTime();
|
this.startTime = new Date().getTime();
|
||||||
this.steps = [];
|
this.steps = [];
|
||||||
|
this.fullDefinitionName = (definitionNames || []).join(' ');
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -142,6 +208,19 @@ angular.scenario.ObjectModel.Spec.prototype.getLastStep = function() {
|
||||||
return this.steps[this.steps.length-1];
|
return this.steps[this.steps.length-1];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set status of the Spec from given Step
|
||||||
|
*
|
||||||
|
* @param {angular.scenario.ObjectModel.Step} step
|
||||||
|
*/
|
||||||
|
angular.scenario.ObjectModel.Spec.prototype.setStatusFromStep = function(step) {
|
||||||
|
if (!this.status || step.status == 'error') {
|
||||||
|
this.status = step.status;
|
||||||
|
this.error = step.error;
|
||||||
|
this.line = step.line;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A single step inside a Spec.
|
* A single step inside a Spec.
|
||||||
*
|
*
|
||||||
|
|
@ -151,3 +230,16 @@ angular.scenario.ObjectModel.Step = function(name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.startTime = new Date().getTime();
|
this.startTime = new Date().getTime();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method for setting all error status related properties
|
||||||
|
*
|
||||||
|
* @param {string} status
|
||||||
|
* @param {string} error
|
||||||
|
* @param {string} line
|
||||||
|
*/
|
||||||
|
angular.scenario.ObjectModel.Step.prototype.setErrorStatus = function(status, error, line) {
|
||||||
|
this.status = status;
|
||||||
|
this.error = error;
|
||||||
|
this.line = line;
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
/**
|
/**
|
||||||
* Runner for scenarios.
|
* Runner for scenarios
|
||||||
|
*
|
||||||
|
* Has to be initialized before any test is loaded,
|
||||||
|
* because it publishes the API into window (global space).
|
||||||
*/
|
*/
|
||||||
angular.scenario.Runner = function($window) {
|
angular.scenario.Runner = function($window) {
|
||||||
this.listeners = [];
|
this.listeners = [];
|
||||||
|
|
|
||||||
|
|
@ -87,17 +87,20 @@ angular.scenario.matcher = angular.scenario.matcher || function(name, fn) {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialization function for the scenario runner.
|
* Initialize the scenario runner and run !
|
||||||
*
|
*
|
||||||
* @param {angular.scenario.Runner} $scenario The runner to setup
|
* Access global window and document object
|
||||||
* @param {Object} config Config options
|
* Access $runner through closure
|
||||||
|
*
|
||||||
|
* @param {Object=} config Config options
|
||||||
*/
|
*/
|
||||||
function angularScenarioInit($scenario, config) {
|
angular.scenario.setUpAndRun = function (config) {
|
||||||
var href = window.location.href;
|
var href = window.location.href;
|
||||||
var body = _jQuery(document.body);
|
var body = _jQuery(document.body);
|
||||||
var output = [];
|
var output = [];
|
||||||
|
var objModel = new angular.scenario.ObjectModel($runner);
|
||||||
|
|
||||||
if (config.scenario_output) {
|
if (config && config.scenario_output) {
|
||||||
output = config.scenario_output.split(',');
|
output = config.scenario_output.split(',');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -105,7 +108,7 @@ function angularScenarioInit($scenario, config) {
|
||||||
if (!output.length || indexOf(output,name) != -1) {
|
if (!output.length || indexOf(output,name) != -1) {
|
||||||
var context = body.append('<div></div>').find('div:last');
|
var context = body.append('<div></div>').find('div:last');
|
||||||
context.attr('id', name);
|
context.attr('id', name);
|
||||||
fn.call({}, context, $scenario);
|
fn.call({}, context, $runner, objModel);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -121,12 +124,12 @@ function angularScenarioInit($scenario, config) {
|
||||||
var appFrame = body.append('<div id="application"></div>').find('#application');
|
var appFrame = body.append('<div id="application"></div>').find('#application');
|
||||||
var application = new angular.scenario.Application(appFrame);
|
var application = new angular.scenario.Application(appFrame);
|
||||||
|
|
||||||
$scenario.on('RunnerEnd', function() {
|
$runner.on('RunnerEnd', function() {
|
||||||
appFrame.css('display', 'none');
|
appFrame.css('display', 'none');
|
||||||
appFrame.find('iframe').attr('src', 'about:blank');
|
appFrame.find('iframe').attr('src', 'about:blank');
|
||||||
});
|
});
|
||||||
|
|
||||||
$scenario.on('RunnerError', function(error) {
|
$runner.on('RunnerError', function(error) {
|
||||||
if (window.console) {
|
if (window.console) {
|
||||||
console.log(formatException(error));
|
console.log(formatException(error));
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -135,8 +138,8 @@ function angularScenarioInit($scenario, config) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$scenario.run(application);
|
$runner.run(application);
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Iterates through list with iterator function that must call the
|
* Iterates through list with iterator function that must call the
|
||||||
|
|
|
||||||
8
src/scenario/angular-bootstrap.js
vendored
8
src/scenario/angular-bootstrap.js
vendored
|
|
@ -23,7 +23,8 @@
|
||||||
try {
|
try {
|
||||||
if (previousOnLoad) previousOnLoad();
|
if (previousOnLoad) previousOnLoad();
|
||||||
} catch(e) {}
|
} catch(e) {}
|
||||||
angularScenarioInit($scenario, angularJsConfig(document));
|
var config = angularJsConfig(document);
|
||||||
|
if (config.autotest) angular.scenario.setUpAndRun(config);
|
||||||
};
|
};
|
||||||
|
|
||||||
addCSS("../../css/angular-scenario.css");
|
addCSS("../../css/angular-scenario.css");
|
||||||
|
|
@ -52,8 +53,7 @@
|
||||||
// Create the runner (which also sets up the global API)
|
// Create the runner (which also sets up the global API)
|
||||||
document.write(
|
document.write(
|
||||||
'<script type="text/javascript">' +
|
'<script type="text/javascript">' +
|
||||||
'var $scenario = new angular.scenario.Runner(window, angular.scenario.SpecRunner);' +
|
' var $runner = new angular.scenario.Runner(window);' +
|
||||||
'</script>'
|
'</script>');
|
||||||
);
|
|
||||||
|
|
||||||
})(window.onload);
|
})(window.onload);
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,10 @@
|
||||||
var $scenario = new angular.scenario.Runner(window);
|
var $runner = new angular.scenario.Runner(window),
|
||||||
|
config = angularJsConfig(document);
|
||||||
|
|
||||||
|
if (config.autotest) {
|
||||||
jqLiteWrap(document).ready(function() {
|
jqLiteWrap(document).ready(function() {
|
||||||
angularScenarioInit($scenario, angularJsConfig(document));
|
angular.scenario.setUpAndRun(config);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
})(window, document);
|
})(window, document);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,9 @@
|
||||||
* TODO(esprehn): This should be refactored now that ObjectModel exists
|
* TODO(esprehn): This should be refactored now that ObjectModel exists
|
||||||
* to use angular bindings for the UI.
|
* to use angular bindings for the UI.
|
||||||
*/
|
*/
|
||||||
angular.scenario.output('html', function(context, runner) {
|
angular.scenario.output('html', function(context, runner, model) {
|
||||||
var model = new angular.scenario.ObjectModel(runner);
|
var specUiMap = {},
|
||||||
|
lastStepUiMap = {};
|
||||||
|
|
||||||
context.append(
|
context.append(
|
||||||
'<div id="header">' +
|
'<div id="header">' +
|
||||||
|
|
@ -22,7 +23,7 @@ angular.scenario.output('html', function(context, runner) {
|
||||||
);
|
);
|
||||||
|
|
||||||
runner.on('InteractiveWait', function(spec, step) {
|
runner.on('InteractiveWait', function(spec, step) {
|
||||||
var ui = model.getSpec(spec.id).getLastStep().ui;
|
var ui = lastStepUiMap[spec.id];
|
||||||
ui.find('.test-title').
|
ui.find('.test-title').
|
||||||
html('waiting for you to <a href="javascript:resume()">resume</a>.');
|
html('waiting for you to <a href="javascript:resume()">resume</a>.');
|
||||||
});
|
});
|
||||||
|
|
@ -58,59 +59,62 @@ angular.scenario.output('html', function(context, runner) {
|
||||||
name.removeClass('closed').addClass('open');
|
name.removeClass('closed').addClass('open');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
model.getSpec(spec.id).ui = ui;
|
|
||||||
|
specUiMap[spec.id] = ui;
|
||||||
});
|
});
|
||||||
|
|
||||||
runner.on('SpecError', function(spec, error) {
|
runner.on('SpecError', function(spec, error) {
|
||||||
var ui = model.getSpec(spec.id).ui;
|
var ui = specUiMap[spec.id];
|
||||||
ui.append('<pre></pre>');
|
ui.append('<pre></pre>');
|
||||||
ui.find('> pre').text(formatException(error));
|
ui.find('> pre').text(formatException(error));
|
||||||
});
|
});
|
||||||
|
|
||||||
runner.on('SpecEnd', function(spec) {
|
runner.on('SpecEnd', function(spec) {
|
||||||
|
var ui = specUiMap[spec.id];
|
||||||
spec = model.getSpec(spec.id);
|
spec = model.getSpec(spec.id);
|
||||||
spec.ui.removeClass('status-pending');
|
ui.removeClass('status-pending');
|
||||||
spec.ui.addClass('status-' + spec.status);
|
ui.addClass('status-' + spec.status);
|
||||||
spec.ui.find("> .test-info .timer-result").text(spec.duration + "ms");
|
ui.find("> .test-info .timer-result").text(spec.duration + "ms");
|
||||||
if (spec.status === 'success') {
|
if (spec.status === 'success') {
|
||||||
spec.ui.find('> .test-info .test-name').addClass('closed');
|
ui.find('> .test-info .test-name').addClass('closed');
|
||||||
spec.ui.find('> .scrollpane .test-actions').hide();
|
ui.find('> .scrollpane .test-actions').hide();
|
||||||
}
|
}
|
||||||
updateTotals(spec.status);
|
updateTotals(spec.status);
|
||||||
});
|
});
|
||||||
|
|
||||||
runner.on('StepBegin', function(spec, step) {
|
runner.on('StepBegin', function(spec, step) {
|
||||||
|
var ui = specUiMap[spec.id];
|
||||||
spec = model.getSpec(spec.id);
|
spec = model.getSpec(spec.id);
|
||||||
step = spec.getLastStep();
|
step = spec.getLastStep();
|
||||||
spec.ui.find('> .scrollpane .test-actions').
|
ui.find('> .scrollpane .test-actions').append('<li class="status-pending"></li>');
|
||||||
append('<li class="status-pending"></li>');
|
var stepUi = lastStepUiMap[spec.id] = ui.find('> .scrollpane .test-actions li:last');
|
||||||
step.ui = spec.ui.find('> .scrollpane .test-actions li:last');
|
stepUi.append(
|
||||||
step.ui.append(
|
|
||||||
'<div class="timer-result"></div>' +
|
'<div class="timer-result"></div>' +
|
||||||
'<div class="test-title"></div>'
|
'<div class="test-title"></div>'
|
||||||
);
|
);
|
||||||
step.ui.find('> .test-title').text(step.name);
|
stepUi.find('> .test-title').text(step.name);
|
||||||
var scrollpane = step.ui.parents('.scrollpane');
|
var scrollpane = stepUi.parents('.scrollpane');
|
||||||
scrollpane.attr('scrollTop', scrollpane.attr('scrollHeight'));
|
scrollpane.attr('scrollTop', scrollpane.attr('scrollHeight'));
|
||||||
});
|
});
|
||||||
|
|
||||||
runner.on('StepFailure', function(spec, step, error) {
|
runner.on('StepFailure', function(spec, step, error) {
|
||||||
var ui = model.getSpec(spec.id).getLastStep().ui;
|
var ui = lastStepUiMap[spec.id];
|
||||||
addError(ui, step.line, error);
|
addError(ui, step.line, error);
|
||||||
});
|
});
|
||||||
|
|
||||||
runner.on('StepError', function(spec, step, error) {
|
runner.on('StepError', function(spec, step, error) {
|
||||||
var ui = model.getSpec(spec.id).getLastStep().ui;
|
var ui = lastStepUiMap[spec.id];
|
||||||
addError(ui, step.line, error);
|
addError(ui, step.line, error);
|
||||||
});
|
});
|
||||||
|
|
||||||
runner.on('StepEnd', function(spec, step) {
|
runner.on('StepEnd', function(spec, step) {
|
||||||
|
var stepUi = lastStepUiMap[spec.id];
|
||||||
spec = model.getSpec(spec.id);
|
spec = model.getSpec(spec.id);
|
||||||
step = spec.getLastStep();
|
step = spec.getLastStep();
|
||||||
step.ui.find('.timer-result').text(step.duration + 'ms');
|
stepUi.find('.timer-result').text(step.duration + 'ms');
|
||||||
step.ui.removeClass('status-pending');
|
stepUi.removeClass('status-pending');
|
||||||
step.ui.addClass('status-' + step.status);
|
stepUi.addClass('status-' + step.status);
|
||||||
var scrollpane = spec.ui.find('> .scrollpane');
|
var scrollpane = specUiMap[spec.id].find('> .scrollpane');
|
||||||
scrollpane.attr('scrollTop', scrollpane.attr('scrollHeight'));
|
scrollpane.attr('scrollTop', scrollpane.attr('scrollHeight'));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,8 @@
|
||||||
/**
|
/**
|
||||||
* Generates JSON output into a context.
|
* Generates JSON output into a context.
|
||||||
*/
|
*/
|
||||||
angular.scenario.output('json', function(context, runner) {
|
angular.scenario.output('json', function(context, runner, model) {
|
||||||
var model = new angular.scenario.ObjectModel(runner);
|
model.on('RunnerEnd', function() {
|
||||||
|
|
||||||
runner.on('RunnerEnd', function() {
|
|
||||||
context.text(angular.toJson(model.value));
|
context.text(angular.toJson(model.value));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
* Creates a global value $result with the result of the runner.
|
* Creates a global value $result with the result of the runner.
|
||||||
*/
|
*/
|
||||||
angular.scenario.output('object', function(context, runner) {
|
angular.scenario.output('object', function(context, runner, model) {
|
||||||
runner.$window.$result = new angular.scenario.ObjectModel(runner).value;
|
runner.$window.$result = model.value;
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,9 @@
|
||||||
/**
|
/**
|
||||||
* Generates XML output into a context.
|
* Generates XML output into a context.
|
||||||
*/
|
*/
|
||||||
angular.scenario.output('xml', function(context, runner) {
|
angular.scenario.output('xml', function(context, runner, model) {
|
||||||
var model = new angular.scenario.ObjectModel(runner);
|
|
||||||
var $ = function(args) {return new context.init(args);};
|
var $ = function(args) {return new context.init(args);};
|
||||||
runner.on('RunnerEnd', function() {
|
model.on('RunnerEnd', function() {
|
||||||
var scenario = $('<scenario></scenario>');
|
var scenario = $('<scenario></scenario>');
|
||||||
context.append(scenario);
|
context.append(scenario);
|
||||||
serializeXml(scenario, model.value);
|
serializeXml(scenario, model.value);
|
||||||
|
|
|
||||||
7
test-scenario.sh
Executable file
7
test-scenario.sh
Executable file
|
|
@ -0,0 +1,7 @@
|
||||||
|
#!/bin/bash
|
||||||
|
tests=$1
|
||||||
|
if [[ $tests = "" ]]; then
|
||||||
|
tests="all"
|
||||||
|
fi
|
||||||
|
|
||||||
|
java -jar lib/jstestdriver/JsTestDriver.jar --tests "$tests" --config jsTestDriver-scenario.conf --reset
|
||||||
320
test/jstd-scenario-adapter/AdapterSpecs.js
Normal file
320
test/jstd-scenario-adapter/AdapterSpecs.js
Normal file
|
|
@ -0,0 +1,320 @@
|
||||||
|
describe('jstd-adapter', function() {
|
||||||
|
var fakeJSTD = { pluginRegistrar: { register: function() {} } },
|
||||||
|
originalNavigateTo = angular.scenario.Application.prototype.navigateTo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverts hack on angular.scenario.Application.navigateTo
|
||||||
|
* We should revert this hack after any single call of initScenarioAdapter,
|
||||||
|
* so that it doesn't influence other tests...
|
||||||
|
*/
|
||||||
|
function revertNavigateToHack() {
|
||||||
|
angular.scenario.Application.prototype.navigateTo = originalNavigateTo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper for building angular.scenario.ObjectModel.Spec
|
||||||
|
* @returns {angular.scenario.ObjectModel.Spec}
|
||||||
|
*/
|
||||||
|
function buildSpec(status, name, duration, definitions, error, line) {
|
||||||
|
var spec = new angular.scenario.ObjectModel.Spec(
|
||||||
|
'fake-id', name || 'name', definitions || ['desc1', 'desc2']);
|
||||||
|
spec.duration = duration || 10;
|
||||||
|
spec.status = status || 'success';
|
||||||
|
spec.error = error || '';
|
||||||
|
spec.line = line || '';
|
||||||
|
|
||||||
|
return spec;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper for building angular.scenario.ObjectModel.Spec with error and error line
|
||||||
|
* @returns {angular.scenario.ObjectModel.Spec}
|
||||||
|
*/
|
||||||
|
function buildErrorSpec(error, line, status, name) {
|
||||||
|
return buildSpec(status || 'error', name, null, null, error, line);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper for building TestConfiguration
|
||||||
|
* @returns {jstestdriver.TestRunConfiguration}
|
||||||
|
*/
|
||||||
|
function buildTestConf(type) {
|
||||||
|
return new jstestdriver.TestRunConfiguration(
|
||||||
|
new jstestdriver.TestCaseInfo('Fake test - ' + Math.random(), function(){}, type), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper for building SCENARIO TestConfiguration
|
||||||
|
* @returns {jstestdriver.TestRunConfiguration}
|
||||||
|
*/
|
||||||
|
function buildScenarioTestConf() {
|
||||||
|
return buildTestConf(SCENARIO_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('initScenarioAdapter', function() {
|
||||||
|
afterEach(revertNavigateToHack);
|
||||||
|
|
||||||
|
it('should create and register plugin if jstestdriver defined', function() {
|
||||||
|
spyOn(fakeJSTD.pluginRegistrar, 'register');
|
||||||
|
initScenarioAdapter(fakeJSTD);
|
||||||
|
expect(fakeJSTD.pluginRegistrar.register).toHaveBeenCalled();
|
||||||
|
expect(fakeJSTD.pluginRegistrar.register.mostRecentCall.args[0] instanceof JstdPlugin);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should do nothing if jstestdriver not defined', function() {
|
||||||
|
expect(function() {
|
||||||
|
initScenarioAdapter(undefined);
|
||||||
|
}).not.toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set setUpAndRun callback to plugin', function() {
|
||||||
|
var runFn = jasmine.createSpy('setUpAndRun');
|
||||||
|
plugin.runScenario = null;
|
||||||
|
|
||||||
|
initScenarioAdapter(fakeJSTD, runFn);
|
||||||
|
expect(plugin.runScenario).toBe(runFn);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('navigateTo', function() {
|
||||||
|
var fakeJSTD = { pluginRegistrar: { register: function() {} } },
|
||||||
|
app = new angular.scenario.Application(_jQuery('<div></div>')),
|
||||||
|
navigateSpy;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
navigateSpy = spyOn(angular.scenario.Application.prototype, 'navigateTo');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should add url prefix when jstd defined', function() {
|
||||||
|
initScenarioAdapter(fakeJSTD, null, {relativeUrlPrefix: '/prefix/'});
|
||||||
|
|
||||||
|
app.navigateTo('test.html');
|
||||||
|
expect(navigateSpy).toHaveBeenCalled();
|
||||||
|
expect(navigateSpy.mostRecentCall.args[0]).toEqual('/prefix/test.html');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should add forward-slash as default url prefix when jstd defined', function() {
|
||||||
|
initScenarioAdapter(fakeJSTD);
|
||||||
|
|
||||||
|
app.navigateTo('test.html');
|
||||||
|
expect(navigateSpy).toHaveBeenCalled();
|
||||||
|
expect(navigateSpy.mostRecentCall.args[0]).toEqual('/test.html');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not change url when jstd not defined', function() {
|
||||||
|
initScenarioAdapter(null);
|
||||||
|
|
||||||
|
app.navigateTo('test.html');
|
||||||
|
expect(navigateSpy).toHaveBeenCalled();
|
||||||
|
expect(navigateSpy.mostRecentCall.args[0]).toEqual('test.html');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not change hash url', function() {
|
||||||
|
initScenarioAdapter(fakeJSTD);
|
||||||
|
|
||||||
|
app.navigateTo('#/index.html/a');
|
||||||
|
expect(navigateSpy).toHaveBeenCalled();
|
||||||
|
expect(navigateSpy.mostRecentCall.args[0]).toEqual('#/index.html/a');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not change absolute url', function() {
|
||||||
|
initScenarioAdapter(fakeJSTD);
|
||||||
|
|
||||||
|
app.navigateTo('/index.html/a');
|
||||||
|
expect(navigateSpy).toHaveBeenCalled();
|
||||||
|
expect(navigateSpy.mostRecentCall.args[0]).toEqual('/index.html/a');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not change "about:blank" url', function() {
|
||||||
|
initScenarioAdapter(fakeJSTD);
|
||||||
|
|
||||||
|
app.navigateTo('about:blank');
|
||||||
|
expect(navigateSpy).toHaveBeenCalled();
|
||||||
|
expect(navigateSpy.mostRecentCall.args[0]).toEqual('about:blank');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not change url with domain', function() {
|
||||||
|
initScenarioAdapter(fakeJSTD);
|
||||||
|
|
||||||
|
app.navigateTo('http://www.google.com');
|
||||||
|
expect(navigateSpy).toHaveBeenCalled();
|
||||||
|
expect(navigateSpy.mostRecentCall.args[0]).toEqual('http://www.google.com');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('JstdPlugin', function() {
|
||||||
|
var p;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
p = new JstdPlugin();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('runTestConfiguration', function() {
|
||||||
|
var initScenarioSpy, onTestSpy, onAllTestsSpy, spec, modelSpec;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
initScenarioSpy = jasmine.createSpy('initScenarioAndRun');
|
||||||
|
onTestSpy = jasmine.createSpy('onOneTest');
|
||||||
|
onAllTestsSpy = jasmine.createSpy('onAllTests');
|
||||||
|
|
||||||
|
p.runScenario = initScenarioSpy;
|
||||||
|
spec = {id: 'fake', name: 'Spec Name'};
|
||||||
|
modelSpec = new angular.scenario.ObjectModel.Spec(spec.id, spec.name);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should ignore non scenario test cases', function() {
|
||||||
|
expect(p.runTestConfiguration(buildTestConf(), onTestSpy, onAllTestsSpy)).toBe(false);
|
||||||
|
expect(p.runTestConfiguration(buildTestConf('async'), onTestSpy, onAllTestsSpy)).toBe(false);
|
||||||
|
expect(initScenarioSpy).not.toHaveBeenCalled();
|
||||||
|
expect(onTestSpy).not.toHaveBeenCalled();
|
||||||
|
expect(onAllTestsSpy).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return true when scenario test case', function() {
|
||||||
|
expect(p.runTestConfiguration(buildScenarioTestConf(), onTestSpy, onAllTestsSpy)).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call initAndRunTests when scenario test case', function() {
|
||||||
|
p.runTestConfiguration(buildScenarioTestConf(), onTestSpy, onAllTestsSpy);
|
||||||
|
expect(initScenarioSpy).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getTestRunsConfigurationFor', function() {
|
||||||
|
it('should add TestRunConfiguration with SCENARIO_TYPE TestCase', function() {
|
||||||
|
var configurations = [];
|
||||||
|
p.getTestRunsConfigurationFor(null, null, configurations);
|
||||||
|
|
||||||
|
expect(configurations.length).toBe(1);
|
||||||
|
expect(configurations[0] instanceof jstestdriver.TestRunConfiguration).toBe(true);
|
||||||
|
expect(configurations[0].getTestCaseInfo().getType()).toEqual(SCENARIO_TYPE);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should always return true', function() {
|
||||||
|
expect(p.getTestRunsConfigurationFor(null, null, [])).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('createTestResultFromSpec', function() {
|
||||||
|
it('should return jstestdriver.TestResult instance', function() {
|
||||||
|
expect(createTestResultFromSpec(buildSpec()) instanceof jstestdriver.TestResult).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set proper test name', function() {
|
||||||
|
expect(createTestResultFromSpec(buildSpec()).testName).toEqual('name');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set duration', function() {
|
||||||
|
expect(createTestResultFromSpec(buildSpec()).time).toEqual(10);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set test case - full definition name', function() {
|
||||||
|
var spec = buildSpec();
|
||||||
|
expect(createTestResultFromSpec(spec).testCaseName).toEqual(spec.fullDefinitionName);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set passed result when success', function() {
|
||||||
|
expect(createTestResultFromSpec(buildSpec('success')).result)
|
||||||
|
.toEqual(jstestdriver.TestResult.RESULT.PASSED);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set error result when error', function() {
|
||||||
|
expect(createTestResultFromSpec(buildSpec('error')).result)
|
||||||
|
.toEqual(jstestdriver.TestResult.RESULT.ERROR);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set failed result when failure', function() {
|
||||||
|
expect(createTestResultFromSpec(buildSpec('failure')).result)
|
||||||
|
.toEqual(jstestdriver.TestResult.RESULT.FAILED);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set error message when error/failure', function() {
|
||||||
|
expect(createTestResultFromSpec(buildErrorSpec('error-message')).message)
|
||||||
|
.toEqual('error-message');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should log line number when error/failure', function() {
|
||||||
|
expect(createTestResultFromSpec(buildErrorSpec('msg', 'line-number')).log)
|
||||||
|
.toEqual('line-number');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('angular.scenario.output.jstd', function() {
|
||||||
|
var model;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
var runner = new angular.scenario.testing.MockRunner(),
|
||||||
|
context = _jQuery("<div></div>");
|
||||||
|
|
||||||
|
plugin = new JstdPlugin();
|
||||||
|
model = new angular.scenario.ObjectModel(runner);
|
||||||
|
angular.scenario.output.jstd(context, runner, model);
|
||||||
|
|
||||||
|
spyOn(plugin, 'reportEnd');
|
||||||
|
spyOn(plugin, 'reportResult');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should report end of all tests', function() {
|
||||||
|
model.emit('RunnerEnd');
|
||||||
|
expect(plugin.reportEnd).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should report jstestdriver.TestResult', function() {
|
||||||
|
model.emit('SpecEnd', buildSpec());
|
||||||
|
expect(plugin.reportResult).toHaveBeenCalled();
|
||||||
|
expect(plugin.reportResult.argsForCall[0][0] instanceof jstestdriver.TestResult).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// couple of higher level tests (wiring objects together)
|
||||||
|
describe('HIGHER LEVEL', function() {
|
||||||
|
var initScenarioSpy, onTestSpy, onAllTestsSpy, model;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
plugin = new JstdPlugin();
|
||||||
|
initScenarioSpy = jasmine.createSpy('initScenarioAndRun');
|
||||||
|
onTestSpy = jasmine.createSpy('onOneTest');
|
||||||
|
onAllTestsSpy = jasmine.createSpy('onAllTests');
|
||||||
|
|
||||||
|
var runner = new angular.scenario.testing.MockRunner(),
|
||||||
|
context = _jQuery("<div></div>");
|
||||||
|
|
||||||
|
model = new angular.scenario.ObjectModel(runner);
|
||||||
|
angular.scenario.output.jstd(context, runner, model);
|
||||||
|
|
||||||
|
initScenarioAdapter(fakeJSTD, initScenarioSpy);
|
||||||
|
plugin.runTestConfiguration(buildScenarioTestConf(), onTestSpy, onAllTestsSpy);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(revertNavigateToHack);
|
||||||
|
|
||||||
|
it('should report and of test suite', function() {
|
||||||
|
model.emit('RunnerEnd');
|
||||||
|
expect(onAllTestsSpy).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should report success test result', function() {
|
||||||
|
model.emit('SpecEnd', buildSpec('success', 'name'));
|
||||||
|
expect(onTestSpy).toHaveBeenCalled();
|
||||||
|
var result = onTestSpy.argsForCall[0][0];
|
||||||
|
expect(result instanceof jstestdriver.TestResult).toBe(true);
|
||||||
|
expect(result.testName).toEqual('name');
|
||||||
|
expect(result.result).toEqual(jstestdriver.TestResult.RESULT.PASSED);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should report error test result', function() {
|
||||||
|
model.emit('SpecEnd', buildSpec('error'));
|
||||||
|
expect(onTestSpy).toHaveBeenCalled();
|
||||||
|
var result = onTestSpy.argsForCall[0][0];
|
||||||
|
expect(result.result).toEqual(jstestdriver.TestResult.RESULT.ERROR);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should report failed test result', function() {
|
||||||
|
model.emit('SpecEnd', buildSpec('failure'));
|
||||||
|
expect(onTestSpy).toHaveBeenCalled();
|
||||||
|
var result = onTestSpy.argsForCall[0][0];
|
||||||
|
expect(result.result).toEqual(jstestdriver.TestResult.RESULT.FAILED);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -107,4 +107,14 @@ describe('angular.scenario.Describe', function() {
|
||||||
var b = new angular.scenario.Describe();
|
var b = new angular.scenario.Describe();
|
||||||
expect(a.id).toNotEqual(b.id);
|
expect(a.id).toNotEqual(b.id);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should create uniqueIds for each spec', function() {
|
||||||
|
var d = new angular.scenario.Describe();
|
||||||
|
d.it('fake', function() {});
|
||||||
|
d.it('fake', function() {});
|
||||||
|
|
||||||
|
expect(d.its[0].id).toBeDefined();
|
||||||
|
expect(d.its[1].id).toBeDefined();
|
||||||
|
expect(d.its[0].id).not.toEqual(d.its[1].id);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -3,18 +3,36 @@ describe('angular.scenario.ObjectModel', function() {
|
||||||
var runner;
|
var runner;
|
||||||
var spec, step;
|
var spec, step;
|
||||||
|
|
||||||
beforeEach(function() {
|
function buildSpec(id, name, definitions) {
|
||||||
spec = {
|
var spec = {
|
||||||
name: 'test spec',
|
id: id,
|
||||||
|
name: name,
|
||||||
definition: {
|
definition: {
|
||||||
id: 10,
|
name: definitions.shift()
|
||||||
name: 'describe 1'
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
step = {
|
var currentDef = spec.definition;
|
||||||
name: 'test step',
|
|
||||||
line: function() { return ''; }
|
forEach(definitions, function(defName) {
|
||||||
|
currentDef.parent = {
|
||||||
|
name: defName
|
||||||
|
};
|
||||||
|
currentDef = currentDef.parent;
|
||||||
|
});
|
||||||
|
|
||||||
|
return spec;
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildStep(name, line) {
|
||||||
|
return {
|
||||||
|
name: name || 'test step',
|
||||||
|
line: function() { return line || ''; }
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
spec = buildSpec(1, 'test spec', ['describe 1']);
|
||||||
|
step = buildStep();
|
||||||
runner = new angular.scenario.testing.MockRunner();
|
runner = new angular.scenario.testing.MockRunner();
|
||||||
model = new angular.scenario.ObjectModel(runner);
|
model = new angular.scenario.ObjectModel(runner);
|
||||||
});
|
});
|
||||||
|
|
@ -27,23 +45,28 @@ describe('angular.scenario.ObjectModel', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should add spec and create describe blocks on SpecBegin event', function() {
|
it('should add spec and create describe blocks on SpecBegin event', function() {
|
||||||
runner.emit('SpecBegin', {
|
runner.emit('SpecBegin', buildSpec(1, 'test spec', ['describe 2', 'describe 1']));
|
||||||
name: 'test spec',
|
|
||||||
definition: {
|
|
||||||
id: 10,
|
|
||||||
name: 'describe 2',
|
|
||||||
parent: {
|
|
||||||
id: 12,
|
|
||||||
name: 'describe 1'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(model.value.children['describe 1']).toBeDefined();
|
expect(model.value.children['describe 1']).toBeDefined();
|
||||||
expect(model.value.children['describe 1'].children['describe 2']).toBeDefined();
|
expect(model.value.children['describe 1'].children['describe 2']).toBeDefined();
|
||||||
expect(model.value.children['describe 1'].children['describe 2'].specs['test spec']).toBeDefined();
|
expect(model.value.children['describe 1'].children['describe 2'].specs['test spec']).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should set fullDefinitionName on SpecBegin event', function() {
|
||||||
|
runner.emit('SpecBegin', buildSpec(1, 'fake spec', ['describe 2']));
|
||||||
|
var spec = model.getSpec(1);
|
||||||
|
|
||||||
|
expect(spec.fullDefinitionName).toBeDefined();
|
||||||
|
expect(spec.fullDefinitionName).toEqual('describe 2');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set fullDefinitionName on SpecBegin event (join more names by space)', function() {
|
||||||
|
runner.emit('SpecBegin', buildSpec(1, 'fake spec', ['describe 2', 'describe 1']));
|
||||||
|
var spec = model.getSpec(1);
|
||||||
|
|
||||||
|
expect(spec.fullDefinitionName).toEqual('describe 1 describe 2');
|
||||||
|
});
|
||||||
|
|
||||||
it('should add step to spec on StepBegin', function() {
|
it('should add step to spec on StepBegin', function() {
|
||||||
runner.emit('SpecBegin', spec);
|
runner.emit('SpecBegin', spec);
|
||||||
runner.emit('StepBegin', spec, step);
|
runner.emit('StepBegin', spec, step);
|
||||||
|
|
@ -109,4 +132,200 @@ describe('angular.scenario.ObjectModel', function() {
|
||||||
|
|
||||||
expect(model.value.children['describe 1'].specs['test spec'].status).toEqual('error');
|
expect(model.value.children['describe 1'].specs['test spec'].status).toEqual('error');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('events', function() {
|
||||||
|
var Spec = angular.scenario.ObjectModel.Spec,
|
||||||
|
Step = angular.scenario.ObjectModel.Step,
|
||||||
|
callback;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
callback = jasmine.createSpy('listener');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should provide method for registering a listener', function() {
|
||||||
|
expect(model.on).toBeDefined();
|
||||||
|
expect(model.on instanceof Function).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should forward SpecBegin event', function() {
|
||||||
|
model.on('SpecBegin', callback);
|
||||||
|
runner.emit('SpecBegin', spec);
|
||||||
|
|
||||||
|
expect(callback).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should forward SpecBegin event with ObjectModel.Spec as a param', function() {
|
||||||
|
model.on('SpecBegin', callback);
|
||||||
|
runner.emit('SpecBegin', spec);
|
||||||
|
|
||||||
|
expect(callback.mostRecentCall.args[0] instanceof Spec).toBe(true);
|
||||||
|
expect(callback.mostRecentCall.args[0].name).toEqual(spec.name);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should forward SpecError event', function() {
|
||||||
|
model.on('SpecError', callback);
|
||||||
|
runner.emit('SpecBegin', spec);
|
||||||
|
runner.emit('SpecError', spec, {});
|
||||||
|
|
||||||
|
expect(callback).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should forward SpecError event with ObjectModel.Spec and error as a params', function() {
|
||||||
|
var error = {};
|
||||||
|
model.on('SpecError', callback);
|
||||||
|
runner.emit('SpecBegin', spec);
|
||||||
|
runner.emit('SpecError', spec, error);
|
||||||
|
|
||||||
|
var param = callback.mostRecentCall.args[0];
|
||||||
|
expect(param instanceof Spec).toBe(true);
|
||||||
|
expect(param.name).toEqual(spec.name);
|
||||||
|
expect(param.status).toEqual('error');
|
||||||
|
expect(param.error).toBe(error);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should forward SpecEnd event', function() {
|
||||||
|
model.on('SpecEnd', callback);
|
||||||
|
runner.emit('SpecBegin', spec);
|
||||||
|
runner.emit('SpecEnd', spec);
|
||||||
|
|
||||||
|
expect(callback).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should forward SpecEnd event with ObjectModel.Spec as a param', function() {
|
||||||
|
model.on('SpecEnd', callback);
|
||||||
|
runner.emit('SpecBegin', spec);
|
||||||
|
runner.emit('SpecEnd', spec);
|
||||||
|
|
||||||
|
expect(callback.mostRecentCall.args[0] instanceof Spec).toBe(true);
|
||||||
|
expect(callback.mostRecentCall.args[0].name).toEqual(spec.name);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should forward StepBegin event', function() {
|
||||||
|
model.on('StepBegin', callback);
|
||||||
|
runner.emit('SpecBegin', spec);
|
||||||
|
runner.emit('StepBegin', spec, step);
|
||||||
|
|
||||||
|
expect(callback).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should forward StepBegin event with Spec and Step as params', function() {
|
||||||
|
model.on('StepBegin', callback);
|
||||||
|
runner.emit('SpecBegin', spec);
|
||||||
|
runner.emit('StepBegin', spec, step);
|
||||||
|
|
||||||
|
var params = callback.mostRecentCall.args;
|
||||||
|
expect(params[0] instanceof Spec).toBe(true);
|
||||||
|
expect(params[0].name).toEqual(spec.name);
|
||||||
|
expect(params[1] instanceof Step).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should forward StepError event', function() {
|
||||||
|
model.on('StepError', callback);
|
||||||
|
runner.emit('SpecBegin', spec);
|
||||||
|
runner.emit('StepBegin', spec, step);
|
||||||
|
runner.emit('StepError', spec, step, {});
|
||||||
|
|
||||||
|
expect(callback).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should forward StepError event with Spec, Step and error as params', function() {
|
||||||
|
var error = {};
|
||||||
|
model.on('StepError', callback);
|
||||||
|
runner.emit('SpecBegin', spec);
|
||||||
|
runner.emit('StepBegin', spec, step);
|
||||||
|
runner.emit('StepError', spec, step, error);
|
||||||
|
|
||||||
|
var params = callback.mostRecentCall.args;
|
||||||
|
expect(params[0] instanceof Spec).toBe(true);
|
||||||
|
expect(params[0].name).toEqual(spec.name);
|
||||||
|
expect(params[1] instanceof Step).toBe(true);
|
||||||
|
expect(params[1].status).toEqual('error');
|
||||||
|
expect(params[2]).toBe(error);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should forward StepFailure event', function() {
|
||||||
|
model.on('StepFailure', callback);
|
||||||
|
runner.emit('SpecBegin', spec);
|
||||||
|
runner.emit('StepBegin', spec, step);
|
||||||
|
runner.emit('StepFailure', spec, step, {});
|
||||||
|
|
||||||
|
expect(callback).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should forward StepFailure event with Spec, Step and error as params', function() {
|
||||||
|
var error = {};
|
||||||
|
model.on('StepFailure', callback);
|
||||||
|
runner.emit('SpecBegin', spec);
|
||||||
|
runner.emit('StepBegin', spec, step);
|
||||||
|
runner.emit('StepFailure', spec, step, error);
|
||||||
|
|
||||||
|
var params = callback.mostRecentCall.args;
|
||||||
|
expect(params[0] instanceof Spec).toBe(true);
|
||||||
|
expect(params[0].name).toEqual(spec.name);
|
||||||
|
expect(params[1] instanceof Step).toBe(true);
|
||||||
|
expect(params[1].status).toEqual('failure');
|
||||||
|
expect(params[2]).toBe(error);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should forward StepEnd event', function() {
|
||||||
|
model.on('StepEnd', callback);
|
||||||
|
runner.emit('SpecBegin', spec);
|
||||||
|
runner.emit('StepBegin', spec, step);
|
||||||
|
runner.emit('StepEnd', spec, step);
|
||||||
|
|
||||||
|
expect(callback).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should forward StepEnd event with Spec and Step as params', function() {
|
||||||
|
model.on('StepEnd', callback);
|
||||||
|
runner.emit('SpecBegin', spec);
|
||||||
|
runner.emit('StepBegin', spec, step);
|
||||||
|
runner.emit('StepEnd', spec, step);
|
||||||
|
|
||||||
|
var params = callback.mostRecentCall.args;
|
||||||
|
expect(params[0] instanceof Spec).toBe(true);
|
||||||
|
expect(params[0].name).toEqual(spec.name);
|
||||||
|
expect(params[1] instanceof Step).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should forward RunnerEnd event', function() {
|
||||||
|
model.on('RunnerEnd', callback);
|
||||||
|
runner.emit('RunnerEnd');
|
||||||
|
expect(callback).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set error of first failure', function() {
|
||||||
|
var error = 'first-error',
|
||||||
|
step2 = buildStep();
|
||||||
|
|
||||||
|
model.on('SpecEnd', function(spec) {
|
||||||
|
expect(spec.error).toBeDefined();
|
||||||
|
expect(spec.error).toBe(error);
|
||||||
|
});
|
||||||
|
|
||||||
|
runner.emit('SpecBegin', spec);
|
||||||
|
runner.emit('StepBegin', spec, step);
|
||||||
|
runner.emit('StepFailure', spec, step, error);
|
||||||
|
runner.emit('StepBegin', spec, step2);
|
||||||
|
runner.emit('StepFailure', spec, step2, 'second-error');
|
||||||
|
runner.emit('SpecEnd', spec);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set line number of first failure', function() {
|
||||||
|
var step = buildStep('fake', 'first-line'),
|
||||||
|
step2 = buildStep('fake2', 'second-line');
|
||||||
|
|
||||||
|
model.on('SpecEnd', function(spec) {
|
||||||
|
expect(spec.line).toBeDefined();
|
||||||
|
expect(spec.line).toBe('first-line');
|
||||||
|
});
|
||||||
|
|
||||||
|
runner.emit('SpecBegin', spec);
|
||||||
|
runner.emit('StepBegin', spec, step);
|
||||||
|
runner.emit('StepFailure', spec, step, null);
|
||||||
|
runner.emit('StepBegin', spec, step2);
|
||||||
|
runner.emit('StepFailure', spec, step2, null);
|
||||||
|
runner.emit('SpecEnd', spec);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
describe('angular.scenario.output.html', function() {
|
describe('angular.scenario.output.html', function() {
|
||||||
var runner, spec, listeners;
|
var runner, model, spec, listeners;
|
||||||
var ui, context;
|
var ui, context;
|
||||||
|
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
|
|
@ -22,8 +22,9 @@ describe('angular.scenario.output.html', function() {
|
||||||
line: function() { return 'unknown:-1'; }
|
line: function() { return 'unknown:-1'; }
|
||||||
};
|
};
|
||||||
runner = new angular.scenario.testing.MockRunner();
|
runner = new angular.scenario.testing.MockRunner();
|
||||||
|
model = new angular.scenario.ObjectModel(runner);
|
||||||
context = _jQuery("<div></div>");
|
context = _jQuery("<div></div>");
|
||||||
ui = angular.scenario.output.html(context, runner);
|
ui = angular.scenario.output.html(context, runner, model);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create nested describe context', function() {
|
it('should create nested describe context', function() {
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,14 @@
|
||||||
describe('angular.scenario.output.json', function() {
|
describe('angular.scenario.output.json', function() {
|
||||||
var output, context;
|
var output, context;
|
||||||
var runner, $window;
|
var runner, model, $window;
|
||||||
var spec, step;
|
var spec, step;
|
||||||
|
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
$window = {};
|
$window = {};
|
||||||
context = _jQuery('<div></div>');
|
context = _jQuery('<div></div>');
|
||||||
runner = new angular.scenario.testing.MockRunner();
|
runner = new angular.scenario.testing.MockRunner();
|
||||||
output = angular.scenario.output.json(context, runner);
|
model = new angular.scenario.ObjectModel(runner);
|
||||||
|
output = angular.scenario.output.json(context, runner, model);
|
||||||
spec = {
|
spec = {
|
||||||
name: 'test spec',
|
name: 'test spec',
|
||||||
definition: {
|
definition: {
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,14 @@
|
||||||
describe('angular.scenario.output.object', function() {
|
describe('angular.scenario.output.object', function() {
|
||||||
var output;
|
var output;
|
||||||
var runner, $window;
|
var runner, model, $window;
|
||||||
var spec, step;
|
var spec, step;
|
||||||
|
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
$window = {};
|
$window = {};
|
||||||
runner = new angular.scenario.testing.MockRunner();
|
runner = new angular.scenario.testing.MockRunner();
|
||||||
|
model = new angular.scenario.ObjectModel(runner);
|
||||||
runner.$window = $window;
|
runner.$window = $window;
|
||||||
output = angular.scenario.output.object(null, runner);
|
output = angular.scenario.output.object(null, runner, model);
|
||||||
spec = {
|
spec = {
|
||||||
name: 'test spec',
|
name: 'test spec',
|
||||||
definition: {
|
definition: {
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,14 @@
|
||||||
describe('angular.scenario.output.json', function() {
|
describe('angular.scenario.output.json', function() {
|
||||||
var output, context;
|
var output, context;
|
||||||
var runner, $window;
|
var runner, model, $window;
|
||||||
var spec, step;
|
var spec, step;
|
||||||
|
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
$window = {};
|
$window = {};
|
||||||
context = _jQuery('<div></div>');
|
context = _jQuery('<div></div>');
|
||||||
runner = new angular.scenario.testing.MockRunner();
|
runner = new angular.scenario.testing.MockRunner();
|
||||||
output = angular.scenario.output.xml(context, runner);
|
model = new angular.scenario.ObjectModel(runner);
|
||||||
|
output = angular.scenario.output.xml(context, runner, model);
|
||||||
spec = {
|
spec = {
|
||||||
name: 'test spec',
|
name: 'test spec',
|
||||||
definition: {
|
definition: {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue