jasmine-core 2.0.2 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/lib/console/console.js +26 -2
  3. data/lib/jasmine-core.js +31 -23
  4. data/lib/jasmine-core/boot.js +1 -1
  5. data/lib/jasmine-core/boot/boot.js +1 -1
  6. data/lib/jasmine-core/example/node_example/spec/PlayerSpec.js +2 -2
  7. data/lib/jasmine-core/jasmine-html.js +16 -2
  8. data/lib/jasmine-core/jasmine.css +11 -10
  9. data/lib/jasmine-core/jasmine.js +709 -395
  10. data/lib/jasmine-core/json2.js +73 -62
  11. data/lib/jasmine-core/spec/console/ConsoleReporterSpec.js +39 -8
  12. data/lib/jasmine-core/spec/core/ClockSpec.js +19 -1
  13. data/lib/jasmine-core/spec/core/DelayedFunctionSchedulerSpec.js +13 -0
  14. data/lib/jasmine-core/spec/core/EnvSpec.js +0 -63
  15. data/lib/jasmine-core/spec/core/ExpectationSpec.js +15 -53
  16. data/lib/jasmine-core/spec/core/JsApiReporterSpec.js +37 -0
  17. data/lib/jasmine-core/spec/core/MockDateSpec.js +1 -0
  18. data/lib/jasmine-core/spec/core/PrettyPrintSpec.js +8 -2
  19. data/lib/jasmine-core/spec/core/QueueRunnerSpec.js +91 -66
  20. data/lib/jasmine-core/spec/core/SpecSpec.js +25 -26
  21. data/lib/jasmine-core/spec/core/SpyRegistrySpec.js +55 -0
  22. data/lib/jasmine-core/spec/core/SpySpec.js +10 -0
  23. data/lib/jasmine-core/spec/core/SpyStrategySpec.js +13 -0
  24. data/lib/jasmine-core/spec/core/SuiteSpec.js +108 -10
  25. data/lib/jasmine-core/spec/core/integration/CustomMatchersSpec.js +34 -32
  26. data/lib/jasmine-core/spec/core/integration/EnvSpec.js +950 -35
  27. data/lib/jasmine-core/spec/core/integration/SpecRunningSpec.js +279 -3
  28. data/lib/jasmine-core/spec/core/matchers/matchersUtilSpec.js +10 -1
  29. data/lib/jasmine-core/spec/core/matchers/toThrowErrorSpec.js +5 -5
  30. data/lib/jasmine-core/spec/html/HtmlReporterSpec.js +30 -2
  31. data/lib/jasmine-core/spec/node_suite.js +195 -0
  32. data/lib/jasmine-core/spec/npmPackage/npmPackageSpec.js +104 -0
  33. data/lib/jasmine-core/version.rb +1 -1
  34. metadata +6 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7c4cf0529b3fa9d73a1d2564efe07c6179aeb27e
4
- data.tar.gz: 2ed25d81371e194e2327a346c9371aa708277261
3
+ metadata.gz: b3c55f40da8c8da5e3d89ae36a5aaae867bd50ea
4
+ data.tar.gz: 3d48a8581f0ca9decccbb8fe75ae82f22bd99e40
5
5
  SHA512:
6
- metadata.gz: 78bc77920cc082290ba96c3f460702bcd87270b25b1602857c604d87ddc5625d9327378d8deb39ef67ee70e64a4f9ad3e7783cf68911c5460725ad6669e371b0
7
- data.tar.gz: 8e427d33f10cfb7d79ba3d61bb8f449d9fef7c82d5205b807e21f2c91949e0823b4e9646a02e4178d5765d6ce9e2982b6ab1992411a21a09bcafb91b2ff6d4f9
6
+ metadata.gz: e506e314ceeef5435bdd4ad916f93efe9c006cc71f5404c0376c2718fe10af4a83a4d51ffc3df7b143d9000484d6ae19013675e00cda8607db9cb0f3f27dbae9
7
+ data.tar.gz: d1856674ca87ce7da66ec763ba372bbc034631943f607ae4b1ece8ee395112cd2027feecb217c115a90de4e0201a614894ff25dff6fd6d6746954af075585113
@@ -54,7 +54,10 @@ getJasmineRequireObj().ConsoleReporter = function() {
54
54
  red: '\x1B[31m',
55
55
  yellow: '\x1B[33m',
56
56
  none: '\x1B[0m'
57
- };
57
+ },
58
+ failedSuites = [];
59
+
60
+ print('ConsoleReporter is deprecated and will be removed in a future version.');
58
61
 
59
62
  this.jasmineStarted = function() {
60
63
  specCount = 0;
@@ -89,9 +92,12 @@ getJasmineRequireObj().ConsoleReporter = function() {
89
92
  printNewline();
90
93
  var seconds = timer.elapsed() / 1000;
91
94
  print('Finished in ' + seconds + ' ' + plural('second', seconds));
92
-
93
95
  printNewline();
94
96
 
97
+ for(i = 0; i < failedSuites.length; i++) {
98
+ suiteFailureDetails(failedSuites[i]);
99
+ }
100
+
95
101
  onComplete(failureCount === 0);
96
102
  };
97
103
 
@@ -116,6 +122,13 @@ getJasmineRequireObj().ConsoleReporter = function() {
116
122
  }
117
123
  };
118
124
 
125
+ this.suiteDone = function(result) {
126
+ if (result.failedExpectations && result.failedExpectations.length > 0) {
127
+ failureCount++;
128
+ failedSuites.push(result);
129
+ }
130
+ };
131
+
119
132
  return this;
120
133
 
121
134
  function printNewline() {
@@ -160,6 +173,17 @@ getJasmineRequireObj().ConsoleReporter = function() {
160
173
 
161
174
  printNewline();
162
175
  }
176
+
177
+ function suiteFailureDetails(result) {
178
+ for (var i = 0; i < result.failedExpectations.length; i++) {
179
+ printNewline();
180
+ print(colored('red', 'An error was thrown in an afterAll'));
181
+ printNewline();
182
+ print(colored('red', 'AfterAll ' + result.failedExpectations[i].message));
183
+
184
+ }
185
+ printNewline();
186
+ }
163
187
  }
164
188
 
165
189
  return ConsoleReporter;
data/lib/jasmine-core.js CHANGED
@@ -1,29 +1,37 @@
1
1
  module.exports = require("./jasmine-core/jasmine.js");
2
2
  module.exports.boot = require('./jasmine-core/node_boot.js');
3
3
 
4
- module.exports.files = (function() {
5
- var path = require('path'),
6
- fs = require('fs'),
7
- glob = require('glob');
4
+ var path = require('path'),
5
+ fs = require('fs');
8
6
 
9
- var rootPath = path.join(__dirname, "jasmine-core"),
10
- bootFiles = ['boot.js'],
11
- nodeBootFiles = ['node_boot.js'];
7
+ var rootPath = path.join(__dirname, "jasmine-core"),
8
+ bootFiles = ['boot.js'],
9
+ nodeBootFiles = ['node_boot.js'],
10
+ cssFiles = [],
11
+ jsFiles = [],
12
+ jsFilesToSkip = ['jasmine.js'].concat(bootFiles, nodeBootFiles);
12
13
 
13
- var cssFiles = glob.sync(path.join(rootPath, '*.css')).map(path.basename);
14
- var jsFiles = glob.sync(path.join(rootPath, '*.js')).map(path.basename);
14
+ fs.readdirSync(rootPath).forEach(function(file) {
15
+ if(fs.statSync(path.join(rootPath, file)).isFile()) {
16
+ switch(path.extname(file)) {
17
+ case '.css':
18
+ cssFiles.push(file);
19
+ break;
20
+ case '.js':
21
+ if (jsFilesToSkip.indexOf(file) < 0) {
22
+ jsFiles.push(file);
23
+ }
24
+ break;
25
+ }
26
+ }
27
+ });
15
28
 
16
- ['jasmine.js'].concat(bootFiles, nodeBootFiles).forEach(function(file) {
17
- jsFiles.splice(jsFiles.indexOf(file), 1);
18
- });
19
-
20
- return {
21
- path: rootPath,
22
- bootDir: rootPath,
23
- bootFiles: bootFiles,
24
- nodeBootFiles: nodeBootFiles,
25
- cssFiles: cssFiles,
26
- jsFiles: ['jasmine.js'].concat(jsFiles),
27
- imagesDir: path.join(__dirname, '../images')
28
- };
29
- }());
29
+ module.exports.files = {
30
+ path: rootPath,
31
+ bootDir: rootPath,
32
+ bootFiles: bootFiles,
33
+ nodeBootFiles: nodeBootFiles,
34
+ cssFiles: cssFiles,
35
+ jsFiles: ['jasmine.js'].concat(jsFiles),
36
+ imagesDir: path.join(__dirname, '../images')
37
+ };
@@ -21,7 +21,7 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
21
  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
22
  */
