jasmine-core 1.3.1 → 2.0.0.rc2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. data/lib/jasmine-core.rb +14 -1
  2. data/lib/jasmine-core/boot.js +131 -0
  3. data/lib/jasmine-core/boot/boot.js +109 -0
  4. data/lib/jasmine-core/example/spec/PlayerSpec.js +2 -2
  5. data/lib/jasmine-core/example/spec/SpecHelper.js +14 -8
  6. data/lib/jasmine-core/jasmine-html.js +289 -616
  7. data/lib/jasmine-core/jasmine.css +52 -80
  8. data/lib/jasmine-core/jasmine.js +1972 -2211
  9. data/lib/jasmine-core/spec/console/ConsoleReporterSpec.js +161 -386
  10. data/lib/jasmine-core/spec/core/AnySpec.js +45 -0
  11. data/lib/jasmine-core/spec/core/CallTrackerSpec.js +105 -0
  12. data/lib/jasmine-core/spec/core/ClockSpec.js +314 -0
  13. data/lib/jasmine-core/spec/core/CustomMatchersSpec.js +96 -97
  14. data/lib/jasmine-core/spec/core/DelayedFunctionSchedulerSpec.js +179 -0
  15. data/lib/jasmine-core/spec/core/EnvSpec.js +454 -102
  16. data/lib/jasmine-core/spec/core/ExceptionFormatterSpec.js +56 -0
  17. data/lib/jasmine-core/spec/core/ExceptionsSpec.js +15 -126
  18. data/lib/jasmine-core/spec/core/ExpectationResultSpec.js +61 -0
  19. data/lib/jasmine-core/spec/core/ExpectationSpec.js +320 -0
  20. data/lib/jasmine-core/spec/core/JsApiReporterSpec.js +150 -38
  21. data/lib/jasmine-core/spec/core/ObjectContainingSpec.js +64 -0
  22. data/lib/jasmine-core/spec/core/PrettyPrintSpec.js +43 -42
  23. data/lib/jasmine-core/spec/core/QueueRunnerSpec.js +147 -0
  24. data/lib/jasmine-core/spec/core/ReportDispatcherSpec.js +40 -0
  25. data/lib/jasmine-core/spec/core/SpecRunningSpec.js +92 -1075
  26. data/lib/jasmine-core/spec/core/SpecSpec.js +215 -95
  27. data/lib/jasmine-core/spec/core/SpySpec.js +28 -196
  28. data/lib/jasmine-core/spec/core/SpyStrategySpec.js +101 -0
  29. data/lib/jasmine-core/spec/core/SuiteSpec.js +216 -106
  30. data/lib/jasmine-core/spec/core/TimerSpec.js +13 -0
  31. data/lib/jasmine-core/spec/core/UtilSpec.js +19 -30
  32. data/lib/jasmine-core/spec/core/matchers/matchersUtilSpec.js +219 -0
  33. data/lib/jasmine-core/spec/core/matchers/toBeCloseToSpec.js +51 -0
  34. data/lib/jasmine-core/spec/core/matchers/toBeDefinedSpec.js +18 -0
  35. data/lib/jasmine-core/spec/core/matchers/toBeFalsySpec.js +38 -0
  36. data/lib/jasmine-core/spec/core/matchers/toBeGreaterThanSpec.js +19 -0
  37. data/lib/jasmine-core/spec/core/matchers/toBeLessThanSpec.js +20 -0
  38. data/lib/jasmine-core/spec/core/matchers/toBeNaNSpec.js +36 -0
  39. data/lib/jasmine-core/spec/core/matchers/toBeNullSpec.js +17 -0
  40. data/lib/jasmine-core/spec/core/matchers/toBeSpec.js +17 -0
  41. data/lib/jasmine-core/spec/core/matchers/toBeTruthySpec.js +38 -0
  42. data/lib/jasmine-core/spec/core/matchers/toBeUndefinedSpec.js +17 -0
  43. data/lib/jasmine-core/spec/core/matchers/toContainSpec.js +24 -0
  44. data/lib/jasmine-core/spec/core/matchers/toEqualSpec.js +28 -0
  45. data/lib/jasmine-core/spec/core/matchers/toHaveBeenCalledSpec.js +46 -0
  46. data/lib/jasmine-core/spec/core/matchers/toHaveBeenCalledWithSpec.js +57 -0
  47. data/lib/jasmine-core/spec/core/matchers/toMatchSpec.js +34 -0
  48. data/lib/jasmine-core/spec/core/matchers/toThrowErrorSpec.js +280 -0
  49. data/lib/jasmine-core/spec/core/matchers/toThrowSpec.js +98 -0
  50. data/lib/jasmine-core/spec/helpers/BrowserFlags.js +19 -0
  51. data/lib/jasmine-core/spec/html/HtmlReporterSpec.js +494 -0
  52. data/lib/jasmine-core/spec/html/HtmlSpecFilterSpec.js +18 -0
  53. data/lib/jasmine-core/spec/html/MatchersHtmlSpec.js +8 -8
  54. data/lib/jasmine-core/spec/html/PrettyPrintHtmlSpec.js +3 -3
  55. data/lib/jasmine-core/spec/html/QueryStringSpec.js +43 -0
  56. data/lib/jasmine-core/spec/html/ResultsNodeSpec.js +62 -0
  57. data/lib/jasmine-core/spec/node_suite.js +137 -79
  58. data/lib/jasmine-core/spec/performance/performance_test.js +10 -0
  59. data/lib/jasmine-core/spec/support/dev_boot.js +118 -0
  60. data/lib/jasmine-core/version.rb +5 -2
  61. metadata +47 -103
  62. data/lib/jasmine-core/example/SpecRunner.html +0 -54
  63. data/lib/jasmine-core/spec/core/BaseSpec.js +0 -27
  64. data/lib/jasmine-core/spec/core/MatchersSpec.js +0 -1157
  65. data/lib/jasmine-core/spec/core/MockClockSpec.js +0 -38
  66. data/lib/jasmine-core/spec/core/MultiReporterSpec.js +0 -45
  67. data/lib/jasmine-core/spec/core/NestedResultsSpec.js +0 -54
  68. data/lib/jasmine-core/spec/core/QueueSpec.js +0 -23
  69. data/lib/jasmine-core/spec/core/ReporterSpec.js +0 -56
  70. data/lib/jasmine-core/spec/core/RunnerSpec.js +0 -280
  71. data/lib/jasmine-core/spec/core/WaitsForBlockSpec.js +0 -118
  72. data/lib/jasmine-core/spec/html/HTMLReporterSpec.js +0 -209
  73. data/lib/jasmine-core/spec/html/TrivialReporterSpec.js +0 -239