23
23
  /**
24
- Starting with version 2.0, this file "boots" Jasmine, performing all of the necessary initialization before executing the loaded environment and all of a project's specs. This file should be loaded after `jasmine.js`, but before any project source files or spec files are loaded. Thus this file can also be used to customize Jasmine for a project.
24
+ Starting with version 2.0, this file "boots" Jasmine, performing all of the necessary initialization before executing the loaded environment and all of a project's specs. This file should be loaded after `jasmine.js` and `jasmine_html.js`, but before any project source files or spec files are loaded. Thus this file can also be used to customize Jasmine for a project.
25
25
 
26
26
  If a project is using Jasmine via the standalone distribution, this file can be customized directly. If a project is using Jasmine via the [Ruby gem][jasmine-gem], this file can be copied into the support directory via `jasmine copy_boot_js`. Other environments (e.g., Python) will have different mechanisms.
27
27
 
@@ -1,5 +1,5 @@
1
1
  /**
2
- Starting with version 2.0, this file "boots" Jasmine, performing all of the necessary initialization before executing the loaded environment and all of a project's specs. This file should be loaded after `jasmine.js`, but before any project source files or spec files are loaded. Thus this file can also be used to customize Jasmine for a project.
2
+ Starting with version 2.0, this file "boots" Jasmine, performing all of the necessary initialization before executing the loaded environment and all of a project's specs. This file should be loaded after `jasmine.js` and `jasmine_html.js`, but before any project source files or spec files are loaded. Thus this file can also be used to customize Jasmine for a project.
3
3
 
4
4
  If a project is using Jasmine via the standalone distribution, this file can be customized directly. If a project is using Jasmine via the [Ruby gem][jasmine-gem], this file can be copied into the support directory via `jasmine copy_boot_js`. Other environments (e.g., Python) will have different mechanisms.
5
5
 
@@ -1,6 +1,6 @@
1
1
  describe("Player", function() {
2
- var Player = require('../../jasmine_examples/Player.js');
3
- var Song = require('../../jasmine_examples/Song.js');
2
+ var Player = require('../src/Player.js');
3
+ var Song = require('../src/Song.js');
4
4
  var player;
5
5
  var song;
6
6
 
@@ -46,7 +46,8 @@ jasmineRequire.HtmlReporter = function(j$) {
46
46
  failureCount = 0,
47
47
  pendingSpecCount = 0,
48
48
  htmlReporterMain,
49
- symbols;
49
+ symbols,
50
+ failedSuites = [];
50
51
 
51
52
  this.initialize = function() {
52
53
  clearPrior();
@@ -83,6 +84,10 @@ jasmineRequire.HtmlReporter = function(j$) {
83
84
  };
84
85
 
85
86
  this.suiteDone = function(result) {
87
+ if (result.status == 'failed') {
88
+ failedSuites.push(result);
89
+ }
90
+
86
91
  if (currentParent == topResults) {
87
92
  return;
88
93
  }
@@ -96,7 +101,7 @@ jasmineRequire.HtmlReporter = function(j$) {
96
101
 
97
102
  var failures = [];
98
103
  this.specDone = function(result) {
99
- if(noExpectations(result) && console && console.error) {
104
+ if(noExpectations(result) && typeof console !== 'undefined' && typeof console.error !== 'undefined') {
100
105
  console.error('Spec \'' + result.fullName + '\' has no expectations.');
101
106
  }
102
107
 
@@ -178,6 +183,15 @@ jasmineRequire.HtmlReporter = function(j$) {
178
183
 
179
184
  alert.appendChild(createDom('span', {className: statusBarClassName}, statusBarMessage));
180
185
 
186
+ for(i = 0; i < failedSuites.length; i++) {
187
+ var failedSuite = failedSuites[i];
188
+ for(var j = 0; j < failedSuite.failedExpectations.length; j++) {
189
+ var errorBarMessage = 'AfterAll ' + failedSuite.failedExpectations[j].message;
190
+ var errorBarClassName = 'bar errored';
191
+ alert.appendChild(createDom('span', {className: errorBarClassName}, errorBarMessage));
192
+ }
193
+ }
194
+
181
195
  var results = find('.results');
182
196
  results.appendChild(summary);
183
197
 
@@ -1,18 +1,18 @@
1
1
  body { overflow-y: scroll; }
2
2
 
3
- .jasmine_html-reporter { background-color: #eeeeee; padding: 5px; margin: -8px; font-size: 11px; font-family: Monaco, "Lucida Console", monospace; line-height: 14px; color: #333333; }
3
+ .jasmine_html-reporter { background-color: #eee; padding: 5px; margin: -8px; font-size: 11px; font-family: Monaco, "Lucida Console", monospace; line-height: 14px; color: #333; }
4
4
  .jasmine_html-reporter a { text-decoration: none; }
5
5
  .jasmine_html-reporter a:hover { text-decoration: underline; }
6
6
  .jasmine_html-reporter p, .jasmine_html-reporter h1, .jasmine_html-reporter h2, .jasmine_html-reporter h3, .jasmine_html-reporter h4, .jasmine_html-reporter h5, .jasmine_html-reporter h6 { margin: 0; line-height: 14px; }
7
7
  .jasmine_html-reporter .banner, .jasmine_html-reporter .symbol-summary, .jasmine_html-reporter .summary, .jasmine_html-reporter .result-message, .jasmine_html-reporter .spec .description, .jasmine_html-reporter .spec-detail .description, .jasmine_html-reporter .alert .bar, .jasmine_html-reporter .stack-trace { padding-left: 9px; padding-right: 9px; }
8
8
  .jasmine_html-reporter .banner { position: relative; }
9
- .jasmine_html-reporter .banner .title { background: url('data:image/png;base64,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') no-repeat; background: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhLS0gQ3JlYXRlZCB3aXRoIElua3NjYXBlIChodHRwOi8vd3d3Lmlua3NjYXBlLm9yZy8pIC0tPgoKPHN2ZwogICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iCiAgIHhtbG5zOmNjPSJodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9ucyMiCiAgIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyIKICAgeG1sbnM6c3ZnPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogICB4bWxuczppbmtzY2FwZT0iaHR0cDovL3d3dy5pbmtzY2FwZS5vcmcvbmFtZXNwYWNlcy9pbmtzY2FwZSIKICAgdmVyc2lvbj0iMS4xIgogICB3aWR0aD0iNjgxLjk2MjUyIgogICBoZWlnaHQ9IjE4Ny41IgogICBpZD0ic3ZnMiIKICAgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+PG1ldGFkYXRhCiAgICAgaWQ9Im1ldGFkYXRhOCI+PHJkZjpSREY+PGNjOldvcmsKICAgICAgICAgcmRmOmFib3V0PSIiPjxkYzpmb3JtYXQ+aW1hZ2Uvc3ZnK3htbDwvZGM6Zm9ybWF0PjxkYzp0eXBlCiAgICAgICAgICAgcmRmOnJlc291cmNlPSJodHRwOi8vcHVybC5vcmcvZGMvZGNtaXR5cGUvU3RpbGxJbWFnZSIgLz48L2NjOldvcms+PC9yZGY6UkRGPjwvbWV0YWRhdGE+PGRlZnMKICAgICBpZD0iZGVmczYiPjxjbGlwUGF0aAogICAgICAgaWQ9ImNsaXBQYXRoMTgiPjxwYXRoCiAgICAgICAgIGQ9Ik0gMCwxNTAwIDAsMCBsIDU0NTUuNzQsMCAwLDE1MDAgTCAwLDE1MDAgeiIKICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgaWQ9InBhdGgyMCIgLz48L2NsaXBQYXRoPjwvZGVmcz48ZwogICAgIHRyYW5zZm9ybT0ibWF0cml4KDEuMjUsMCwwLC0xLjI1LDAsMTg3LjUpIgogICAgIGlkPSJnMTAiPjxnCiAgICAgICB0cmFuc2Zvcm09InNjYWxlKDAuMSwwLjEpIgogICAgICAgaWQ9ImcxMiI+PGcKICAgICAgICAgaWQ9ImcxNCI+PGcKICAgICAgICAgICBjbGlwLXBhdGg9InVybCgjY2xpcFBhdGgxOCkiCiAgICAgICAgICAgaWQ9ImcxNiI+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gMTU0NCw1OTkuNDM0IGMgMC45MiwtNDAuMzUyIDI1LjY4LC04MS42MDIgNzEuNTMsLTgxLjYwMiAyNy41MSwwIDQ3LjY4LDEyLjgzMiA2MS40NCwzNS43NTQgMTIuODMsMjIuOTMgMTIuODMsNTYuODUyIDEyLjgzLDgyLjUyNyBsIDAsMzI5LjE4NCAtNzEuNTIsMCAwLDEwNC41NDMgMjY2LjgzLDAgMCwtMTA0LjU0MyAtNzAuNiwwIDAsLTM0NC43NyBjIDAsLTU4LjY5MSAtMy42OCwtMTA0LjUzMSAtNDQuOTMsLTE1Mi4yMTggLTM2LjY4LC00Mi4xOCAtOTYuMjgsLTY2LjAyIC0xNTMuMTQsLTY2LjAyIC0xMTcuMzcsMCAtMjA3LjI0LDc3Ljk0MSAtMjAyLjY0LDE5Ny4xNDUgbCAxMzAuMiwwIgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMjIiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDIzMDEuNCw2NjIuNjk1IGMgMCw4MC43MDMgLTY2Ljk0LDE0NS44MTMgLTE0Ny42MywxNDUuODEzIC04My40NCwwIC0xNDcuNjMsLTY4Ljc4MSAtMTQ3LjYzLC0xNTEuMzAxIDAsLTc5Ljc4NSA2Ni45NCwtMTQ1LjgwMSAxNDUuOCwtMTQ1LjgwMSA4NC4zNSwwIDE0OS40Niw2Ny44NTIgMTQ5LjQ2LDE1MS4yODkgeiBtIC0xLjgzLC0xODEuNTQ3IGMgLTM1Ljc3LC01NC4wOTcgLTkzLjUzLC03OC44NTkgLTE1Ny43MiwtNzguODU5IC0xNDAuMywwIC0yNTEuMjQsMTE2LjQ0OSAtMjUxLjI0LDI1NC45MTggMCwxNDIuMTI5IDExMy43LDI2MC40MSAyNTYuNzQsMjYwLjQxIDYzLjI3LDAgMTE4LjI5LC0yOS4zMzYgMTUyLjIyLC04Mi41MjMgbCAwLDY5LjY4NyAxNzUuMTQsMCAwLC0xMDQuNTI3IC02MS40NCwwIDAsLTI4MC41OTggNjEuNDQsMCAwLC0xMDQuNTI3IC0xNzUuMTQsMCAwLDY2LjAxOSIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDI0IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSAyNjIyLjMzLDU1Ny4yNTggYyAzLjY3LC00NC4wMTYgMzMuMDEsLTczLjM0OCA3OC44NiwtNzMuMzQ4IDMzLjkzLDAgNjYuOTMsMjMuODI0IDY2LjkzLDYwLjUwNCAwLDQ4LjYwNiAtNDUuODQsNTYuODU2IC04My40NCw2Ni45NDEgLTg1LjI4LDIyLjAwNCAtMTc4LjgxLDQ4LjYwNiAtMTc4LjgxLDE1NS44NzkgMCw5My41MzYgNzguODYsMTQ3LjYzMyAxNjUuOTgsMTQ3LjYzMyA0NCwwIDgzLjQzLC05LjE3NiAxMTAuOTQsLTQ0LjAwOCBsIDAsMzMuOTIyIDgyLjUzLDAgMCwtMTMyLjk2NSAtMTA4LjIxLDAgYyAtMS44MywzNC44NTYgLTI4LjQyLDU3Ljc3NCAtNjMuMjYsNTcuNzc0IC0zMC4yNiwwIC02Mi4zNSwtMTcuNDIyIC02Mi4zNSwtNTEuMzQ4IDAsLTQ1Ljg0NyA0NC45MywtNTUuOTMgODAuNjksLTY0LjE4IDg4LjAyLC0yMC4xNzUgMTgyLjQ3LC00Ny42OTUgMTgyLjQ3LC0xNTcuNzM0IDAsLTk5LjAyNyAtODMuNDQsLTE1NC4wMzkgLTE3NS4xMywtMTU0LjAzOSAtNDkuNTMsMCAtOTQuNDYsMTUuNTgyIC0xMjYuNTUsNTMuMTggbCAwLC00MC4zNCAtODUuMjcsMCAwLDE0Mi4xMjkgMTE0LjYyLDAiCiAgICAgICAgICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIgogICAgICAgICAgICAgaWQ9InBhdGgyNiIKICAgICAgICAgICAgIHN0eWxlPSJmaWxsOiM4YTQxODI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiIC8+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gMjk4OC4xOCw4MDAuMjU0IC02My4yNiwwIDAsMTA0LjUyNyAxNjUuMDUsMCAwLC03My4zNTUgYyAzMS4xOCw1MS4zNDcgNzguODYsODUuMjc3IDE0MS4yMSw4NS4yNzcgNjcuODUsMCAxMjQuNzEsLTQxLjI1OCAxNTIuMjEsLTEwMi42OTkgMjYuNiw2Mi4zNTEgOTIuNjIsMTAyLjY5OSAxNjAuNDcsMTAyLjY5OSA1My4xOSwwIDEwNS40NiwtMjIgMTQxLjIxLC02Mi4zNTEgMzguNTIsLTQ0LjkzOCAzOC41MiwtOTMuNTMyIDM4LjUyLC0xNDkuNDU3IGwgMCwtMTg1LjIzOSA2My4yNywwIDAsLTEwNC41MjcgLTIzOC40MiwwIDAsMTA0LjUyNyA2My4yOCwwIDAsMTU3LjcxNSBjIDAsMzIuMTAyIDAsNjAuNTI3IC0xNC42Nyw4OC45NTcgLTE4LjM0LDI2LjU4MiAtNDguNjEsNDAuMzQ0IC03OS43Nyw0MC4zNDQgLTMwLjI2LDAgLTYzLjI4LC0xMi44NDQgLTgyLjUzLC0zNi42NzIgLTIyLjkzLC0yOS4zNTUgLTIyLjkzLC01Ni44NjMgLTIyLjkzLC05Mi42MjkgbCAwLC0xNTcuNzE1IDYzLjI3LDAgMCwtMTA0LjUyNyAtMjM4LjQxLDAgMCwxMDQuNTI3IDYzLjI4LDAgMCwxNTAuMzgzIGMgMCwyOS4zNDggMCw2Ni4wMjMgLTE0LjY3LDkxLjY5OSAtMTUuNTksMjkuMzM2IC00Ny42OSw0NC45MzQgLTgwLjcsNDQuOTM0IC0zMS4xOCwwIC01Ny43NywtMTEuMDA4IC03Ny45NCwtMzUuNzc0IC0yNC43NywtMzAuMjUzIC0yNi42LC02Mi4zNDMgLTI2LjYsLTk5Ljk0MSBsIDAsLTE1MS4zMDEgNjMuMjcsMCAwLC0xMDQuNTI3IC0yMzguNCwwIDAsMTA0LjUyNyA2My4yNiwwIDAsMjgwLjU5OCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDI4IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSAzOTk4LjY2LDk1MS41NDcgLTExMS44NywwIDAsMTE4LjI5MyAxMTEuODcsMCAwLC0xMTguMjkzIHogbSAwLC00MzEuODkxIDYzLjI3LDAgMCwtMTA0LjUyNyAtMjM5LjMzLDAgMCwxMDQuNTI3IDY0LjE5LDAgMCwyODAuNTk4IC02My4yNywwIDAsMTA0LjUyNyAxNzUuMTQsMCAwLC0zODUuMTI1IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMzAiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDQxNTkuMTIsODAwLjI1NCAtNjMuMjcsMCAwLDEwNC41MjcgMTc1LjE0LDAgMCwtNjkuNjg3IGMgMjkuMzUsNTQuMTAxIDg0LjM2LDgwLjY5OSAxNDQuODcsODAuNjk5IDUzLjE5LDAgMTA1LjQ1LC0yMi4wMTYgMTQxLjIyLC02MC41MjcgNDAuMzQsLTQ0LjkzNCA0MS4yNiwtODguMDMyIDQxLjI2LC0xNDMuOTU3IGwgMCwtMTkxLjY1MyA2My4yNywwIDAsLTEwNC41MjcgLTIzOC40LDAgMCwxMDQuNTI3IDYzLjI2LDAgMCwxNTguNjM3IGMgMCwzMC4yNjIgMCw2MS40MzQgLTE5LjI2LDg4LjAzNSAtMjAuMTcsMjYuNTgyIC01My4xOCwzOS40MTQgLTg2LjE5LDM5LjQxNCAtMzMuOTMsMCAtNjguNzcsLTEzLjc1IC04OC45NCwtNDEuMjUgLTIxLjA5LC0yNy41IC0yMS4wOSwtNjkuNjg3IC0yMS4wOSwtMTAyLjcwNyBsIDAsLTE0Mi4xMjkgNjMuMjYsMCAwLC0xMDQuNTI3IC0yMzguNCwwIDAsMTA0LjUyNyA2My4yNywwIDAsMjgwLjU5OCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDMyIgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA1MDgyLjQ4LDcwMy45NjUgYyAtMTkuMjQsNzAuNjA1IC04MS42LDExNS41NDcgLTE1NC4wNCwxMTUuNTQ3IC02Ni4wNCwwIC0xMjkuMywtNTEuMzQ4IC0xNDMuMDUsLTExNS41NDcgbCAyOTcuMDksMCB6IG0gODUuMjcsLTE0NC44ODMgYyAtMzguNTEsLTkzLjUyMyAtMTI5LjI3LC0xNTYuNzkzIC0yMzEuMDUsLTE1Ni43OTMgLTE0My4wNywwIC0yNTcuNjgsMTExLjg3MSAtMjU3LjY4LDI1NS44MzYgMCwxNDQuODgzIDEwOS4xMiwyNjEuMzI4IDI1NC45MSwyNjEuMzI4IDY3Ljg3LDAgMTM1LjcyLC0zMC4yNTggMTgzLjM5LC03OC44NjMgNDguNjIsLTUxLjM0NCA2OC43OSwtMTEzLjY5NSA2OC43OSwtMTgzLjM4MyBsIC0zLjY3LC0zOS40MzQgLTM5Ni4xMywwIGMgMTQuNjcsLTY3Ljg2MyA3Ny4wMywtMTE3LjM2MyAxNDYuNzIsLTExNy4zNjMgNDguNTksMCA5MC43NiwxOC4zMjggMTE4LjI4LDU4LjY3MiBsIDExNi40NCwwIgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMzQiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDY5MC44OTUsODUwLjcwMyA5MC43NSwwIDIyLjU0MywzMS4wMzUgMCwyNDMuMTIyIC0xMzUuODI5LDAgMCwtMjQzLjE0MSAyMi41MzYsLTMxLjAxNiIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDM2IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA2MzIuMzk1LDc0Mi4yNTggMjguMDM5LDg2LjMwNCAtMjIuNTUxLDMxLjA0IC0yMzEuMjIzLDc1LjEyOCAtNDEuOTc2LC0xMjkuMTgzIDIzMS4yNTcsLTc1LjEzNyAzNi40NTQsMTEuODQ4IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMzgiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDcxNy40NDksNjUzLjEwNSAtNzMuNDEsNTMuMzYgLTM2LjQ4OCwtMTEuODc1IC0xNDIuOTAzLC0xOTYuNjkyIDEwOS44ODMsLTc5LjgyOCAxNDIuOTE4LDE5Ni43MDMgMCwzOC4zMzIiCiAgICAgICAgICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIgogICAgICAgICAgICAgaWQ9InBhdGg0MCIKICAgICAgICAgICAgIHN0eWxlPSJmaWxsOiM4YTQxODI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiIC8+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gODI4LjUyLDcwNi40NjUgLTczLjQyNiwtNTMuMzQgMC4wMTEsLTM4LjM1OSBMIDg5OC4wMDQsNDE4LjA3IDEwMDcuOSw0OTcuODk4IDg2NC45NzMsNjk0LjYwOSA4MjguNTIsNzA2LjQ2NSIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDQyIgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA4MTIuMDg2LDgyOC41ODYgMjguMDU1LC04Ni4zMiAzNi40ODQsLTExLjgzNiAyMzEuMjI1LDc1LjExNyAtNDEuOTcsMTI5LjE4MyAtMjMxLjIzOSwtNzUuMTQgLTIyLjU1NSwtMzEuMDA0IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoNDQiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDczNi4zMDEsMTMzNS44OCBjIC0zMjMuMDQ3LDAgLTU4NS44NzUsLTI2Mi43OCAtNTg1Ljg3NSwtNTg1Ljc4MiAwLC0zMjMuMTE4IDI2Mi44MjgsLTU4NS45NzcgNTg1Ljg3NSwtNTg1Ljk3NyAzMjMuMDE5LDAgNTg1LjgwOSwyNjIuODU5IDU4NS44MDksNTg1Ljk3NyAwLDMyMy4wMDIgLTI2Mi43OSw1ODUuNzgyIC01ODUuODA5LDU4NS43ODIgbCAwLDAgeiBtIDAsLTExOC42MSBjIDI1Ny45NzIsMCA0NjcuMTg5LC0yMDkuMTMgNDY3LjE4OSwtNDY3LjE3MiAwLC0yNTguMTI5IC0yMDkuMjE3LC00NjcuMzQ4IC00NjcuMTg5LC00NjcuMzQ4IC0yNTguMDc0LDAgLTQ2Ny4yNTQsMjA5LjIxOSAtNDY3LjI1NCw0NjcuMzQ4IDAsMjU4LjA0MiAyMDkuMTgsNDY3LjE3MiA0NjcuMjU0LDQ2Ny4xNzIiCiAgICAgICAgICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIgogICAgICAgICAgICAgaWQ9InBhdGg0NiIKICAgICAgICAgICAgIHN0eWxlPSJmaWxsOiM4YTQxODI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiIC8+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gMTA5MS4xMyw2MTkuODgzIC0xNzUuNzcxLDU3LjEyMSAxMS42MjksMzUuODA4IDE3NS43NjIsLTU3LjEyMSAtMTEuNjIsLTM1LjgwOCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDQ4IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0iTSA4NjYuOTU3LDkwMi4wNzQgODM2LjUsOTI0LjE5OSA5NDUuMTIxLDEwNzMuNzMgOTc1LjU4NiwxMDUxLjYxIDg2Ni45NTcsOTAyLjA3NCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDUwIgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0iTSA2MDcuNDY1LDkwMy40NDUgNDk4Ljg1NSwxMDUyLjk3IDUyOS4zMiwxMDc1LjEgNjM3LjkzLDkyNS41NjYgNjA3LjQ2NSw5MDMuNDQ1IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoNTIiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDM4MC42ODgsNjIyLjEyOSAtMTEuNjI2LDM1LjgwMSAxNzUuNzU4LDU3LjA5IDExLjYyMSwtMzUuODAxIC0xNzUuNzUzLC01Ny4wOSIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDU0IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA3MTYuMjg5LDM3Ni41OSAzNy42NDA2LDAgMCwxODQuODE2IC0zNy42NDA2LDAgMCwtMTg0LjgxNiB6IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoNTYiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjwvZz48L2c+PC9nPjwvZz48L3N2Zz4=') no-repeat, none; -webkit-background-size: 100%; -moz-background-size: 100%; -o-background-size: 100%; background-size: 100%; display: block; float: left; width: 90px; height: 25px; }
9
+ .jasmine_html-reporter .banner .title { background: url('data:image/png;base64,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') no-repeat; background: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhLS0gQ3JlYXRlZCB3aXRoIElua3NjYXBlIChodHRwOi8vd3d3Lmlua3NjYXBlLm9yZy8pIC0tPgoKPHN2ZwogICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iCiAgIHhtbG5zOmNjPSJodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9ucyMiCiAgIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyIKICAgeG1sbnM6c3ZnPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogICB4bWxuczppbmtzY2FwZT0iaHR0cDovL3d3dy5pbmtzY2FwZS5vcmcvbmFtZXNwYWNlcy9pbmtzY2FwZSIKICAgdmVyc2lvbj0iMS4xIgogICB3aWR0aD0iNjgxLjk2MjUyIgogICBoZWlnaHQ9IjE4Ny41IgogICBpZD0ic3ZnMiIKICAgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+PG1ldGFkYXRhCiAgICAgaWQ9Im1ldGFkYXRhOCI+PHJkZjpSREY+PGNjOldvcmsKICAgICAgICAgcmRmOmFib3V0PSIiPjxkYzpmb3JtYXQ+aW1hZ2Uvc3ZnK3htbDwvZGM6Zm9ybWF0PjxkYzp0eXBlCiAgICAgICAgICAgcmRmOnJlc291cmNlPSJodHRwOi8vcHVybC5vcmcvZGMvZGNtaXR5cGUvU3RpbGxJbWFnZSIgLz48L2NjOldvcms+PC9yZGY6UkRGPjwvbWV0YWRhdGE+PGRlZnMKICAgICBpZD0iZGVmczYiPjxjbGlwUGF0aAogICAgICAgaWQ9ImNsaXBQYXRoMTgiPjxwYXRoCiAgICAgICAgIGQ9Ik0gMCwxNTAwIDAsMCBsIDU0NTUuNzQsMCAwLDE1MDAgTCAwLDE1MDAgeiIKICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgaWQ9InBhdGgyMCIgLz48L2NsaXBQYXRoPjwvZGVmcz48ZwogICAgIHRyYW5zZm9ybT0ibWF0cml4KDEuMjUsMCwwLC0xLjI1LDAsMTg3LjUpIgogICAgIGlkPSJnMTAiPjxnCiAgICAgICB0cmFuc2Zvcm09InNjYWxlKDAuMSwwLjEpIgogICAgICAgaWQ9ImcxMiI+PGcKICAgICAgICAgaWQ9ImcxNCI+PGcKICAgICAgICAgICBjbGlwLXBhdGg9InVybCgjY2xpcFBhdGgxOCkiCiAgICAgICAgICAgaWQ9ImcxNiI+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gMTU0NCw1OTkuNDM0IGMgMC45MiwtNDAuMzUyIDI1LjY4LC04MS42MDIgNzEuNTMsLTgxLjYwMiAyNy41MSwwIDQ3LjY4LDEyLjgzMiA2MS40NCwzNS43NTQgMTIuODMsMjIuOTMgMTIuODMsNTYuODUyIDEyLjgzLDgyLjUyNyBsIDAsMzI5LjE4NCAtNzEuNTIsMCAwLDEwNC41NDMgMjY2LjgzLDAgMCwtMTA0LjU0MyAtNzAuNiwwIDAsLTM0NC43NyBjIDAsLTU4LjY5MSAtMy42OCwtMTA0LjUzMSAtNDQuOTMsLTE1Mi4yMTggLTM2LjY4LC00Mi4xOCAtOTYuMjgsLTY2LjAyIC0xNTMuMTQsLTY2LjAyIC0xMTcuMzcsMCAtMjA3LjI0LDc3Ljk0MSAtMjAyLjY0LDE5Ny4xNDUgbCAxMzAuMiwwIgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMjIiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDIzMDEuNCw2NjIuNjk1IGMgMCw4MC43MDMgLTY2Ljk0LDE0NS44MTMgLTE0Ny42MywxNDUuODEzIC04My40NCwwIC0xNDcuNjMsLTY4Ljc4MSAtMTQ3LjYzLC0xNTEuMzAxIDAsLTc5Ljc4NSA2Ni45NCwtMTQ1LjgwMSAxNDUuOCwtMTQ1LjgwMSA4NC4zNSwwIDE0OS40Niw2Ny44NTIgMTQ5LjQ2LDE1MS4yODkgeiBtIC0xLjgzLC0xODEuNTQ3IGMgLTM1Ljc3LC01NC4wOTcgLTkzLjUzLC03OC44NTkgLTE1Ny43MiwtNzguODU5IC0xNDAuMywwIC0yNTEuMjQsMTE2LjQ0OSAtMjUxLjI0LDI1NC45MTggMCwxNDIuMTI5IDExMy43LDI2MC40MSAyNTYuNzQsMjYwLjQxIDYzLjI3LDAgMTE4LjI5LC0yOS4zMzYgMTUyLjIyLC04Mi41MjMgbCAwLDY5LjY4NyAxNzUuMTQsMCAwLC0xMDQuNTI3IC02MS40NCwwIDAsLTI4MC41OTggNjEuNDQsMCAwLC0xMDQuNTI3IC0xNzUuMTQsMCAwLDY2LjAxOSIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDI0IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSAyNjIyLjMzLDU1Ny4yNTggYyAzLjY3LC00NC4wMTYgMzMuMDEsLTczLjM0OCA3OC44NiwtNzMuMzQ4IDMzLjkzLDAgNjYuOTMsMjMuODI0IDY2LjkzLDYwLjUwNCAwLDQ4LjYwNiAtNDUuODQsNTYuODU2IC04My40NCw2Ni45NDEgLTg1LjI4LDIyLjAwNCAtMTc4LjgxLDQ4LjYwNiAtMTc4LjgxLDE1NS44NzkgMCw5My41MzYgNzguODYsMTQ3LjYzMyAxNjUuOTgsMTQ3LjYzMyA0NCwwIDgzLjQzLC05LjE3NiAxMTAuOTQsLTQ0LjAwOCBsIDAsMzMuOTIyIDgyLjUzLDAgMCwtMTMyLjk2NSAtMTA4LjIxLDAgYyAtMS44MywzNC44NTYgLTI4LjQyLDU3Ljc3NCAtNjMuMjYsNTcuNzc0IC0zMC4yNiwwIC02Mi4zNSwtMTcuNDIyIC02Mi4zNSwtNTEuMzQ4IDAsLTQ1Ljg0NyA0NC45MywtNTUuOTMgODAuNjksLTY0LjE4IDg4LjAyLC0yMC4xNzUgMTgyLjQ3LC00Ny42OTUgMTgyLjQ3LC0xNTcuNzM0IDAsLTk5LjAyNyAtODMuNDQsLTE1NC4wMzkgLTE3NS4xMywtMTU0LjAzOSAtNDkuNTMsMCAtOTQuNDYsMTUuNTgyIC0xMjYuNTUsNTMuMTggbCAwLC00MC4zNCAtODUuMjcsMCAwLDE0Mi4xMjkgMTE0LjYyLDAiCiAgICAgICAgICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIgogICAgICAgICAgICAgaWQ9InBhdGgyNiIKICAgICAgICAgICAgIHN0eWxlPSJmaWxsOiM4YTQxODI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiIC8+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gMjk4OC4xOCw4MDAuMjU0IC02My4yNiwwIDAsMTA0LjUyNyAxNjUuMDUsMCAwLC03My4zNTUgYyAzMS4xOCw1MS4zNDcgNzguODYsODUuMjc3IDE0MS4yMSw4NS4yNzcgNjcuODUsMCAxMjQuNzEsLTQxLjI1OCAxNTIuMjEsLTEwMi42OTkgMjYuNiw2Mi4zNTEgOTIuNjIsMTAyLjY5OSAxNjAuNDcsMTAyLjY5OSA1My4xOSwwIDEwNS40NiwtMjIgMTQxLjIxLC02Mi4zNTEgMzguNTIsLTQ0LjkzOCAzOC41MiwtOTMuNTMyIDM4LjUyLC0xNDkuNDU3IGwgMCwtMTg1LjIzOSA2My4yNywwIDAsLTEwNC41MjcgLTIzOC40MiwwIDAsMTA0LjUyNyA2My4yOCwwIDAsMTU3LjcxNSBjIDAsMzIuMTAyIDAsNjAuNTI3IC0xNC42Nyw4OC45NTcgLTE4LjM0LDI2LjU4MiAtNDguNjEsNDAuMzQ0IC03OS43Nyw0MC4zNDQgLTMwLjI2LDAgLTYzLjI4LC0xMi44NDQgLTgyLjUzLC0zNi42NzIgLTIyLjkzLC0yOS4zNTUgLTIyLjkzLC01Ni44NjMgLTIyLjkzLC05Mi42MjkgbCAwLC0xNTcuNzE1IDYzLjI3LDAgMCwtMTA0LjUyNyAtMjM4LjQxLDAgMCwxMDQuNTI3IDYzLjI4LDAgMCwxNTAuMzgzIGMgMCwyOS4zNDggMCw2Ni4wMjMgLTE0LjY3LDkxLjY5OSAtMTUuNTksMjkuMzM2IC00Ny42OSw0NC45MzQgLTgwLjcsNDQuOTM0IC0zMS4xOCwwIC01Ny43NywtMTEuMDA4IC03Ny45NCwtMzUuNzc0IC0yNC43NywtMzAuMjUzIC0yNi42LC02Mi4zNDMgLTI2LjYsLTk5Ljk0MSBsIDAsLTE1MS4zMDEgNjMuMjcsMCAwLC0xMDQuNTI3IC0yMzguNCwwIDAsMTA0LjUyNyA2My4yNiwwIDAsMjgwLjU5OCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDI4IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSAzOTk4LjY2LDk1MS41NDcgLTExMS44NywwIDAsMTE4LjI5MyAxMTEuODcsMCAwLC0xMTguMjkzIHogbSAwLC00MzEuODkxIDYzLjI3LDAgMCwtMTA0LjUyNyAtMjM5LjMzLDAgMCwxMDQuNTI3IDY0LjE5LDAgMCwyODAuNTk4IC02My4yNywwIDAsMTA0LjUyNyAxNzUuMTQsMCAwLC0zODUuMTI1IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMzAiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDQxNTkuMTIsODAwLjI1NCAtNjMuMjcsMCAwLDEwNC41MjcgMTc1LjE0LDAgMCwtNjkuNjg3IGMgMjkuMzUsNTQuMTAxIDg0LjM2LDgwLjY5OSAxNDQuODcsODAuNjk5IDUzLjE5LDAgMTA1LjQ1LC0yMi4wMTYgMTQxLjIyLC02MC41MjcgNDAuMzQsLTQ0LjkzNCA0MS4yNiwtODguMDMyIDQxLjI2LC0xNDMuOTU3IGwgMCwtMTkxLjY1MyA2My4yNywwIDAsLTEwNC41MjcgLTIzOC40LDAgMCwxMDQuNTI3IDYzLjI2LDAgMCwxNTguNjM3IGMgMCwzMC4yNjIgMCw2MS40MzQgLTE5LjI2LDg4LjAzNSAtMjAuMTcsMjYuNTgyIC01My4xOCwzOS40MTQgLTg2LjE5LDM5LjQxNCAtMzMuOTMsMCAtNjguNzcsLTEzLjc1IC04OC45NCwtNDEuMjUgLTIxLjA5LC0yNy41IC0yMS4wOSwtNjkuNjg3IC0yMS4wOSwtMTAyLjcwNyBsIDAsLTE0Mi4xMjkgNjMuMjYsMCAwLC0xMDQuNTI3IC0yMzguNCwwIDAsMTA0LjUyNyA2My4yNywwIDAsMjgwLjU5OCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDMyIgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA1MDgyLjQ4LDcwMy45NjUgYyAtMTkuMjQsNzAuNjA1IC04MS42LDExNS41NDcgLTE1NC4wNCwxMTUuNTQ3IC02Ni4wNCwwIC0xMjkuMywtNTEuMzQ4IC0xNDMuMDUsLTExNS41NDcgbCAyOTcuMDksMCB6IG0gODUuMjcsLTE0NC44ODMgYyAtMzguNTEsLTkzLjUyMyAtMTI5LjI3LC0xNTYuNzkzIC0yMzEuMDUsLTE1Ni43OTMgLTE0My4wNywwIC0yNTcuNjgsMTExLjg3MSAtMjU3LjY4LDI1NS44MzYgMCwxNDQuODgzIDEwOS4xMiwyNjEuMzI4IDI1NC45MSwyNjEuMzI4IDY3Ljg3LDAgMTM1LjcyLC0zMC4yNTggMTgzLjM5LC03OC44NjMgNDguNjIsLTUxLjM0NCA2OC43OSwtMTEzLjY5NSA2OC43OSwtMTgzLjM4MyBsIC0zLjY3LC0zOS40MzQgLTM5Ni4xMywwIGMgMTQuNjcsLTY3Ljg2MyA3Ny4wMywtMTE3LjM2MyAxNDYuNzIsLTExNy4zNjMgNDguNTksMCA5MC43NiwxOC4zMjggMTE4LjI4LDU4LjY3MiBsIDExNi40NCwwIgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMzQiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDY5MC44OTUsODUwLjcwMyA5MC43NSwwIDIyLjU0MywzMS4wMzUgMCwyNDMuMTIyIC0xMzUuODI5LDAgMCwtMjQzLjE0MSAyMi41MzYsLTMxLjAxNiIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDM2IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA2MzIuMzk1LDc0Mi4yNTggMjguMDM5LDg2LjMwNCAtMjIuNTUxLDMxLjA0IC0yMzEuMjIzLDc1LjEyOCAtNDEuOTc2LC0xMjkuMTgzIDIzMS4yNTcsLTc1LjEzNyAzNi40NTQsMTEuODQ4IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMzgiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDcxNy40NDksNjUzLjEwNSAtNzMuNDEsNTMuMzYgLTM2LjQ4OCwtMTEuODc1IC0xNDIuOTAzLC0xOTYuNjkyIDEwOS44ODMsLTc5LjgyOCAxNDIuOTE4LDE5Ni43MDMgMCwzOC4zMzIiCiAgICAgICAgICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIgogICAgICAgICAgICAgaWQ9InBhdGg0MCIKICAgICAgICAgICAgIHN0eWxlPSJmaWxsOiM4YTQxODI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiIC8+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gODI4LjUyLDcwNi40NjUgLTczLjQyNiwtNTMuMzQgMC4wMTEsLTM4LjM1OSBMIDg5OC4wMDQsNDE4LjA3IDEwMDcuOSw0OTcuODk4IDg2NC45NzMsNjk0LjYwOSA4MjguNTIsNzA2LjQ2NSIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDQyIgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA4MTIuMDg2LDgyOC41ODYgMjguMDU1LC04Ni4zMiAzNi40ODQsLTExLjgzNiAyMzEuMjI1LDc1LjExNyAtNDEuOTcsMTI5LjE4MyAtMjMxLjIzOSwtNzUuMTQgLTIyLjU1NSwtMzEuMDA0IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoNDQiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDczNi4zMDEsMTMzNS44OCBjIC0zMjMuMDQ3LDAgLTU4NS44NzUsLTI2Mi43OCAtNTg1Ljg3NSwtNTg1Ljc4MiAwLC0zMjMuMTE4IDI2Mi44MjgsLTU4NS45NzcgNTg1Ljg3NSwtNTg1Ljk3NyAzMjMuMDE5LDAgNTg1LjgwOSwyNjIuODU5IDU4NS44MDksNTg1Ljk3NyAwLDMyMy4wMDIgLTI2Mi43OSw1ODUuNzgyIC01ODUuODA5LDU4NS43ODIgbCAwLDAgeiBtIDAsLTExOC42MSBjIDI1Ny45NzIsMCA0NjcuMTg5LC0yMDkuMTMgNDY3LjE4OSwtNDY3LjE3MiAwLC0yNTguMTI5IC0yMDkuMjE3LC00NjcuMzQ4IC00NjcuMTg5LC00NjcuMzQ4IC0yNTguMDc0LDAgLTQ2Ny4yNTQsMjA5LjIxOSAtNDY3LjI1NCw0NjcuMzQ4IDAsMjU4LjA0MiAyMDkuMTgsNDY3LjE3MiA0NjcuMjU0LDQ2Ny4xNzIiCiAgICAgICAgICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIgogICAgICAgICAgICAgaWQ9InBhdGg0NiIKICAgICAgICAgICAgIHN0eWxlPSJmaWxsOiM4YTQxODI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiIC8+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gMTA5MS4xMyw2MTkuODgzIC0xNzUuNzcxLDU3LjEyMSAxMS42MjksMzUuODA4IDE3NS43NjIsLTU3LjEyMSAtMTEuNjIsLTM1LjgwOCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDQ4IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0iTSA4NjYuOTU3LDkwMi4wNzQgODM2LjUsOTI0LjE5OSA5NDUuMTIxLDEwNzMuNzMgOTc1LjU4NiwxMDUxLjYxIDg2Ni45NTcsOTAyLjA3NCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDUwIgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0iTSA2MDcuNDY1LDkwMy40NDUgNDk4Ljg1NSwxMDUyLjk3IDUyOS4zMiwxMDc1LjEgNjM3LjkzLDkyNS41NjYgNjA3LjQ2NSw5MDMuNDQ1IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoNTIiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDM4MC42ODgsNjIyLjEyOSAtMTEuNjI2LDM1LjgwMSAxNzUuNzU4LDU3LjA5IDExLjYyMSwtMzUuODAxIC0xNzUuNzUzLC01Ny4wOSIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDU0IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA3MTYuMjg5LDM3Ni41OSAzNy42NDA2LDAgMCwxODQuODE2IC0zNy42NDA2LDAgMCwtMTg0LjgxNiB6IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoNTYiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjwvZz48L2c+PC9nPjwvZz48L3N2Zz4=') no-repeat, none; -moz-background-size: 100%; -o-background-size: 100%; -webkit-background-size: 100%; background-size: 100%; display: block; float: left; width: 90px; height: 25px; }
10
10
  .jasmine_html-reporter .banner .version { margin-left: 14px; position: relative; top: 6px; }
11
11
  .jasmine_html-reporter .banner .duration { position: absolute; right: 14px; top: 6px; }
12
12
  .jasmine_html-reporter #jasmine_content { position: fixed; right: 100%; }
13
- .jasmine_html-reporter .version { color: #aaaaaa; }
13
+ .jasmine_html-reporter .version { color: #aaa; }
14
14
  .jasmine_html-reporter .banner { margin-top: 14px; }
15
- .jasmine_html-reporter .duration { color: #aaaaaa; float: right; }
15
+ .jasmine_html-reporter .duration { color: #aaa; float: right; }
16
16
  .jasmine_html-reporter .symbol-summary { overflow: hidden; *zoom: 1; margin: 14px 0; }
17
17
  .jasmine_html-reporter .symbol-summary li { display: inline-block; height: 8px; width: 14px; font-size: 16px; }
18
18
  .jasmine_html-reporter .symbol-summary li.passed { font-size: 14px; }
@@ -30,12 +30,13 @@ body { overflow-y: scroll; }
30
30
  .jasmine_html-reporter .bar.failed { background-color: #ca3a11; }
31
31
  .jasmine_html-reporter .bar.passed { background-color: #007069; }
32
32
  .jasmine_html-reporter .bar.skipped { background-color: #bababa; }
33
- .jasmine_html-reporter .bar.menu { background-color: #fff; color: #aaaaaa; }
34
- .jasmine_html-reporter .bar.menu a { color: #333333; }
33
+ .jasmine_html-reporter .bar.errored { background-color: #ca3a11; }
34
+ .jasmine_html-reporter .bar.menu { background-color: #fff; color: #aaa; }
35
+ .jasmine_html-reporter .bar.menu a { color: #333; }
35
36
  .jasmine_html-reporter .bar a { color: white; }
36
37
  .jasmine_html-reporter.spec-list .bar.menu.failure-list, .jasmine_html-reporter.spec-list .results .failures { display: none; }
37
38
  .jasmine_html-reporter.failure-list .bar.menu.spec-list, .jasmine_html-reporter.failure-list .summary { display: none; }
38
- .jasmine_html-reporter .running-alert { background-color: #666666; }
39
+ .jasmine_html-reporter .running-alert { background-color: #666; }
39
40
  .jasmine_html-reporter .results { margin-top: 14px; }
40
41
  .jasmine_html-reporter.showDetails .summaryMenuItem { font-weight: normal; text-decoration: inherit; }
41
42
  .jasmine_html-reporter.showDetails .summaryMenuItem:hover { text-decoration: underline; }
@@ -52,10 +53,10 @@ body { overflow-y: scroll; }
52
53
  .jasmine_html-reporter .summary li.pending a { color: #ba9d37; }
53
54
  .jasmine_html-reporter .description + .suite { margin-top: 0; }
54
55
  .jasmine_html-reporter .suite { margin-top: 14px; }
55
- .jasmine_html-reporter .suite a { color: #333333; }
56
+ .jasmine_html-reporter .suite a { color: #333; }
56
57
  .jasmine_html-reporter .failures .spec-detail { margin-bottom: 28px; }
57
58
  .jasmine_html-reporter .failures .spec-detail .description { background-color: #ca3a11; }
58
59
  .jasmine_html-reporter .failures .spec-detail .description a { color: white; }
59
- .jasmine_html-reporter .result-message { padding-top: 14px; color: #333333; white-space: pre; }
60
+ .jasmine_html-reporter .result-message { padding-top: 14px; color: #333; white-space: pre; }
60
61
  .jasmine_html-reporter .result-message span.result { display: block; }
61
- .jasmine_html-reporter .stack-trace { margin: 5px 0 0 0; max-height: 224px; overflow: auto; line-height: 18px; color: #666666; border: 1px solid #ddd; background: white; white-space: pre; }
62
+ .jasmine_html-reporter .stack-trace { margin: 5px 0 0 0; max-height: 224px; overflow: auto; line-height: 18px; color: #666; border: 1px solid #ddd; background: white; white-space: pre; }
@@ -20,45 +20,54 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
20
  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
21
  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
22
  */
23
- function getJasmineRequireObj() {
23
+ getJasmineRequireObj = (function (jasmineGlobal) {
24
+ var jasmineRequire;
25
+
24
26
  if (typeof module !== 'undefined' && module.exports) {
25
- return exports;
27
+ jasmineGlobal = global;
28
+ jasmineRequire = exports;
26
29
  } else {
27
- window.jasmineRequire = window.jasmineRequire || {};
28
- return window.jasmineRequire;
30
+ jasmineRequire = jasmineGlobal.jasmineRequire = jasmineGlobal.jasmineRequire || {};
29
31
  }
30
- }
31
32
 
32
- getJasmineRequireObj().core = function(jRequire) {
33
- var j$ = {};
34
-
35
- jRequire.base(j$);
36
- j$.util = jRequire.util();
37
- j$.Any = jRequire.Any();
38
- j$.CallTracker = jRequire.CallTracker();
39
- j$.MockDate = jRequire.MockDate();
40
- j$.Clock = jRequire.Clock();
41
- j$.DelayedFunctionScheduler = jRequire.DelayedFunctionScheduler();
42
- j$.Env = jRequire.Env(j$);
43
- j$.ExceptionFormatter = jRequire.ExceptionFormatter();
44
- j$.Expectation = jRequire.Expectation();
45
- j$.buildExpectationResult = jRequire.buildExpectationResult();
46
- j$.JsApiReporter = jRequire.JsApiReporter();
47
- j$.matchersUtil = jRequire.matchersUtil(j$);
48
- j$.ObjectContaining = jRequire.ObjectContaining(j$);
49
- j$.pp = jRequire.pp(j$);
50
- j$.QueueRunner = jRequire.QueueRunner(j$);
51
- j$.ReportDispatcher = jRequire.ReportDispatcher();
52
- j$.Spec = jRequire.Spec(j$);
53
- j$.SpyStrategy = jRequire.SpyStrategy();
54
- j$.Suite = jRequire.Suite();
55
- j$.Timer = jRequire.Timer();
56
- j$.version = jRequire.version();
57
-
58
- j$.matchers = jRequire.requireMatchers(jRequire, j$);
59
-
60
- return j$;
61
- };
33
+ function getJasmineRequire() {
34
+ return jasmineRequire;
35
+ }
36
+
37
+ getJasmineRequire().core = function(jRequire) {
38
+ var j$ = {};
39
+
40
+ jRequire.base(j$, jasmineGlobal);
41
+ j$.util = jRequire.util();
42
+ j$.Any = jRequire.Any();
43
+ j$.CallTracker = jRequire.CallTracker();
44
+ j$.MockDate = jRequire.MockDate();
45
+ j$.Clock = jRequire.Clock();
46
+ j$.DelayedFunctionScheduler = jRequire.DelayedFunctionScheduler();
47
+ j$.Env = jRequire.Env(j$);
48
+ j$.ExceptionFormatter = jRequire.ExceptionFormatter();
49
+ j$.Expectation = jRequire.Expectation();
50
+ j$.buildExpectationResult = jRequire.buildExpectationResult();
51
+ j$.JsApiReporter = jRequire.JsApiReporter();
52
+ j$.matchersUtil = jRequire.matchersUtil(j$);
53
+ j$.ObjectContaining = jRequire.ObjectContaining(j$);
54
+ j$.pp = jRequire.pp(j$);
55
+ j$.QueueRunner = jRequire.QueueRunner(j$);
56
+ j$.ReportDispatcher = jRequire.ReportDispatcher();
57
+ j$.Spec = jRequire.Spec(j$);
58
+ j$.SpyRegistry = jRequire.SpyRegistry(j$);
59
+ j$.SpyStrategy = jRequire.SpyStrategy();
60
+ j$.Suite = jRequire.Suite();
61
+ j$.Timer = jRequire.Timer();
62
+ j$.version = jRequire.version();
63
+
64
+ j$.matchers = jRequire.requireMatchers(jRequire, j$);
65
+
66
+ return j$;
67
+ };
68
+
69
+ return getJasmineRequire;
70
+ })(this);
62
71
 