@@ -1,82 +1,54 @@
1
1
  body { background-color: #eeeeee; padding: 0; margin: 5px; overflow-y: scroll; }
2
2
 
3
- #HTMLReporter { font-size: 11px; font-family: Monaco, "Lucida Console", monospace; line-height: 14px; color: #333333; }
4
- #HTMLReporter a { text-decoration: none; }
5
- #HTMLReporter a:hover { text-decoration: underline; }
6
- #HTMLReporter p, #HTMLReporter h1, #HTMLReporter h2, #HTMLReporter h3, #HTMLReporter h4, #HTMLReporter h5, #HTMLReporter h6 { margin: 0; line-height: 14px; }
7
- #HTMLReporter .banner, #HTMLReporter .symbolSummary, #HTMLReporter .summary, #HTMLReporter .resultMessage, #HTMLReporter .specDetail .description, #HTMLReporter .alert .bar, #HTMLReporter .stackTrace { padding-left: 9px; padding-right: 9px; }
8
- #HTMLReporter #jasmine_content { position: fixed; right: 100%; }
9
- #HTMLReporter .version { color: #aaaaaa; }
10
- #HTMLReporter .banner { margin-top: 14px; }
11
- #HTMLReporter .duration { color: #aaaaaa; float: right; }
12
- #HTMLReporter .symbolSummary { overflow: hidden; *zoom: 1; margin: 14px 0; }
13
- #HTMLReporter .symbolSummary li { display: block; float: left; height: 7px; width: 14px; margin-bottom: 7px; font-size: 16px; }
14
- #HTMLReporter .symbolSummary li.passed { font-size: 14px; }
15
- #HTMLReporter .symbolSummary li.passed:before { color: #5e7d00; content: "\02022"; }
16
- #HTMLReporter .symbolSummary li.failed { line-height: 9px; }
17
- #HTMLReporter .symbolSummary li.failed:before { color: #b03911; content: "x"; font-weight: bold; margin-left: -1px; }
18
- #HTMLReporter .symbolSummary li.skipped { font-size: 14px; }
19
- #HTMLReporter .symbolSummary li.skipped:before { color: #bababa; content: "\02022"; }
20
- #HTMLReporter .symbolSummary li.pending { line-height: 11px; }
21
- #HTMLReporter .symbolSummary li.pending:before { color: #aaaaaa; content: "-"; }
22
- #HTMLReporter .exceptions { color: #fff; float: right; margin-top: 5px; margin-right: 5px; }
23
- #HTMLReporter .bar { line-height: 28px; font-size: 14px; display: block; color: #eee; }
24
- #HTMLReporter .runningAlert { background-color: #666666; }
25
- #HTMLReporter .skippedAlert { background-color: #aaaaaa; }
26
- #HTMLReporter .skippedAlert:first-child { background-color: #333333; }
27
- #HTMLReporter .skippedAlert:hover { text-decoration: none; color: white; text-decoration: underline; }
28
- #HTMLReporter .passingAlert { background-color: #a6b779; }
29
- #HTMLReporter .passingAlert:first-child { background-color: #5e7d00; }
30
- #HTMLReporter .failingAlert { background-color: #cf867e; }
31
- #HTMLReporter .failingAlert:first-child { background-color: #b03911; }
32
- #HTMLReporter .results { margin-top: 14px; }
33
- #HTMLReporter #details { display: none; }
34
- #HTMLReporter .resultsMenu, #HTMLReporter .resultsMenu a { background-color: #fff; color: #333333; }
35
- #HTMLReporter.showDetails .summaryMenuItem { font-weight: normal; text-decoration: inherit; }
36
- #HTMLReporter.showDetails .summaryMenuItem:hover { text-decoration: underline; }
37
- #HTMLReporter.showDetails .detailsMenuItem { font-weight: bold; text-decoration: underline; }
38
- #HTMLReporter.showDetails .summary { display: none; }
39
- #HTMLReporter.showDetails #details { display: block; }
40
- #HTMLReporter .summaryMenuItem { font-weight: bold; text-decoration: underline; }
41
- #HTMLReporter .summary { margin-top: 14px; }
42
- #HTMLReporter .summary .suite .suite, #HTMLReporter .summary .specSummary { margin-left: 14px; }
43
- #HTMLReporter .summary .specSummary.passed a { color: #5e7d00; }
44
- #HTMLReporter .summary .specSummary.failed a { color: #b03911; }
45
- #HTMLReporter .description + .suite { margin-top: 0; }
46
- #HTMLReporter .suite { margin-top: 14px; }
47
- #HTMLReporter .suite a { color: #333333; }
48
- #HTMLReporter #details .specDetail { margin-bottom: 28px; }
49
- #HTMLReporter #details .specDetail .description { display: block; color: white; background-color: #b03911; }
50
- #HTMLReporter .resultMessage { padding-top: 14px; color: #333333; }
51
- #HTMLReporter .resultMessage span.result { display: block; }
52
- #HTMLReporter .stackTrace { margin: 5px 0 0 0; max-height: 224px; overflow: auto; line-height: 18px; color: #666666; border: 1px solid #ddd; background: white; white-space: pre; }
53
-
54
- #TrivialReporter { padding: 8px 13px; position: absolute; top: 0; bottom: 0; left: 0; right: 0; overflow-y: scroll; background-color: white; font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif; /*.resultMessage {*/ /*white-space: pre;*/ /*}*/ }
55
- #TrivialReporter a:visited, #TrivialReporter a { color: #303; }
56
- #TrivialReporter a:hover, #TrivialReporter a:active { color: blue; }
57
- #TrivialReporter .run_spec { float: right; padding-right: 5px; font-size: .8em; text-decoration: none; }
58
- #TrivialReporter .banner { color: #303; background-color: #fef; padding: 5px; }
59
- #TrivialReporter .logo { float: left; font-size: 1.1em; padding-left: 5px; }
60
- #TrivialReporter .logo .version { font-size: .6em; padding-left: 1em; }
61
- #TrivialReporter .runner.running { background-color: yellow; }
62
- #TrivialReporter .options { text-align: right; font-size: .8em; }
63
- #TrivialReporter .suite { border: 1px outset gray; margin: 5px 0; padding-left: 1em; }
64
- #TrivialReporter .suite .suite { margin: 5px; }
65
- #TrivialReporter .suite.passed { background-color: #dfd; }
66
- #TrivialReporter .suite.failed { background-color: #fdd; }
67
- #TrivialReporter .spec { margin: 5px; padding-left: 1em; clear: both; }
68
- #TrivialReporter .spec.failed, #TrivialReporter .spec.passed, #TrivialReporter .spec.skipped { padding-bottom: 5px; border: 1px solid gray; }
69
- #TrivialReporter .spec.failed { background-color: #fbb; border-color: red; }
70
- #TrivialReporter .spec.passed { background-color: #bfb; border-color: green; }
71
- #TrivialReporter .spec.skipped { background-color: #bbb; }
72
- #TrivialReporter .messages { border-left: 1px dashed gray; padding-left: 1em; padding-right: 1em; }
73
- #TrivialReporter .passed { background-color: #cfc; display: none; }
74
- #TrivialReporter .failed { background-color: #fbb; }
75
- #TrivialReporter .skipped { color: #777; background-color: #eee; display: none; }
76
- #TrivialReporter .resultMessage span.result { display: block; line-height: 2em; color: black; }
77
- #TrivialReporter .resultMessage .mismatch { color: black; }
78
- #TrivialReporter .stackTrace { white-space: pre; font-size: .8em; margin-left: 10px; max-height: 5em; overflow: auto; border: 1px inset red; padding: 1em; background: #eef; }
79
- #TrivialReporter .finished-at { padding-left: 1em; font-size: .6em; }
80
- #TrivialReporter.show-passed .passed, #TrivialReporter.show-skipped .skipped { display: block; }
81
- #TrivialReporter #jasmine_content { position: fixed; right: 100%; }
82
- #TrivialReporter .runner { border: 1px solid gray; display: block; margin: 5px 0; padding: 2px 0 2px 10px; }
3
+ .html-reporter { font-size: 11px; font-family: Monaco, "Lucida Console", monospace; line-height: 14px; color: #333333; }
4
+ .html-reporter a { text-decoration: none; }
5
+ .html-reporter a:hover { text-decoration: underline; }
6
+ .html-reporter p, .html-reporter h1, .html-reporter h2, .html-reporter h3, .html-reporter h4, .html-reporter h5, .html-reporter h6 { margin: 0; line-height: 14px; }
7
+ .html-reporter .banner, .html-reporter .symbol-summary, .html-reporter .summary, .html-reporter .result-message, .html-reporter .spec .description, .html-reporter .spec-detail .description, .html-reporter .alert .bar, .html-reporter .stack-trace { padding-left: 9px; padding-right: 9px; }
8
+ .html-reporter .banner .version { margin-left: 14px; }
9
+ .html-reporter #jasmine_content { position: fixed; right: 100%; }
10
+ .html-reporter .version { color: #aaaaaa; }
11
+ .html-reporter .banner { margin-top: 14px; }
12
+ .html-reporter .duration { color: #aaaaaa; float: right; }
13
+ .html-reporter .symbol-summary { overflow: hidden; *zoom: 1; margin: 14px 0; }
14
+ .html-reporter .symbol-summary li { display: block; float: left; height: 7px; width: 14px; margin-bottom: 7px; font-size: 16px; }
15
+ .html-reporter .symbol-summary li.passed { font-size: 14px; }
16
+ .html-reporter .symbol-summary li.passed:before { color: #5e7d00; content: "\02022"; }
17
+ .html-reporter .symbol-summary li.failed { line-height: 9px; }
18
+ .html-reporter .symbol-summary li.failed:before { color: #b03911; content: "x"; font-weight: bold; margin-left: -1px; }
19
+ .html-reporter .symbol-summary li.disabled { font-size: 14px; }
20
+ .html-reporter .symbol-summary li.disabled:before { color: #bababa; content: "\02022"; }
21
+ .html-reporter .symbol-summary li.pending { line-height: 17px; }
22
+ .html-reporter .symbol-summary li.pending:before { color: #ba9d37; content: "*"; }
23
+ .html-reporter .exceptions { color: #fff; float: right; margin-top: 5px; margin-right: 5px; }
24
+ .html-reporter .bar { line-height: 28px; font-size: 14px; display: block; color: #eee; }
25
+ .html-reporter .bar.failed { background-color: #b03911; }
26
+ .html-reporter .bar.passed { background-color: #a6b779; }
27
+ .html-reporter .bar.skipped { background-color: #bababa; }
28
+ .html-reporter .bar.menu { background-color: #fff; color: #aaaaaa; }
29
+ .html-reporter .bar.menu a { color: #333333; }
30
+ .html-reporter .bar a { color: white; }
31
+ .html-reporter.spec-list .bar.menu.failure-list, .html-reporter.spec-list .results .failures { display: none; }
32
+ .html-reporter.failure-list .bar.menu.spec-list, .html-reporter.failure-list .summary { display: none; }
33
+ .html-reporter .running-alert { background-color: #666666; }
34
+ .html-reporter .results { margin-top: 14px; }
35
+ .html-reporter.showDetails .summaryMenuItem { font-weight: normal; text-decoration: inherit; }
36
+ .html-reporter.showDetails .summaryMenuItem:hover { text-decoration: underline; }
37
+ .html-reporter.showDetails .detailsMenuItem { font-weight: bold; text-decoration: underline; }
38
+ .html-reporter.showDetails .summary { display: none; }
39
+ .html-reporter.showDetails #details { display: block; }
40
+ .html-reporter .summaryMenuItem { font-weight: bold; text-decoration: underline; }
41
+ .html-reporter .summary { margin-top: 14px; }
42
+ .html-reporter .summary ul { list-style-type: none; margin-left: 14px; padding-top: 0; padding-left: 0; }
43
+ .html-reporter .summary ul.suite { margin-top: 7px; margin-bottom: 7px; }
44
+ .html-reporter .summary li.passed a { color: #5e7d00; }
45
+ .html-reporter .summary li.failed a { color: #b03911; }
46
+ .html-reporter .summary li.pending a { color: #ba9d37; }
47
+ .html-reporter .description + .suite { margin-top: 0; }
48
+ .html-reporter .suite { margin-top: 14px; }
49
+ .html-reporter .suite a { color: #333333; }
50
+ .html-reporter .failures .spec-detail { margin-bottom: 28px; }
51
+ .html-reporter .failures .spec-detail .description { display: block; color: white; background-color: #b03911; }
52
+ .html-reporter .result-message { padding-top: 14px; color: #333333; white-space: pre; }
53
+ .html-reporter .result-message span.result { display: block; }
54
+ .html-reporter .stack-trace { margin: 5px 0 0 0; max-height: 224px; overflow: auto; line-height: 18px; color: #666666; border: 1px solid #dddddd; background: white; white-space: pre; }
@@ -1,2600 +1,2361 @@
1
- var isCommonJS = typeof window == "undefined" && typeof exports == "object";
2
-
3
- /**
4
- * Top level namespace for Jasmine, a lightweight JavaScript BDD/spec/testing framework.
5
- *
6
- * @namespace
7
- */
8
- var jasmine = {};
9
- if (isCommonJS) exports.jasmine = jasmine;
10
- /**
11
- * @private
12
- */
13
- jasmine.unimplementedMethod_ = function() {
14
- throw new Error("unimplemented method");
15
- };
1
+ /*
2
+ Copyright (c) 2008-2013 Pivotal Labs
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining
5
+ a copy of this software and associated documentation files (the
6
+ "Software"), to deal in the Software without restriction, including
7
+ without limitation the rights to use, copy, modify, merge, publish,
8
+ distribute, sublicense, and/or sell copies of the Software, and to
9
+ permit persons to whom the Software is furnished to do so, subject to
10
+ the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ */
23
+ function getJasmineRequireObj() {
24
+ if (typeof module !== "undefined" && module.exports) {
25
+ return exports;
26
+ } else {
27
+ window.jasmineRequire = window.jasmineRequire || {};
28
+ return window.jasmineRequire;
29
+ }
30
+ }
31
+
32
+ getJasmineRequireObj().core = function(jRequire) {
33
+ j$ = {};
34
+
35
+ jRequire.base(j$);
36
+ j$.util = jRequire.util();
37
+ j$.Any = jRequire.Any();
38
+ j$.CallTracker = jRequire.CallTracker();
39
+ j$.Clock = jRequire.Clock();
40
+ j$.DelayedFunctionScheduler = jRequire.DelayedFunctionScheduler();
41
+ j$.Env = jRequire.Env(j$);
42
+ j$.ExceptionFormatter = jRequire.ExceptionFormatter();
43
+ j$.Expectation = jRequire.Expectation();
44
+ j$.buildExpectationResult = jRequire.buildExpectationResult();
45
+ j$.JsApiReporter = jRequire.JsApiReporter();
46
+ j$.matchersUtil = jRequire.matchersUtil(j$);
47
+ j$.ObjectContaining = jRequire.ObjectContaining(j$);
48
+ j$.pp = jRequire.pp(j$);
49
+ j$.QueueRunner = jRequire.QueueRunner();
50
+ j$.ReportDispatcher = jRequire.ReportDispatcher();
51
+ j$.Spec = jRequire.Spec();
52
+ j$.SpyStrategy = jRequire.SpyStrategy();
53
+ j$.Suite = jRequire.Suite();
54
+ j$.Timer = jRequire.Timer();
55
+ j$.version = jRequire.version();
56
+
57
+ j$.matchers = jRequire.requireMatchers(jRequire, j$);
58
+
59
+ return j$;
60
+ };
61
+
62
+ getJasmineRequireObj().requireMatchers = function(jRequire, j$) {
63
+ var availableMatchers = [
64
+ "toBe",
65
+ "toBeCloseTo",
66
+ "toBeDefined",
67
+ "toBeFalsy",
68
+ "toBeGreaterThan",
69
+ "toBeLessThan",
70
+ "toBeNaN",
71
+ "toBeNull",
72
+ "toBeTruthy",
73
+ "toBeUndefined",
74
+ "toContain",
75
+ "toEqual",
76
+ "toHaveBeenCalled",
77
+ "toHaveBeenCalledWith",
78
+ "toMatch",
79
+ "toThrow",
80
+ "toThrowError"
81
+ ],
82
+ matchers = {};
83
+
84
+ for (var i = 0; i < availableMatchers.length; i++) {
85
+ var name = availableMatchers[i];
86
+ matchers[name] = jRequire[name](j$);
87
+ }
88
+
89
+ return matchers;
90
+ };
91
+
92
+ getJasmineRequireObj().base = function(j$) {
93
+ j$.unimplementedMethod_ = function() {
94
+ throw new Error("unimplemented method");
95
+ };
16
96
 
17
- /**
18
- * Use <code>jasmine.undefined</code> instead of <code>undefined</code>, since <code>undefined</code> is just
19
- * a plain old variable and may be redefined by somebody else.
20
- *
21
- * @private
22
- */
23
- jasmine.undefined = jasmine.___undefined___;
24
-
25
- /**
26
- * Show diagnostic messages in the console if set to true
27
- *
28
- */
29
- jasmine.VERBOSE = false;
30
-
31
- /**
32
- * Default interval in milliseconds for event loop yields (e.g. to allow network activity or to refresh the screen with the HTML-based runner). Small values here may result in slow test running. Zero means no updates until all tests have completed.
33
- *
34
- */
35
- jasmine.DEFAULT_UPDATE_INTERVAL = 250;
36
-
37
- /**
38
- * Maximum levels of nesting that will be included when an object is pretty-printed
39
- */
40
- jasmine.MAX_PRETTY_PRINT_DEPTH = 40;
41
-
42
- /**
43
- * Default timeout interval in milliseconds for waitsFor() blocks.
44
- */
45
- jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000;
46
-
47
- /**
48
- * By default exceptions thrown in the context of a test are caught by jasmine so that it can run the remaining tests in the suite.
49
- * Set to false to let the exception bubble up in the browser.
50
- *
51
- */
52
- jasmine.CATCH_EXCEPTIONS = true;
53
-
54
- jasmine.getGlobal = function() {
55
- function getGlobal() {
56
- return this;
57
- }
97
+ j$.DEFAULT_UPDATE_INTERVAL = 250;
98
+ j$.MAX_PRETTY_PRINT_DEPTH = 40;
99
+ j$.DEFAULT_TIMEOUT_INTERVAL = 5000;
100
+
101
+ j$.getGlobal = function() {
102
+ function getGlobal() {
103
+ return this;
104
+ }
105
+
106
+ return getGlobal();
107
+ };
108
+
109
+ j$.getEnv = function(options) {
110
+ var env = j$.currentEnv_ = j$.currentEnv_ || new j$.Env(options);
111
+ //jasmine. singletons in here (setTimeout blah blah).
112
+ return env;
113
+ };
114
+
115
+ j$.isArray_ = function(value) {
116
+ return j$.isA_("Array", value);
117
+ };
118
+
119
+ j$.isString_ = function(value) {
120
+ return j$.isA_("String", value);
121
+ };
122
+
123
+ j$.isNumber_ = function(value) {
124
+ return j$.isA_("Number", value);
125
+ };
126
+
127
+ j$.isA_ = function(typeName, value) {
128
+ return Object.prototype.toString.apply(value) === '[object ' + typeName + ']';
129
+ };
130
+
131
+ j$.isDomNode = function(obj) {
132
+ return obj.nodeType > 0;
133
+ };
58
134
 
59
- return getGlobal();
135
+ j$.any = function(clazz) {
136
+ return new j$.Any(clazz);
137
+ };
138
+
139
+ j$.objectContaining = function(sample) {
140
+ return new j$.ObjectContaining(sample);
141
+ };
142
+
143
+ j$.createSpy = function(name, originalFn) {
144
+
145
+ var spyStrategy = new j$.SpyStrategy({
146
+ name: name,
147
+ fn: originalFn,
148
+ getSpy: function() { return spy; }
149
+ }),
150
+ callTracker = new j$.CallTracker(),
151
+ spy = function() {
152
+ callTracker.track({
153
+ object: this,
154
+ args: Array.prototype.slice.apply(arguments)
155
+ });
156
+ return spyStrategy.exec.apply(this, arguments);
157
+ };
158
+
159
+ for (var prop in originalFn) {
160
+ if (prop === 'and' || prop === 'calls') {
161
+ throw new Error("Jasmine spies would overwrite the 'and' and 'calls' properties on the object being spied upon");
162
+ }
163
+
164
+ spy[prop] = originalFn[prop];
165
+ }
166
+
167
+ spy.and = spyStrategy;
168
+ spy.calls = callTracker;
169
+
170
+ return spy;
171
+ };
172
+
173
+ j$.isSpy = function(putativeSpy) {
174
+ if (!putativeSpy) {
175
+ return false;
176
+ }
177
+ return putativeSpy.and instanceof j$.SpyStrategy &&
178
+ putativeSpy.calls instanceof j$.CallTracker;
179
+ };
180
+
181
+ j$.createSpyObj = function(baseName, methodNames) {
182
+ if (!j$.isArray_(methodNames) || methodNames.length === 0) {
183
+ throw "createSpyObj requires a non-empty array of method names to create spies for";
184
+ }
185
+ var obj = {};
186
+ for (var i = 0; i < methodNames.length; i++) {
187
+ obj[methodNames[i]] = j$.createSpy(baseName + '.' + methodNames[i]);
188
+ }
189
+ return obj;
190
+ };
60
191
  };
61
192
 
62
- /**
63
- * Allows for bound functions to be compared. Internal use only.
64
- *
65
- * @ignore
66
- * @private
67
- * @param base {Object} bound 'this' for the function
68
- * @param name {Function} function to find
69
- */
70
- jasmine.bindOriginal_ = function(base, name) {
71
- var original = base[name];
72
- if (original.apply) {
73
- return function() {
74
- return original.apply(base, arguments);
193
+ getJasmineRequireObj().util = function() {
194
+
195
+ var util = {};
196
+
197
+ util.inherit = function(childClass, parentClass) {
198
+ var subclass = function() {
75
199
  };
76
- } else {
77
- // IE support
78
- return jasmine.getGlobal()[name];
79
- }
80
- };
200
+ subclass.prototype = parentClass.prototype;
201
+ childClass.prototype = new subclass();
202
+ };
81
203
 
82
- jasmine.setTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'setTimeout');
83
- jasmine.clearTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearTimeout');
84
- jasmine.setInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'setInterval');
85
- jasmine.clearInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearInterval');
204
+ util.htmlEscape = function(str) {
205
+ if (!str) return str;
206
+ return str.replace(/&/g, '&amp;')
207
+ .replace(/</g, '&lt;')
208
+ .replace(/>/g, '&gt;');
209
+ };
86
210
 
87
- jasmine.MessageResult = function(values) {
88
- this.type = 'log';
89
- this.values = values;
90
- this.trace = new Error(); // todo: test better
91
- };
211
+ util.argsToArray = function(args) {
212
+ var arrayOfArgs = [];
213
+ for (var i = 0; i < args.length; i++) arrayOfArgs.push(args[i]);
214
+ return arrayOfArgs;
215
+ };
92
216
 
93
- jasmine.MessageResult.prototype.toString = function() {
94
- var text = "";
95
- for (var i = 0; i < this.values.length; i++) {
96
- if (i > 0) text += " ";
97
- if (jasmine.isString_(this.values[i])) {
98
- text += this.values[i];
99
- } else {
100
- text += jasmine.pp(this.values[i]);
217
+ util.isUndefined = function(obj) {
218
+ return obj === void 0;
219
+ };
220
+
221
+ return util;
222
+ };
223
+
224
+ getJasmineRequireObj().Spec = function() {
225
+ function Spec(attrs) {
226
+ this.encounteredExpectations = false;
227
+ this.expectationFactory = attrs.expectationFactory;
228
+ this.resultCallback = attrs.resultCallback || function() {};
229
+ this.id = attrs.id;
230
+ this.description = attrs.description || '';
231
+ this.fn = attrs.fn;
232
+ this.beforeFns = attrs.beforeFns || function() {};
233
+ this.afterFns = attrs.afterFns || function() {};
234
+ this.catchingExceptions = attrs.catchingExceptions;
235
+ this.onStart = attrs.onStart || function() {};
236
+ this.exceptionFormatter = attrs.exceptionFormatter || function() {};
237
+ this.getSpecName = attrs.getSpecName || function() { return ''; };
238
+ this.expectationResultFactory = attrs.expectationResultFactory || function() { };
239
+ this.queueRunner = attrs.queueRunner || function() {};
240
+ this.catchingExceptions = attrs.catchingExceptions || function() { return true; };
241
+
242
+ this.timer = attrs.timer || {setTimeout: setTimeout, clearTimeout: clearTimeout};
243
+
244
+ if (!this.fn) {
245
+ this.pend();
101
246
  }
247
+
248
+ this.result = {
249
+ id: this.id,
250
+ description: this.description,
251
+ fullName: this.getFullName(),
252
+ status: this.status(),
253
+ failedExpectations: []
254
+ };
102
255
  }
103
- return text;
104
- };
105
256
 
106
- jasmine.ExpectationResult = function(params) {
107
- this.type = 'expect';
108
- this.matcherName = params.matcherName;
109
- this.passed_ = params.passed;
110
- this.expected = params.expected;
111
- this.actual = params.actual;
112
- this.message = this.passed_ ? 'Passed.' : params.message;
257
+ Spec.prototype.addExpectationResult = function(passed, data) {
258
+ this.encounteredExpectations = true;
259
+ if (passed) {
260
+ return;
261
+ }
262
+ this.result.failedExpectations.push(this.expectationResultFactory(data));
263
+ };
113
264
 
114
- var trace = (params.trace || new Error(this.message));
115
- this.trace = this.passed_ ? '' : trace;
116
- };
265
+ Spec.prototype.expect = function(actual) {
266
+ return this.expectationFactory(actual, this);
267
+ };
117
268
 
118
- jasmine.ExpectationResult.prototype.toString = function () {
119
- return this.message;
120
- };
269
+ Spec.prototype.execute = function(onComplete) {
270
+ var self = this;
121
271
 
122
- jasmine.ExpectationResult.prototype.passed = function () {
123
- return this.passed_;
124
- };
272
+ this.onStart(this);
125
273
 
126
- /**
127
- * Getter for the Jasmine environment. Ensures one gets created
128
- */
129
- jasmine.getEnv = function() {
130
- var env = jasmine.currentEnv_ = jasmine.currentEnv_ || new jasmine.Env();
131
- return env;
132
- };
274
+ if (this.markedPending || this.disabled) {
275
+ complete();
276
+ return;
277
+ }
133
278
 
134
- /**
135
- * @ignore
136
- * @private
137
- * @param value
138
- * @returns {Boolean}
139
- */
140
- jasmine.isArray_ = function(value) {
141
- return jasmine.isA_("Array", value);
142
- };
279
+ function timeoutable(fn) {
280
+ return function(done) {
281
+ var timeout = Function.prototype.apply.apply(self.timer.setTimeout, [j$.getGlobal(), [function() {
282
+ onException(new Error('timeout'));
283
+ done();
284
+ }, 10000]]);
143
285
 
144
- /**
145
- * @ignore
146
- * @private
147
- * @param value
148
- * @returns {Boolean}
149
- */
150
- jasmine.isString_ = function(value) {
151
- return jasmine.isA_("String", value);
152
- };
286
+ var callDone = function() {
287
+ Function.prototype.apply.apply(self.timer.clearTimeout, [j$.getGlobal(), [timeout]]);
288
+ done();
289
+ };
153
290
 
154
- /**
155
- * @ignore
156
- * @private
157
- * @param value
158
- * @returns {Boolean}
159
- */
160
- jasmine.isNumber_ = function(value) {
161
- return jasmine.isA_("Number", value);
162
- };
291
+ fn(callDone); //TODO: do we care about more than 1 arg?
292
+ };
293
+ }
163
294
 
164
- /**
165
- * @ignore
166
- * @private
167
- * @param {String} typeName
168
- * @param value
169
- * @returns {Boolean}
170
- */
171
- jasmine.isA_ = function(typeName, value) {
172
- return Object.prototype.toString.apply(value) === '[object ' + typeName + ']';
173
- };
295
+ var befores = this.beforeFns() || [],
296
+ afters = this.afterFns() || [],
297
+ thisOne = (this.fn.length) ? timeoutable(this.fn) : this.fn;
298
+ var allFns = befores.concat(thisOne).concat(afters);
174
299
 
175
- /**
176
- * Pretty printer for expecations. Takes any object and turns it into a human-readable string.
177
- *
178
- * @param value {Object} an object to be outputted
179
- * @returns {String}
180
- */
181
- jasmine.pp = function(value) {
182
- var stringPrettyPrinter = new jasmine.StringPrettyPrinter();
183
- stringPrettyPrinter.format(value);
184
- return stringPrettyPrinter.string;
185
- };
300
+ this.queueRunner({
301
+ fns: allFns,
302
+ onException: onException,
303
+ onComplete: complete
304
+ });
186
305
 
187
- /**
188
- * Returns true if the object is a DOM Node.
189
- *
190
- * @param {Object} obj object to check
191
- * @returns {Boolean}
192
- */
193
- jasmine.isDomNode = function(obj) {
194
- return obj.nodeType > 0;
195
- };
306
+ function onException(e) {
307
+ if (Spec.isPendingSpecException(e)) {
308
+ self.pend();
309
+ return;
310
+ }
196
311
 
197
- /**
198
- * Returns a matchable 'generic' object of the class type. For use in expecations of type when values don't matter.
199
- *
200
- * @example
201
- * // don't care about which function is passed in, as long as it's a function
202
- * expect(mySpy).toHaveBeenCalledWith(jasmine.any(Function));
203
- *
204
- * @param {Class} clazz
205
- * @returns matchable object of the type clazz
206
- */
207
- jasmine.any = function(clazz) {
208
- return new jasmine.Matchers.Any(clazz);
209
- };
312
+ self.addExpectationResult(false, {
313
+ matcherName: "",
314
+ passed: false,
315
+ expected: "",
316
+ actual: "",
317
+ error: e
318
+ });
319
+ }
210
320
 
211
- /**
212
- * Returns a matchable subset of a JSON object. For use in expectations when you don't care about all of the
213
- * attributes on the object.
214
- *
215
- * @example
216
- * // don't care about any other attributes than foo.
217
- * expect(mySpy).toHaveBeenCalledWith(jasmine.objectContaining({foo: "bar"});
218
- *
219
- * @param sample {Object} sample
220
- * @returns matchable object for the sample
221
- */
222
- jasmine.objectContaining = function (sample) {
223
- return new jasmine.Matchers.ObjectContaining(sample);
224
- };
321
+ function complete() {
322
+ self.result.status = self.status();
323
+ self.resultCallback(self.result);
225
324
 
226
- /**
227
- * Jasmine Spies are test doubles that can act as stubs, spies, fakes or when used in an expecation, mocks.
228
- *
229
- * Spies should be created in test setup, before expectations. They can then be checked, using the standard Jasmine
230
- * expectation syntax. Spies can be checked if they were called or not and what the calling params were.
231
- *
232
- * A Spy has the following fields: wasCalled, callCount, mostRecentCall, and argsForCall (see docs).
233
- *
234
- * Spies are torn down at the end of every spec.
235
- *
236
- * Note: Do <b>not</b> call new jasmine.Spy() directly - a spy must be created using spyOn, jasmine.createSpy or jasmine.createSpyObj.
237
- *
238
- * @example
239
- * // a stub
240
- * var myStub = jasmine.createSpy('myStub'); // can be used anywhere
241
- *
242
- * // spy example
243
- * var foo = {
244
- * not: function(bool) { return !bool; }
245
- * }
246
- *
247
- * // actual foo.not will not be called, execution stops
248
- * spyOn(foo, 'not');
249
-
250
- // foo.not spied upon, execution will continue to implementation
251
- * spyOn(foo, 'not').andCallThrough();
252
- *
253
- * // fake example
254
- * var foo = {
255
- * not: function(bool) { return !bool; }
256
- * }
257
- *
258
- * // foo.not(val) will return val
259
- * spyOn(foo, 'not').andCallFake(function(value) {return value;});
260
- *
261
- * // mock example
262
- * foo.not(7 == 7);
263
- * expect(foo.not).toHaveBeenCalled();
264
- * expect(foo.not).toHaveBeenCalledWith(true);
265
- *
266
- * @constructor
267
- * @see spyOn, jasmine.createSpy, jasmine.createSpyObj
268
- * @param {String} name
269
- */
270
- jasmine.Spy = function(name) {
271
- /**
272
- * The name of the spy, if provided.
273
- */
274
- this.identity = name || 'unknown';
275
- /**
276
- * Is this Object a spy?
277
- */
278
- this.isSpy = true;
279
- /**
280
- * The actual function this spy stubs.
281
- */
282
- this.plan = function() {
283
- };
284
- /**
285
- * Tracking of the most recent call to the spy.
286
- * @example
287
- * var mySpy = jasmine.createSpy('foo');
288
- * mySpy(1, 2);
289
- * mySpy.mostRecentCall.args = [1, 2];
290
- */
291
- this.mostRecentCall = {};
292
-
293
- /**
294
- * Holds arguments for each call to the spy, indexed by call count
295
- * @example
296
- * var mySpy = jasmine.createSpy('foo');
297
- * mySpy(1, 2);
298
- * mySpy(7, 8);
299
- * mySpy.mostRecentCall.args = [7, 8];
300
- * mySpy.argsForCall[0] = [1, 2];
301
- * mySpy.argsForCall[1] = [7, 8];
302
- */
303
- this.argsForCall = [];
304
- this.calls = [];
305
- };
325
+ if (onComplete) {
326
+ onComplete();
327
+ }
328
+ }
329
+ };
306
330
 
307
- /**
308
- * Tells a spy to call through to the actual implemenatation.
309
- *
310
- * @example
311
- * var foo = {
312
- * bar: function() { // do some stuff }
313
- * }
314
- *
315
- * // defining a spy on an existing property: foo.bar
316
- * spyOn(foo, 'bar').andCallThrough();
317
- */
318
- jasmine.Spy.prototype.andCallThrough = function() {
319
- this.plan = this.originalValue;
320
- return this;
321
- };
331
+ Spec.prototype.disable = function() {
332
+ this.disabled = true;
333
+ };
322
334
 
323
- /**
324
- * For setting the return value of a spy.
325
- *
326
- * @example
327
- * // defining a spy from scratch: foo() returns 'baz'
328
- * var foo = jasmine.createSpy('spy on foo').andReturn('baz');
329
- *
330
- * // defining a spy on an existing property: foo.bar() returns 'baz'
331
- * spyOn(foo, 'bar').andReturn('baz');
332
- *
333
- * @param {Object} value
334
- */
335
- jasmine.Spy.prototype.andReturn = function(value) {
336
- this.plan = function() {
337
- return value;
338
- };
339
- return this;
340
- };
335
+ Spec.prototype.pend = function() {
336
+ this.markedPending = true;
337
+ };
341
338
 
342
- /**
343
- * For throwing an exception when a spy is called.
344
- *
345
- * @example
346
- * // defining a spy from scratch: foo() throws an exception w/ message 'ouch'
347
- * var foo = jasmine.createSpy('spy on foo').andThrow('baz');
348
- *
349
- * // defining a spy on an existing property: foo.bar() throws an exception w/ message 'ouch'
350
- * spyOn(foo, 'bar').andThrow('baz');
351
- *
352
- * @param {String} exceptionMsg
353
- */
354
- jasmine.Spy.prototype.andThrow = function(exceptionMsg) {
355
- this.plan = function() {
356
- throw exceptionMsg;
357
- };
358
- return this;
359
- };
339
+ Spec.prototype.status = function() {
340
+ if (this.disabled) {
341
+ return 'disabled';
342
+ }
360
343
 
361
- /**
362
- * Calls an alternate implementation when a spy is called.
363
- *
364
- * @example
365
- * var baz = function() {
366
- * // do some stuff, return something
367
- * }
368
- * // defining a spy from scratch: foo() calls the function baz
369
- * var foo = jasmine.createSpy('spy on foo').andCall(baz);
370
- *
371
- * // defining a spy on an existing property: foo.bar() calls an anonymnous function
372
- * spyOn(foo, 'bar').andCall(function() { return 'baz';} );
373
- *
374
- * @param {Function} fakeFunc
375
- */
376
- jasmine.Spy.prototype.andCallFake = function(fakeFunc) {
377
- this.plan = fakeFunc;
378
- return this;
379
- };
344
+ if (this.markedPending || !this.encounteredExpectations) {
345
+ return 'pending';
346
+ }
380
347
 
381
- /**
382
- * Resets all of a spy's the tracking variables so that it can be used again.
383
- *
384
- * @example
385
- * spyOn(foo, 'bar');
386
- *
387
- * foo.bar();
388
- *
389
- * expect(foo.bar.callCount).toEqual(1);
390
- *
391
- * foo.bar.reset();
392
- *
393
- * expect(foo.bar.callCount).toEqual(0);
394
- */
395
- jasmine.Spy.prototype.reset = function() {
396
- this.wasCalled = false;
397
- this.callCount = 0;
398
- this.argsForCall = [];
399
- this.calls = [];
400
- this.mostRecentCall = {};
401
- };
348
+ if (this.result.failedExpectations.length > 0) {
349
+ return 'failed';
350
+ } else {
351
+ return 'passed';
352
+ }
353
+ };
402
354
 
403
- jasmine.createSpy = function(name) {
355
+ Spec.prototype.getFullName = function() {
356
+ return this.getSpecName(this);
357
+ };
358
+
359
+ Spec.pendingSpecExceptionMessage = "=> marked Pending";
404
360
 
405
- var spyObj = function() {
406
- spyObj.wasCalled = true;
407
- spyObj.callCount++;
408
- var args = jasmine.util.argsToArray(arguments);
409
- spyObj.mostRecentCall.object = this;
410
- spyObj.mostRecentCall.args = args;
411
- spyObj.argsForCall.push(args);
412
- spyObj.calls.push({object: this, args: args});
413
- return spyObj.plan.apply(this, arguments);
361
+ Spec.isPendingSpecException = function(e) {
362
+ return e.toString().indexOf(Spec.pendingSpecExceptionMessage) !== -1;
414
363
  };
415
364
 
416
- var spy = new jasmine.Spy(name);
365
+ return Spec;
366
+ };
417
367
 
418
- for (var prop in spy) {
419
- spyObj[prop] = spy[prop];
420
- }
368
+ if (typeof window == void 0 && typeof exports == "object") {
369
+ exports.Spec = jasmineRequire.Spec;
370
+ }
421
371
 
422
- spyObj.reset();
372
+ getJasmineRequireObj().Env = function(j$) {
373
+ function Env(options) {
374
+ options = options || {};
423
375
 
424
- return spyObj;
425
- };
376
+ var self = this;
377
+ var global = options.global || j$.getGlobal();
426
378
 
427
- /**
428
- * Determines whether an object is a spy.
429
- *
430
- * @param {jasmine.Spy|Object} putativeSpy
431
- * @returns {Boolean}
432
- */
433
- jasmine.isSpy = function(putativeSpy) {
434
- return putativeSpy && putativeSpy.isSpy;
435
- };
379
+ var catchExceptions = true;
436
380
 
437
- /**
438
- * Creates a more complicated spy: an Object that has every property a function that is a spy. Used for stubbing something
439
- * large in one call.
440
- *
441
- * @param {String} baseName name of spy class
442
- * @param {Array} methodNames array of names of methods to make spies
443
- */
444
- jasmine.createSpyObj = function(baseName, methodNames) {
445
- if (!jasmine.isArray_(methodNames) || methodNames.length === 0) {
446
- throw new Error('createSpyObj requires a non-empty array of method names to create spies for');
447
- }
448
- var obj = {};
449
- for (var i = 0; i < methodNames.length; i++) {
450
- obj[methodNames[i]] = jasmine.createSpy(baseName + '.' + methodNames[i]);
451
- }
452
- return obj;
453
- };
381
+ var realSetTimeout = j$.getGlobal().setTimeout;
382
+ var realClearTimeout = j$.getGlobal().clearTimeout;
383
+ this.clock = new j$.Clock(global, new j$.DelayedFunctionScheduler());
454
384
 
455
- /**
456
- * All parameters are pretty-printed and concatenated together, then written to the current spec's output.
457
- *
458
- * Be careful not to leave calls to <code>jasmine.log</code> in production code.
459
- */
460
- jasmine.log = function() {
461
- var spec = jasmine.getEnv().currentSpec;
462
- spec.log.apply(spec, arguments);
463
- };
385
+ var spies = [];
464
386
 
465
- /**
466
- * Function that installs a spy on an existing object's method name. Used within a Spec to create a spy.
467
- *
468
- * @example
469
- * // spy example
470
- * var foo = {
471
- * not: function(bool) { return !bool; }
472
- * }
473
- * spyOn(foo, 'not'); // actual foo.not will not be called, execution stops
474
- *
475
- * @see jasmine.createSpy
476
- * @param obj
477
- * @param methodName
478
- * @return {jasmine.Spy} a Jasmine spy that can be chained with all spy methods
479
- */
480
- var spyOn = function(obj, methodName) {
481
- return jasmine.getEnv().currentSpec.spyOn(obj, methodName);
482
- };
483
- if (isCommonJS) exports.spyOn = spyOn;
484
-
485
- /**
486
- * Creates a Jasmine spec that will be added to the current suite.
487
- *
488
- * // TODO: pending tests
489
- *
490
- * @example
491
- * it('should be true', function() {
492
- * expect(true).toEqual(true);
493
- * });
494
- *
495
- * @param {String} desc description of this specification
496
- * @param {Function} func defines the preconditions and expectations of the spec
497
- */
498
- var it = function(desc, func) {
499
- return jasmine.getEnv().it(desc, func);
500
- };
501
- if (isCommonJS) exports.it = it;
502
-
503
- /**
504
- * Creates a <em>disabled</em> Jasmine spec.
505
- *
506
- * A convenience method that allows existing specs to be disabled temporarily during development.
507
- *
508
- * @param {String} desc description of this specification
509
- * @param {Function} func defines the preconditions and expectations of the spec
510
- */
511
- var xit = function(desc, func) {
512
- return jasmine.getEnv().xit(desc, func);
513
- };
514
- if (isCommonJS) exports.xit = xit;
515
-
516
- /**
517
- * Starts a chain for a Jasmine expectation.
518
- *
519
- * It is passed an Object that is the actual value and should chain to one of the many
520
- * jasmine.Matchers functions.
521
- *
522
- * @param {Object} actual Actual value to test against and expected value
523
- * @return {jasmine.Matchers}
524
- */
525
- var expect = function(actual) {
526
- return jasmine.getEnv().currentSpec.expect(actual);
527
- };
528
- if (isCommonJS) exports.expect = expect;
529
-
530
- /**
531
- * Defines part of a jasmine spec. Used in cominbination with waits or waitsFor in asynchrnous specs.
532
- *
533
- * @param {Function} func Function that defines part of a jasmine spec.
534
- */
535
- var runs = function(func) {
536
- jasmine.getEnv().currentSpec.runs(func);
537
- };
538
- if (isCommonJS) exports.runs = runs;
539
-
540
- /**
541
- * Waits a fixed time period before moving to the next block.
542
- *
543
- * @deprecated Use waitsFor() instead
544
- * @param {Number} timeout milliseconds to wait
545
- */
546
- var waits = function(timeout) {
547
- jasmine.getEnv().currentSpec.waits(timeout);
548
- };
549
- if (isCommonJS) exports.waits = waits;
550
-
551
- /**
552
- * Waits for the latchFunction to return true before proceeding to the next block.
553
- *
554
- * @param {Function} latchFunction
555
- * @param {String} optional_timeoutMessage
556
- * @param {Number} optional_timeout
557
- */
558
- var waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) {
559
- jasmine.getEnv().currentSpec.waitsFor.apply(jasmine.getEnv().currentSpec, arguments);
560
- };
561
- if (isCommonJS) exports.waitsFor = waitsFor;
562
-
563
- /**
564
- * A function that is called before each spec in a suite.
565
- *
566
- * Used for spec setup, including validating assumptions.
567
- *
568
- * @param {Function} beforeEachFunction
569
- */
570
- var beforeEach = function(beforeEachFunction) {
571
- jasmine.getEnv().beforeEach(beforeEachFunction);
572
- };
573
- if (isCommonJS) exports.beforeEach = beforeEach;
574
-
575
- /**
576
- * A function that is called after each spec in a suite.
577
- *
578
- * Used for restoring any state that is hijacked during spec execution.
579
- *
580
- * @param {Function} afterEachFunction
581
- */
582
- var afterEach = function(afterEachFunction) {
583
- jasmine.getEnv().afterEach(afterEachFunction);
584
- };
585
- if (isCommonJS) exports.afterEach = afterEach;
586
-
587
- /**
588
- * Defines a suite of specifications.
589
- *
590
- * Stores the description and all defined specs in the Jasmine environment as one suite of specs. Variables declared
591
- * are accessible by calls to beforeEach, it, and afterEach. Describe blocks can be nested, allowing for specialization
592
- * of setup in some tests.
593
- *
594
- * @example
595
- * // TODO: a simple suite
596
- *
597
- * // TODO: a simple suite with a nested describe block
598
- *
599
- * @param {String} description A string, usually the class under test.
600
- * @param {Function} specDefinitions function that defines several specs.
601
- */
602
- var describe = function(description, specDefinitions) {
603
- return jasmine.getEnv().describe(description, specDefinitions);
604
- };
605
- if (isCommonJS) exports.describe = describe;
606
-
607
- /**
608
- * Disables a suite of specifications. Used to disable some suites in a file, or files, temporarily during development.
609
- *
610
- * @param {String} description A string, usually the class under test.
611
- * @param {Function} specDefinitions function that defines several specs.
612
- */
613
- var xdescribe = function(description, specDefinitions) {
614
- return jasmine.getEnv().xdescribe(description, specDefinitions);
615
- };
616
- if (isCommonJS) exports.xdescribe = xdescribe;
387
+ this.currentSpec = null;
617
388
 
389
+ this.reporter = new j$.ReportDispatcher([
390
+ "jasmineStarted",
391
+ "jasmineDone",
392
+ "suiteStarted",
393
+ "suiteDone",
394
+ "specStarted",
395
+ "specDone"
396
+ ]);
618
397
 
619
- // Provide the XMLHttpRequest class for IE 5.x-6.x:
620
- jasmine.XmlHttpRequest = (typeof XMLHttpRequest == "undefined") ? function() {
621
- function tryIt(f) {
622
- try {
623
- return f();
624
- } catch(e) {
398
+ this.lastUpdate = 0;
399
+ this.specFilter = function() {
400
+ return true;
401
+ };
402
+
403
+ this.nextSpecId_ = 0;
404
+ this.nextSuiteId_ = 0;
405
+ this.equalityTesters_ = [];
406
+
407
+ var customEqualityTesters = [];
408
+ this.addCustomEqualityTester = function(tester) {
409
+ customEqualityTesters.push(tester);
410
+ };
411
+
412
+ j$.Expectation.addCoreMatchers(j$.matchers);
413
+
414
+ var expectationFactory = function(actual, spec) {
415
+ return j$.Expectation.Factory({
416
+ util: j$.matchersUtil,
417
+ customEqualityTesters: customEqualityTesters,
418
+ actual: actual,
419
+ addExpectationResult: addExpectationResult
420
+ });
421
+
422
+ function addExpectationResult(passed, result) {
423
+ return spec.addExpectationResult(passed, result);
424
+ }
425
+ };
426
+
427
+ var specStarted = function(spec) {
428
+ self.currentSpec = spec;
429
+ self.reporter.specStarted(spec.result);
430
+ };
431
+
432
+ var beforeFns = function(currentSuite) {
433
+ return function() {
434
+ var befores = [];
435
+ for (var suite = currentSuite; suite; suite = suite.parentSuite) {
436
+ befores = befores.concat(suite.beforeFns);
437
+ }
438
+ return befores.reverse();
439
+ };
440
+ };
441
+
442
+ var afterFns = function(currentSuite) {
443
+ return function() {
444
+ var afters = [];
445
+ for (var suite = currentSuite; suite; suite = suite.parentSuite) {
446
+ afters = afters.concat(suite.afterFns);
447
+ }
448
+ return afters;
449
+ };
450
+ };
451
+
452
+ var getSpecName = function(spec, currentSuite) {
453
+ return currentSuite.getFullName() + ' ' + spec.description + '.';
454
+ };
455
+
456
+ // TODO: we may just be able to pass in the fn instead of wrapping here
457
+ var buildExpectationResult = j$.buildExpectationResult,
458
+ exceptionFormatter = new j$.ExceptionFormatter(),
459
+ expectationResultFactory = function(attrs) {
460
+ attrs.messageFormatter = exceptionFormatter.message;
461
+ attrs.stackFormatter = exceptionFormatter.stack;
462
+
463
+ return buildExpectationResult(attrs);
464
+ };
465
+
466
+ // TODO: fix this naming, and here's where the value comes in
467
+ this.catchExceptions = function(value) {
468
+ catchExceptions = !!value;
469
+ return catchExceptions;
470
+ };
471
+
472
+ this.catchingExceptions = function() {
473
+ return catchExceptions;
474
+ };
475
+
476
+ this.catchException = function(e) {
477
+ return j$.Spec.isPendingSpecException(e) || catchExceptions;
478
+ };
479
+
480
+ var maximumSpecCallbackDepth = 20;
481
+ var currentSpecCallbackDepth = 0;
482
+
483
+ function clearStack(fn) {
484
+ currentSpecCallbackDepth++;
485
+ if (currentSpecCallbackDepth >= maximumSpecCallbackDepth) {
486
+ currentSpecCallbackDepth = 0;
487
+ realSetTimeout(fn, 0);
488
+ } else {
489
+ fn();
490
+ }
625
491
  }
626
- return null;
627
- }
628
492
 
629
- var xhr = tryIt(function() {
630
- return new ActiveXObject("Msxml2.XMLHTTP.6.0");
631
- }) ||
632
- tryIt(function() {
633
- return new ActiveXObject("Msxml2.XMLHTTP.3.0");
634
- }) ||
635
- tryIt(function() {
636
- return new ActiveXObject("Msxml2.XMLHTTP");
637
- }) ||
638
- tryIt(function() {
639
- return new ActiveXObject("Microsoft.XMLHTTP");
493
+ var queueRunnerFactory = function(options) {
494
+ options.catchException = self.catchException;
495
+ options.clearStack = options.clearStack || clearStack;
496
+
497
+ new j$.QueueRunner(options).run(options.fns, 0);
498
+ };
499
+
500
+ var totalSpecsDefined = 0;
501
+ this.specFactory = function(description, fn, suite) {
502
+ totalSpecsDefined++;
503
+
504
+ var spec = new j$.Spec({
505
+ id: self.nextSpecId(),
506
+ beforeFns: beforeFns(suite),
507
+ afterFns: afterFns(suite),
508
+ expectationFactory: expectationFactory,
509
+ exceptionFormatter: exceptionFormatter,
510
+ resultCallback: specResultCallback,
511
+ getSpecName: function(spec) {
512
+ return getSpecName(spec, suite);
513
+ },
514
+ onStart: specStarted,
515
+ description: description,
516
+ expectationResultFactory: expectationResultFactory,
517
+ queueRunner: queueRunnerFactory,
518
+ fn: fn,
519
+ timer: {setTimeout: realSetTimeout, clearTimeout: realClearTimeout}
520
+ });
521
+
522
+ if (!self.specFilter(spec)) {
523
+ spec.disable();
524
+ }
525
+
526
+ return spec;
527
+
528
+ function removeAllSpies() {
529
+ for (var i = 0; i < spies.length; i++) {
530
+ var spyEntry = spies[i];
531
+ spyEntry.baseObj[spyEntry.methodName] = spyEntry.originalValue;
532
+ }
533
+ spies = [];
534
+ }
535
+
536
+ function specResultCallback(result) {
537
+ removeAllSpies();
538
+ j$.Expectation.resetMatchers();
539
+ customEqualityTesters.length = 0;
540
+ self.clock.uninstall();
541
+ self.currentSpec = null;
542
+ self.reporter.specDone(result);
543
+ }
544
+ };
545
+
546
+ var suiteStarted = function(suite) {
547
+ self.reporter.suiteStarted(suite.result);
548
+ };
549
+
550
+ var suiteConstructor = j$.Suite;
551
+
552
+ this.topSuite = new j$.Suite({
553
+ env: this,
554
+ id: this.nextSuiteId(),
555
+ description: 'Jasmine__TopLevel__Suite',
556
+ queueRunner: queueRunnerFactory,
557
+ completeCallback: function() {}, // TODO - hook this up
558
+ resultCallback: function() {} // TODO - hook this up
640
559
  });
560
+ this.currentSuite = this.topSuite;
561
+
562
+ this.suiteFactory = function(description) {
563
+ return new suiteConstructor({
564
+ env: self,
565
+ id: self.nextSuiteId(),
566
+ description: description,
567
+ parentSuite: self.currentSuite,
568
+ queueRunner: queueRunnerFactory,
569
+ onStart: suiteStarted,
570
+ resultCallback: function(attrs) {
571
+ self.reporter.suiteDone(attrs);
572
+ }
573
+ });
574
+ };
641
575
 
642
- if (!xhr) throw new Error("This browser does not support XMLHttpRequest.");
643
-
644
- return xhr;
645
- } : XMLHttpRequest;
646
- /**
647
- * @namespace
648
- */
649
- jasmine.util = {};
650
-
651
- /**
652
- * Declare that a child class inherit it's prototype from the parent class.
653
- *
654
- * @private
655
- * @param {Function} childClass
656
- * @param {Function} parentClass
657
- */
658
- jasmine.util.inherit = function(childClass, parentClass) {
659
- /**
660
- * @private
661
- */
662
- var subclass = function() {
663
- };
664
- subclass.prototype = parentClass.prototype;
665
- childClass.prototype = new subclass();
666
- };
576
+ this.execute = function() {
577
+ this.reporter.jasmineStarted({
578
+ totalSpecsDefined: totalSpecsDefined
579
+ });
580
+ this.topSuite.execute(self.reporter.jasmineDone);
581
+ };
667
582
 
668
- jasmine.util.formatException = function(e) {
669
- var lineNumber;
670
- if (e.line) {
671
- lineNumber = e.line;
672
- }
673
- else if (e.lineNumber) {
674
- lineNumber = e.lineNumber;
675
- }
583
+ this.spyOn = function(obj, methodName) {
584
+ if (j$.util.isUndefined(obj)) {
585
+ throw new Error("spyOn could not find an object to spy upon for " + methodName + "()");
586
+ }
676
587
 
677
- var file;
588
+ if (j$.util.isUndefined(obj[methodName])) {
589
+ throw new Error(methodName + '() method does not exist');
590
+ }
678
591
 
679
- if (e.sourceURL) {
680
- file = e.sourceURL;
681
- }
682
- else if (e.fileName) {
683
- file = e.fileName;
684
- }
592
+ if (obj[methodName] && j$.isSpy(obj[methodName])) {
593
+ //TODO?: should this return the current spy? Downside: may cause user confusion about spy state
594
+ throw new Error(methodName + ' has already been spied upon');
595
+ }
596
+
597
+ var spy = j$.createSpy(methodName, obj[methodName]);
598
+
599
+ spies.push({
600
+ spy: spy,
601
+ baseObj: obj,
602
+ methodName: methodName,
603
+ originalValue: obj[methodName]
604
+ });
685
605
 
686
- var message = (e.name && e.message) ? (e.name + ': ' + e.message) : e.toString();
606
+ obj[methodName] = spy;
687
607
 
688
- if (file && lineNumber) {
689
- message += ' in ' + file + ' (line ' + lineNumber + ')';
608
+ return spy;
609
+ };
690
610
  }
691
611
 
692
- return message;
693
- };
612
+ Env.prototype.addMatchers = function(matchersToAdd) {
613
+ j$.Expectation.addMatchers(matchersToAdd);
614
+ };
694
615
 
695
- jasmine.util.htmlEscape = function(str) {
696
- if (!str) return str;
697
- return str.replace(/&/g, '&amp;')
698
- .replace(/</g, '&lt;')
699
- .replace(/>/g, '&gt;');
700
- };
616
+ Env.prototype.version = function() {
617
+ return j$.version;
618
+ };
701
619
 
702
- jasmine.util.argsToArray = function(args) {
703
- var arrayOfArgs = [];
704
- for (var i = 0; i < args.length; i++) arrayOfArgs.push(args[i]);
705
- return arrayOfArgs;
706
- };
620
+ Env.prototype.expect = function(actual) {
621
+ return this.currentSpec.expect(actual);
622
+ };
707
623
 
708
- jasmine.util.extend = function(destination, source) {
709
- for (var property in source) destination[property] = source[property];
710
- return destination;
711
- };
712
624
 
713
- /**
714
- * Environment for Jasmine
715
- *
716
- * @constructor
717
- */
718
- jasmine.Env = function() {
719
- this.currentSpec = null;
720
- this.currentSuite = null;
721
- this.currentRunner_ = new jasmine.Runner(this);
625
+ // TODO: move this to closure
626
+ Env.prototype.versionString = function() {
627
+ console.log("DEPRECATED == use j$.version");
628
+ return j$.version;
629
+ };
630
+
631
+ // TODO: move this to closure
632
+ Env.prototype.nextSpecId = function() {
633
+ return this.nextSpecId_++;
634
+ };
635
+
636
+ // TODO: move this to closure
637
+ Env.prototype.nextSuiteId = function() {
638
+ return this.nextSuiteId_++;
639
+ };
640
+
641
+ // TODO: move this to closure
642
+ Env.prototype.addReporter = function(reporter) {
643
+ this.reporter.addReporter(reporter);
644
+ };
645
+
646
+ // TODO: move this to closure
647
+ Env.prototype.describe = function(description, specDefinitions) {
648
+ var suite = this.suiteFactory(description);
649
+
650
+ var parentSuite = this.currentSuite;
651
+ parentSuite.addSuite(suite);
652
+ this.currentSuite = suite;
653
+
654
+ var declarationError = null;
655
+ try {
656
+ specDefinitions.call(suite);
657
+ } catch (e) {
658
+ declarationError = e;
659
+ }
660
+
661
+ if (declarationError) {
662
+ this.it("encountered a declaration exception", function() {
663
+ throw declarationError;
664
+ });
665
+ }
666
+
667
+ this.currentSuite = parentSuite;
668
+
669
+ return suite;
670
+ };
671
+
672
+ // TODO: move this to closure
673
+ Env.prototype.xdescribe = function(description, specDefinitions) {
674
+ var suite = this.describe(description, specDefinitions);
675
+ suite.disable();
676
+ return suite;
677
+ };
722
678
 
723
- this.reporter = new jasmine.MultiReporter();
679
+ // TODO: move this to closure
680
+ Env.prototype.it = function(description, fn) {
681
+ var spec = this.specFactory(description, fn, this.currentSuite);
682
+ this.currentSuite.addSpec(spec);
683
+ return spec;
684
+ };
724
685
 
725
- this.updateInterval = jasmine.DEFAULT_UPDATE_INTERVAL;
726
- this.defaultTimeoutInterval = jasmine.DEFAULT_TIMEOUT_INTERVAL;
727
- this.lastUpdate = 0;
728
- this.specFilter = function() {
729
- return true;
686
+ // TODO: move this to closure
687
+ Env.prototype.xit = function(description, fn) {
688
+ var spec = this.it(description, fn);
689
+ spec.pend();
690
+ return spec;
730
691
  };
731
692
 
732
- this.nextSpecId_ = 0;
733
- this.nextSuiteId_ = 0;
734
- this.equalityTesters_ = [];
693
+ // TODO: move this to closure
694
+ Env.prototype.beforeEach = function(beforeEachFunction) {
695
+ this.currentSuite.beforeEach(beforeEachFunction);
696
+ };
697
+
698
+ // TODO: move this to closure
699
+ Env.prototype.afterEach = function(afterEachFunction) {
700
+ this.currentSuite.afterEach(afterEachFunction);
701
+ };
702
+
703
+ // TODO: move this to closure
704
+ Env.prototype.pending = function() {
705
+ throw j$.Spec.pendingSpecExceptionMessage;
706
+ };
735
707
 
736
- // wrap matchers
737
- this.matchersClass = function() {
738
- jasmine.Matchers.apply(this, arguments);
708
+ // TODO: Still needed?
709
+ Env.prototype.currentRunner = function() {
710
+ return this.topSuite;
739
711
  };
740
- jasmine.util.inherit(this.matchersClass, jasmine.Matchers);
741
712
 
742
- jasmine.Matchers.wrapInto_(jasmine.Matchers.prototype, this.matchersClass);
713
+ return Env;
743
714
  };
744
715
 
716
+ getJasmineRequireObj().JsApiReporter = function() {
745
717
 
746
- jasmine.Env.prototype.setTimeout = jasmine.setTimeout;
747
- jasmine.Env.prototype.clearTimeout = jasmine.clearTimeout;
748
- jasmine.Env.prototype.setInterval = jasmine.setInterval;
749
- jasmine.Env.prototype.clearInterval = jasmine.clearInterval;
718
+ var noopTimer = {
719
+ start: function(){},
720
+ elapsed: function(){ return 0; }
721
+ };
722
+
723
+ function JsApiReporter(options) {
724
+ var timer = options.timer || noopTimer,
725
+ status = "loaded";
726
+
727
+ this.started = false;
728
+ this.finished = false;
729
+
730
+ this.jasmineStarted = function() {
731
+ this.started = true;
732
+ status = 'started';
733
+ timer.start();
734
+ };
735
+
736
+ var executionTime;
737
+
738
+ this.jasmineDone = function() {
739
+ this.finished = true;
740
+ executionTime = timer.elapsed();
741
+ status = 'done';
742
+ };
743
+
744
+ this.status = function() {
745
+ return status;
746
+ };
747
+
748
+ var suites = {};
749
+
750
+ this.suiteStarted = function(result) {
751
+ storeSuite(result);
752
+ };
753
+
754
+ this.suiteDone = function(result) {
755
+ storeSuite(result);
756
+ };
757
+
758
+ function storeSuite(result) {
759
+ suites[result.id] = result;
760
+ }
761
+
762
+ this.suites = function() {
763
+ return suites;
764
+ };
765
+
766
+ var specs = [];
767
+ this.specStarted = function(result) { };
768
+
769
+ this.specDone = function(result) {
770
+ specs.push(result);
771
+ };
772
+
773
+ this.specResults = function(index, length) {
774
+ return specs.slice(index, index + length);
775
+ };
776
+
777
+ this.specs = function() {
778
+ return specs;
779
+ };
780
+
781
+ this.executionTime = function() {
782
+ return executionTime;
783
+ };
750
784
 
751
- /**
752
- * @returns an object containing jasmine version build info, if set.
753
- */
754
- jasmine.Env.prototype.version = function () {
755
- if (jasmine.version_) {
756
- return jasmine.version_;
757
- } else {
758
- throw new Error('Version not set');
759
785
  }
786
+
787
+ return JsApiReporter;
760
788
  };
761
789
 
762
- /**
763
- * @returns string containing jasmine version build info, if set.
764
- */
765
- jasmine.Env.prototype.versionString = function() {
766
- if (!jasmine.version_) {
767
- return "version unknown";
768
- }
790
+ getJasmineRequireObj().Any = function() {
769
791
 
770
- var version = this.version();
771
- var versionString = version.major + "." + version.minor + "." + version.build;
772
- if (version.release_candidate) {
773
- versionString += ".rc" + version.release_candidate;
792
+ function Any(expectedObject) {
793
+ this.expectedObject = expectedObject;
774
794
  }
775
- versionString += " revision " + version.revision;
776
- return versionString;
777
- };
778
795
 
779
- /**
780
- * @returns a sequential integer starting at 0
781
- */
782
- jasmine.Env.prototype.nextSpecId = function () {
783
- return this.nextSpecId_++;
784
- };
796
+ Any.prototype.jasmineMatches = function(other) {
797
+ if (this.expectedObject == String) {
798
+ return typeof other == 'string' || other instanceof String;
799
+ }
785
800
 
786
- /**
787
- * @returns a sequential integer starting at 0
788
- */
789
- jasmine.Env.prototype.nextSuiteId = function () {
790
- return this.nextSuiteId_++;
791
- };
801
+ if (this.expectedObject == Number) {
802
+ return typeof other == 'number' || other instanceof Number;
803
+ }
792
804
 
793
- /**
794
- * Register a reporter to receive status updates from Jasmine.
795
- * @param {jasmine.Reporter} reporter An object which will receive status updates.
796
- */
797
- jasmine.Env.prototype.addReporter = function(reporter) {
798
- this.reporter.addReporter(reporter);
799
- };
805
+ if (this.expectedObject == Function) {
806
+ return typeof other == 'function' || other instanceof Function;
807
+ }
800
808
 
801
- jasmine.Env.prototype.execute = function() {
802
- this.currentRunner_.execute();
809
+ if (this.expectedObject == Object) {
810
+ return typeof other == 'object';
811
+ }
812
+
813
+ if (this.expectedObject == Boolean) {
814
+ return typeof other == 'boolean';
815
+ }
816
+
817
+ return other instanceof this.expectedObject;
818
+ };
819
+
820
+ Any.prototype.jasmineToString = function() {
821
+ return '<jasmine.any(' + this.expectedClass + ')>';
822
+ };
823
+
824
+ return Any;
803
825
  };
826
+ getJasmineRequireObj().CallTracker = function() {
804
827
 
805
- jasmine.Env.prototype.describe = function(description, specDefinitions) {
806
- var suite = new jasmine.Suite(this, description, specDefinitions, this.currentSuite);
828
+ function CallTracker() {
829
+ var calls = [];
807
830
 
808
- var parentSuite = this.currentSuite;
809
- if (parentSuite) {
810
- parentSuite.add(suite);
811
- } else {
812
- this.currentRunner_.add(suite);
813
- }
831
+ this.track = function(context) {
832
+ calls.push(context);
833
+ };
814
834
 
815
- this.currentSuite = suite;
835
+ this.any = function() {
836
+ return !!calls.length;
837
+ };
816
838
 
817
- var declarationError = null;
818
- try {
819
- specDefinitions.call(suite);
820
- } catch(e) {
821
- declarationError = e;
822
- }
839
+ this.count = function() {
840
+ return calls.length;
841
+ };
823
842
 
824
- if (declarationError) {
825
- this.it("encountered a declaration exception", function() {
826
- throw declarationError;
827
- });
828
- }
843
+ this.argsFor = function(index) {
844
+ var call = calls[index];
845
+ return call ? call.args : [];
846
+ };
829
847
 
830
- this.currentSuite = parentSuite;
848
+ this.all = function() {
849
+ return calls;
850
+ };
831
851
 
832
- return suite;
833
- };
852
+ this.allArgs = function() {
853
+ var callArgs = [];
854
+ for(var i = 0; i < calls.length; i++){
855
+ callArgs.push(calls[i].args);
856
+ }
834
857
 
835
- jasmine.Env.prototype.beforeEach = function(beforeEachFunction) {
836
- if (this.currentSuite) {
837
- this.currentSuite.beforeEach(beforeEachFunction);
838
- } else {
839
- this.currentRunner_.beforeEach(beforeEachFunction);
840
- }
841
- };
858
+ return callArgs;
859
+ };
842
860
 
843
- jasmine.Env.prototype.currentRunner = function () {
844
- return this.currentRunner_;
845
- };
861
+ this.first = function() {
862
+ return calls[0];
863
+ };
846
864
 
847
- jasmine.Env.prototype.afterEach = function(afterEachFunction) {
848
- if (this.currentSuite) {
849
- this.currentSuite.afterEach(afterEachFunction);
850
- } else {
851
- this.currentRunner_.afterEach(afterEachFunction);
865
+ this.mostRecent = function() {
866
+ return calls[calls.length - 1];
867
+ };
868
+
869
+ this.reset = function() {
870
+ calls = [];
871
+ };
852
872
  }
853
873
 
854
- };
874
+ return CallTracker;
875
+ };
876
+
877
+ getJasmineRequireObj().Clock = function() {
878
+ function Clock(global, delayedFunctionScheduler) {
879
+ var self = this,
880
+ realTimingFunctions = {
881
+ setTimeout: global.setTimeout,
882
+ clearTimeout: global.clearTimeout,
883
+ setInterval: global.setInterval,
884
+ clearInterval: global.clearInterval
885
+ },
886
+ fakeTimingFunctions = {
887
+ setTimeout: setTimeout,
888
+ clearTimeout: clearTimeout,
889
+ setInterval: setInterval,
890
+ clearInterval: clearInterval
891
+ },
892
+ timer = realTimingFunctions,
893
+ installed = false;
894
+
895
+ self.install = function() {
896
+ installed = true;
897
+ timer = fakeTimingFunctions;
898
+ };
855
899
 
856
- jasmine.Env.prototype.xdescribe = function(desc, specDefinitions) {
857
- return {
858
- execute: function() {
900
+ self.uninstall = function() {
901
+ delayedFunctionScheduler.reset();
902
+ installed = false;
903
+ timer = realTimingFunctions;
904
+ };
905
+
906
+ self.setTimeout = function(fn, delay, params) {
907
+ if (legacyIE()) {
908
+ if (arguments.length > 2) {
909
+ throw new Error("IE < 9 cannot support extra params to setTimeout without a polyfill");
910
+ }
911
+ return timer.setTimeout(fn, delay);
912
+ }
913
+ return Function.prototype.apply.apply(timer.setTimeout, [global, arguments]);
914
+ };
915
+
916
+ self.setInterval = function(fn, delay, params) {
917
+ if (legacyIE()) {
918
+ if (arguments.length > 2) {
919
+ throw new Error("IE < 9 cannot support extra params to setInterval without a polyfill");
920
+ }
921
+ return timer.setInterval(fn, delay);
922
+ }
923
+ return Function.prototype.apply.apply(timer.setInterval, [global, arguments]);
924
+ };
925
+
926
+ self.clearTimeout = function(id) {
927
+ return Function.prototype.call.apply(timer.clearTimeout, [global, id]);
928
+ };
929
+
930
+ self.clearInterval = function(id) {
931
+ return Function.prototype.call.apply(timer.clearInterval, [global, id]);
932
+ };
933
+
934
+ self.tick = function(millis) {
935
+ if (installed) {
936
+ delayedFunctionScheduler.tick(millis);
937
+ } else {
938
+ throw new Error("Mock clock is not installed, use jasmine.Clock.useMock()");
939
+ }
940
+ };
941
+
942
+ return self;
943
+
944
+ function legacyIE() {
945
+ //if these methods are polyfilled, apply will be present
946
+ //TODO: it may be difficult to load the polyfill before jasmine loads
947
+ //(env should be new-ed inside of onload)
948
+ return !(global.setTimeout || global.setInterval).apply;
859
949
  }
860
- };
950
+
951
+ function setTimeout(fn, delay) {
952
+ return delayedFunctionScheduler.scheduleFunction(fn, delay, argSlice(arguments, 2));
953
+ }
954
+
955
+ function clearTimeout(id) {
956
+ return delayedFunctionScheduler.removeFunctionWithId(id);
957
+ }
958
+
959
+ function setInterval(fn, interval) {
960
+ return delayedFunctionScheduler.scheduleFunction(fn, interval, argSlice(arguments, 2), true);
961
+ }
962
+
963
+ function clearInterval(id) {
964
+ return delayedFunctionScheduler.removeFunctionWithId(id);
965
+ }
966
+
967
+ function argSlice(argsObj, n) {
968
+ return Array.prototype.slice.call(argsObj, 2);
969
+ }
970
+ }
971
+
972
+ return Clock;
861
973
  };
862
974
 
863
- jasmine.Env.prototype.it = function(description, func) {
864
- var spec = new jasmine.Spec(this, this.currentSuite, description);
865
- this.currentSuite.add(spec);
866
- this.currentSpec = spec;
975
+ getJasmineRequireObj().DelayedFunctionScheduler = function() {
976
+ function DelayedFunctionScheduler() {
977
+ var self = this;
978
+ var scheduledFunctions = {};
979
+ var currentTime = 0;
980
+ var delayedFnCount = 0;
981
+
982
+ self.tick = function(millis) {
983
+ millis = millis || 0;
984
+ runFunctionsWithinRange(currentTime, currentTime + millis);
985
+ currentTime = currentTime + millis;
986
+ };
987
+
988
+ self.scheduleFunction = function(funcToCall, millis, params, recurring, timeoutKey, runAtMillis) {
989
+ var f;
990
+ if (typeof(funcToCall) === 'string') {
991
+ /* jshint evil: true */
992
+ f = function() { return eval(funcToCall); };
993
+ /* jshint evil: false */
994
+ } else {
995
+ f = funcToCall;
996
+ }
997
+
998
+ millis = millis || 0;
999
+ timeoutKey = timeoutKey || ++delayedFnCount;
1000
+ runAtMillis = runAtMillis || (currentTime + millis);
1001
+ scheduledFunctions[timeoutKey] = {
1002
+ runAtMillis: runAtMillis,
1003
+ funcToCall: f,
1004
+ recurring: recurring,
1005
+ params: params,
1006
+ timeoutKey: timeoutKey,
1007
+ millis: millis
1008
+ };
1009
+ return timeoutKey;
1010
+ };
1011
+
1012
+ self.removeFunctionWithId = function(timeoutKey) {
1013
+ delete scheduledFunctions[timeoutKey];
1014
+ };
867
1015
 
868
- if (func) {
869
- spec.runs(func);
870
- }
1016
+ self.reset = function() {
1017
+ currentTime = 0;
1018
+ scheduledFunctions = {};
1019
+ delayedFnCount = 0;
1020
+ };
871
1021
 
872
- return spec;
873
- };
1022
+ return self;
1023
+
1024
+ // finds/dupes functions within range and removes them.
1025
+ function functionsWithinRange(startMillis, endMillis) {
1026
+ var fnsToRun = [];
1027
+ for (var timeoutKey in scheduledFunctions) {
1028
+ var scheduledFunc = scheduledFunctions[timeoutKey];
1029
+ if (scheduledFunc &&
1030
+ scheduledFunc.runAtMillis >= startMillis &&
1031
+ scheduledFunc.runAtMillis <= endMillis) {
1032
+
1033
+ // remove fn -- we'll reschedule later if it is recurring.
1034
+ self.removeFunctionWithId(timeoutKey);
1035
+ if (!scheduledFunc.recurring) {
1036
+ fnsToRun.push(scheduledFunc); // schedules each function only once
1037
+ } else {
1038
+ fnsToRun.push(buildNthInstanceOf(scheduledFunc, 0));
1039
+ var additionalTimesFnRunsInRange =
1040
+ Math.floor((endMillis - scheduledFunc.runAtMillis) / scheduledFunc.millis);
1041
+ for (var i = 0; i < additionalTimesFnRunsInRange; i++) {
1042
+ fnsToRun.push(buildNthInstanceOf(scheduledFunc, i + 1));
1043
+ }
1044
+ reschedule(buildNthInstanceOf(scheduledFunc, additionalTimesFnRunsInRange));
1045
+ }
1046
+ }
1047
+ }
874
1048
 
875
- jasmine.Env.prototype.xit = function(desc, func) {
876
- return {
877
- id: this.nextSpecId(),
878
- runs: function() {
1049
+ return fnsToRun;
879
1050
  }
880
- };
881
- };
882
-
883
- jasmine.Env.prototype.compareRegExps_ = function(a, b, mismatchKeys, mismatchValues) {
884
- if (a.source != b.source)
885
- mismatchValues.push("expected pattern /" + b.source + "/ is not equal to the pattern /" + a.source + "/");
886
1051
 
887
- if (a.ignoreCase != b.ignoreCase)
888
- mismatchValues.push("expected modifier i was" + (b.ignoreCase ? " " : " not ") + "set and does not equal the origin modifier");
1052
+ function buildNthInstanceOf(scheduledFunc, n) {
1053
+ return {
1054
+ runAtMillis: scheduledFunc.runAtMillis + (scheduledFunc.millis * n),
1055
+ funcToCall: scheduledFunc.funcToCall,
1056
+ params: scheduledFunc.params,
1057
+ millis: scheduledFunc.millis,
1058
+ recurring: scheduledFunc.recurring,
1059
+ timeoutKey: scheduledFunc.timeoutKey
1060
+ };
1061
+ }
889
1062
 
890
- if (a.global != b.global)
891
- mismatchValues.push("expected modifier g was" + (b.global ? " " : " not ") + "set and does not equal the origin modifier");
1063
+ function reschedule(scheduledFn) {
1064
+ self.scheduleFunction(scheduledFn.funcToCall,
1065
+ scheduledFn.millis,
1066
+ scheduledFn.params,
1067
+ true,
1068
+ scheduledFn.timeoutKey,
1069
+ scheduledFn.runAtMillis + scheduledFn.millis);
1070
+ }
892
1071
 
893
- if (a.multiline != b.multiline)
894
- mismatchValues.push("expected modifier m was" + (b.multiline ? " " : " not ") + "set and does not equal the origin modifier");
895
1072
 
896
- if (a.sticky != b.sticky)
897
- mismatchValues.push("expected modifier y was" + (b.sticky ? " " : " not ") + "set and does not equal the origin modifier");
1073
+ function runFunctionsWithinRange(startMillis, endMillis) {
1074
+ var funcsToRun = functionsWithinRange(startMillis, endMillis);
1075
+ if (funcsToRun.length === 0) {
1076
+ return;
1077
+ }
898
1078
 
899
- return (mismatchValues.length === 0);
900
- };
1079
+ funcsToRun.sort(function(a, b) {
1080
+ return a.runAtMillis - b.runAtMillis;
1081
+ });
901
1082
 
902
- jasmine.Env.prototype.compareObjects_ = function(a, b, mismatchKeys, mismatchValues) {
903
- if (a.__Jasmine_been_here_before__ === b && b.__Jasmine_been_here_before__ === a) {
904
- return true;
1083
+ for (var i = 0; i < funcsToRun.length; ++i) {
1084
+ var funcToRun = funcsToRun[i];
1085
+ funcToRun.funcToCall.apply(null, funcToRun.params || []);
1086
+ }
1087
+ }
905
1088
  }
906
1089
 
907
- a.__Jasmine_been_here_before__ = b;
908
- b.__Jasmine_been_here_before__ = a;
909
-
910
- var hasKey = function(obj, keyName) {
911
- return obj !== null && obj[keyName] !== jasmine.undefined;
912
- };
1090
+ return DelayedFunctionScheduler;
1091
+ };
913
1092
 
914
- for (var property in b) {
915
- if (!hasKey(a, property) && hasKey(b, property)) {
916
- mismatchKeys.push("expected has key '" + property + "', but missing from actual.");
917
- }
918
- }
919
- for (property in a) {
920
- if (!hasKey(b, property) && hasKey(a, property)) {
921
- mismatchKeys.push("expected missing key '" + property + "', but present in actual.");
922
- }
923
- }
924
- for (property in b) {
925
- if (property == '__Jasmine_been_here_before__') continue;
926
- if (!this.equals_(a[property], b[property], mismatchKeys, mismatchValues)) {
927
- mismatchValues.push("'" + property + "' was '" + (b[property] ? jasmine.util.htmlEscape(b[property].toString()) : b[property]) + "' in expected, but was '" + (a[property] ? jasmine.util.htmlEscape(a[property].toString()) : a[property]) + "' in actual.");
928
- }
929
- }
1093
+ getJasmineRequireObj().ExceptionFormatter = function() {
1094
+ function ExceptionFormatter() {
1095
+ this.message = function(error) {
1096
+ var message = error.name +
1097
+ ': ' +
1098
+ error.message;
930
1099
 
931
- if (jasmine.isArray_(a) && jasmine.isArray_(b) && a.length != b.length) {
932
- mismatchValues.push("arrays were not the same length");
933
- }
1100
+ if (error.fileName || error.sourceURL) {
1101
+ message += " in " + (error.fileName || error.sourceURL);
1102
+ }
934
1103
 
935
- delete a.__Jasmine_been_here_before__;
936
- delete b.__Jasmine_been_here_before__;
937
- return (mismatchKeys.length === 0 && mismatchValues.length === 0);
938
- };
1104
+ if (error.line || error.lineNumber) {
1105
+ message += " (line " + (error.line || error.lineNumber) + ")";
1106
+ }
939
1107
 
940
- jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) {
941
- mismatchKeys = mismatchKeys || [];
942
- mismatchValues = mismatchValues || [];
1108
+ return message;
1109
+ };
943
1110
 
944
- for (var i = 0; i < this.equalityTesters_.length; i++) {
945
- var equalityTester = this.equalityTesters_[i];
946
- var result = equalityTester(a, b, this, mismatchKeys, mismatchValues);
947
- if (result !== jasmine.undefined) return result;
1111
+ this.stack = function(error) {
1112
+ return error ? error.stack : null;
1113
+ };
948
1114
  }
949
1115
 
950
- if (a === b) return true;
1116
+ return ExceptionFormatter;
1117
+ };
951
1118
 
952
- if (a === jasmine.undefined || a === null || b === jasmine.undefined || b === null) {
953
- return (a == jasmine.undefined && b == jasmine.undefined);
954
- }
1119
+ getJasmineRequireObj().Expectation = function() {
955
1120
 
956
- if (jasmine.isDomNode(a) && jasmine.isDomNode(b)) {
957
- return a === b;
958
- }
1121
+ var matchers = {};
959
1122
 
960
- if (a instanceof Date && b instanceof Date) {
961
- return a.getTime() == b.getTime();
962
- }
1123
+ function Expectation(options) {
1124
+ this.util = options.util || { buildFailureMessage: function() {} };
1125
+ this.customEqualityTesters = options.customEqualityTesters || [];
1126
+ this.actual = options.actual;
1127
+ this.addExpectationResult = options.addExpectationResult || function(){};
1128
+ this.isNot = options.isNot;
963
1129
 
964
- if (a.jasmineMatches) {
965
- return a.jasmineMatches(b);
1130
+ for (var matcherName in matchers) {
1131
+ this[matcherName] = matchers[matcherName];
1132
+ }
966
1133
  }
967
1134
 
968
- if (b.jasmineMatches) {
969
- return b.jasmineMatches(a);
970
- }
1135
+ Expectation.prototype.wrapCompare = function(name, matcherFactory) {
1136
+ return function() {
1137
+ var args = Array.prototype.slice.call(arguments, 0),
1138
+ expected = args.slice(0),
1139
+ message = "";
971
1140
 
972
- if (a instanceof jasmine.Matchers.ObjectContaining) {
973
- return a.matches(b);
974
- }
1141
+ args.unshift(this.actual);
975
1142
 
976
- if (b instanceof jasmine.Matchers.ObjectContaining) {
977
- return b.matches(a);
978
- }
1143
+ var result = matcherFactory(this.util, this.customEqualityTesters).compare.apply(null, args);
979
1144
 
980
- if (jasmine.isString_(a) && jasmine.isString_(b)) {
981
- return (a == b);
982
- }
1145
+ if (this.isNot) {
1146
+ result.pass = !result.pass;
1147
+ }
983
1148
 
984
- if (jasmine.isNumber_(a) && jasmine.isNumber_(b)) {
985
- return (a == b);
986
- }
1149
+ if (!result.pass) {
1150
+ if (!result.message) {
1151
+ args.unshift(this.isNot);
1152
+ args.unshift(name);
1153
+ message = this.util.buildFailureMessage.apply(null, args);
1154
+ } else {
1155
+ message = result.message;
1156
+ }
1157
+ }
987
1158
 
988
- if (a instanceof RegExp && b instanceof RegExp) {
989
- return this.compareRegExps_(a, b, mismatchKeys, mismatchValues);
990
- }
1159
+ if (expected.length == 1) {
1160
+ expected = expected[0];
1161
+ }
991
1162
 
992
- if (typeof a === "object" && typeof b === "object") {
993
- return this.compareObjects_(a, b, mismatchKeys, mismatchValues);
994
- }
1163
+ // TODO: how many of these params are needed?
1164
+ this.addExpectationResult(
1165
+ result.pass,
1166
+ {
1167
+ matcherName: name,
1168
+ passed: result.pass,
1169
+ message: message,
1170
+ actual: this.actual,
1171
+ expected: expected // TODO: this may need to be arrayified/sliced
1172
+ }
1173
+ );
1174
+ };
1175
+ };
995
1176
 
996
- //Straight check
997
- return (a === b);
998
- };
1177
+ Expectation.addCoreMatchers = function(matchers) {
1178
+ var prototype = Expectation.prototype;
1179
+ for (var matcherName in matchers) {
1180
+ var matcher = matchers[matcherName];
1181
+ prototype[matcherName] = prototype.wrapCompare(matcherName, matcher);
1182
+ }
1183
+ };
999
1184
 
1000
- jasmine.Env.prototype.contains_ = function(haystack, needle) {
1001
- if (jasmine.isArray_(haystack)) {
1002
- for (var i = 0; i < haystack.length; i++) {
1003
- if (this.equals_(haystack[i], needle)) return true;
1185
+ Expectation.addMatchers = function(matchersToAdd) {
1186
+ for (var name in matchersToAdd) {
1187
+ var matcher = matchersToAdd[name];
1188
+ matchers[name] = Expectation.prototype.wrapCompare(name, matcher);
1004
1189
  }
1005
- return false;
1006
- }
1007
- return haystack.indexOf(needle) >= 0;
1008
- };
1190
+ };
1009
1191
 
1010
- jasmine.Env.prototype.addEqualityTester = function(equalityTester) {
1011
- this.equalityTesters_.push(equalityTester);
1012
- };
1013
- /** No-op base class for Jasmine reporters.
1014
- *
1015
- * @constructor
1016
- */
1017
- jasmine.Reporter = function() {
1018
- };
1192
+ Expectation.resetMatchers = function() {
1193
+ for (var name in matchers) {
1194
+ delete matchers[name];
1195
+ }
1196
+ };
1019
1197
 
1020
- //noinspection JSUnusedLocalSymbols
1021
- jasmine.Reporter.prototype.reportRunnerStarting = function(runner) {
1022
- };
1198
+ Expectation.Factory = function(options) {
1199
+ options = options || {};
1023
1200
 
1024
- //noinspection JSUnusedLocalSymbols
1025
- jasmine.Reporter.prototype.reportRunnerResults = function(runner) {
1026
- };
1201
+ var expect = new Expectation(options);
1027
1202
 
1028
- //noinspection JSUnusedLocalSymbols
1029
- jasmine.Reporter.prototype.reportSuiteResults = function(suite) {
1030
- };
1203
+ // TODO: this would be nice as its own Object - NegativeExpectation
1204
+ // TODO: copy instead of mutate options
1205
+ options.isNot = true;
1206
+ expect.not = new Expectation(options);
1031
1207
 
1032
- //noinspection JSUnusedLocalSymbols
1033
- jasmine.Reporter.prototype.reportSpecStarting = function(spec) {
1034
- };
1208
+ return expect;
1209
+ };
1035
1210
 
1036
- //noinspection JSUnusedLocalSymbols
1037
- jasmine.Reporter.prototype.reportSpecResults = function(spec) {
1211
+ return Expectation;
1038
1212
  };
1039
1213
 
1040
- //noinspection JSUnusedLocalSymbols
1041
- jasmine.Reporter.prototype.log = function(str) {
1042
- };
1214
+ //TODO: expectation result may make more sense as a presentation of an expectation.
1215
+ getJasmineRequireObj().buildExpectationResult = function() {
1216
+ function buildExpectationResult(options) {
1217
+ var messageFormatter = options.messageFormatter || function() {},
1218
+ stackFormatter = options.stackFormatter || function() {};
1043
1219
 
1044
- /**
1045
- * Blocks are functions with executable code that make up a spec.
1046
- *
1047
- * @constructor
1048
- * @param {jasmine.Env} env
1049
- * @param {Function} func
1050
- * @param {jasmine.Spec} spec
1051
- */
1052
- jasmine.Block = function(env, func, spec) {
1053
- this.env = env;
1054
- this.func = func;
1055
- this.spec = spec;
1056
- };
1220
+ return {
1221
+ matcherName: options.matcherName,
1222
+ expected: options.expected,
1223
+ actual: options.actual,
1224
+ message: message(),
1225
+ stack: stack(),
1226
+ passed: options.passed
1227
+ };
1057
1228
 
1058
- jasmine.Block.prototype.execute = function(onComplete) {
1059
- if (!jasmine.CATCH_EXCEPTIONS) {
1060
- this.func.apply(this.spec);
1061
- }
1062
- else {
1063
- try {
1064
- this.func.apply(this.spec);
1065
- } catch (e) {
1066
- this.spec.fail(e);
1229
+ function message() {
1230
+ if (options.passed) {
1231
+ return "Passed.";
1232
+ } else if (options.message) {
1233
+ return options.message;
1234
+ } else if (options.error) {
1235
+ return messageFormatter(options.error);
1236
+ }
1237
+ return "";
1067
1238
  }
1068
- }
1069
- onComplete();
1070
- };
1071
- /** JavaScript API reporter.
1072
- *
1073
- * @constructor
1074
- */
1075
- jasmine.JsApiReporter = function() {
1076
- this.started = false;
1077
- this.finished = false;
1078
- this.suites_ = [];
1079
- this.results_ = {};
1080
- };
1081
-
1082
- jasmine.JsApiReporter.prototype.reportRunnerStarting = function(runner) {
1083
- this.started = true;
1084
- var suites = runner.topLevelSuites();
1085
- for (var i = 0; i < suites.length; i++) {
1086
- var suite = suites[i];
1087
- this.suites_.push(this.summarize_(suite));
1088
- }
1089
- };
1090
1239
 
1091
- jasmine.JsApiReporter.prototype.suites = function() {
1092
- return this.suites_;
1093
- };
1240
+ function stack() {
1241
+ if (options.passed) {
1242
+ return "";
1243
+ }
1094
1244
 
1095
- jasmine.JsApiReporter.prototype.summarize_ = function(suiteOrSpec) {
1096
- var isSuite = suiteOrSpec instanceof jasmine.Suite;
1097
- var summary = {
1098
- id: suiteOrSpec.id,
1099
- name: suiteOrSpec.description,
1100
- type: isSuite ? 'suite' : 'spec',
1101
- children: []
1102
- };
1103
-
1104
- if (isSuite) {
1105
- var children = suiteOrSpec.children();
1106
- for (var i = 0; i < children.length; i++) {
1107
- summary.children.push(this.summarize_(children[i]));
1245
+ var error = options.error;
1246
+ if (!error) {
1247
+ try {
1248
+ throw new Error(message());
1249
+ } catch (e) {
1250
+ error = e;
1251
+ }
1252
+ }
1253
+ return stackFormatter(error);
1108
1254
  }
1109
1255
  }
1110
- return summary;
1111
- };
1112
-
1113
- jasmine.JsApiReporter.prototype.results = function() {
1114
- return this.results_;
1115
- };
1116
1256
 
1117
- jasmine.JsApiReporter.prototype.resultsForSpec = function(specId) {
1118
- return this.results_[specId];
1257
+ return buildExpectationResult;
1119
1258
  };
1120
1259
 
1121
- //noinspection JSUnusedLocalSymbols
1122
- jasmine.JsApiReporter.prototype.reportRunnerResults = function(runner) {
1123
- this.finished = true;
1124
- };
1260
+ getJasmineRequireObj().ObjectContaining = function(j$) {
1125
1261
 
1126
- //noinspection JSUnusedLocalSymbols
1127
- jasmine.JsApiReporter.prototype.reportSuiteResults = function(suite) {
1128
- };
1262
+ function ObjectContaining(sample) {
1263
+ this.sample = sample;
1264
+ }
1129
1265
 
1130
- //noinspection JSUnusedLocalSymbols
1131
- jasmine.JsApiReporter.prototype.reportSpecResults = function(spec) {
1132
- this.results_[spec.id] = {
1133
- messages: spec.results().getItems(),
1134
- result: spec.results().failedCount > 0 ? "failed" : "passed"
1135
- };
1136
- };
1266
+ ObjectContaining.prototype.jasmineMatches = function(other, mismatchKeys, mismatchValues) {
1267
+ if (typeof(this.sample) !== "object") { throw new Error("You must provide an object to objectContaining, not '"+this.sample+"'."); }
1137
1268
 
1138
- //noinspection JSUnusedLocalSymbols
1139
- jasmine.JsApiReporter.prototype.log = function(str) {
1140
- };
1269
+ mismatchKeys = mismatchKeys || [];
1270
+ mismatchValues = mismatchValues || [];
1141
1271
 
1142
- jasmine.JsApiReporter.prototype.resultsForSpecs = function(specIds){
1143
- var results = {};
1144
- for (var i = 0; i < specIds.length; i++) {
1145
- var specId = specIds[i];
1146
- results[specId] = this.summarizeResult_(this.results_[specId]);
1147
- }
1148
- return results;
1149
- };
1272
+ var hasKey = function(obj, keyName) {
1273
+ return obj !== null && !j$.util.isUndefined(obj[keyName]);
1274
+ };
1150
1275
 
1151
- jasmine.JsApiReporter.prototype.summarizeResult_ = function(result){
1152
- var summaryMessages = [];
1153
- var messagesLength = result.messages.length;
1154
- for (var messageIndex = 0; messageIndex < messagesLength; messageIndex++) {
1155
- var resultMessage = result.messages[messageIndex];
1156
- summaryMessages.push({
1157
- text: resultMessage.type == 'log' ? resultMessage.toString() : jasmine.undefined,
1158
- passed: resultMessage.passed ? resultMessage.passed() : true,
1159
- type: resultMessage.type,
1160
- message: resultMessage.message,
1161
- trace: {
1162
- stack: resultMessage.passed && !resultMessage.passed() ? resultMessage.trace.stack : jasmine.undefined
1276
+ for (var property in this.sample) {
1277
+ if (!hasKey(other, property) && hasKey(this.sample, property)) {
1278
+ mismatchKeys.push("expected has key '" + property + "', but missing from actual.");
1163
1279
  }
1164
- });
1165
- }
1280
+ else if (!j$.matchersUtil.equals(this.sample[property], other[property])) {
1281
+ mismatchValues.push("'" + property + "' was '" + (other[property] ? j$.util.htmlEscape(other[property].toString()) : other[property]) + "' in actual, but was '" + (this.sample[property] ? j$.util.htmlEscape(this.sample[property].toString()) : this.sample[property]) + "' in expected.");
1282
+ }
1283
+ }
1166
1284
 
1167
- return {
1168
- result : result.result,
1169
- messages : summaryMessages
1285
+ return (mismatchKeys.length === 0 && mismatchValues.length === 0);
1170
1286
  };
1171
- };
1172
1287
 
1173
- /**
1174
- * @constructor
1175
- * @param {jasmine.Env} env
1176
- * @param actual
1177
- * @param {jasmine.Spec} spec
1178
- */
1179
- jasmine.Matchers = function(env, actual, spec, opt_isNot) {
1180
- this.env = env;
1181
- this.actual = actual;
1182
- this.spec = spec;
1183
- this.isNot = opt_isNot || false;
1184
- this.reportWasCalled_ = false;
1185
- };
1288
+ ObjectContaining.prototype.jasmineToString = function() {
1289
+ return "<jasmine.objectContaining(" + j$.pp(this.sample) + ")>";
1290
+ };
1186
1291
 
1187
- // todo: @deprecated as of Jasmine 0.11, remove soon [xw]
1188
- jasmine.Matchers.pp = function(str) {
1189
- throw new Error("jasmine.Matchers.pp() is no longer supported, please use jasmine.pp() instead!");
1292
+ return ObjectContaining;
1190
1293
  };
1191
1294
 
1192
- // todo: @deprecated Deprecated as of Jasmine 0.10. Rewrite your custom matchers to return true or false. [xw]
1193
- jasmine.Matchers.prototype.report = function(result, failing_message, details) {
1194
- throw new Error("As of jasmine 0.11, custom matchers must be implemented differently -- please see jasmine docs");
1195
- };
1295
+ getJasmineRequireObj().pp = function(j$) {
1196
1296
 
1197
- jasmine.Matchers.wrapInto_ = function(prototype, matchersClass) {
1198
- for (var methodName in prototype) {
1199
- if (methodName == 'report') continue;
1200
- var orig = prototype[methodName];
1201
- matchersClass.prototype[methodName] = jasmine.Matchers.matcherFn_(methodName, orig);
1297
+ function PrettyPrinter() {
1298
+ this.ppNestLevel_ = 0;
1202
1299
  }
1203
- };
1204
-
1205
- jasmine.Matchers.matcherFn_ = function(matcherName, matcherFunction) {
1206
- return function() {
1207
- var matcherArgs = jasmine.util.argsToArray(arguments);
1208
- var result = matcherFunction.apply(this, arguments);
1209
1300
 
1210
- if (this.isNot) {
1211
- result = !result;
1212
- }
1213
-
1214
- if (this.reportWasCalled_) return result;
1215
-
1216
- var message;
1217
- if (!result) {
1218
- if (this.message) {
1219
- message = this.message.apply(this, arguments);
1220
- if (jasmine.isArray_(message)) {
1221
- message = message[this.isNot ? 1 : 0];
1301
+ PrettyPrinter.prototype.format = function(value) {
1302
+ this.ppNestLevel_++;
1303
+ try {
1304
+ if (j$.util.isUndefined(value)) {
1305
+ this.emitScalar('undefined');
1306
+ } else if (value === null) {
1307
+ this.emitScalar('null');
1308
+ } else if (value === j$.getGlobal()) {
1309
+ this.emitScalar('<global>');
1310
+ } else if (value.jasmineToString) {
1311
+ this.emitScalar(value.jasmineToString());
1312
+ } else if (typeof value === 'string') {
1313
+ this.emitString(value);
1314
+ } else if (j$.isSpy(value)) {
1315
+ this.emitScalar("spy on " + value.and.identity());
1316
+ } else if (value instanceof RegExp) {
1317
+ this.emitScalar(value.toString());
1318
+ } else if (typeof value === 'function') {
1319
+ this.emitScalar('Function');
1320
+ } else if (typeof value.nodeType === 'number') {
1321
+ this.emitScalar('HTMLNode');
1322
+ } else if (value instanceof Date) {
1323
+ this.emitScalar('Date(' + value + ')');
1324
+ } else if (value.__Jasmine_been_here_before__) {
1325
+ this.emitScalar('<circular reference: ' + (j$.isArray_(value) ? 'Array' : 'Object') + '>');
1326
+ } else if (j$.isArray_(value) || typeof value == 'object') {
1327
+ value.__Jasmine_been_here_before__ = true;
1328
+ if (j$.isArray_(value)) {
1329
+ this.emitArray(value);
1330
+ } else {
1331
+ this.emitObject(value);
1222
1332
  }
1333
+ delete value.__Jasmine_been_here_before__;
1223
1334
  } else {
1224
- var englishyPredicate = matcherName.replace(/[A-Z]/g, function(s) { return ' ' + s.toLowerCase(); });
1225
- message = "Expected " + jasmine.pp(this.actual) + (this.isNot ? " not " : " ") + englishyPredicate;
1226
- if (matcherArgs.length > 0) {
1227
- for (var i = 0; i < matcherArgs.length; i++) {
1228
- if (i > 0) message += ",";
1229
- message += " " + jasmine.pp(matcherArgs[i]);
1230
- }
1231
- }
1232
- message += ".";
1335
+ this.emitScalar(value.toString());
1233
1336
  }
1337
+ } finally {
1338
+ this.ppNestLevel_--;
1234
1339
  }
1235
- var expectationResult = new jasmine.ExpectationResult({
1236
- matcherName: matcherName,
1237
- passed: result,
1238
- expected: matcherArgs.length > 1 ? matcherArgs : matcherArgs[0],
1239
- actual: this.actual,
1240
- message: message
1241
- });
1242
- this.spec.addMatcherResult(expectationResult);
1243
- return jasmine.undefined;
1244
1340
  };
1245
- };
1246
-
1247
1341
 
1342
+ PrettyPrinter.prototype.iterateObject = function(obj, fn) {
1343
+ for (var property in obj) {
1344
+ if (!obj.hasOwnProperty(property)) continue;
1345
+ if (property == '__Jasmine_been_here_before__') continue;
1346
+ fn(property, obj.__lookupGetter__ ? (!j$.util.isUndefined(obj.__lookupGetter__(property)) &&
1347
+ obj.__lookupGetter__(property) !== null) : false);
1348
+ }
1349
+ };
1248
1350
 
1351
+ PrettyPrinter.prototype.emitArray = j$.unimplementedMethod_;
1352
+ PrettyPrinter.prototype.emitObject = j$.unimplementedMethod_;
1353
+ PrettyPrinter.prototype.emitScalar = j$.unimplementedMethod_;
1354
+ PrettyPrinter.prototype.emitString = j$.unimplementedMethod_;
1249
1355
 
1250
- /**
1251
- * toBe: compares the actual to the expected using ===
1252
- * @param expected
1253
- */
1254
- jasmine.Matchers.prototype.toBe = function(expected) {
1255
- return this.actual === expected;
1256
- };
1356
+ function StringPrettyPrinter() {
1357
+ PrettyPrinter.call(this);
1257
1358
 
1258
- /**
1259
- * toNotBe: compares the actual to the expected using !==
1260
- * @param expected
1261
- * @deprecated as of 1.0. Use not.toBe() instead.
1262
- */
1263
- jasmine.Matchers.prototype.toNotBe = function(expected) {
1264
- return this.actual !== expected;
1265
- };
1359
+ this.string = '';
1360
+ }
1266
1361
 
1267
- /**
1268
- * toEqual: compares the actual to the expected using common sense equality. Handles Objects, Arrays, etc.
1269
- *
1270
- * @param expected
1271
- */
1272
- jasmine.Matchers.prototype.toEqual = function(expected) {
1273
- return this.env.equals_(this.actual, expected);
1274
- };
1362
+ j$.util.inherit(StringPrettyPrinter, PrettyPrinter);
1275
1363
 
1276
- /**
1277
- * toNotEqual: compares the actual to the expected using the ! of jasmine.Matchers.toEqual
1278
- * @param expected
1279
- * @deprecated as of 1.0. Use not.toEqual() instead.
1280
- */
1281
- jasmine.Matchers.prototype.toNotEqual = function(expected) {
1282
- return !this.env.equals_(this.actual, expected);
1283
- };
1364
+ StringPrettyPrinter.prototype.emitScalar = function(value) {
1365
+ this.append(value);
1366
+ };
1284
1367
 
1285
- /**
1286
- * Matcher that compares the actual to the expected using a regular expression. Constructs a RegExp, so takes
1287
- * a pattern or a String.
1288
- *
1289
- * @param expected
1290
- */
1291
- jasmine.Matchers.prototype.toMatch = function(expected) {
1292
- return new RegExp(expected).test(this.actual);
1293
- };
1368
+ StringPrettyPrinter.prototype.emitString = function(value) {
1369
+ this.append("'" + value + "'");
1370
+ };
1294
1371
 
1295
- /**
1296
- * Matcher that compares the actual to the expected using the boolean inverse of jasmine.Matchers.toMatch
1297
- * @param expected
1298
- * @deprecated as of 1.0. Use not.toMatch() instead.
1299
- */
1300
- jasmine.Matchers.prototype.toNotMatch = function(expected) {
1301
- return !(new RegExp(expected).test(this.actual));
1302
- };
1372
+ StringPrettyPrinter.prototype.emitArray = function(array) {
1373
+ if (this.ppNestLevel_ > j$.MAX_PRETTY_PRINT_DEPTH) {
1374
+ this.append("Array");
1375
+ return;
1376
+ }
1303
1377
 
1304
- /**
1305
- * Matcher that compares the actual to jasmine.undefined.
1306
- */
1307
- jasmine.Matchers.prototype.toBeDefined = function() {
1308
- return (this.actual !== jasmine.undefined);
1309
- };
1378
+ this.append('[ ');
1379
+ for (var i = 0; i < array.length; i++) {
1380
+ if (i > 0) {
1381
+ this.append(', ');
1382
+ }
1383
+ this.format(array[i]);
1384
+ }
1385
+ this.append(' ]');
1386
+ };
1310
1387
 
1311
- /**
1312
- * Matcher that compares the actual to jasmine.undefined.
1313
- */
1314
- jasmine.Matchers.prototype.toBeUndefined = function() {
1315
- return (this.actual === jasmine.undefined);
1316
- };
1388
+ StringPrettyPrinter.prototype.emitObject = function(obj) {
1389
+ if (this.ppNestLevel_ > j$.MAX_PRETTY_PRINT_DEPTH) {
1390
+ this.append("Object");
1391
+ return;
1392
+ }
1317
1393
 
1318
- /**
1319
- * Matcher that compares the actual to null.
1320
- */
1321
- jasmine.Matchers.prototype.toBeNull = function() {
1322
- return (this.actual === null);
1323
- };
1394
+ var self = this;
1395
+ this.append('{ ');
1396
+ var first = true;
1324
1397
 
1325
- /**
1326
- * Matcher that compares the actual to NaN.
1327
- */
1328
- jasmine.Matchers.prototype.toBeNaN = function() {
1329
- this.message = function() {
1330
- return [ "Expected " + jasmine.pp(this.actual) + " to be NaN." ];
1331
- };
1398
+ this.iterateObject(obj, function(property, isGetter) {
1399
+ if (first) {
1400
+ first = false;
1401
+ } else {
1402
+ self.append(', ');
1403
+ }
1332
1404
 
1333
- return (this.actual !== this.actual);
1334
- };
1405
+ self.append(property);
1406
+ self.append(' : ');
1407
+ if (isGetter) {
1408
+ self.append('<getter>');
1409
+ } else {
1410
+ self.format(obj[property]);
1411
+ }
1412
+ });
1335
1413
 
1336
- /**
1337
- * Matcher that boolean not-nots the actual.
1338
- */
1339
- jasmine.Matchers.prototype.toBeTruthy = function() {
1340
- return !!this.actual;
1341
- };
1414
+ this.append(' }');
1415
+ };
1342
1416
 
1417
+ StringPrettyPrinter.prototype.append = function(value) {
1418
+ this.string += value;
1419
+ };
1343
1420
 
1344
- /**
1345
- * Matcher that boolean nots the actual.
1346
- */
1347
- jasmine.Matchers.prototype.toBeFalsy = function() {
1348
- return !this.actual;
1421
+ return function(value) {
1422
+ var stringPrettyPrinter = new StringPrettyPrinter();
1423
+ stringPrettyPrinter.format(value);
1424
+ return stringPrettyPrinter.string;
1425
+ };
1349
1426
  };
1350
1427
 
1428
+ getJasmineRequireObj().QueueRunner = function() {
1351
1429
 
1352
- /**
1353
- * Matcher that checks to see if the actual, a Jasmine spy, was called.
1354
- */
1355
- jasmine.Matchers.prototype.toHaveBeenCalled = function() {
1356
- if (arguments.length > 0) {
1357
- throw new Error('toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith');
1430
+ function QueueRunner(attrs) {
1431
+ this.fns = attrs.fns || [];
1432
+ this.onComplete = attrs.onComplete || function() {};
1433
+ this.clearStack = attrs.clearStack || function(fn) {fn();};
1434
+ this.onException = attrs.onException || function() {};
1435
+ this.catchException = attrs.catchException || function() { return true; };
1358
1436
  }
1359
1437
 
1360
- if (!jasmine.isSpy(this.actual)) {
1361
- throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
1362
- }
1363
-
1364
- this.message = function() {
1365
- return [
1366
- "Expected spy " + this.actual.identity + " to have been called.",
1367
- "Expected spy " + this.actual.identity + " not to have been called."
1368
- ];
1438
+ QueueRunner.prototype.execute = function() {
1439
+ this.run(this.fns, 0);
1369
1440
  };
1370
1441
 
1371
- return this.actual.wasCalled;
1372
- };
1373
-
1374
- /** @deprecated Use expect(xxx).toHaveBeenCalled() instead */
1375
- jasmine.Matchers.prototype.wasCalled = jasmine.Matchers.prototype.toHaveBeenCalled;
1376
-
1377
- /**
1378
- * Matcher that checks to see if the actual, a Jasmine spy, was not called.
1379
- *
1380
- * @deprecated Use expect(xxx).not.toHaveBeenCalled() instead
1381
- */
1382
- jasmine.Matchers.prototype.wasNotCalled = function() {
1383
- if (arguments.length > 0) {
1384
- throw new Error('wasNotCalled does not take arguments');
1385
- }
1386
-
1387
- if (!jasmine.isSpy(this.actual)) {
1388
- throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
1389
- }
1442
+ QueueRunner.prototype.run = function(fns, recursiveIndex) {
1443
+ var length = fns.length,
1444
+ self = this,
1445
+ iterativeIndex;
1390
1446
 
1391
- this.message = function() {
1392
- return [
1393
- "Expected spy " + this.actual.identity + " to not have been called.",
1394
- "Expected spy " + this.actual.identity + " to have been called."
1395
- ];
1396
- };
1447
+ for(iterativeIndex = recursiveIndex; iterativeIndex < length; iterativeIndex++) {
1448
+ var fn = fns[iterativeIndex];
1449
+ if (fn.length > 0) {
1450
+ return attemptAsync(fn);
1451
+ } else {
1452
+ attemptSync(fn);
1453
+ }
1454
+ }
1397
1455
 
1398
- return !this.actual.wasCalled;
1399
- };
1456
+ var runnerDone = iterativeIndex >= length;
1400
1457
 
1401
- /**
1402
- * Matcher that checks to see if the actual, a Jasmine spy, was called with a set of parameters.
1403
- *
1404
- * @example
1405
- *
1406
- */
1407
- jasmine.Matchers.prototype.toHaveBeenCalledWith = function() {
1408
- var expectedArgs = jasmine.util.argsToArray(arguments);
1409
- if (!jasmine.isSpy(this.actual)) {
1410
- throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
1411
- }
1412
- this.message = function() {
1413
- var invertedMessage = "Expected spy " + this.actual.identity + " not to have been called with " + jasmine.pp(expectedArgs) + " but it was.";
1414
- var positiveMessage = "";
1415
- if (this.actual.callCount === 0) {
1416
- positiveMessage = "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but it was never called.";
1417
- } else {
1418
- positiveMessage = "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but actual calls were " + jasmine.pp(this.actual.argsForCall).replace(/^\[ | \]$/g, '')
1458
+ if (runnerDone) {
1459
+ this.clearStack(this.onComplete);
1419
1460
  }
1420
- return [positiveMessage, invertedMessage];
1421
- };
1422
1461
 
1423
- return this.env.contains_(this.actual.argsForCall, expectedArgs);
1424
- };
1462
+ function attemptSync(fn) {
1463
+ try {
1464
+ fn.call(self);
1465
+ } catch (e) {
1466
+ handleException(e);
1467
+ }
1468
+ }
1425
1469
 
1426
- /** @deprecated Use expect(xxx).toHaveBeenCalledWith() instead */
1427
- jasmine.Matchers.prototype.wasCalledWith = jasmine.Matchers.prototype.toHaveBeenCalledWith;
1470
+ function attemptAsync(fn) {
1471
+ var next = function () { self.run(fns, iterativeIndex + 1); };
1428
1472
 
1429
- /** @deprecated Use expect(xxx).not.toHaveBeenCalledWith() instead */
1430
- jasmine.Matchers.prototype.wasNotCalledWith = function() {
1431
- var expectedArgs = jasmine.util.argsToArray(arguments);
1432
- if (!jasmine.isSpy(this.actual)) {
1433
- throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
1434
- }
1473
+ try {
1474
+ fn.call(self, next);
1475
+ } catch (e) {
1476
+ handleException(e);
1477
+ next();
1478
+ }
1479
+ }
1435
1480
 
1436
- this.message = function() {
1437
- return [
1438
- "Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but it was",
1439
- "Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but it was"
1440
- ];
1481
+ function handleException(e) {
1482
+ self.onException(e);
1483
+ if (!self.catchException(e)) {
1484
+ //TODO: set a var when we catch an exception and
1485
+ //use a finally block to close the loop in a nice way..
1486
+ throw e;
1487
+ }
1488
+ }
1441
1489
  };
1442
1490
 
1443
- return !this.env.contains_(this.actual.argsForCall, expectedArgs);
1491
+ return QueueRunner;
1444
1492
  };
1445
1493
 
1446
- /**
1447
- * Matcher that checks that the expected item is an element in the actual Array.
1448
- *
1449
- * @param {Object} expected
1450
- */
1451
- jasmine.Matchers.prototype.toContain = function(expected) {
1452
- return this.env.contains_(this.actual, expected);
1453
- };
1494
+ getJasmineRequireObj().ReportDispatcher = function() {
1495
+ function ReportDispatcher(methods) {
1454
1496
 
1455
- /**
1456
- * Matcher that checks that the expected item is NOT an element in the actual Array.
1457
- *
1458
- * @param {Object} expected
1459
- * @deprecated as of 1.0. Use not.toContain() instead.
1460
- */
1461
- jasmine.Matchers.prototype.toNotContain = function(expected) {
1462
- return !this.env.contains_(this.actual, expected);
1463
- };
1497
+ var dispatchedMethods = methods || [];
1464
1498
 
1465
- jasmine.Matchers.prototype.toBeLessThan = function(expected) {
1466
- return this.actual < expected;
1467
- };
1499
+ for (var i = 0; i < dispatchedMethods.length; i++) {
1500
+ var method = dispatchedMethods[i];
1501
+ this[method] = function(m) {
1502
+ return function() {
1503
+ dispatch(m, arguments);
1504
+ };
1505
+ }(method);
1506
+ }
1468
1507
 
1469
- jasmine.Matchers.prototype.toBeGreaterThan = function(expected) {
1470
- return this.actual > expected;
1471
- };
1508
+ var reporters = [];
1509
+
1510
+ this.addReporter = function(reporter) {
1511
+ reporters.push(reporter);
1512
+ };
1472
1513
 
1473
- /**
1474
- * Matcher that checks that the expected item is equal to the actual item
1475
- * up to a given level of decimal precision (default 2).
1476
- *
1477
- * @param {Number} expected
1478
- * @param {Number} precision, as number of decimal places
1479
- */
1480
- jasmine.Matchers.prototype.toBeCloseTo = function(expected, precision) {
1481
- if (!(precision === 0)) {
1482
- precision = precision || 2;
1514
+ return this;
1515
+
1516
+ function dispatch(method, args) {
1517
+ for (var i = 0; i < reporters.length; i++) {
1518
+ var reporter = reporters[i];
1519
+ if (reporter[method]) {
1520
+ reporter[method].apply(reporter, args);
1521
+ }
1522
+ }
1523
+ }
1483
1524
  }
1484
- return Math.abs(expected - this.actual) < (Math.pow(10, -precision) / 2);
1525
+
1526
+ return ReportDispatcher;
1485
1527
  };
1486
1528
 
1487
- /**
1488
- * Matcher that checks that the expected exception was thrown by the actual.
1489
- *
1490
- * @param {String} [expected]
1491
- */
1492
- jasmine.Matchers.prototype.toThrow = function(expected) {
1493
- var result = false;
1494
- var exception;
1495
- if (typeof this.actual != 'function') {
1496
- throw new Error('Actual is not a function');
1497
- }
1498
- try {
1499
- this.actual();
1500
- } catch (e) {
1501
- exception = e;
1502
- }
1503
- if (exception) {
1504
- result = (expected === jasmine.undefined || this.env.equals_(exception.message || exception, expected.message || expected));
1505
- }
1506
1529
 
1507
- var not = this.isNot ? "not " : "";
1530
+ getJasmineRequireObj().SpyStrategy = function() {
1508
1531
 
1509
- this.message = function() {
1510
- if (exception && (expected === jasmine.undefined || !this.env.equals_(exception.message || exception, expected.message || expected))) {
1511
- return ["Expected function " + not + "to throw", expected ? expected.message || expected : "an exception", ", but it threw", exception.message || exception].join(' ');
1512
- } else {
1513
- return "Expected function to throw an exception.";
1514
- }
1515
- };
1532
+ function SpyStrategy(options) {
1533
+ options = options || {};
1516
1534
 
1517
- return result;
1518
- };
1535
+ var identity = options.name || "unknown",
1536
+ originalFn = options.fn || function() {},
1537
+ getSpy = options.getSpy || function() {},
1538
+ plan = function() {};
1519
1539
 
1520
- jasmine.Matchers.Any = function(expectedClass) {
1521
- this.expectedClass = expectedClass;
1522
- };
1540
+ this.identity = function() {
1541
+ return identity;
1542
+ };
1523
1543
 
1524
- jasmine.Matchers.Any.prototype.jasmineMatches = function(other) {
1525
- if (this.expectedClass == String) {
1526
- return typeof other == 'string' || other instanceof String;
1527
- }
1544
+ this.exec = function() {
1545
+ return plan.apply(this, arguments);
1546
+ };
1528
1547
 
1529
- if (this.expectedClass == Number) {
1530
- return typeof other == 'number' || other instanceof Number;
1531
- }
1548
+ this.callThrough = function() {
1549
+ plan = originalFn;
1550
+ return getSpy();
1551
+ };
1532
1552
 
1533
- if (this.expectedClass == Function) {
1534
- return typeof other == 'function' || other instanceof Function;
1535
- }
1553
+ this.callReturn = function(value) {
1554
+ plan = function() {
1555
+ return value;
1556
+ };
1557
+ return getSpy();
1558
+ };
1536
1559
 
1537
- if (this.expectedClass == Object) {
1538
- return typeof other == 'object';
1539
- }
1560
+ this.callThrow = function(something) {
1561
+ plan = function() {
1562
+ throw something;
1563
+ };
1564
+ return getSpy();
1565
+ };
1540
1566
 
1541
- return other instanceof this.expectedClass;
1542
- };
1567
+ this.callFake = function(fn) {
1568
+ plan = fn;
1569
+ return getSpy();
1570
+ };
1543
1571
 
1544
- jasmine.Matchers.Any.prototype.jasmineToString = function() {
1545
- return '<jasmine.any(' + this.expectedClass + ')>';
1546
- };
1572
+ this.stub = function(fn) {
1573
+ plan = function() {};
1574
+ return getSpy();
1575
+ };
1576
+ }
1547
1577
 
1548
- jasmine.Matchers.ObjectContaining = function (sample) {
1549
- this.sample = sample;
1578
+ return SpyStrategy;
1550
1579
  };
1551
1580
 
1552
- jasmine.Matchers.ObjectContaining.prototype.jasmineMatches = function(other, mismatchKeys, mismatchValues) {
1553
- mismatchKeys = mismatchKeys || [];
1554
- mismatchValues = mismatchValues || [];
1581
+ getJasmineRequireObj().Suite = function() {
1582
+ function Suite(attrs) {
1583
+ this.env = attrs.env;
1584
+ this.id = attrs.id;
1585
+ this.parentSuite = attrs.parentSuite;
1586
+ this.description = attrs.description;
1587
+ this.onStart = attrs.onStart || function() {};
1588
+ this.completeCallback = attrs.completeCallback || function() {}; // TODO: this is unused
1589
+ this.resultCallback = attrs.resultCallback || function() {};
1590
+ this.clearStack = attrs.clearStack || function(fn) {fn();};
1555
1591
 
1556
- var env = jasmine.getEnv();
1592
+ this.beforeFns = [];
1593
+ this.afterFns = [];
1594
+ this.queueRunner = attrs.queueRunner || function() {};
1595
+ this.disabled = false;
1557
1596
 
1558
- var hasKey = function(obj, keyName) {
1559
- return obj != null && obj[keyName] !== jasmine.undefined;
1560
- };
1597
+ this.children_ = []; // TODO: rename
1598
+ this.suites = []; // TODO: needed?
1599
+ this.specs = []; // TODO: needed?
1561
1600
 
1562
- for (var property in this.sample) {
1563
- if (!hasKey(other, property) && hasKey(this.sample, property)) {
1564
- mismatchKeys.push("expected has key '" + property + "', but missing from actual.");
1565
- }
1566
- else if (!env.equals_(this.sample[property], other[property], mismatchKeys, mismatchValues)) {
1567
- mismatchValues.push("'" + property + "' was '" + (other[property] ? jasmine.util.htmlEscape(other[property].toString()) : other[property]) + "' in expected, but was '" + (this.sample[property] ? jasmine.util.htmlEscape(this.sample[property].toString()) : this.sample[property]) + "' in actual.");
1568
- }
1601
+ this.result = {
1602
+ id: this.id,
1603
+ status: this.disabled ? 'disabled' : '',
1604
+ description: this.description,
1605
+ fullName: this.getFullName()
1606
+ };
1569
1607
  }
1570
1608
 
1571
- return (mismatchKeys.length === 0 && mismatchValues.length === 0);
1572
- };
1573
-
1574
- jasmine.Matchers.ObjectContaining.prototype.jasmineToString = function () {
1575
- return "<jasmine.objectContaining(" + jasmine.pp(this.sample) + ")>";
1576
- };
1577
- // Mock setTimeout, clearTimeout
1578
- // Contributed by Pivotal Computer Systems, www.pivotalsf.com
1609
+ Suite.prototype.getFullName = function() {
1610
+ var fullName = this.description;
1611
+ for (var parentSuite = this.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) {
1612
+ if (parentSuite.parentSuite) {
1613
+ fullName = parentSuite.description + ' ' + fullName;
1614
+ }
1615
+ }
1616
+ return fullName;
1617
+ };
1579
1618
 
1580
- jasmine.FakeTimer = function() {
1581
- this.reset();
1619
+ Suite.prototype.disable = function() {
1620
+ this.disabled = true;
1621
+ };
1582
1622
 
1583
- var self = this;
1584
- self.setTimeout = function(funcToCall, millis) {
1585
- self.timeoutsMade++;
1586
- self.scheduleFunction(self.timeoutsMade, funcToCall, millis, false);
1587
- return self.timeoutsMade;
1623
+ Suite.prototype.beforeEach = function(fn) {
1624
+ this.beforeFns.unshift(fn);
1588
1625
  };
1589
1626
 
1590
- self.setInterval = function(funcToCall, millis) {
1591
- self.timeoutsMade++;
1592
- self.scheduleFunction(self.timeoutsMade, funcToCall, millis, true);
1593
- return self.timeoutsMade;
1627
+ Suite.prototype.afterEach = function(fn) {
1628
+ this.afterFns.unshift(fn);
1594
1629
  };
1595
1630
 
1596
- self.clearTimeout = function(timeoutKey) {
1597
- self.scheduledFunctions[timeoutKey] = jasmine.undefined;
1631
+ Suite.prototype.addSpec = function(spec) {
1632
+ this.children_.push(spec);
1633
+ this.specs.push(spec); // TODO: needed?
1598
1634
  };
1599
1635
 
1600
- self.clearInterval = function(timeoutKey) {
1601
- self.scheduledFunctions[timeoutKey] = jasmine.undefined;
1636
+ Suite.prototype.addSuite = function(suite) {
1637
+ suite.parentSuite = this;
1638
+ this.children_.push(suite);
1639
+ this.suites.push(suite); // TODO: needed?
1602
1640
  };
1603
1641
 
1604
- };
1642
+ Suite.prototype.children = function() {
1643
+ return this.children_;
1644
+ };
1605
1645
 
1606
- jasmine.FakeTimer.prototype.reset = function() {
1607
- this.timeoutsMade = 0;
1608
- this.scheduledFunctions = {};
1609
- this.nowMillis = 0;
1610
- };
1646
+ Suite.prototype.execute = function(onComplete) {
1647
+ var self = this;
1648
+ if (this.disabled) {
1649
+ complete();
1650
+ return;
1651
+ }
1611
1652
 
1612
- jasmine.FakeTimer.prototype.tick = function(millis) {
1613
- var oldMillis = this.nowMillis;
1614
- var newMillis = oldMillis + millis;
1615
- this.runFunctionsWithinRange(oldMillis, newMillis);
1616
- this.nowMillis = newMillis;
1617
- };
1653
+ var allFns = [],
1654
+ children = this.children_;
1618
1655
 
1619
- jasmine.FakeTimer.prototype.runFunctionsWithinRange = function(oldMillis, nowMillis) {
1620
- var scheduledFunc;
1621
- var funcsToRun = [];
1622
- for (var timeoutKey in this.scheduledFunctions) {
1623
- scheduledFunc = this.scheduledFunctions[timeoutKey];
1624
- if (scheduledFunc != jasmine.undefined &&
1625
- scheduledFunc.runAtMillis >= oldMillis &&
1626
- scheduledFunc.runAtMillis <= nowMillis) {
1627
- funcsToRun.push(scheduledFunc);
1628
- this.scheduledFunctions[timeoutKey] = jasmine.undefined;
1656
+ for (var i = 0; i < children.length; i++) {
1657
+ allFns.push(wrapChildAsAsync(children[i]));
1629
1658
  }
1630
- }
1631
1659
 
1632
- if (funcsToRun.length > 0) {
1633
- funcsToRun.sort(function(a, b) {
1634
- return a.runAtMillis - b.runAtMillis;
1660
+ this.onStart(this);
1661
+
1662
+ this.queueRunner({
1663
+ fns: allFns,
1664
+ onComplete: complete
1635
1665
  });
1636
- for (var i = 0; i < funcsToRun.length; ++i) {
1637
- try {
1638
- var funcToRun = funcsToRun[i];
1639
- this.nowMillis = funcToRun.runAtMillis;
1640
- funcToRun.funcToCall();
1641
- if (funcToRun.recurring) {
1642
- this.scheduleFunction(funcToRun.timeoutKey,
1643
- funcToRun.funcToCall,
1644
- funcToRun.millis,
1645
- true);
1646
- }
1647
- } catch(e) {
1666
+
1667
+ function complete() {
1668
+ self.resultCallback(self.result);
1669
+
1670
+ if (onComplete) {
1671
+ onComplete();
1648
1672
  }
1649
1673
  }
1650
- this.runFunctionsWithinRange(oldMillis, nowMillis);
1674
+
1675
+ function wrapChildAsAsync(child) {
1676
+ return function(done) { child.execute(done); };
1677
+ }
1678
+ };
1679
+
1680
+ return Suite;
1681
+ };
1682
+
1683
+ if (typeof window == void 0 && typeof exports == "object") {
1684
+ exports.Suite = jasmineRequire.Suite;
1685
+ }
1686
+
1687
+ getJasmineRequireObj().Timer = function() {
1688
+ function Timer(options) {
1689
+ options = options || {};
1690
+
1691
+ var now = options.now || function() { return new Date().getTime(); },
1692
+ startTime;
1693
+
1694
+ this.start = function() {
1695
+ startTime = now();
1696
+ };
1697
+
1698
+ this.elapsed = function() {
1699
+ return now() - startTime;
1700
+ };
1651
1701
  }
1652
- };
1653
1702
 
1654
- jasmine.FakeTimer.prototype.scheduleFunction = function(timeoutKey, funcToCall, millis, recurring) {
1655
- this.scheduledFunctions[timeoutKey] = {
1656
- runAtMillis: this.nowMillis + millis,
1657
- funcToCall: funcToCall,
1658
- recurring: recurring,
1659
- timeoutKey: timeoutKey,
1660
- millis: millis
1661
- };
1703
+ return Timer;
1662
1704
  };
1705
+ getJasmineRequireObj().matchersUtil = function(j$) {
1706
+ // TODO: what to do about jasmine.pp not being inject? move to JSON.stringify? gut PrettyPrinter?
1663
1707
 
1664
- /**
1665
- * @namespace
1666
- */
1667
- jasmine.Clock = {
1668
- defaultFakeTimer: new jasmine.FakeTimer(),
1708
+ return {
1709
+ equals: function(a, b, customTesters) {
1710
+ customTesters = customTesters || [];
1669
1711
 
1670
- reset: function() {
1671
- jasmine.Clock.assertInstalled();
1672
- jasmine.Clock.defaultFakeTimer.reset();
1673
- },
1712
+ return eq(a, b, [], [], customTesters);
1713
+ },
1674
1714
 
1675
- tick: function(millis) {
1676
- jasmine.Clock.assertInstalled();
1677
- jasmine.Clock.defaultFakeTimer.tick(millis);
1678
- },
1715
+ contains: function(haystack, needle, customTesters) {
1716
+ customTesters = customTesters || [];
1679
1717
 
1680
- runFunctionsWithinRange: function(oldMillis, nowMillis) {
1681
- jasmine.Clock.defaultFakeTimer.runFunctionsWithinRange(oldMillis, nowMillis);
1682
- },
1718
+ if (Object.prototype.toString.apply(haystack) === "[object Array]") {
1719
+ for (var i = 0; i < haystack.length; i++) {
1720
+ if (eq(haystack[i], needle, [], [], customTesters)) {
1721
+ return true;
1722
+ }
1723
+ }
1724
+ return false;
1725
+ }
1726
+ return haystack.indexOf(needle) >= 0;
1727
+ },
1728
+
1729
+ buildFailureMessage: function() {
1730
+ var args = Array.prototype.slice.call(arguments, 0),
1731
+ matcherName = args[0],
1732
+ isNot = args[1],
1733
+ actual = args[2],
1734
+ expected = args.slice(3),
1735
+ englishyPredicate = matcherName.replace(/[A-Z]/g, function(s) { return ' ' + s.toLowerCase(); });
1736
+
1737
+ var message = "Expected " +
1738
+ j$.pp(actual) +
1739
+ (isNot ? " not " : " ") +
1740
+ englishyPredicate;
1741
+
1742
+ if (expected.length > 0) {
1743
+ for (var i = 0; i < expected.length; i++) {
1744
+ if (i > 0) message += ",";
1745
+ message += " " + j$.pp(expected[i]);
1746
+ }
1747
+ }
1683
1748
 
1684
- scheduleFunction: function(timeoutKey, funcToCall, millis, recurring) {
1685
- jasmine.Clock.defaultFakeTimer.scheduleFunction(timeoutKey, funcToCall, millis, recurring);
1686
- },
1749
+ return message + ".";
1750
+ }
1751
+ };
1687
1752
 
1688
- useMock: function() {
1689
- if (!jasmine.Clock.isInstalled()) {
1690
- var spec = jasmine.getEnv().currentSpec;
1691
- spec.after(jasmine.Clock.uninstallMock);
1753
+ // Equality function lovingly adapted from isEqual in
1754
+ // [Underscore](http://underscorejs.org)
1755
+ function eq(a, b, aStack, bStack, customTesters) {
1756
+ var result = true;
1692
1757
 
1693
- jasmine.Clock.installMock();
1758
+ for (var i = 0; i < customTesters.length; i++) {
1759
+ result = customTesters[i](a, b);
1760
+ if (result) {
1761
+ return true;
1762
+ }
1694
1763
  }
1695
- },
1696
-
1697
- installMock: function() {
1698
- jasmine.Clock.installed = jasmine.Clock.defaultFakeTimer;
1699
- },
1700
1764
 
1701
- uninstallMock: function() {
1702
- jasmine.Clock.assertInstalled();
1703
- jasmine.Clock.installed = jasmine.Clock.real;
1704
- },
1765
+ if (a instanceof j$.Any) {
1766
+ result = a.jasmineMatches(b);
1767
+ if (result) {
1768
+ return true;
1769
+ }
1770
+ }
1705
1771
 
1706
- real: {
1707
- setTimeout: jasmine.getGlobal().setTimeout,
1708
- clearTimeout: jasmine.getGlobal().clearTimeout,
1709
- setInterval: jasmine.getGlobal().setInterval,
1710
- clearInterval: jasmine.getGlobal().clearInterval
1711
- },
1772
+ if (b instanceof j$.Any) {
1773
+ result = b.jasmineMatches(a);
1774
+ if (result) {
1775
+ return true;
1776
+ }
1777
+ }
1712
1778
 
1713
- assertInstalled: function() {
1714
- if (!jasmine.Clock.isInstalled()) {
1715
- throw new Error("Mock clock is not installed, use jasmine.Clock.useMock()");
1779
+ if (b instanceof j$.ObjectContaining) {
1780
+ result = b.jasmineMatches(a);
1781
+ if (result) {
1782
+ return true;
1783
+ }
1716
1784
  }
1717
- },
1718
1785
 
1719
- isInstalled: function() {
1720
- return jasmine.Clock.installed == jasmine.Clock.defaultFakeTimer;
1721
- },
1786
+ if (a instanceof Error && b instanceof Error) {
1787
+ return a.message == b.message;
1788
+ }
1722
1789
 
1723
- installed: null
1724
- };
1725
- jasmine.Clock.installed = jasmine.Clock.real;
1790
+ // Identical objects are equal. `0 === -0`, but they aren't identical.
1791
+ // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
1792
+ if (a === b) return a !== 0 || 1 / a == 1 / b;
1793
+ // A strict comparison is necessary because `null == undefined`.
1794
+ if (a === null || b === null) return a === b;
1795
+ var className = Object.prototype.toString.call(a);
1796
+ if (className != Object.prototype.toString.call(b)) return false;
1797
+ switch (className) {
1798
+ // Strings, numbers, dates, and booleans are compared by value.
1799
+ case '[object String]':
1800
+ // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
1801
+ // equivalent to `new String("5")`.
1802
+ return a == String(b);
1803
+ case '[object Number]':
1804
+ // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for
1805
+ // other numeric values.
1806
+ return a != +a ? b != +b : (a === 0 ? 1 / a == 1 / b : a == +b);
1807
+ case '[object Date]':
1808
+ case '[object Boolean]':
1809
+ // Coerce dates and booleans to numeric primitive values. Dates are compared by their
1810
+ // millisecond representations. Note that invalid dates with millisecond representations
1811
+ // of `NaN` are not equivalent.
1812
+ return +a == +b;
1813
+ // RegExps are compared by their source patterns and flags.
1814
+ case '[object RegExp]':
1815
+ return a.source == b.source &&
1816
+ a.global == b.global &&
1817
+ a.multiline == b.multiline &&
1818
+ a.ignoreCase == b.ignoreCase;
1819
+ }
1820
+ if (typeof a != 'object' || typeof b != 'object') return false;
1821
+ // Assume equality for cyclic structures. The algorithm for detecting cyclic
1822
+ // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
1823
+ var length = aStack.length;
1824
+ while (length--) {
1825
+ // Linear search. Performance is inversely proportional to the number of
1826
+ // unique nested structures.
1827
+ if (aStack[length] == a) return bStack[length] == b;
1828
+ }
1829
+ // Add the first object to the stack of traversed objects.
1830
+ aStack.push(a);
1831
+ bStack.push(b);
1832
+ var size = 0;
1833
+ // Recursively compare objects and arrays.
1834
+ if (className == '[object Array]') {
1835
+ // Compare array lengths to determine if a deep comparison is necessary.
1836
+ size = a.length;
1837
+ result = size == b.length;
1838
+ if (result) {
1839
+ // Deep compare the contents, ignoring non-numeric properties.
1840
+ while (size--) {
1841
+ if (!(result = eq(a[size], b[size], aStack, bStack, customTesters))) break;
1842
+ }
1843
+ }
1844
+ } else {
1845
+ // Objects with different constructors are not equivalent, but `Object`s
1846
+ // from different frames are.
1847
+ var aCtor = a.constructor, bCtor = b.constructor;
1848
+ if (aCtor !== bCtor && !(isFunction(aCtor) && (aCtor instanceof aCtor) &&
1849
+ isFunction(bCtor) && (bCtor instanceof bCtor))) {
1850
+ return false;
1851
+ }
1852
+ // Deep compare objects.
1853
+ for (var key in a) {
1854
+ if (has(a, key)) {
1855
+ // Count the expected number of properties.
1856
+ size++;
1857
+ // Deep compare each member.
1858
+ if (!(result = has(b, key) && eq(a[key], b[key], aStack, bStack, customTesters))) break;
1859
+ }
1860
+ }
1861
+ // Ensure that both objects contain the same number of properties.
1862
+ if (result) {
1863
+ for (key in b) {
1864
+ if (has(b, key) && !(size--)) break;
1865
+ }
1866
+ result = !size;
1867
+ }
1868
+ }
1869
+ // Remove the first object from the stack of traversed objects.
1870
+ aStack.pop();
1871
+ bStack.pop();
1726
1872
 
1727
- //else for IE support
1728
- jasmine.getGlobal().setTimeout = function(funcToCall, millis) {
1729
- if (jasmine.Clock.installed.setTimeout.apply) {
1730
- return jasmine.Clock.installed.setTimeout.apply(this, arguments);
1731
- } else {
1732
- return jasmine.Clock.installed.setTimeout(funcToCall, millis);
1733
- }
1734
- };
1873
+ return result;
1735
1874
 
1736
- jasmine.getGlobal().setInterval = function(funcToCall, millis) {
1737
- if (jasmine.Clock.installed.setInterval.apply) {
1738
- return jasmine.Clock.installed.setInterval.apply(this, arguments);
1739
- } else {
1740
- return jasmine.Clock.installed.setInterval(funcToCall, millis);
1741
- }
1742
- };
1875
+ function has(obj, key) {
1876
+ return obj.hasOwnProperty(key);
1877
+ }
1743
1878
 
1744
- jasmine.getGlobal().clearTimeout = function(timeoutKey) {
1745
- if (jasmine.Clock.installed.clearTimeout.apply) {
1746
- return jasmine.Clock.installed.clearTimeout.apply(this, arguments);
1747
- } else {
1748
- return jasmine.Clock.installed.clearTimeout(timeoutKey);
1879
+ function isFunction(obj) {
1880
+ return typeof obj === 'function';
1881
+ }
1749
1882
  }
1750
1883
  };
1751
-
1752
- jasmine.getGlobal().clearInterval = function(timeoutKey) {
1753
- if (jasmine.Clock.installed.clearTimeout.apply) {
1754
- return jasmine.Clock.installed.clearInterval.apply(this, arguments);
1755
- } else {
1756
- return jasmine.Clock.installed.clearInterval(timeoutKey);
1884
+ getJasmineRequireObj().toBe = function() {
1885
+ function toBe() {
1886
+ return {
1887
+ compare: function(actual, expected) {
1888
+ return {
1889
+ pass: actual === expected
1890
+ };
1891
+ }
1892
+ };
1757
1893
  }
1758
- };
1759
1894
 
1760
- /**
1761
- * @constructor
1762
- */
1763
- jasmine.MultiReporter = function() {
1764
- this.subReporters_ = [];
1895
+ return toBe;
1765
1896
  };
1766
- jasmine.util.inherit(jasmine.MultiReporter, jasmine.Reporter);
1767
1897
 
1768
- jasmine.MultiReporter.prototype.addReporter = function(reporter) {
1769
- this.subReporters_.push(reporter);
1770
- };
1898
+ getJasmineRequireObj().toBeCloseTo = function() {
1771
1899
 
1772
- (function() {
1773
- var functionNames = [
1774
- "reportRunnerStarting",
1775
- "reportRunnerResults",
1776
- "reportSuiteResults",
1777
- "reportSpecStarting",
1778
- "reportSpecResults",
1779
- "log"
1780
- ];
1781
- for (var i = 0; i < functionNames.length; i++) {
1782
- var functionName = functionNames[i];
1783
- jasmine.MultiReporter.prototype[functionName] = (function(functionName) {
1784
- return function() {
1785
- for (var j = 0; j < this.subReporters_.length; j++) {
1786
- var subReporter = this.subReporters_[j];
1787
- if (subReporter[functionName]) {
1788
- subReporter[functionName].apply(subReporter, arguments);
1789
- }
1900
+ function toBeCloseTo() {
1901
+ return {
1902
+ compare: function(actual, expected, precision) {
1903
+ if (precision !== 0) {
1904
+ precision = precision || 2;
1790
1905
  }
1791
- };
1792
- })(functionName);
1793
- }
1794
- })();
1795
- /**
1796
- * Holds results for a set of Jasmine spec. Allows for the results array to hold another jasmine.NestedResults
1797
- *
1798
- * @constructor
1799
- */
1800
- jasmine.NestedResults = function() {
1801
- /**
1802
- * The total count of results
1803
- */
1804
- this.totalCount = 0;
1805
- /**
1806
- * Number of passed results
1807
- */
1808
- this.passedCount = 0;
1809
- /**
1810
- * Number of failed results
1811
- */
1812
- this.failedCount = 0;
1813
- /**
1814
- * Was this suite/spec skipped?
1815
- */
1816
- this.skipped = false;
1817
- /**
1818
- * @ignore
1819
- */
1820
- this.items_ = [];
1821
- };
1822
-
1823
- /**
1824
- * Roll up the result counts.
1825
- *
1826
- * @param result
1827
- */
1828
- jasmine.NestedResults.prototype.rollupCounts = function(result) {
1829
- this.totalCount += result.totalCount;
1830
- this.passedCount += result.passedCount;
1831
- this.failedCount += result.failedCount;
1832
- };
1833
1906
 
1834
- /**
1835
- * Adds a log message.
1836
- * @param values Array of message parts which will be concatenated later.
1837
- */
1838
- jasmine.NestedResults.prototype.log = function(values) {
1839
- this.items_.push(new jasmine.MessageResult(values));
1840
- };
1907
+ return {
1908
+ pass: Math.abs(expected - actual) < (Math.pow(10, -precision) / 2)
1909
+ };
1910
+ }
1911
+ };
1912
+ }
1841
1913
 
1842
- /**
1843
- * Getter for the results: message & results.
1844
- */
1845
- jasmine.NestedResults.prototype.getItems = function() {
1846
- return this.items_;
1914
+ return toBeCloseTo;
1847
1915
  };
1848
1916
 
1849
- /**
1850
- * Adds a result, tracking counts (total, passed, & failed)
1851
- * @param {jasmine.ExpectationResult|jasmine.NestedResults} result
1852
- */
1853
- jasmine.NestedResults.prototype.addResult = function(result) {
1854
- if (result.type != 'log') {
1855
- if (result.items_) {
1856
- this.rollupCounts(result);
1857
- } else {
1858
- this.totalCount++;
1859
- if (result.passed()) {
1860
- this.passedCount++;
1861
- } else {
1862
- this.failedCount++;
1917
+ getJasmineRequireObj().toBeDefined = function() {
1918
+ function toBeDefined() {
1919
+ return {
1920
+ compare: function(actual) {
1921
+ return {
1922
+ pass: (void 0 !== actual)
1923
+ };
1863
1924
  }
1864
- }
1925
+ };
1865
1926
  }
1866
- this.items_.push(result);
1867
- };
1868
1927
 
1869
- /**
1870
- * @returns {Boolean} True if <b>everything</b> below passed
1871
- */
1872
- jasmine.NestedResults.prototype.passed = function() {
1873
- return this.passedCount === this.totalCount;
1874
- };
1875
- /**
1876
- * Base class for pretty printing for expectation results.
1877
- */
1878
- jasmine.PrettyPrinter = function() {
1879
- this.ppNestLevel_ = 0;
1928
+ return toBeDefined;
1880
1929
  };
1881
1930
 
1882
- /**
1883
- * Formats a value in a nice, human-readable string.
1884
- *
1885
- * @param value
1886
- */
1887
- jasmine.PrettyPrinter.prototype.format = function(value) {
1888
- this.ppNestLevel_++;
1889
- try {
1890
- if (value === jasmine.undefined) {
1891
- this.emitScalar('undefined');
1892
- } else if (value === null) {
1893
- this.emitScalar('null');
1894
- } else if (value === jasmine.getGlobal()) {
1895
- this.emitScalar('<global>');
1896
- } else if (value.jasmineToString) {
1897
- this.emitScalar(value.jasmineToString());
1898
- } else if (typeof value === 'string') {
1899
- this.emitString(value);
1900
- } else if (jasmine.isSpy(value)) {
1901
- this.emitScalar("spy on " + value.identity);
1902
- } else if (value instanceof RegExp) {
1903
- this.emitScalar(value.toString());
1904
- } else if (typeof value === 'function') {
1905
- this.emitScalar('Function');
1906
- } else if (typeof value.nodeType === 'number') {
1907
- this.emitScalar('HTMLNode');
1908
- } else if (value instanceof Date) {
1909
- this.emitScalar('Date(' + value + ')');
1910
- } else if (value.__Jasmine_been_here_before__) {
1911
- this.emitScalar('<circular reference: ' + (jasmine.isArray_(value) ? 'Array' : 'Object') + '>');
1912
- } else if (jasmine.isArray_(value) || typeof value == 'object') {
1913
- value.__Jasmine_been_here_before__ = true;
1914
- if (jasmine.isArray_(value)) {
1915
- this.emitArray(value);
1916
- } else {
1917
- this.emitObject(value);
1931
+ getJasmineRequireObj().toBeFalsy = function() {
1932
+ function toBeFalsy() {
1933
+ return {
1934
+ compare: function(actual) {
1935
+ return {
1936
+ pass: !!!actual
1937
+ };
1918
1938
  }
1919
- delete value.__Jasmine_been_here_before__;
1920
- } else {
1921
- this.emitScalar(value.toString());
1922
- }
1923
- } finally {
1924
- this.ppNestLevel_--;
1939
+ };
1925
1940
  }
1926
- };
1927
1941
 
1928
- jasmine.PrettyPrinter.prototype.iterateObject = function(obj, fn) {
1929
- for (var property in obj) {
1930
- if (!obj.hasOwnProperty(property)) continue;
1931
- if (property == '__Jasmine_been_here_before__') continue;
1932
- fn(property, obj.__lookupGetter__ ? (obj.__lookupGetter__(property) !== jasmine.undefined &&
1933
- obj.__lookupGetter__(property) !== null) : false);
1934
- }
1942
+ return toBeFalsy;
1935
1943
  };
1936
1944
 
1937
- jasmine.PrettyPrinter.prototype.emitArray = jasmine.unimplementedMethod_;
1938
- jasmine.PrettyPrinter.prototype.emitObject = jasmine.unimplementedMethod_;
1939
- jasmine.PrettyPrinter.prototype.emitScalar = jasmine.unimplementedMethod_;
1940
- jasmine.PrettyPrinter.prototype.emitString = jasmine.unimplementedMethod_;
1945
+ getJasmineRequireObj().toBeGreaterThan = function() {
1941
1946
 
1942
- jasmine.StringPrettyPrinter = function() {
1943
- jasmine.PrettyPrinter.call(this);
1947
+ function toBeGreaterThan() {
1948
+ return {
1949
+ compare: function(actual, expected) {
1950
+ return {
1951
+ pass: actual > expected
1952
+ };
1953
+ }
1954
+ };
1955
+ }
1944
1956
 
1945
- this.string = '';
1957
+ return toBeGreaterThan;
1946
1958
  };
1947
- jasmine.util.inherit(jasmine.StringPrettyPrinter, jasmine.PrettyPrinter);
1948
1959
 
1949
- jasmine.StringPrettyPrinter.prototype.emitScalar = function(value) {
1950
- this.append(value);
1951
- };
1952
1960
 
1953
- jasmine.StringPrettyPrinter.prototype.emitString = function(value) {
1954
- this.append("'" + value + "'");
1955
- };
1961
+ getJasmineRequireObj().toBeLessThan = function() {
1962
+ function toBeLessThan() {
1963
+ return {
1956
1964
 
1957
- jasmine.StringPrettyPrinter.prototype.emitArray = function(array) {
1958
- if (this.ppNestLevel_ > jasmine.MAX_PRETTY_PRINT_DEPTH) {
1959
- this.append("Array");
1960
- return;
1965
+ compare: function(actual, expected) {
1966
+ return {
1967
+ pass: actual < expected
1968
+ };
1969
+ }
1970
+ };
1961
1971
  }
1962
1972
 
1963
- this.append('[ ');
1964
- for (var i = 0; i < array.length; i++) {
1965
- if (i > 0) {
1966
- this.append(', ');
1967
- }
1968
- this.format(array[i]);
1969
- }
1970
- this.append(' ]');
1973
+ return toBeLessThan;
1971
1974
  };
1975
+ getJasmineRequireObj().toBeNaN = function(j$) {
1972
1976
 
1973
- jasmine.StringPrettyPrinter.prototype.emitObject = function(obj) {
1974
- if (this.ppNestLevel_ > jasmine.MAX_PRETTY_PRINT_DEPTH) {
1975
- this.append("Object");
1976
- return;
1977
- }
1978
-
1979
- var self = this;
1980
- this.append('{ ');
1981
- var first = true;
1977
+ function toBeNaN() {
1978
+ return {
1979
+ compare: function(actual) {
1980
+ var result = {
1981
+ pass: (actual !== actual)
1982
+ };
1982
1983
 
1983
- this.iterateObject(obj, function(property, isGetter) {
1984
- if (first) {
1985
- first = false;
1986
- } else {
1987
- self.append(', ');
1988
- }
1984
+ if (result.pass) {
1985
+ result.message = "Expected actual not to be NaN.";
1986
+ } else {
1987
+ result.message = "Expected " + j$.pp(actual) + " to be NaN.";
1988
+ }
1989
1989
 
1990
- self.append(property);
1991
- self.append(' : ');
1992
- if (isGetter) {
1993
- self.append('<getter>');
1994
- } else {
1995
- self.format(obj[property]);
1996
- }
1997
- });
1990
+ return result;
1991
+ }
1992
+ };
1993
+ }
1998
1994
 
1999
- this.append(' }');
1995
+ return toBeNaN;
2000
1996
  };
2001
1997
 
2002
- jasmine.StringPrettyPrinter.prototype.append = function(value) {
2003
- this.string += value;
2004
- };
2005
- jasmine.Queue = function(env) {
2006
- this.env = env;
2007
-
2008
- // parallel to blocks. each true value in this array means the block will
2009
- // get executed even if we abort
2010
- this.ensured = [];
2011
- this.blocks = [];
2012
- this.running = false;
2013
- this.index = 0;
2014
- this.offset = 0;
2015
- this.abort = false;
2016
- };
1998
+ getJasmineRequireObj().toBeNull = function() {
2017
1999
 
2018
- jasmine.Queue.prototype.addBefore = function(block, ensure) {
2019
- if (ensure === jasmine.undefined) {
2020
- ensure = false;
2000
+ function toBeNull() {
2001
+ return {
2002
+ compare: function(actual) {
2003
+ return {
2004
+ pass: actual === null
2005
+ };
2006
+ }
2007
+ };
2021
2008
  }
2022
2009
 
2023
- this.blocks.unshift(block);
2024
- this.ensured.unshift(ensure);
2010
+ return toBeNull;
2025
2011
  };
2026
2012
 
2027
- jasmine.Queue.prototype.add = function(block, ensure) {
2028
- if (ensure === jasmine.undefined) {
2029
- ensure = false;
2030
- }
2031
-
2032
- this.blocks.push(block);
2033
- this.ensured.push(ensure);
2034
- };
2013
+ getJasmineRequireObj().toBeTruthy = function() {
2035
2014
 
2036
- jasmine.Queue.prototype.insertNext = function(block, ensure) {
2037
- if (ensure === jasmine.undefined) {
2038
- ensure = false;
2015
+ function toBeTruthy() {
2016
+ return {
2017
+ compare: function(actual) {
2018
+ return {
2019
+ pass: !!actual
2020
+ };
2021
+ }
2022
+ };
2039
2023
  }
2040
2024
 
2041
- this.ensured.splice((this.index + this.offset + 1), 0, ensure);
2042
- this.blocks.splice((this.index + this.offset + 1), 0, block);
2043
- this.offset++;
2044
- };
2045
-
2046
- jasmine.Queue.prototype.start = function(onComplete) {
2047
- this.running = true;
2048
- this.onComplete = onComplete;
2049
- this.next_();
2050
- };
2051
-
2052
- jasmine.Queue.prototype.isRunning = function() {
2053
- return this.running;
2025
+ return toBeTruthy;
2054
2026
  };
2055
2027
 
2056
- jasmine.Queue.LOOP_DONT_RECURSE = true;
2057
-
2058
- jasmine.Queue.prototype.next_ = function() {
2059
- var self = this;
2060
- var goAgain = true;
2061
-
2062
- while (goAgain) {
2063
- goAgain = false;
2064
-
2065
- if (self.index < self.blocks.length && !(this.abort && !this.ensured[self.index])) {
2066
- var calledSynchronously = true;
2067
- var completedSynchronously = false;
2068
-
2069
- var onComplete = function () {
2070
- if (jasmine.Queue.LOOP_DONT_RECURSE && calledSynchronously) {
2071
- completedSynchronously = true;
2072
- return;
2073
- }
2074
-
2075
- if (self.blocks[self.index].abort) {
2076
- self.abort = true;
2077
- }
2078
-
2079
- self.offset = 0;
2080
- self.index++;
2081
-
2082
- var now = new Date().getTime();
2083
- if (self.env.updateInterval && now - self.env.lastUpdate > self.env.updateInterval) {
2084
- self.env.lastUpdate = now;
2085
- self.env.setTimeout(function() {
2086
- self.next_();
2087
- }, 0);
2088
- } else {
2089
- if (jasmine.Queue.LOOP_DONT_RECURSE && completedSynchronously) {
2090
- goAgain = true;
2091
- } else {
2092
- self.next_();
2093
- }
2094
- }
2095
- };
2096
- self.blocks[self.index].execute(onComplete);
2028
+ getJasmineRequireObj().toBeUndefined = function() {
2097
2029
 
2098
- calledSynchronously = false;
2099
- if (completedSynchronously) {
2100
- onComplete();
2101
- }
2102
-
2103
- } else {
2104
- self.running = false;
2105
- if (self.onComplete) {
2106
- self.onComplete();
2030
+ function toBeUndefined() {
2031
+ return {
2032
+ compare: function(actual) {
2033
+ return {
2034
+ pass: void 0 === actual
2035
+ };
2107
2036
  }
2108
- }
2037
+ };
2109
2038
  }
2110
- };
2111
2039
 
2112
- jasmine.Queue.prototype.results = function() {
2113
- var results = new jasmine.NestedResults();
2114
- for (var i = 0; i < this.blocks.length; i++) {
2115
- if (this.blocks[i].results) {
2116
- results.addResult(this.blocks[i].results());
2117
- }
2118
- }
2119
- return results;
2040
+ return toBeUndefined;
2120
2041
  };
2121
2042
 
2043
+ getJasmineRequireObj().toContain = function() {
2044
+ function toContain(util, customEqualityTesters) {
2045
+ customEqualityTesters = customEqualityTesters || [];
2122
2046
 
2123
- /**
2124
- * Runner
2125
- *
2126
- * @constructor
2127
- * @param {jasmine.Env} env
2128
- */
2129
- jasmine.Runner = function(env) {
2130
- var self = this;
2131
- self.env = env;
2132
- self.queue = new jasmine.Queue(env);
2133
- self.before_ = [];
2134
- self.after_ = [];
2135
- self.suites_ = [];
2136
- };
2047
+ return {
2048
+ compare: function(actual, expected) {
2137
2049
 
2138
- jasmine.Runner.prototype.execute = function() {
2139
- var self = this;
2140
- if (self.env.reporter.reportRunnerStarting) {
2141
- self.env.reporter.reportRunnerStarting(this);
2050
+ return {
2051
+ pass: util.contains(actual, expected, customEqualityTesters)
2052
+ };
2053
+ }
2054
+ };
2142
2055
  }
2143
- self.queue.start(function () {
2144
- self.finishCallback();
2145
- });
2146
- };
2147
2056
 
2148
- jasmine.Runner.prototype.beforeEach = function(beforeEachFunction) {
2149
- beforeEachFunction.typeName = 'beforeEach';
2150
- this.before_.splice(0,0,beforeEachFunction);
2151
- };
2152
-
2153
- jasmine.Runner.prototype.afterEach = function(afterEachFunction) {
2154
- afterEachFunction.typeName = 'afterEach';
2155
- this.after_.splice(0,0,afterEachFunction);
2057
+ return toContain;
2156
2058
  };
2157
2059
 
2060
+ getJasmineRequireObj().toEqual = function() {
2158
2061
 
2159
- jasmine.Runner.prototype.finishCallback = function() {
2160
- this.env.reporter.reportRunnerResults(this);
2161
- };
2062
+ function toEqual(util, customEqualityTesters) {
2063
+ customEqualityTesters = customEqualityTesters || [];
2162
2064
 
2163
- jasmine.Runner.prototype.addSuite = function(suite) {
2164
- this.suites_.push(suite);
2165
- };
2065
+ return {
2066
+ compare: function(actual, expected) {
2067
+ var result = {
2068
+ pass: false
2069
+ };
2166
2070
 
2167
- jasmine.Runner.prototype.add = function(block) {
2168
- if (block instanceof jasmine.Suite) {
2169
- this.addSuite(block);
2170
- }
2171
- this.queue.add(block);
2172
- };
2071
+ result.pass = util.equals(actual, expected, customEqualityTesters);
2173
2072
 
2174
- jasmine.Runner.prototype.specs = function () {
2175
- var suites = this.suites();
2176
- var specs = [];
2177
- for (var i = 0; i < suites.length; i++) {
2178
- specs = specs.concat(suites[i].specs());
2073
+ return result;
2074
+ }
2075
+ };
2179
2076
  }
2180
- return specs;
2181
- };
2182
-
2183
- jasmine.Runner.prototype.suites = function() {
2184
- return this.suites_;
2185
- };
2186
2077
 
2187
- jasmine.Runner.prototype.topLevelSuites = function() {
2188
- var topLevelSuites = [];
2189
- for (var i = 0; i < this.suites_.length; i++) {
2190
- if (!this.suites_[i].parentSuite) {
2191
- topLevelSuites.push(this.suites_[i]);
2192
- }
2193
- }
2194
- return topLevelSuites;
2078
+ return toEqual;
2195
2079
  };
2196
2080
 
2197
- jasmine.Runner.prototype.results = function() {
2198
- return this.queue.results();
2199
- };
2200
- /**
2201
- * Internal representation of a Jasmine specification, or test.
2202
- *
2203
- * @constructor
2204
- * @param {jasmine.Env} env
2205
- * @param {jasmine.Suite} suite
2206
- * @param {String} description
2207
- */
2208
- jasmine.Spec = function(env, suite, description) {
2209
- if (!env) {
2210
- throw new Error('jasmine.Env() required');
2211
- }
2212
- if (!suite) {
2213
- throw new Error('jasmine.Suite() required');
2214
- }
2215
- var spec = this;
2216
- spec.id = env.nextSpecId ? env.nextSpecId() : null;
2217
- spec.env = env;
2218
- spec.suite = suite;
2219
- spec.description = description;
2220
- spec.queue = new jasmine.Queue(env);
2221
-
2222
- spec.afterCallbacks = [];
2223
- spec.spies_ = [];
2224
-
2225
- spec.results_ = new jasmine.NestedResults();
2226
- spec.results_.description = description;
2227
- spec.matchersClass = null;
2228
- };
2081
+ getJasmineRequireObj().toHaveBeenCalled = function(j$) {
2229
2082
 
2230
- jasmine.Spec.prototype.getFullName = function() {
2231
- return this.suite.getFullName() + ' ' + this.description + '.';
2232
- };
2083
+ function toHaveBeenCalled() {
2084
+ return {
2085
+ compare: function(actual) {
2086
+ var result = {};
2233
2087
 
2088
+ if (!j$.isSpy(actual)) {
2089
+ throw new Error('Expected a spy, but got ' + j$.pp(actual) + '.');
2090
+ }
2234
2091
 
2235
- jasmine.Spec.prototype.results = function() {
2236
- return this.results_;
2237
- };
2092
+ if (arguments.length > 1) {
2093
+ throw new Error('toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith');
2094
+ }
2238
2095
 
2239
- /**
2240
- * All parameters are pretty-printed and concatenated together, then written to the spec's output.
2241
- *
2242
- * Be careful not to leave calls to <code>jasmine.log</code> in production code.
2243
- */
2244
- jasmine.Spec.prototype.log = function() {
2245
- return this.results_.log(arguments);
2246
- };
2096
+ result.pass = actual.calls.any();
2247
2097
 
2248
- jasmine.Spec.prototype.runs = function (func) {
2249
- var block = new jasmine.Block(this.env, func, this);
2250
- this.addToQueue(block);
2251
- return this;
2252
- };
2098
+ result.message = result.pass ?
2099
+ "Expected spy " + actual.and.identity() + " not to have been called." :
2100
+ "Expected spy " + actual.and.identity() + " to have been called.";
2253
2101
 
2254
- jasmine.Spec.prototype.addToQueue = function (block) {
2255
- if (this.queue.isRunning()) {
2256
- this.queue.insertNext(block);
2257
- } else {
2258
- this.queue.add(block);
2102
+ return result;
2103
+ }
2104
+ };
2259
2105
  }
2260
- };
2261
2106
 
2262
- /**
2263
- * @param {jasmine.ExpectationResult} result
2264
- */
2265
- jasmine.Spec.prototype.addMatcherResult = function(result) {
2266
- this.results_.addResult(result);
2107
+ return toHaveBeenCalled;
2267
2108
  };
2268
2109
 
2269
- jasmine.Spec.prototype.expect = function(actual) {
2270
- var positive = new (this.getMatchersClass_())(this.env, actual, this);
2271
- positive.not = new (this.getMatchersClass_())(this.env, actual, this, true);
2272
- return positive;
2273
- };
2110
+ getJasmineRequireObj().toHaveBeenCalledWith = function(j$) {
2274
2111
 
2275
- /**
2276
- * Waits a fixed time period before moving to the next block.
2277
- *
2278
- * @deprecated Use waitsFor() instead
2279
- * @param {Number} timeout milliseconds to wait
2280
- */
2281
- jasmine.Spec.prototype.waits = function(timeout) {
2282
- var waitsFunc = new jasmine.WaitsBlock(this.env, timeout, this);
2283
- this.addToQueue(waitsFunc);
2284
- return this;
2285
- };
2112
+ function toHaveBeenCalledWith(util) {
2113
+ return {
2114
+ compare: function() {
2115
+ var args = Array.prototype.slice.call(arguments, 0),
2116
+ actual = args[0],
2117
+ expectedArgs = args.slice(1);
2286
2118
 
2287
- /**
2288
- * Waits for the latchFunction to return true before proceeding to the next block.
2289
- *
2290
- * @param {Function} latchFunction
2291
- * @param {String} optional_timeoutMessage
2292
- * @param {Number} optional_timeout
2293
- */
2294
- jasmine.Spec.prototype.waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) {
2295
- var latchFunction_ = null;
2296
- var optional_timeoutMessage_ = null;
2297
- var optional_timeout_ = null;
2298
-
2299
- for (var i = 0; i < arguments.length; i++) {
2300
- var arg = arguments[i];
2301
- switch (typeof arg) {
2302
- case 'function':
2303
- latchFunction_ = arg;
2304
- break;
2305
- case 'string':
2306
- optional_timeoutMessage_ = arg;
2307
- break;
2308
- case 'number':
2309
- optional_timeout_ = arg;
2310
- break;
2311
- }
2119
+ if (!j$.isSpy(actual)) {
2120
+ throw new Error('Expected a spy, but got ' + j$.pp(actual) + '.');
2121
+ }
2122
+
2123
+ return {
2124
+ pass: util.contains(actual.calls.allArgs(), expectedArgs)
2125
+ };
2126
+ },
2127
+ message: function(actual) {
2128
+ return {
2129
+ affirmative: "Expected spy " + actual.and.identity() + " to have been called.",
2130
+ negative: "Expected spy " + actual.and.identity() + " not to have been called."
2131
+ };
2132
+ }
2133
+ };
2312
2134
  }
2313
2135
 
2314
- var waitsForFunc = new jasmine.WaitsForBlock(this.env, optional_timeout_, latchFunction_, optional_timeoutMessage_, this);
2315
- this.addToQueue(waitsForFunc);
2316
- return this;
2136
+ return toHaveBeenCalledWith;
2317
2137
  };
2318
2138
 
2319
- jasmine.Spec.prototype.fail = function (e) {
2320
- var expectationResult = new jasmine.ExpectationResult({
2321
- passed: false,
2322
- message: e ? jasmine.util.formatException(e) : 'Exception',
2323
- trace: { stack: e.stack }
2324
- });
2325
- this.results_.addResult(expectationResult);
2326
- };
2139
+ getJasmineRequireObj().toMatch = function() {
2327
2140
 
2328
- jasmine.Spec.prototype.getMatchersClass_ = function() {
2329
- return this.matchersClass || this.env.matchersClass;
2330
- };
2141
+ function toMatch() {
2142
+ return {
2143
+ compare: function(actual, expected) {
2144
+ var regexp = new RegExp(expected);
2331
2145
 
2332
- jasmine.Spec.prototype.addMatchers = function(matchersPrototype) {
2333
- var parent = this.getMatchersClass_();
2334
- var newMatchersClass = function() {
2335
- parent.apply(this, arguments);
2336
- };
2337
- jasmine.util.inherit(newMatchersClass, parent);
2338
- jasmine.Matchers.wrapInto_(matchersPrototype, newMatchersClass);
2339
- this.matchersClass = newMatchersClass;
2340
- };
2146
+ return {
2147
+ pass: regexp.test(actual)
2148
+ };
2149
+ }
2150
+ };
2151
+ }
2341
2152
 
2342
- jasmine.Spec.prototype.finishCallback = function() {
2343
- this.env.reporter.reportSpecResults(this);
2153
+ return toMatch;
2344
2154
  };
2345
2155
 
2346
- jasmine.Spec.prototype.finish = function(onComplete) {
2347
- this.removeAllSpies();
2348
- this.finishCallback();
2349
- if (onComplete) {
2350
- onComplete();
2351
- }
2352
- };
2156
+ getJasmineRequireObj().toThrow = function(j$) {
2353
2157
 
2354
- jasmine.Spec.prototype.after = function(doAfter) {
2355
- if (this.queue.isRunning()) {
2356
- this.queue.add(new jasmine.Block(this.env, doAfter, this), true);
2357
- } else {
2358
- this.afterCallbacks.unshift(doAfter);
2359
- }
2360
- };
2158
+ function toThrow(util) {
2159
+ return {
2160
+ compare: function(actual, expected) {
2161
+ var result = { pass: false },
2162
+ threw = false,
2163
+ thrown;
2361
2164
 
2362
- jasmine.Spec.prototype.execute = function(onComplete) {
2363
- var spec = this;
2364
- if (!spec.env.specFilter(spec)) {
2365
- spec.results_.skipped = true;
2366
- spec.finish(onComplete);
2367
- return;
2368
- }
2165
+ if (typeof actual != "function") {
2166
+ throw new Error("Actual is not a Function");
2167
+ }
2369
2168
 
2370
- this.env.reporter.reportSpecStarting(this);
2169
+ try {
2170
+ actual();
2171
+ } catch (e) {
2172
+ threw = true;
2173
+ thrown = e;
2174
+ }
2371
2175
 
2372
- spec.env.currentSpec = spec;
2176
+ if (!threw) {
2177
+ result.message = "Expected function to throw an exception.";
2178
+ return result;
2179
+ }
2373
2180
 
2374
- spec.addBeforesAndAftersToQueue();
2181
+ if (arguments.length == 1) {
2182
+ result.pass = true;
2183
+ result.message = "Expected function not to throw, but it threw " + j$.pp(thrown) + ".";
2375
2184
 
2376
- spec.queue.start(function () {
2377
- spec.finish(onComplete);
2378
- });
2379
- };
2185
+ return result;
2186
+ }
2380
2187
 
2381
- jasmine.Spec.prototype.addBeforesAndAftersToQueue = function() {
2382
- var runner = this.env.currentRunner();
2383
- var i;
2188
+ if (util.equals(thrown, expected)) {
2189
+ result.pass = true;
2190
+ result.message = "Expected function not to throw " + j$.pp(expected) + ".";
2191
+ } else {
2192
+ result.message = "Expected function to throw " + j$.pp(expected) + ", but it threw " + j$.pp(thrown) + ".";
2193
+ }
2384
2194
 
2385
- for (var suite = this.suite; suite; suite = suite.parentSuite) {
2386
- for (i = 0; i < suite.before_.length; i++) {
2387
- this.queue.addBefore(new jasmine.Block(this.env, suite.before_[i], this));
2388
- }
2389
- }
2390
- for (i = 0; i < runner.before_.length; i++) {
2391
- this.queue.addBefore(new jasmine.Block(this.env, runner.before_[i], this));
2392
- }
2393
- for (i = 0; i < this.afterCallbacks.length; i++) {
2394
- this.queue.add(new jasmine.Block(this.env, this.afterCallbacks[i], this), true);
2395
- }
2396
- for (suite = this.suite; suite; suite = suite.parentSuite) {
2397
- for (i = 0; i < suite.after_.length; i++) {
2398
- this.queue.add(new jasmine.Block(this.env, suite.after_[i], this), true);
2399
- }
2400
- }
2401
- for (i = 0; i < runner.after_.length; i++) {
2402
- this.queue.add(new jasmine.Block(this.env, runner.after_[i], this), true);
2195
+ return result;
2196
+ }
2197
+ };
2403
2198
  }
2404
- };
2405
2199
 
2406
- jasmine.Spec.prototype.explodes = function() {
2407
- throw 'explodes function should not have been called';
2200
+ return toThrow;
2408
2201
  };
2409
2202
 
2410
- jasmine.Spec.prototype.spyOn = function(obj, methodName, ignoreMethodDoesntExist) {
2411
- if (obj == jasmine.undefined) {
2412
- throw "spyOn could not find an object to spy upon for " + methodName + "()";
2413
- }
2414
-
2415
- if (!ignoreMethodDoesntExist && obj[methodName] === jasmine.undefined) {
2416
- throw methodName + '() method does not exist';
2417
- }
2203
+ getJasmineRequireObj().toThrowError = function(j$) {
2204
+ function toThrowError (util) {
2205
+ return {
2206
+ compare: function(actual) {
2207
+ var threw = false,
2208
+ thrown,
2209
+ errorType,
2210
+ message,
2211
+ regexp,
2212
+ name,
2213
+ constructorName;
2418
2214
 
2419
- if (!ignoreMethodDoesntExist && obj[methodName] && obj[methodName].isSpy) {
2420
- throw new Error(methodName + ' has already been spied upon');
2421
- }
2215
+ if (typeof actual != "function") {
2216
+ throw new Error("Actual is not a Function");
2217
+ }
2422
2218
 
2423
- var spyObj = jasmine.createSpy(methodName);
2219
+ extractExpectedParams.apply(null, arguments);
2424
2220
 
2425
- this.spies_.push(spyObj);
2426
- spyObj.baseObj = obj;
2427
- spyObj.methodName = methodName;
2428
- spyObj.originalValue = obj[methodName];
2221
+ try {
2222
+ actual();
2223
+ } catch (e) {
2224
+ threw = true;
2225
+ thrown = e;
2226
+ }
2429
2227
 
2430
- obj[methodName] = spyObj;
2228
+ if (!threw) {
2229
+ return fail("Expected function to throw an Error.");
2230
+ }
2431
2231
 
2432
- return spyObj;
2433
- };
2232
+ if (!(thrown instanceof Error)) {
2233
+ return fail("Expected function to throw an Error, but it threw " + thrown + ".");
2234
+ }
2434
2235
 
2435
- jasmine.Spec.prototype.removeAllSpies = function() {
2436
- for (var i = 0; i < this.spies_.length; i++) {
2437
- var spy = this.spies_[i];
2438
- spy.baseObj[spy.methodName] = spy.originalValue;
2439
- }
2440
- this.spies_ = [];
2441
- };
2236
+ if (arguments.length == 1) {
2237
+ return pass("Expected function not to throw an Error, but it threw " + fnNameFor(thrown) + ".");
2238
+ }
2442
2239
 
2443
- /**
2444
- * Internal representation of a Jasmine suite.
2445
- *
2446
- * @constructor
2447
- * @param {jasmine.Env} env
2448
- * @param {String} description
2449
- * @param {Function} specDefinitions
2450
- * @param {jasmine.Suite} parentSuite
2451
- */
2452
- jasmine.Suite = function(env, description, specDefinitions, parentSuite) {
2453
- var self = this;
2454
- self.id = env.nextSuiteId ? env.nextSuiteId() : null;
2455
- self.description = description;
2456
- self.queue = new jasmine.Queue(env);
2457
- self.parentSuite = parentSuite;
2458
- self.env = env;
2459
- self.before_ = [];
2460
- self.after_ = [];
2461
- self.children_ = [];
2462
- self.suites_ = [];
2463
- self.specs_ = [];
2464
- };
2240
+ if (errorType) {
2241
+ name = fnNameFor(errorType);
2242
+ constructorName = fnNameFor(thrown.constructor);
2243
+ }
2465
2244
 
2466
- jasmine.Suite.prototype.getFullName = function() {
2467
- var fullName = this.description;
2468
- for (var parentSuite = this.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) {
2469
- fullName = parentSuite.description + ' ' + fullName;
2470
- }
2471
- return fullName;
2472
- };
2245
+ if (errorType && message) {
2246
+ if (thrown.constructor == errorType && util.equals(thrown.message, message)) {
2247
+ return pass("Expected function not to throw " + name + " with message \"" + message + "\".");
2248
+ } else {
2249
+ return fail("Expected function to throw " + name + " with message \"" + message +
2250
+ "\", but it threw " + constructorName + " with message \"" + thrown.message + "\".");
2251
+ }
2252
+ }
2473
2253
 
2474
- jasmine.Suite.prototype.finish = function(onComplete) {
2475
- this.env.reporter.reportSuiteResults(this);
2476
- this.finished = true;
2477
- if (typeof(onComplete) == 'function') {
2478
- onComplete();
2479
- }
2480
- };
2254
+ if (errorType && regexp) {
2255
+ if (thrown.constructor == errorType && regexp.test(thrown.message)) {
2256
+ return pass("Expected function not to throw " + name + " with message matching " + regexp + ".");
2257
+ } else {
2258
+ return fail("Expected function to throw " + name + " with message matching " + regexp +
2259
+ ", but it threw " + constructorName + " with message \"" + thrown.message + "\".");
2260
+ }
2261
+ }
2481
2262
 
2482
- jasmine.Suite.prototype.beforeEach = function(beforeEachFunction) {
2483
- beforeEachFunction.typeName = 'beforeEach';
2484
- this.before_.unshift(beforeEachFunction);
2485
- };
2263
+ if (errorType) {
2264
+ if (thrown.constructor == errorType) {
2265
+ return pass("Expected function not to throw " + name + ".");
2266
+ } else {
2267
+ return fail("Expected function to throw " + name + ", but it threw " + constructorName + ".");
2268
+ }
2269
+ }
2486
2270
 
2487
- jasmine.Suite.prototype.afterEach = function(afterEachFunction) {
2488
- afterEachFunction.typeName = 'afterEach';
2489
- this.after_.unshift(afterEachFunction);
2490
- };
2271
+ if (message) {
2272
+ if (thrown.message == message) {
2273
+ return pass("Expected function not to throw an exception with message " + j$.pp(message) + ".");
2274
+ } else {
2275
+ return fail("Expected function to throw an exception with message " + j$.pp(message) +
2276
+ ", but it threw an exception with message " + j$.pp(thrown.message) + ".");
2277
+ }
2278
+ }
2491
2279
 
2492
- jasmine.Suite.prototype.results = function() {
2493
- return this.queue.results();
2494
- };
2280
+ if (regexp) {
2281
+ if (regexp.test(thrown.message)) {
2282
+ return pass("Expected function not to throw an exception with a message matching " + j$.pp(regexp) + ".");
2283
+ } else {
2284
+ return fail("Expected function to throw an exception with a message matching " + j$.pp(regexp) +
2285
+ ", but it threw an exception with message " + j$.pp(thrown.message) + ".");
2286
+ }
2287
+ }
2495
2288
 
2496
- jasmine.Suite.prototype.add = function(suiteOrSpec) {
2497
- this.children_.push(suiteOrSpec);
2498
- if (suiteOrSpec instanceof jasmine.Suite) {
2499
- this.suites_.push(suiteOrSpec);
2500
- this.env.currentRunner().addSuite(suiteOrSpec);
2501
- } else {
2502
- this.specs_.push(suiteOrSpec);
2503
- }
2504
- this.queue.add(suiteOrSpec);
2505
- };
2289
+ function fnNameFor(func) {
2290
+ return func.name || func.toString().match(/^\s*function\s*(\w*)\s*\(/)[1];
2291
+ }
2506
2292
 
2507
- jasmine.Suite.prototype.specs = function() {
2508
- return this.specs_;
2509
- };
2293
+ function pass(notMessage) {
2294
+ return {
2295
+ pass: true,
2296
+ message: notMessage
2297
+ };
2298
+ }
2510
2299
 
2511
- jasmine.Suite.prototype.suites = function() {
2512
- return this.suites_;
2513
- };
2300
+ function fail(message) {
2301
+ return {
2302
+ pass: false,
2303
+ message: message
2304
+ };
2305
+ }
2514
2306
 
2515
- jasmine.Suite.prototype.children = function() {
2516
- return this.children_;
2517
- };
2307
+ function extractExpectedParams() {
2308
+ if (arguments.length == 1) {
2309
+ return;
2310
+ }
2518
2311
 
2519
- jasmine.Suite.prototype.execute = function(onComplete) {
2520
- var self = this;
2521
- this.queue.start(function () {
2522
- self.finish(onComplete);
2523
- });
2524
- };
2525
- jasmine.WaitsBlock = function(env, timeout, spec) {
2526
- this.timeout = timeout;
2527
- jasmine.Block.call(this, env, null, spec);
2528
- };
2312
+ if (arguments.length == 2) {
2313
+ var expected = arguments[1];
2529
2314
 
2530
- jasmine.util.inherit(jasmine.WaitsBlock, jasmine.Block);
2315
+ if (expected instanceof RegExp) {
2316
+ regexp = expected;
2317
+ } else if (typeof expected == "string") {
2318
+ message = expected;
2319
+ } else if (checkForAnErrorType(expected)) {
2320
+ errorType = expected;
2321
+ }
2531
2322
 
2532
- jasmine.WaitsBlock.prototype.execute = function (onComplete) {
2533
- if (jasmine.VERBOSE) {
2534
- this.env.reporter.log('>> Jasmine waiting for ' + this.timeout + ' ms...');
2535
- }
2536
- this.env.setTimeout(function () {
2537
- onComplete();
2538
- }, this.timeout);
2539
- };
2540
- /**
2541
- * A block which waits for some condition to become true, with timeout.
2542
- *
2543
- * @constructor
2544
- * @extends jasmine.Block
2545
- * @param {jasmine.Env} env The Jasmine environment.
2546
- * @param {Number} timeout The maximum time in milliseconds to wait for the condition to become true.
2547
- * @param {Function} latchFunction A function which returns true when the desired condition has been met.
2548
- * @param {String} message The message to display if the desired condition hasn't been met within the given time period.
2549
- * @param {jasmine.Spec} spec The Jasmine spec.
2550
- */
2551
- jasmine.WaitsForBlock = function(env, timeout, latchFunction, message, spec) {
2552
- this.timeout = timeout || env.defaultTimeoutInterval;
2553
- this.latchFunction = latchFunction;
2554
- this.message = message;
2555
- this.totalTimeSpentWaitingForLatch = 0;
2556
- jasmine.Block.call(this, env, null, spec);
2557
- };
2558
- jasmine.util.inherit(jasmine.WaitsForBlock, jasmine.Block);
2323
+ if (!(errorType || message || regexp)) {
2324
+ throw new Error("Expected is not an Error, string, or RegExp.");
2325
+ }
2326
+ } else {
2327
+ if (checkForAnErrorType(arguments[1])) {
2328
+ errorType = arguments[1];
2329
+ } else {
2330
+ throw new Error("Expected error type is not an Error.");
2331
+ }
2332
+
2333
+ if (arguments[2] instanceof RegExp) {
2334
+ regexp = arguments[2];
2335
+ } else if (typeof arguments[2] == "string") {
2336
+ message = arguments[2];
2337
+ } else {
2338
+ throw new Error("Expected error message is not a string or RegExp.");
2339
+ }
2340
+ }
2341
+ }
2559
2342
 
2560
- jasmine.WaitsForBlock.TIMEOUT_INCREMENT = 10;
2343
+ function checkForAnErrorType(type) {
2344
+ if (typeof type !== "function") {
2345
+ return false;
2346
+ }
2561
2347
 
2562
- jasmine.WaitsForBlock.prototype.execute = function(onComplete) {
2563
- if (jasmine.VERBOSE) {
2564
- this.env.reporter.log('>> Jasmine waiting for ' + (this.message || 'something to happen'));
2565
- }
2566
- var latchFunctionResult;
2567
- try {
2568
- latchFunctionResult = this.latchFunction.apply(this.spec);
2569
- } catch (e) {
2570
- this.spec.fail(e);
2571
- onComplete();
2572
- return;
2348
+ var Surrogate = function() {};
2349
+ Surrogate.prototype = type.prototype;
2350
+ return (new Surrogate()) instanceof Error;
2351
+ }
2352
+ }
2353
+ };
2573
2354
  }
2574
2355
 
2575
- if (latchFunctionResult) {
2576
- onComplete();
2577
- } else if (this.totalTimeSpentWaitingForLatch >= this.timeout) {
2578
- var message = 'timed out after ' + this.timeout + ' msec waiting for ' + (this.message || 'something to happen');
2579
- this.spec.fail({
2580
- name: 'timeout',
2581
- message: message
2582
- });
2583
-
2584
- this.abort = true;
2585
- onComplete();
2586
- } else {
2587
- this.totalTimeSpentWaitingForLatch += jasmine.WaitsForBlock.TIMEOUT_INCREMENT;
2588
- var self = this;
2589
- this.env.setTimeout(function() {
2590
- self.execute(onComplete);
2591
- }, jasmine.WaitsForBlock.TIMEOUT_INCREMENT);
2592
- }
2356
+ return toThrowError;
2593
2357
  };
2594
2358
 
2595
- jasmine.version_= {
2596
- "major": 1,
2597
- "minor": 3,
2598
- "build": 1,
2599
- "revision": 1354556913
2600
- };
2359
+ getJasmineRequireObj().version = function() {
2360
+ return "2.0.0-rc2";
2361
+ };