63
72
  getJasmineRequireObj().requireMatchers = function(jRequire, j$) {
64
73
  var availableMatchers = [
@@ -90,108 +99,107 @@ getJasmineRequireObj().requireMatchers = function(jRequire, j$) {
90
99
  return matchers;
91
100
  };
92
101
 
93
- getJasmineRequireObj().base = (function (jasmineGlobal) {
94
- if (typeof module !== 'undefined' && module.exports) {
95
- jasmineGlobal = global;
96
- }
97
-
98
- return function(j$) {
99
- j$.unimplementedMethod_ = function() {
100
- throw new Error('unimplemented method');
101
- };
102
-
103
- j$.MAX_PRETTY_PRINT_DEPTH = 40;
104
- j$.MAX_PRETTY_PRINT_ARRAY_LENGTH = 100;
105
- j$.DEFAULT_TIMEOUT_INTERVAL = 5000;
102
+ getJasmineRequireObj().base = function(j$, jasmineGlobal) {
103
+ j$.unimplementedMethod_ = function() {
104
+ throw new Error('unimplemented method');
105
+ };
106
106
 
107
- j$.getGlobal = function() {
108
- return jasmineGlobal;
109
- };
107
+ j$.MAX_PRETTY_PRINT_DEPTH = 40;
108
+ j$.MAX_PRETTY_PRINT_ARRAY_LENGTH = 100;
109
+ j$.DEFAULT_TIMEOUT_INTERVAL = 5000;
110
110
 
111
- j$.getEnv = function(options) {
112
- var env = j$.currentEnv_ = j$.currentEnv_ || new j$.Env(options);
113
- //jasmine. singletons in here (setTimeout blah blah).
114
- return env;
115
- };
111
+ j$.getGlobal = function() {
112
+ return jasmineGlobal;
113
+ };
116
114
 
117
- j$.isArray_ = function(value) {
118
- return j$.isA_('Array', value);
119
- };
115
+ j$.getEnv = function(options) {
116
+ var env = j$.currentEnv_ = j$.currentEnv_ || new j$.Env(options);
117
+ //jasmine. singletons in here (setTimeout blah blah).
118
+ return env;
119
+ };
120
120
 
121
- j$.isString_ = function(value) {
122
- return j$.isA_('String', value);
123
- };
121
+ j$.isArray_ = function(value) {
122
+ return j$.isA_('Array', value);
123
+ };
124
124
 
125
- j$.isNumber_ = function(value) {
126
- return j$.isA_('Number', value);
127
- };
125
+ j$.isString_ = function(value) {
126
+ return j$.isA_('String', value);
127
+ };
128
128
 
129
- j$.isA_ = function(typeName, value) {
130
- return Object.prototype.toString.apply(value) === '[object ' + typeName + ']';
131
- };
129
+ j$.isNumber_ = function(value) {
130
+ return j$.isA_('Number', value);
131
+ };
132
132
 
133
- j$.isDomNode = function(obj) {
134
- return obj.nodeType > 0;
135
- };
133
+ j$.isA_ = function(typeName, value) {
134
+ return Object.prototype.toString.apply(value) === '[object ' + typeName + ']';
135
+ };
136
136
 
137
- j$.any = function(clazz) {
138
- return new j$.Any(clazz);
139
- };
137
+ j$.isDomNode = function(obj) {
138
+ return obj.nodeType > 0;
139
+ };
140
140
 
141
- j$.objectContaining = function(sample) {
142
- return new j$.ObjectContaining(sample);
143
- };
141
+ j$.any = function(clazz) {
142
+ return new j$.Any(clazz);
143
+ };
144
144
 
145
- j$.createSpy = function(name, originalFn) {
145
+ j$.objectContaining = function(sample) {
146
+ return new j$.ObjectContaining(sample);
147
+ };
146
148
 
147
- var spyStrategy = new j$.SpyStrategy({
148
- name: name,
149
- fn: originalFn,
150
- getSpy: function() { return spy; }
151
- }),
152
- callTracker = new j$.CallTracker(),
153
- spy = function() {
154
- callTracker.track({
155
- object: this,
156
- args: Array.prototype.slice.apply(arguments)
157
- });
158
- return spyStrategy.exec.apply(this, arguments);
149
+ j$.createSpy = function(name, originalFn) {
150
+
151
+ var spyStrategy = new j$.SpyStrategy({
152
+ name: name,
153
+ fn: originalFn,
154
+ getSpy: function() { return spy; }
155
+ }),
156
+ callTracker = new j$.CallTracker(),
157
+ spy = function() {
158
+ var callData = {
159
+ object: this,
160
+ args: Array.prototype.slice.apply(arguments)
159
161
  };
160
162
 
161
- for (var prop in originalFn) {
162
- if (prop === 'and' || prop === 'calls') {
163
- throw new Error('Jasmine spies would overwrite the \'and\' and \'calls\' properties on the object being spied upon');
164
- }
163
+ callTracker.track(callData);
164
+ var returnValue = spyStrategy.exec.apply(this, arguments);
165
+ callData.returnValue = returnValue;
165
166
 
166
- spy[prop] = originalFn[prop];
167
+ return returnValue;
168
+ };
169
+
170
+ for (var prop in originalFn) {
171
+ if (prop === 'and' || prop === 'calls') {
172
+ throw new Error('Jasmine spies would overwrite the \'and\' and \'calls\' properties on the object being spied upon');
167
173
  }
168
174
 
169
- spy.and = spyStrategy;
170
- spy.calls = callTracker;
175
+ spy[prop] = originalFn[prop];
176
+ }
171
177
 
172
- return spy;
173
- };
178
+ spy.and = spyStrategy;
179
+ spy.calls = callTracker;
174
180
 
175
- j$.isSpy = function(putativeSpy) {
176
- if (!putativeSpy) {
177
- return false;
178
- }
179
- return putativeSpy.and instanceof j$.SpyStrategy &&
180
- putativeSpy.calls instanceof j$.CallTracker;
181
- };
181
+ return spy;
182
+ };
182
183
 
183
- j$.createSpyObj = function(baseName, methodNames) {
184
- if (!j$.isArray_(methodNames) || methodNames.length === 0) {
185
- throw 'createSpyObj requires a non-empty array of method names to create spies for';
186
- }
187
- var obj = {};
188
- for (var i = 0; i < methodNames.length; i++) {
189
- obj[methodNames[i]] = j$.createSpy(baseName + '.' + methodNames[i]);
190
- }
191
- return obj;
192
- };
184
+ j$.isSpy = function(putativeSpy) {
185
+ if (!putativeSpy) {
186
+ return false;
187
+ }
188
+ return putativeSpy.and instanceof j$.SpyStrategy &&
189
+ putativeSpy.calls instanceof j$.CallTracker;
193
190
  };
194
- })(this);
191
+
192
+ j$.createSpyObj = function(baseName, methodNames) {
193
+ if (!j$.isArray_(methodNames) || methodNames.length === 0) {
194
+ throw 'createSpyObj requires a non-empty array of method names to create spies for';
195
+ }
196
+ var obj = {};
197
+ for (var i = 0; i < methodNames.length; i++) {
198
+ obj[methodNames[i]] = j$.createSpy(baseName + '.' + methodNames[i]);
199
+ }
200
+ return obj;
201
+ };
202
+ };
195
203
 
196
204
  getJasmineRequireObj().util = function() {
197
205
 
@@ -228,13 +236,28 @@ getJasmineRequireObj().util = function() {
228
236
  util.arrayContains = function(array, search) {
229
237
  var i = array.length;
230
238
  while (i--) {
231
- if (array[i] == search) {
239
+ if (array[i] === search) {
232
240
  return true;
233
241
  }
234
242
  }
235
243
  return false;
236
244
  };
237
245
 
246
+ util.clone = function(obj) {
247
+ if (Object.prototype.toString.apply(obj) === '[object Array]') {
248
+ return obj.slice();
249
+ }
250
+
251
+ var cloned = {};
252
+ for (var prop in obj) {
253
+ if (obj.hasOwnProperty(prop)) {
254
+ cloned[prop] = obj[prop];
255
+ }
256
+ }
257
+
258
+ return cloned;
259
+ };
260
+
238
261
  return util;
239
262
  };
240
263
 
@@ -244,17 +267,16 @@ getJasmineRequireObj().Spec = function(j$) {
244
267
  this.resultCallback = attrs.resultCallback || function() {};
245
268
  this.id = attrs.id;
246
269
  this.description = attrs.description || '';
247
- this.fn = attrs.fn;
248
- this.beforeFns = attrs.beforeFns || function() { return []; };
249
- this.afterFns = attrs.afterFns || function() { return []; };
270
+ this.queueableFn = attrs.queueableFn;
271
+ this.beforeAndAfterFns = attrs.beforeAndAfterFns || function() { return {befores: [], afters: []}; };
272
+ this.userContext = attrs.userContext || function() { return {}; };
250
273
  this.onStart = attrs.onStart || function() {};
251
- this.exceptionFormatter = attrs.exceptionFormatter || function() {};
252
274
  this.getSpecName = attrs.getSpecName || function() { return ''; };
253
275
  this.expectationResultFactory = attrs.expectationResultFactory || function() { };
254
276
  this.queueRunnerFactory = attrs.queueRunnerFactory || function() {};
255
277
  this.catchingExceptions = attrs.catchingExceptions || function() { return true; };
256
278
 
257
- if (!this.fn) {
279
+ if (!this.queueableFn.fn) {
258
280
  this.pend();
259
281
  }
260
282
 
@@ -290,30 +312,16 @@ getJasmineRequireObj().Spec = function(j$) {
290
312
  return;
291
313
  }
292
314
 
293
- var allFns = this.beforeFns().concat(this.fn).concat(this.afterFns());
315
+ var fns = this.beforeAndAfterFns();
316
+ var allFns = fns.befores.concat(this.queueableFn).concat(fns.afters);
294
317
 
295
318
  this.queueRunnerFactory({
296
- fns: allFns,
297
- onException: onException,
319
+ queueableFns: allFns,
320
+ onException: function() { self.onException.apply(self, arguments); },
298
321
  onComplete: complete,
299
- enforceTimeout: function() { return true; }
322
+ userContext: this.userContext()
300
323
  });
301
324
 
302
- function onException(e) {
303
- if (Spec.isPendingSpecException(e)) {
304
- self.pend();
305
- return;
306
- }
307
-
308
- self.addExpectationResult(false, {
309
- matcherName: '',
310
- passed: false,
311
- expected: '',
312
- actual: '',
313
- error: e
314
- });
315
- }
316
-
317
325
  function complete() {
318
326
  self.result.status = self.status();
319
327
  self.resultCallback(self.result);
@@ -324,6 +332,21 @@ getJasmineRequireObj().Spec = function(j$) {
324
332
  }
325
333
  };
326
334
 
335
+ Spec.prototype.onException = function onException(e) {
336
+ if (Spec.isPendingSpecException(e)) {
337
+ this.pend();
338
+ return;
339
+ }
340
+
341
+ this.addExpectationResult(false, {
342
+ matcherName: '',
343
+ passed: false,
344
+ expected: '',
345
+ actual: '',
346
+ error: e
347
+ });
348
+ };
349
+
327
350
  Spec.prototype.disable = function() {
328
351
  this.disabled = true;
329
352
  };
@@ -348,6 +371,10 @@ getJasmineRequireObj().Spec = function(j$) {
348
371
  }
349
372
  };
350
373
 
374
+ Spec.prototype.isExecutable = function() {
375
+ return !this.disabled && !this.markedPending;
376
+ };
377
+
351
378
  Spec.prototype.getFullName = function() {
352
379
  return this.getSpecName(this);
353
380
  };
@@ -381,11 +408,19 @@ getJasmineRequireObj().Env = function(j$) {
381
408
  this.clock = new j$.Clock(global, new j$.DelayedFunctionScheduler(), new j$.MockDate(global));
382
409
 
383
410
  var runnableLookupTable = {};
384
-
385
- var spies = [];
411
+ var runnableResources = {};
386
412
 
387
413
  var currentSpec = null;
388
- var currentSuite = null;
414
+ var currentlyExecutingSuites = [];
415
+ var currentDeclarationSuite = null;
416
+
417
+ var currentSuite = function() {
418
+ return currentlyExecutingSuites[currentlyExecutingSuites.length - 1];
419
+ };
420
+
421
+ var currentRunnable = function() {
422
+ return currentSpec || currentSuite();
423
+ };
389
424
 
390
425
  var reporter = new j$.ReportDispatcher([
391
426
  'jasmineStarted',
@@ -400,11 +435,21 @@ getJasmineRequireObj().Env = function(j$) {
400
435
  return true;
401
436
  };
402
437
 
403
- var equalityTesters = [];
404
-
405
- var customEqualityTesters = [];
406
438
  this.addCustomEqualityTester = function(tester) {
407
- customEqualityTesters.push(tester);
439
+ if(!currentRunnable()) {
440
+ throw new Error('Custom Equalities must be added in a before function or a spec');
441
+ }
442
+ runnableResources[currentRunnable().id].customEqualityTesters.push(tester);
443
+ };
444
+
445
+ this.addMatchers = function(matchersToAdd) {
446
+ if(!currentRunnable()) {
447
+ throw new Error('Matchers must be added in a before function or a spec');
448
+ }
449
+ var customMatchers = runnableResources[currentRunnable().id].customMatchers;
450
+ for (var matcherName in matchersToAdd) {
451
+ customMatchers[matcherName] = matchersToAdd[matcherName];
452
+ }
408
453
  };
409
454
 
410
455
  j$.Expectation.addCoreMatchers(j$.matchers);
@@ -422,7 +467,8 @@ getJasmineRequireObj().Env = function(j$) {
422
467
  var expectationFactory = function(actual, spec) {
423
468
  return j$.Expectation.Factory({
424
469
  util: j$.matchersUtil,
425
- customEqualityTesters: customEqualityTesters,
470
+ customEqualityTesters: runnableResources[spec.id].customEqualityTesters,
471
+ customMatchers: runnableResources[spec.id].customMatchers,
426
472
  actual: actual,
427
473
  addExpectationResult: addExpectationResult
428
474
  });
@@ -432,30 +478,44 @@ getJasmineRequireObj().Env = function(j$) {
432
478
  }
433
479
  };
434
480
 
435
- var specStarted = function(spec) {
436
- currentSpec = spec;
437
- reporter.specStarted(spec.result);
481
+ var defaultResourcesForRunnable = function(id, parentRunnableId) {
482
+ var resources = {spies: [], customEqualityTesters: [], customMatchers: {}};
483
+
484
+ if(runnableResources[parentRunnableId]){
485
+ resources.customEqualityTesters = j$.util.clone(runnableResources[parentRunnableId].customEqualityTesters);
486
+ resources.customMatchers = j$.util.clone(runnableResources[parentRunnableId].customMatchers);
487
+ }
488
+
489
+ runnableResources[id] = resources;
438
490
  };
439
491
 
440
- var beforeFns = function(suite) {
441
- return function() {
442
- var befores = [];
443
- while(suite) {
444
- befores = befores.concat(suite.beforeFns);
445
- suite = suite.parentSuite;
446
- }
447
- return befores.reverse();
448
- };
492
+ var clearResourcesForRunnable = function(id) {
493
+ spyRegistry.clearSpies();
494
+ delete runnableResources[id];
449
495
  };
450
496
 
451
- var afterFns = function(suite) {
497
+ var beforeAndAfterFns = function(suite, runnablesExplictlySet) {
452
498
  return function() {
453
- var afters = [];
499
+ var befores = [],
500
+ afters = [],
501
+ beforeAlls = [],
502
+ afterAlls = [];
503
+
454
504
  while(suite) {
505
+ befores = befores.concat(suite.beforeFns);
455
506
  afters = afters.concat(suite.afterFns);
507
+
508
+ if (runnablesExplictlySet()) {
509
+ beforeAlls = beforeAlls.concat(suite.beforeAllFns);
510
+ afterAlls = afterAlls.concat(suite.afterAllFns);
511
+ }
512
+
456
513
  suite = suite.parentSuite;
457
514
  }
458
- return afters;
515
+ return {
516
+ befores: beforeAlls.reverse().concat(befores.reverse()),
517
+ afters: afters.concat(afterAlls)
518
+ };
459
519
  };
460
520
  };
461
521
 
@@ -504,6 +564,7 @@ getJasmineRequireObj().Env = function(j$) {
504
564
  options.catchException = catchException;
505
565
  options.clearStack = options.clearStack || clearStack;
506
566
  options.timer = {setTimeout: realSetTimeout, clearTimeout: realClearTimeout};
567
+ options.fail = self.fail;
507
568
 
508
569
  new j$.QueueRunner(options).execute();
509
570
  };
@@ -513,65 +574,54 @@ getJasmineRequireObj().Env = function(j$) {
513
574
  id: getNextSuiteId(),
514
575
  description: 'Jasmine__TopLevel__Suite',
515
576
  queueRunner: queueRunnerFactory,
516
- resultCallback: function() {} // TODO - hook this up
577
+ resultCallback: function(attrs) {
578
+ reporter.suiteDone(attrs);
579
+ }
517
580
  });
518
581
  runnableLookupTable[topSuite.id] = topSuite;
519
- currentSuite = topSuite;
582
+ defaultResourcesForRunnable(topSuite.id);
583
+ currentDeclarationSuite = topSuite;
520
584
 
521
585
  this.topSuite = function() {
522
586
  return topSuite;
523
587
  };
524
588
 
525
589
  this.execute = function(runnablesToRun) {
526
- runnablesToRun = runnablesToRun || [topSuite.id];
590
+ if(runnablesToRun) {
591
+ runnablesExplictlySet = true;
592
+ } else if (focusedRunnables.length) {
593
+ runnablesExplictlySet = true;
594
+ runnablesToRun = focusedRunnables;
595
+ } else {
596
+ runnablesToRun = [topSuite.id];
597
+ }
527
598
 
528
599
  var allFns = [];
529
600
  for(var i = 0; i < runnablesToRun.length; i++) {
530
601
  var runnable = runnableLookupTable[runnablesToRun[i]];
531
- allFns.push((function(runnable) { return function(done) { runnable.execute(done); }; })(runnable));
602
+ allFns.push((function(runnable) { return { fn: function(done) { runnable.execute(done); } }; })(runnable));
532
603
  }
533
604
 
534
605
  reporter.jasmineStarted({
535
606
  totalSpecsDefined: totalSpecsDefined
536
607
  });
537
608
 
538
- queueRunnerFactory({fns: allFns, onComplete: reporter.jasmineDone});
609
+ queueRunnerFactory({queueableFns: allFns, onComplete: reporter.jasmineDone});
539
610
  };
540
611
 
541
612
  this.addReporter = function(reporterToAdd) {
542
613
  reporter.addReporter(reporterToAdd);
543
614
  };
544
615
 
545
- this.addMatchers = function(matchersToAdd) {
546
- j$.Expectation.addMatchers(matchersToAdd);
547
- };
548
-
549
- this.spyOn = function(obj, methodName) {
550
- if (j$.util.isUndefined(obj)) {
551
- throw new Error('spyOn could not find an object to spy upon for ' + methodName + '()');
616
+ var spyRegistry = new j$.SpyRegistry({currentSpies: function() {
617
+ if(!currentRunnable()) {
618
+ throw new Error('Spies must be created in a before function or a spec');
552
619
  }
620
+ return runnableResources[currentRunnable().id].spies;
621
+ }});
553
622
 
554
- if (j$.util.isUndefined(obj[methodName])) {
555
- throw new Error(methodName + '() method does not exist');
556
- }
557
-
558
- if (obj[methodName] && j$.isSpy(obj[methodName])) {
559
- //TODO?: should this return the current spy? Downside: may cause user confusion about spy state
560
- throw new Error(methodName + ' has already been spied upon');
561
- }
562
-
563
- var spy = j$.createSpy(methodName, obj[methodName]);
564
-
565
- spies.push({
566
- spy: spy,
567
- baseObj: obj,
568
- methodName: methodName,
569
- originalValue: obj[methodName]
570
- });
571
-
572
- obj[methodName] = spy;
573
-
574
- return spy;
623
+ this.spyOn = function() {
624
+ return spyRegistry.spyOn.apply(spyRegistry, arguments);
575
625
  };
576
626
 
577
627
  var suiteFactory = function(description) {
@@ -579,24 +629,59 @@ getJasmineRequireObj().Env = function(j$) {
579
629
  env: self,
580
630
  id: getNextSuiteId(),
581
631
  description: description,
582
- parentSuite: currentSuite,
632
+ parentSuite: currentDeclarationSuite,
583
633
  queueRunner: queueRunnerFactory,
584
634
  onStart: suiteStarted,
635
+ expectationFactory: expectationFactory,
636
+ expectationResultFactory: expectationResultFactory,
585
637
  resultCallback: function(attrs) {
638
+ if (!suite.disabled) {
639
+ clearResourcesForRunnable(suite.id);
640
+ currentlyExecutingSuites.pop();
641
+ }
586
642
  reporter.suiteDone(attrs);
587
643
  }
588
644
  });
589
645
 
590
646
  runnableLookupTable[suite.id] = suite;
591
647
  return suite;
648
+
649
+ function suiteStarted(suite) {
650
+ currentlyExecutingSuites.push(suite);
651
+ defaultResourcesForRunnable(suite.id, suite.parentSuite.id);
652
+ reporter.suiteStarted(suite.result);
653
+ }
592
654
  };
593
655
 
594
656
  this.describe = function(description, specDefinitions) {
595
657
  var suite = suiteFactory(description);
658
+ addSpecsToSuite(suite, specDefinitions);
659
+ return suite;
660
+ };
661
+
662
+ this.xdescribe = function(description, specDefinitions) {
663
+ var suite = this.describe(description, specDefinitions);
664
+ suite.disable();
665
+ return suite;
666
+ };
667
+
668
+ var focusedRunnables = [];
669
+
670
+ this.fdescribe = function(description, specDefinitions) {
671
+ var suite = suiteFactory(description);
672
+ suite.isFocused = true;
673
+
674
+ focusedRunnables.push(suite.id);
675
+ unfocusAncestor();
676
+ addSpecsToSuite(suite, specDefinitions);
677
+
678
+ return suite;
679
+ };
596
680
 
597
- var parentSuite = currentSuite;
681
+ function addSpecsToSuite(suite, specDefinitions) {
682
+ var parentSuite = currentDeclarationSuite;
598
683
  parentSuite.addChild(suite);
599
- currentSuite = suite;
684
+ currentDeclarationSuite = suite;
600
685
 
601
686
  var declarationError = null;
602
687
  try {
@@ -606,31 +691,49 @@ getJasmineRequireObj().Env = function(j$) {
606
691
  }
607
692
 
608
693
  if (declarationError) {
609
- this.it('encountered a declaration exception', function() {
694
+ self.it('encountered a declaration exception', function() {
610
695
  throw declarationError;
611
696
  });
612
697
  }
613
698
 
614
- currentSuite = parentSuite;
699
+ currentDeclarationSuite = parentSuite;
700
+ }
615
701
 
616
- return suite;
617
- };
702
+ function findFocusedAncestor(suite) {
703
+ while (suite) {
704
+ if (suite.isFocused) {
705
+ return suite.id;
706
+ }
707
+ suite = suite.parentSuite;
708
+ }
618
709
 
619
- this.xdescribe = function(description, specDefinitions) {
620
- var suite = this.describe(description, specDefinitions);
621
- suite.disable();
622
- return suite;
710
+ return null;
711
+ }
712
+
713
+ function unfocusAncestor() {
714
+ var focusedAncestor = findFocusedAncestor(currentDeclarationSuite);
715
+ if (focusedAncestor) {
716
+ for (var i = 0; i < focusedRunnables.length; i++) {
717
+ if (focusedRunnables[i] === focusedAncestor) {
718
+ focusedRunnables.splice(i, 1);
719
+ break;
720
+ }
721
+ }
722
+ }
723
+ }
724
+
725
+ var runnablesExplictlySet = false;
726
+
727
+ var runnablesExplictlySetGetter = function(){
728
+ return runnablesExplictlySet;
623
729
  };
624
730
 
625
- var specFactory = function(description, fn, suite) {
731
+ var specFactory = function(description, fn, suite, timeout) {
626
732
  totalSpecsDefined++;
627
-
628
733
  var spec = new j$.Spec({
629
734
  id: getNextSpecId(),
630
- beforeFns: beforeFns(suite),
631
- afterFns: afterFns(suite),
735
+ beforeAndAfterFns: beforeAndAfterFns(suite, runnablesExplictlySetGetter),
632
736
  expectationFactory: expectationFactory,
633
- exceptionFormatter: exceptionFormatter,
634
737
  resultCallback: specResultCallback,
635
738
  getSpecName: function(spec) {
636
739
  return getSpecName(spec, suite);
@@ -639,7 +742,11 @@ getJasmineRequireObj().Env = function(j$) {
639
742
  description: description,
640
743
  expectationResultFactory: expectationResultFactory,
641
744
  queueRunnerFactory: queueRunnerFactory,
642
- fn: fn
745
+ userContext: function() { return suite.clonedSharedUserContext(); },
746
+ queueableFn: {
747
+ fn: fn,
748
+ timeout: function() { return timeout || j$.DEFAULT_TIMEOUT_INTERVAL; }
749
+ }
643
750
  });
644
751
 
645
752
  runnableLookupTable[spec.id] = spec;
@@ -650,58 +757,94 @@ getJasmineRequireObj().Env = function(j$) {
650
757
 
651
758
  return spec;
652
759
 
653
- function removeAllSpies() {
654
- for (var i = 0; i < spies.length; i++) {
655
- var spyEntry = spies[i];
656
- spyEntry.baseObj[spyEntry.methodName] = spyEntry.originalValue;
657
- }
658
- spies = [];
659
- }
660
-
661
760
  function specResultCallback(result) {
662
- removeAllSpies();
663
- j$.Expectation.resetMatchers();
664
- customEqualityTesters = [];
761
+ clearResourcesForRunnable(spec.id);
665
762
  currentSpec = null;
666
763
  reporter.specDone(result);
667
764
  }
668
- };
669
765
 
670
- var suiteStarted = function(suite) {
671
- reporter.suiteStarted(suite.result);
766
+ function specStarted(spec) {
767
+ currentSpec = spec;
768
+ defaultResourcesForRunnable(spec.id, suite.id);
769
+ reporter.specStarted(spec.result);
770
+ }
672
771
  };
673
772
 
674
- this.it = function(description, fn) {
675
- var spec = specFactory(description, fn, currentSuite);
676
- currentSuite.addChild(spec);
773
+ this.it = function(description, fn, timeout) {
774
+ var spec = specFactory(description, fn, currentDeclarationSuite, timeout);
775
+ currentDeclarationSuite.addChild(spec);
677
776
  return spec;
678
777
  };
679
778
 
680
- this.xit = function(description, fn) {
681
- var spec = this.it(description, fn);
779
+ this.xit = function() {
780
+ var spec = this.it.apply(this, arguments);
682
781
  spec.pend();
683
782
  return spec;
684
783
  };
685
784
 
785
+ this.fit = function(){
786
+ var spec = this.it.apply(this, arguments);
787
+
788
+ focusedRunnables.push(spec.id);
789
+ unfocusAncestor();
790
+ return spec;
791
+ };
792
+
686
793
  this.expect = function(actual) {
687
- if (!currentSpec) {
794
+ if (!currentRunnable()) {
688
795
  throw new Error('\'expect\' was used when there was no current spec, this could be because an asynchronous test timed out');
689
796
  }
690
797
 
691
- return currentSpec.expect(actual);
798
+ return currentRunnable().expect(actual);
799
+ };
800
+
801
+ this.beforeEach = function(beforeEachFunction, timeout) {
802
+ currentDeclarationSuite.beforeEach({
803
+ fn: beforeEachFunction,
804
+ timeout: function() { return timeout || j$.DEFAULT_TIMEOUT_INTERVAL; }
805
+ });
806
+ };
807
+
808
+ this.beforeAll = function(beforeAllFunction, timeout) {
809
+ currentDeclarationSuite.beforeAll({
810
+ fn: beforeAllFunction,
811
+ timeout: function() { return timeout || j$.DEFAULT_TIMEOUT_INTERVAL; }
812
+ });
692
813
  };
693
814
 
694
- this.beforeEach = function(beforeEachFunction) {
695
- currentSuite.beforeEach(beforeEachFunction);
815
+ this.afterEach = function(afterEachFunction, timeout) {
816
+ currentDeclarationSuite.afterEach({
817
+ fn: afterEachFunction,
818
+ timeout: function() { return timeout || j$.DEFAULT_TIMEOUT_INTERVAL; }
819
+ });
696
820
  };
697
821
 
698
- this.afterEach = function(afterEachFunction) {
699
- currentSuite.afterEach(afterEachFunction);
822
+ this.afterAll = function(afterAllFunction, timeout) {
823
+ currentDeclarationSuite.afterAll({
824
+ fn: afterAllFunction,
825
+ timeout: function() { return timeout || j$.DEFAULT_TIMEOUT_INTERVAL; }
826
+ });
700
827
  };
701
828
 
702
829
  this.pending = function() {
703
830
  throw j$.Spec.pendingSpecExceptionMessage;
704
831
  };
832
+
833
+ this.fail = function(error) {
834
+ var message = 'Failed';
835
+ if (error) {
836
+ message += ': ';
837
+ message += error.message || error;
838
+ }
839
+
840
+ currentRunnable().addExpectationResult(false, {
841
+ matcherName: '',
842
+ passed: false,
843
+ expected: '',
844
+ actual: '',
845
+ message: message
846
+ });
847
+ };
705
848
  }
706
849
 
707
850
  return Env;
@@ -739,26 +882,31 @@ getJasmineRequireObj().JsApiReporter = function() {
739
882
  return status;
740
883
  };
741
884
 
742
- var suites = {};
885
+ var suites = [],
886
+ suites_hash = {};
743
887
 
744
888
  this.suiteStarted = function(result) {
745
- storeSuite(result);
889
+ suites_hash[result.id] = result;
746
890
  };
747
891
 
748
892
  this.suiteDone = function(result) {
749
893
  storeSuite(result);
750
894
  };
751
895
 
896
+ this.suiteResults = function(index, length) {
897
+ return suites.slice(index, index + length);
898
+ };
899
+
752
900
  function storeSuite(result) {
753
- suites[result.id] = result;
901
+ suites.push(result);
902
+ suites_hash[result.id] = result;
754
903
  }
755
904
 
756
905
  this.suites = function() {
757
- return suites;
906
+ return suites_hash;
758
907
  };
759
908
 
760
909
  var specs = [];
761
- this.specStarted = function(result) { };
762
910
 
763
911
  this.specDone = function(result) {
764
912
  specs.push(result);
@@ -1112,11 +1260,12 @@ getJasmineRequireObj().DelayedFunctionScheduler = function() {
1112
1260
 
1113
1261
  for (var i = 0; i < funcsToRun.length; ++i) {
1114
1262
  var funcToRun = funcsToRun[i];
1115
- funcToRun.funcToCall.apply(null, funcToRun.params || []);
1116
1263
 
1117
1264
  if (funcToRun.recurring) {
1118
1265
  reschedule(funcToRun);
1119
1266
  }
1267
+
1268
+ funcToRun.funcToCall.apply(null, funcToRun.params || []);
1120
1269
  }
1121
1270
  } while (scheduledLookup.length > 0 &&
1122
1271
  // checking first if we're out of time prevents setTimeout(0)
@@ -1161,8 +1310,6 @@ getJasmineRequireObj().ExceptionFormatter = function() {
1161
1310
 
1162
1311
  getJasmineRequireObj().Expectation = function() {
1163
1312
 
1164
- var matchers = {};
1165
-
1166
1313
  function Expectation(options) {
1167
1314
  this.util = options.util || { buildFailureMessage: function() {} };
1168
1315
  this.customEqualityTesters = options.customEqualityTesters || [];
@@ -1170,8 +1317,9 @@ getJasmineRequireObj().Expectation = function() {
1170
1317
  this.addExpectationResult = options.addExpectationResult || function(){};
1171
1318
  this.isNot = options.isNot;
1172
1319
 
1173
- for (var matcherName in matchers) {
1174
- this[matcherName] = matchers[matcherName];
1320
+ var customMatchers = options.customMatchers || {};
1321
+ for (var matcherName in customMatchers) {
1322
+ this[matcherName] = Expectation.prototype.wrapCompare(matcherName, customMatchers[matcherName]);
1175
1323
  }
1176
1324
  }
1177
1325
 
@@ -1238,19 +1386,6 @@ getJasmineRequireObj().Expectation = function() {
1238
1386
  }
1239
1387
  };
1240
1388
 
1241
- Expectation.addMatchers = function(matchersToAdd) {
1242
- for (var name in matchersToAdd) {
1243
- var matcher = matchersToAdd[name];
1244
- matchers[name] = Expectation.prototype.wrapCompare(name, matcher);
1245
- }
1246
- };
1247
-
1248
- Expectation.resetMatchers = function() {
1249
- for (var name in matchers) {
1250
- delete matchers[name];
1251
- }
1252
- };
1253
-
1254
1389
  Expectation.Factory = function(options) {
1255
1390
  options = options || {};
1256
1391
 
@@ -1376,6 +1511,7 @@ getJasmineRequireObj().MockDate = function() {
1376
1511
  }
1377
1512
 
1378
1513
  function createDateProperties() {
1514
+ FakeDate.prototype = GlobalDate.prototype;
1379
1515
 
1380
1516
  FakeDate.now = function() {
1381
1517
  if (GlobalDate.now) {
@@ -1581,31 +1717,32 @@ getJasmineRequireObj().QueueRunner = function(j$) {
1581
1717
  }
1582
1718
 
1583
1719
  function QueueRunner(attrs) {
1584
- this.fns = attrs.fns || [];
1720
+ this.queueableFns = attrs.queueableFns || [];
1585
1721
  this.onComplete = attrs.onComplete || function() {};
1586
1722
  this.clearStack = attrs.clearStack || function(fn) {fn();};
1587
1723
  this.onException = attrs.onException || function() {};
1588
1724
  this.catchException = attrs.catchException || function() { return true; };
1589
- this.enforceTimeout = attrs.enforceTimeout || function() { return false; };
1590
- this.userContext = {};
1725
+ this.userContext = attrs.userContext || {};
1591
1726
  this.timer = attrs.timeout || {setTimeout: setTimeout, clearTimeout: clearTimeout};
1727
+ this.fail = attrs.fail || function() {};
1592
1728
  }
1593
1729
 
1594
1730
  QueueRunner.prototype.execute = function() {
1595
- this.run(this.fns, 0);
1731
+ this.run(this.queueableFns, 0);
1596
1732
  };
1597
1733
 
1598
- QueueRunner.prototype.run = function(fns, recursiveIndex) {
1599
- var length = fns.length,
1600
- self = this,
1601
- iterativeIndex;
1734
+ QueueRunner.prototype.run = function(queueableFns, recursiveIndex) {
1735
+ var length = queueableFns.length,
1736
+ self = this,
1737
+ iterativeIndex;
1738
+
1602
1739
 
1603
1740
  for(iterativeIndex = recursiveIndex; iterativeIndex < length; iterativeIndex++) {
1604
- var fn = fns[iterativeIndex];
1605
- if (fn.length > 0) {
1606
- return attemptAsync(fn);
1741
+ var queueableFn = queueableFns[iterativeIndex];
1742
+ if (queueableFn.fn.length > 0) {
1743
+ return attemptAsync(queueableFn);
1607
1744
  } else {
1608
- attemptSync(fn);
1745
+ attemptSync(queueableFn);
1609
1746
  }
1610
1747
  }
1611
1748
 
@@ -1615,41 +1752,51 @@ getJasmineRequireObj().QueueRunner = function(j$) {
1615
1752
  this.clearStack(this.onComplete);
1616
1753
  }
1617
1754
 
1618
- function attemptSync(fn) {
1755
+ function attemptSync(queueableFn) {
1619
1756
  try {
1620
- fn.call(self.userContext);
1757
+ queueableFn.fn.call(self.userContext);
1621
1758
  } catch (e) {
1622
- handleException(e);
1759
+ handleException(e, queueableFn);
1623
1760
  }
1624
1761
  }
1625
1762
 
1626
- function attemptAsync(fn) {
1763
+ function attemptAsync(queueableFn) {
1627
1764
  var clearTimeout = function () {
1628
1765
  Function.prototype.apply.apply(self.timer.clearTimeout, [j$.getGlobal(), [timeoutId]]);
1629
1766
  },
1630
1767
  next = once(function () {
1631
1768
  clearTimeout(timeoutId);
1632
- self.run(fns, iterativeIndex + 1);
1769
+ self.run(queueableFns, iterativeIndex + 1);
1633
1770
  }),
1634
1771
  timeoutId;
1635
1772
 
1636
- if (self.enforceTimeout()) {
1773
+ next.fail = function() {
1774
+ self.fail.apply(null, arguments);
1775
+ next();
1776
+ };
1777
+
1778
+ if (queueableFn.timeout) {
1637
1779
  timeoutId = Function.prototype.apply.apply(self.timer.setTimeout, [j$.getGlobal(), [function() {
1638
- self.onException(new Error('Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.'));
1780
+ var error = new Error('Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.');
1781
+ onException(error, queueableFn);
1639
1782
  next();
1640
- }, j$.DEFAULT_TIMEOUT_INTERVAL]]);
1783
+ }, queueableFn.timeout()]]);
1641
1784
  }
1642
1785
 
1643
1786
  try {
1644
- fn.call(self.userContext, next);
1787
+ queueableFn.fn.call(self.userContext, next);
1645
1788
  } catch (e) {
1646
- handleException(e);
1789
+ handleException(e, queueableFn);
1647
1790
  next();
1648
1791
  }
1649
1792
  }
1650
1793
 
1651
- function handleException(e) {
1794
+ function onException(e, queueableFn) {
1652
1795
  self.onException(e);
1796
+ }
1797
+
1798
+ function handleException(e, queueableFn) {
1799
+ onException(e, queueableFn);
1653
1800
  if (!self.catchException(e)) {
1654
1801
  //TODO: set a var when we catch an exception and
1655
1802
  //use a finally block to close the loop in a nice way..
@@ -1697,6 +1844,52 @@ getJasmineRequireObj().ReportDispatcher = function() {
1697
1844
  };
1698
1845
 
1699
1846
 
1847
+ getJasmineRequireObj().SpyRegistry = function(j$) {
1848
+
1849
+ function SpyRegistry(options) {
1850
+ options = options || {};
1851
+ var currentSpies = options.currentSpies || function() { return []; };
1852
+
1853
+ this.spyOn = function(obj, methodName) {
1854
+ if (j$.util.isUndefined(obj)) {
1855
+ throw new Error('spyOn could not find an object to spy upon for ' + methodName + '()');
1856
+ }
1857
+
1858
+ if (j$.util.isUndefined(obj[methodName])) {
1859
+ throw new Error(methodName + '() method does not exist');
1860
+ }
1861
+
1862
+ if (obj[methodName] && j$.isSpy(obj[methodName])) {
1863
+ //TODO?: should this return the current spy? Downside: may cause user confusion about spy state
1864
+ throw new Error(methodName + ' has already been spied upon');
1865
+ }
1866
+
1867
+ var spy = j$.createSpy(methodName, obj[methodName]);
1868
+
1869
+ currentSpies().push({
1870
+ spy: spy,
1871
+ baseObj: obj,
1872
+ methodName: methodName,
1873
+ originalValue: obj[methodName]
1874
+ });
1875
+
1876
+ obj[methodName] = spy;
1877
+
1878
+ return spy;
1879
+ };
1880
+
1881
+ this.clearSpies = function() {
1882
+ var spies = currentSpies();
1883
+ for (var i = 0; i < spies.length; i++) {
1884
+ var spyEntry = spies[i];
1885
+ spyEntry.baseObj[spyEntry.methodName] = spyEntry.originalValue;
1886
+ }
1887
+ };
1888
+ }
1889
+
1890
+ return SpyRegistry;
1891
+ };
1892
+
1700
1893
  getJasmineRequireObj().SpyStrategy = function() {
1701
1894
 
1702
1895
  function SpyStrategy(options) {
@@ -1727,6 +1920,14 @@ getJasmineRequireObj().SpyStrategy = function() {
1727
1920
  return getSpy();
1728
1921
  };
1729
1922
 
1923
+ this.returnValues = function() {
1924
+ var values = Array.prototype.slice.call(arguments);
1925
+ plan = function () {
1926
+ return values.shift();
1927
+ };
1928
+ return getSpy();
1929
+ };
1930
+
1730
1931
  this.throwError = function(something) {
1731
1932
  var error = (something instanceof Error) ? something : new Error(something);
1732
1933
  plan = function() {
@@ -1758,9 +1959,13 @@ getJasmineRequireObj().Suite = function() {
1758
1959
  this.onStart = attrs.onStart || function() {};
1759
1960
  this.resultCallback = attrs.resultCallback || function() {};
1760
1961
  this.clearStack = attrs.clearStack || function(fn) {fn();};
1962
+ this.expectationFactory = attrs.expectationFactory;
1963
+ this.expectationResultFactory = attrs.expectationResultFactory;
1761
1964
 
1762
1965
  this.beforeFns = [];
1763
1966
  this.afterFns = [];
1967
+ this.beforeAllFns = [];
1968
+ this.afterAllFns = [];
1764
1969
  this.queueRunner = attrs.queueRunner || function() {};
1765
1970
  this.disabled = false;
1766
1971
 
@@ -1768,12 +1973,16 @@ getJasmineRequireObj().Suite = function() {
1768
1973
 
1769
1974
  this.result = {
1770
1975
  id: this.id,
1771
- status: this.disabled ? 'disabled' : '',
1772
1976
  description: this.description,
1773
- fullName: this.getFullName()
1977
+ fullName: this.getFullName(),
1978
+ failedExpectations: []
1774
1979
  };
1775
1980
  }
1776
1981
 
1982
+ Suite.prototype.expect = function(actual) {
1983
+ return this.expectationFactory(actual, this);
1984
+ };
1985
+
1777
1986
  Suite.prototype.getFullName = function() {
1778
1987
  var fullName = this.description;
1779
1988
  for (var parentSuite = this.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) {
@@ -1786,21 +1995,40 @@ getJasmineRequireObj().Suite = function() {
1786
1995
 
1787
1996
  Suite.prototype.disable = function() {
1788
1997
  this.disabled = true;
1789
- this.result.status = 'disabled';
1790
1998
  };
1791
1999
 
1792
2000
  Suite.prototype.beforeEach = function(fn) {
1793
2001
  this.beforeFns.unshift(fn);
1794
2002
  };
1795
2003
 
2004
+ Suite.prototype.beforeAll = function(fn) {
2005
+ this.beforeAllFns.push(fn);
2006
+ };
2007
+
1796
2008
  Suite.prototype.afterEach = function(fn) {
1797
2009
  this.afterFns.unshift(fn);
1798
2010
  };
1799
2011
 
2012
+ Suite.prototype.afterAll = function(fn) {
2013
+ this.afterAllFns.push(fn);
2014
+ };
2015
+
1800
2016
  Suite.prototype.addChild = function(child) {
1801
2017
  this.children.push(child);
1802
2018
  };
1803
2019
 
2020
+ Suite.prototype.status = function() {
2021
+ if (this.disabled) {
2022
+ return 'disabled';
2023
+ }
2024
+
2025
+ if (this.result.failedExpectations.length > 0) {
2026
+ return 'failed';
2027
+ } else {
2028
+ return 'finished';
2029
+ }
2030
+ };
2031
+
1804
2032
  Suite.prototype.execute = function(onComplete) {
1805
2033
  var self = this;
1806
2034
 
@@ -1813,16 +2041,25 @@ getJasmineRequireObj().Suite = function() {
1813
2041
 
1814
2042
  var allFns = [];
1815
2043
 
1816
- for (var i = 0; i < this.children.length; i++) {
1817
- allFns.push(wrapChildAsAsync(this.children[i]));
2044
+ if (this.isExecutable()) {
2045
+ allFns = allFns.concat(this.beforeAllFns);
2046
+
2047
+ for (var i = 0; i < this.children.length; i++) {
2048
+ allFns.push(wrapChildAsAsync(this.children[i]));
2049
+ }
2050
+
2051
+ allFns = allFns.concat(this.afterAllFns);
1818
2052
  }
1819
2053
 
1820
2054
  this.queueRunner({
1821
- fns: allFns,
1822
- onComplete: complete
2055
+ queueableFns: allFns,
2056
+ onComplete: complete,
2057
+ userContext: this.sharedUserContext(),
2058
+ onException: function() { self.onException.apply(self, arguments); }
1823
2059
  });
1824
2060
 
1825
2061
  function complete() {
2062
+ self.result.status = self.status();
1826
2063
  self.resultCallback(self.result);
1827
2064
 
1828
2065
  if (onComplete) {
@@ -1831,10 +2068,82 @@ getJasmineRequireObj().Suite = function() {
1831
2068
  }
1832
2069
 
1833
2070
  function wrapChildAsAsync(child) {
1834
- return function(done) { child.execute(done); };
2071
+ return { fn: function(done) { child.execute(done); } };
2072
+ }
2073
+ };
2074
+
2075
+ Suite.prototype.isExecutable = function() {
2076
+ var foundActive = false;
2077
+ for(var i = 0; i < this.children.length; i++) {
2078
+ if(this.children[i].isExecutable()) {
2079
+ foundActive = true;
2080
+ break;
2081
+ }
2082
+ }
2083
+ return foundActive;
2084
+ };
2085
+
2086
+ Suite.prototype.sharedUserContext = function() {
2087
+ if (!this.sharedContext) {
2088
+ this.sharedContext = this.parentSuite ? clone(this.parentSuite.sharedUserContext()) : {};
1835
2089
  }
2090
+
2091
+ return this.sharedContext;
2092
+ };
2093
+
2094
+ Suite.prototype.clonedSharedUserContext = function() {
2095
+ return clone(this.sharedUserContext());
1836
2096
  };
1837
2097
 
2098
+ Suite.prototype.onException = function() {
2099
+ if(isAfterAll(this.children)) {
2100
+ var data = {
2101
+ matcherName: '',
2102
+ passed: false,
2103
+ expected: '',
2104
+ actual: '',
2105
+ error: arguments[0]
2106
+ };
2107
+ this.result.failedExpectations.push(this.expectationResultFactory(data));
2108
+ } else {
2109
+ for (var i = 0; i < this.children.length; i++) {
2110
+ var child = this.children[i];
2111
+ child.onException.apply(child, arguments);
2112
+ }
2113
+ }
2114
+ };
2115
+
2116
+ Suite.prototype.addExpectationResult = function () {
2117
+ if(isAfterAll(this.children) && isFailure(arguments)){
2118
+ var data = arguments[1];
2119
+ this.result.failedExpectations.push(this.expectationResultFactory(data));
2120
+ } else {
2121
+ for (var i = 0; i < this.children.length; i++) {
2122
+ var child = this.children[i];
2123
+ child.addExpectationResult.apply(child, arguments);
2124
+ }
2125
+ }
2126
+ };
2127
+
2128
+ function isAfterAll(children) {
2129
+ return children && children[0].result.status;
2130
+ }
2131
+
2132
+ function isFailure(args) {
2133
+ return !args[0];
2134
+ }
2135
+
2136
+ function clone(obj) {
2137
+ var clonedObj = {};
2138
+ for (var prop in obj) {
2139
+ if (obj.hasOwnProperty(prop)) {
2140
+ clonedObj[prop] = obj[prop];
2141
+ }
2142
+ }
2143
+
2144
+ return clonedObj;
2145
+ }
2146
+
1838
2147
  return Suite;
1839
2148
  };
1840
2149
 
@@ -1878,7 +2187,9 @@ getJasmineRequireObj().matchersUtil = function(j$) {
1878
2187
  contains: function(haystack, needle, customTesters) {
1879
2188
  customTesters = customTesters || [];
1880
2189
 
1881
- if (Object.prototype.toString.apply(haystack) === '[object Array]') {
2190
+ if ((Object.prototype.toString.apply(haystack) === '[object Array]') ||
2191
+ (!!haystack && !haystack.indexOf))
2192
+ {
1882
2193
  for (var i = 0; i < haystack.length; i++) {
1883
2194
  if (eq(haystack[i], needle, [], [], customTesters)) {
1884
2195
  return true;
@@ -1886,6 +2197,7 @@ getJasmineRequireObj().matchersUtil = function(j$) {
1886
2197
  }
1887
2198
  return false;
1888
2199
  }
2200
+
1889
2201
  return !!haystack && haystack.indexOf(needle) >= 0;
1890
2202
  },
1891
2203
 
@@ -2378,18 +2690,13 @@ getJasmineRequireObj().toThrowError = function(j$) {
2378
2690
  var threw = false,
2379
2691
  pass = {pass: true},
2380
2692
  fail = {pass: false},
2381
- thrown,
2382
- errorType,
2383
- message,
2384
- regexp,
2385
- name,
2386
- constructorName;
2693
+ thrown;
2387
2694
 
2388
2695
  if (typeof actual != 'function') {
2389
2696
  throw new Error('Actual is not a Function');
2390
2697
  }
2391
2698
 
2392
- extractExpectedParams.apply(null, arguments);
2699
+ var errorMatcher = getMatcher.apply(null, arguments);
2393
2700
 
2394
2701
  try {
2395
2702
  actual();
@@ -2408,121 +2715,108 @@ getJasmineRequireObj().toThrowError = function(j$) {
2408
2715
  return fail;
2409
2716
  }
2410
2717
 
2411
- if (arguments.length == 1) {
2718
+ if (errorMatcher.hasNoSpecifics()) {
2412
2719
  pass.message = 'Expected function not to throw an Error, but it threw ' + fnNameFor(thrown) + '.';
2413
2720
  return pass;
2414
2721
  }
2415
2722
 
2416
- if (errorType) {
2417
- name = fnNameFor(errorType);
2418
- constructorName = fnNameFor(thrown.constructor);
2723
+ if (errorMatcher.matches(thrown)) {
2724
+ pass.message = function() {
2725
+ return 'Expected function not to throw ' + errorMatcher.errorTypeDescription + errorMatcher.messageDescription() + '.';
2726
+ };
2727
+ return pass;
2728
+ } else {
2729
+ fail.message = function() {
2730
+ return 'Expected function to throw ' + errorMatcher.errorTypeDescription + errorMatcher.messageDescription() +
2731
+ ', but it threw ' + errorMatcher.thrownDescription(thrown) + '.';
2732
+ };
2733
+ return fail;
2419
2734
  }
2735
+ }
2736
+ };
2420
2737
 
2421
- if (errorType && message) {
2422
- if (thrown.constructor == errorType && util.equals(thrown.message, message)) {
2423
- pass.message = function() { return 'Expected function not to throw ' + name + ' with message ' + j$.pp(message) + '.'; };
2424
- return pass;
2425
- } else {
2426
- fail.message = function() { return 'Expected function to throw ' + name + ' with message ' + j$.pp(message) +
2427
- ', but it threw ' + constructorName + ' with message ' + j$.pp(thrown.message) + '.'; };
2428
- return fail;
2429
- }
2430
- }
2738
+ function getMatcher() {
2739
+ var expected = null,
2740
+ errorType = null;
2431
2741
 
2432
- if (errorType && regexp) {
2433
- if (thrown.constructor == errorType && regexp.test(thrown.message)) {
2434
- pass.message = function() { return 'Expected function not to throw ' + name + ' with message matching ' + j$.pp(regexp) + '.'; };
2435
- return pass;
2436
- } else {
2437
- fail.message = function() { return 'Expected function to throw ' + name + ' with message matching ' + j$.pp(regexp) +
2438
- ', but it threw ' + constructorName + ' with message ' + j$.pp(thrown.message) + '.'; };
2439
- return fail;
2440
- }
2742
+ if (arguments.length == 2) {
2743
+ expected = arguments[1];
2744
+ if (isAnErrorType(expected)) {
2745
+ errorType = expected;
2746
+ expected = null;
2441
2747
  }
2442
-
2443
- if (errorType) {
2444
- if (thrown.constructor == errorType) {
2445
- pass.message = 'Expected function not to throw ' + name + '.';
2446
- return pass;
2447
- } else {
2448
- fail.message = 'Expected function to throw ' + name + ', but it threw ' + constructorName + '.';
2449
- return fail;
2450
- }
2748
+ } else if (arguments.length > 2) {
2749
+ errorType = arguments[1];
2750
+ expected = arguments[2];
2751
+ if (!isAnErrorType(errorType)) {
2752
+ throw new Error('Expected error type is not an Error.');
2451
2753
  }
2754
+ }
2452
2755
 
2453
- if (message) {
2454
- if (thrown.message == message) {
2455
- pass.message = function() { return 'Expected function not to throw an exception with message ' + j$.pp(message) + '.'; };
2456
- return pass;
2457
- } else {
2458
- fail.message = function() { return 'Expected function to throw an exception with message ' + j$.pp(message) +
2459
- ', but it threw an exception with message ' + j$.pp(thrown.message) + '.'; };
2460
- return fail;
2461
- }
2756
+ if (expected && !isStringOrRegExp(expected)) {
2757
+ if (errorType) {
2758
+ throw new Error('Expected error message is not a string or RegExp.');
2759
+ } else {
2760
+ throw new Error('Expected is not an Error, string, or RegExp.');
2462
2761
  }
2762
+ }
2463
2763
 
2464
- if (regexp) {
2465
- if (regexp.test(thrown.message)) {
2466
- pass.message = function() { return 'Expected function not to throw an exception with a message matching ' + j$.pp(regexp) + '.'; };
2467
- return pass;
2468
- } else {
2469
- fail.message = function() { return 'Expected function to throw an exception with a message matching ' + j$.pp(regexp) +
2470
- ', but it threw an exception with message ' + j$.pp(thrown.message) + '.'; };
2471
- return fail;
2472
- }
2764
+ function messageMatch(message) {
2765
+ if (typeof expected == 'string') {
2766
+ return expected == message;
2767
+ } else {
2768
+ return expected.test(message);
2473
2769
  }
2770
+ }
2474
2771
 
2475
- function fnNameFor(func) {
2476
- return func.name || func.toString().match(/^\s*function\s*(\w*)\s*\(/)[1];
2477
- }
2772
+ return {
2773
+ errorTypeDescription: errorType ? fnNameFor(errorType) : 'an exception',
2774
+ thrownDescription: function(thrown) {
2775
+ var thrownName = errorType ? fnNameFor(thrown.constructor) : 'an exception',
2776
+ thrownMessage = '';
2478
2777
 
2479
- function extractExpectedParams() {
2480
- if (arguments.length == 1) {
2481
- return;
2778
+ if (expected) {
2779
+ thrownMessage = ' with message ' + j$.pp(thrown.message);
2482
2780
  }
2483
2781
 
2484
- if (arguments.length == 2) {
2485
- var expected = arguments[1];
2486
-
2487
- if (expected instanceof RegExp) {
2488
- regexp = expected;
2489
- } else if (typeof expected == 'string') {
2490
- message = expected;
2491
- } else if (checkForAnErrorType(expected)) {
2492
- errorType = expected;
2493
- }
2494
-
2495
- if (!(errorType || message || regexp)) {
2496
- throw new Error('Expected is not an Error, string, or RegExp.');
2497
- }
2782
+ return thrownName + thrownMessage;
2783
+ },
2784
+ messageDescription: function() {
2785
+ if (expected === null) {
2786
+ return '';
2787
+ } else if (expected instanceof RegExp) {
2788
+ return ' with a message matching ' + j$.pp(expected);
2498
2789
  } else {
2499
- if (checkForAnErrorType(arguments[1])) {
2500
- errorType = arguments[1];
2501
- } else {
2502
- throw new Error('Expected error type is not an Error.');
2503
- }
2504
-
2505
- if (arguments[2] instanceof RegExp) {
2506
- regexp = arguments[2];
2507
- } else if (typeof arguments[2] == 'string') {
2508
- message = arguments[2];
2509
- } else {
2510
- throw new Error('Expected error message is not a string or RegExp.');
2511
- }
2790
+ return ' with message ' + j$.pp(expected);
2512
2791
  }
2792
+ },
2793
+ hasNoSpecifics: function() {
2794
+ return expected === null && errorType === null;
2795
+ },
2796
+ matches: function(error) {
2797
+ return (errorType === null || error.constructor === errorType) &&
2798
+ (expected === null || messageMatch(error.message));
2513
2799
  }
2800
+ };
2801
+ }
2514
2802
 
2515
- function checkForAnErrorType(type) {
2516
- if (typeof type !== 'function') {
2517
- return false;
2518
- }
2803
+ function fnNameFor(func) {
2804
+ return func.name || func.toString().match(/^\s*function\s*(\w*)\s*\(/)[1];
2805
+ }
2519
2806
 
2520
- var Surrogate = function() {};
2521
- Surrogate.prototype = type.prototype;
2522
- return (new Surrogate()) instanceof Error;
2523
- }
2807
+ function isStringOrRegExp(potential) {
2808
+ return potential instanceof RegExp || (typeof potential == 'string');
2809
+ }
2810
+
2811
+ function isAnErrorType(type) {
2812
+ if (typeof type !== 'function') {
2813
+ return false;
2524
2814
  }
2525
- };
2815
+
2816
+ var Surrogate = function() {};
2817
+ Surrogate.prototype = type.prototype;
2818
+ return (new Surrogate()) instanceof Error;
2819
+ }
2526
2820
  }
2527
2821
 
2528
2822
  return toThrowError;
@@ -2538,6 +2832,10 @@ getJasmineRequireObj().interface = function(jasmine, env) {
2538
2832
  return env.xdescribe(description, specDefinitions);
2539
2833
  },
2540
2834
 
2835
+ fdescribe: function(description, specDefinitions) {
2836
+ return env.fdescribe(description, specDefinitions);
2837
+ },
2838
+
2541
2839
  it: function(desc, func) {
2542
2840
  return env.it(desc, func);
2543
2841
  },
@@ -2546,6 +2844,10 @@ getJasmineRequireObj().interface = function(jasmine, env) {
2546
2844
  return env.xit(desc, func);
2547
2845
  },
2548
2846
 
2847
+ fit: function(desc, func) {
2848
+ return env.fit(desc, func);
2849
+ },
2850
+
2549
2851
  beforeEach: function(beforeEachFunction) {
2550
2852
  return env.beforeEach(beforeEachFunction);
2551
2853
  },
@@ -2554,6 +2856,14 @@ getJasmineRequireObj().interface = function(jasmine, env) {
2554
2856
  return env.afterEach(afterEachFunction);
2555
2857
  },
2556
2858
 
2859
+ beforeAll: function(beforeAllFunction) {
2860
+ return env.beforeAll(beforeAllFunction);
2861
+ },
2862
+
2863
+ afterAll: function(afterAllFunction) {
2864
+ return env.afterAll(afterAllFunction);
2865
+ },
2866
+
2557
2867
  expect: function(actual) {
2558
2868
  return env.expect(actual);
2559
2869
  },
@@ -2562,6 +2872,10 @@ getJasmineRequireObj().interface = function(jasmine, env) {
2562
2872
  return env.pending();
2563
2873
  },
2564
2874
 
2875
+ fail: function() {
2876
+ return env.fail.apply(env, arguments);
2877
+ },
2878
+
2565
2879
  spyOn: function(obj, methodName) {
2566
2880
  return env.spyOn(obj, methodName);
2567
2881
  },
@@ -2589,5 +2903,5 @@ getJasmineRequireObj().interface = function(jasmine, env) {
2589
2903
  };
2590
2904
 
2591
2905
  getJasmineRequireObj().version = function() {
2592
- return '2.0.2';
2906
+ return '2.1.0';
2593
2907
  };