jasmine-core 2.5.0 → 2.99.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/console/console.js +1 -1
- data/lib/jasmine-core/boot/boot.js +4 -1
- data/lib/jasmine-core/boot.js +5 -2
- data/lib/jasmine-core/jasmine-html.js +95 -31
- data/lib/jasmine-core/jasmine.css +1 -0
- data/lib/jasmine-core/jasmine.js +3635 -1684
- data/lib/jasmine-core/node_boot.js +1 -1
- data/lib/jasmine-core/spec/core/CallTrackerSpec.js +10 -0
- data/lib/jasmine-core/spec/core/ClearStackSpec.js +137 -0
- data/lib/jasmine-core/spec/core/ClockSpec.js +94 -14
- data/lib/jasmine-core/spec/core/DelayedFunctionSchedulerSpec.js +26 -8
- data/lib/jasmine-core/spec/core/EnvSpec.js +142 -10
- data/lib/jasmine-core/spec/core/ExpectationSpec.js +52 -7
- data/lib/jasmine-core/spec/core/GlobalErrorsSpec.js +110 -0
- data/lib/jasmine-core/spec/core/PrettyPrintSpec.js +132 -4
- data/lib/jasmine-core/spec/core/QueueRunnerSpec.js +333 -23
- data/lib/jasmine-core/spec/core/ReportDispatcherSpec.js +16 -1
- data/lib/jasmine-core/spec/core/SpecSpec.js +30 -8
- data/lib/jasmine-core/spec/core/SpyRegistrySpec.js +225 -1
- data/lib/jasmine-core/spec/core/SpySpec.js +44 -2
- data/lib/jasmine-core/spec/core/SpyStrategySpec.js +28 -5
- data/lib/jasmine-core/spec/core/SuiteSpec.js +14 -19
- data/lib/jasmine-core/spec/core/UserContextSpec.js +54 -0
- data/lib/jasmine-core/spec/core/UtilSpec.js +71 -0
- data/lib/jasmine-core/spec/core/asymmetric_equality/AnySpec.js +32 -0
- data/lib/jasmine-core/spec/core/asymmetric_equality/AnythingSpec.js +32 -0
- data/lib/jasmine-core/spec/core/asymmetric_equality/ArrayContainingSpec.js +13 -0
- data/lib/jasmine-core/spec/core/asymmetric_equality/ArrayWithExactContentsSpec.js +47 -0
- data/lib/jasmine-core/spec/core/asymmetric_equality/ObjectContainingSpec.js +13 -0
- data/lib/jasmine-core/spec/core/integration/CustomMatchersSpec.js +48 -0
- data/lib/jasmine-core/spec/core/integration/EnvSpec.js +339 -38
- data/lib/jasmine-core/spec/core/integration/SpecRunningSpec.js +156 -3
- data/lib/jasmine-core/spec/core/matchers/DiffBuilderSpec.js +47 -0
- data/lib/jasmine-core/spec/core/matchers/NullDiffBuilderSpec.js +13 -0
- data/lib/jasmine-core/spec/core/matchers/ObjectPathSpec.js +43 -0
- data/lib/jasmine-core/spec/core/matchers/matchersUtilSpec.js +231 -8
- data/lib/jasmine-core/spec/core/matchers/nothingSpec.js +8 -0
- data/lib/jasmine-core/spec/core/matchers/toBeCloseToSpec.js +42 -0
- data/lib/jasmine-core/spec/core/matchers/toBeNegativeInfinitySpec.js +31 -0
- data/lib/jasmine-core/spec/core/matchers/toBePositiveInfinitySpec.js +31 -0
- data/lib/jasmine-core/spec/core/matchers/toEqualSpec.js +780 -4
- data/lib/jasmine-core/spec/core/matchers/toHaveBeenCalledBeforeSpec.js +99 -0
- data/lib/jasmine-core/spec/core/matchers/toThrowErrorSpec.js +37 -0
- data/lib/jasmine-core/spec/helpers/BrowserFlags.js +4 -0
- data/lib/jasmine-core/spec/helpers/asyncAwait.js +27 -0
- data/lib/jasmine-core/spec/helpers/checkForMap.js +37 -0
- data/lib/jasmine-core/spec/helpers/checkForSet.js +41 -0
- data/lib/jasmine-core/spec/helpers/checkForSymbol.js +28 -0
- data/lib/jasmine-core/spec/helpers/checkForTypedArrays.js +20 -0
- data/lib/jasmine-core/spec/html/HtmlReporterSpec.js +105 -23
- data/lib/jasmine-core/spec/html/SpyRegistryHtmlSpec.js +34 -0
- data/lib/jasmine-core/spec/npmPackage/npmPackageSpec.js +1 -1
- data/lib/jasmine-core/version.rb +1 -1
- metadata +19 -4
@@ -0,0 +1,110 @@
|
|
1
|
+
describe("GlobalErrors", function() {
|
2
|
+
it("calls the added handler on error", function() {
|
3
|
+
var fakeGlobal = { onerror: null },
|
4
|
+
handler = jasmine.createSpy('errorHandler'),
|
5
|
+
errors = new jasmineUnderTest.GlobalErrors(fakeGlobal);
|
6
|
+
|
7
|
+
errors.install();
|
8
|
+
errors.pushListener(handler);
|
9
|
+
|
10
|
+
fakeGlobal.onerror('foo');
|
11
|
+
|
12
|
+
expect(handler).toHaveBeenCalledWith('foo');
|
13
|
+
});
|
14
|
+
|
15
|
+
it("only calls the most recent handler", function() {
|
16
|
+
var fakeGlobal = { onerror: null },
|
17
|
+
handler1 = jasmine.createSpy('errorHandler1'),
|
18
|
+
handler2 = jasmine.createSpy('errorHandler2'),
|
19
|
+
errors = new jasmineUnderTest.GlobalErrors(fakeGlobal);
|
20
|
+
|
21
|
+
errors.install();
|
22
|
+
errors.pushListener(handler1);
|
23
|
+
errors.pushListener(handler2);
|
24
|
+
|
25
|
+
fakeGlobal.onerror('foo');
|
26
|
+
|
27
|
+
expect(handler1).not.toHaveBeenCalled();
|
28
|
+
expect(handler2).toHaveBeenCalledWith('foo');
|
29
|
+
});
|
30
|
+
|
31
|
+
it("calls previous handlers when one is removed", function() {
|
32
|
+
var fakeGlobal = { onerror: null },
|
33
|
+
handler1 = jasmine.createSpy('errorHandler1'),
|
34
|
+
handler2 = jasmine.createSpy('errorHandler2'),
|
35
|
+
errors = new jasmineUnderTest.GlobalErrors(fakeGlobal);
|
36
|
+
|
37
|
+
errors.install();
|
38
|
+
errors.pushListener(handler1);
|
39
|
+
errors.pushListener(handler2);
|
40
|
+
|
41
|
+
errors.popListener();
|
42
|
+
|
43
|
+
fakeGlobal.onerror('foo');
|
44
|
+
|
45
|
+
expect(handler1).toHaveBeenCalledWith('foo');
|
46
|
+
expect(handler2).not.toHaveBeenCalled();
|
47
|
+
});
|
48
|
+
|
49
|
+
it("uninstalls itself, putting back a previous callback", function() {
|
50
|
+
var originalCallback = jasmine.createSpy('error'),
|
51
|
+
fakeGlobal = { onerror: originalCallback },
|
52
|
+
errors = new jasmineUnderTest.GlobalErrors(fakeGlobal);
|
53
|
+
|
54
|
+
expect(fakeGlobal.onerror).toBe(originalCallback);
|
55
|
+
|
56
|
+
errors.install();
|
57
|
+
|
58
|
+
expect(fakeGlobal.onerror).not.toBe(originalCallback);
|
59
|
+
|
60
|
+
errors.uninstall();
|
61
|
+
|
62
|
+
expect(fakeGlobal.onerror).toBe(originalCallback);
|
63
|
+
});
|
64
|
+
|
65
|
+
it("rethrows the original error when there is no handler", function() {
|
66
|
+
var fakeGlobal = { },
|
67
|
+
errors = new jasmineUnderTest.GlobalErrors(fakeGlobal),
|
68
|
+
originalError = new Error('nope');
|
69
|
+
|
70
|
+
errors.install();
|
71
|
+
|
72
|
+
try {
|
73
|
+
fakeGlobal.onerror(originalError);
|
74
|
+
} catch (e) {
|
75
|
+
expect(e).toBe(originalError);
|
76
|
+
}
|
77
|
+
|
78
|
+
errors.uninstall();
|
79
|
+
});
|
80
|
+
|
81
|
+
it("works in node.js", function() {
|
82
|
+
var fakeGlobal = {
|
83
|
+
process: {
|
84
|
+
on: jasmine.createSpy('process.on'),
|
85
|
+
removeListener: jasmine.createSpy('process.removeListener'),
|
86
|
+
listeners: jasmine.createSpy('process.listeners').and.returnValue(['foo']),
|
87
|
+
removeAllListeners: jasmine.createSpy('process.removeAllListeners')
|
88
|
+
}
|
89
|
+
},
|
90
|
+
handler = jasmine.createSpy('errorHandler'),
|
91
|
+
errors = new jasmineUnderTest.GlobalErrors(fakeGlobal);
|
92
|
+
|
93
|
+
errors.install();
|
94
|
+
expect(fakeGlobal.process.on).toHaveBeenCalledWith('uncaughtException', jasmine.any(Function));
|
95
|
+
expect(fakeGlobal.process.listeners).toHaveBeenCalledWith('uncaughtException');
|
96
|
+
expect(fakeGlobal.process.removeAllListeners).toHaveBeenCalledWith('uncaughtException');
|
97
|
+
|
98
|
+
errors.pushListener(handler);
|
99
|
+
|
100
|
+
var addedListener = fakeGlobal.process.on.calls.argsFor(0)[1];
|
101
|
+
addedListener(new Error('bar'));
|
102
|
+
|
103
|
+
expect(handler).toHaveBeenCalledWith(new Error('bar'));
|
104
|
+
|
105
|
+
errors.uninstall();
|
106
|
+
|
107
|
+
expect(fakeGlobal.process.removeListener).toHaveBeenCalledWith('uncaughtException', addedListener);
|
108
|
+
expect(fakeGlobal.process.on).toHaveBeenCalledWith('uncaughtException', 'foo');
|
109
|
+
});
|
110
|
+
});
|
@@ -14,6 +14,58 @@ describe("jasmineUnderTest.pp", function () {
|
|
14
14
|
expect(jasmineUnderTest.pp(-0)).toEqual("-0");
|
15
15
|
});
|
16
16
|
|
17
|
+
describe('stringify sets', function() {
|
18
|
+
it("should stringify sets properly", function() {
|
19
|
+
jasmine.getEnv().requireFunctioningSets();
|
20
|
+
var set = new Set();
|
21
|
+
set.add(1);
|
22
|
+
set.add(2);
|
23
|
+
expect(jasmineUnderTest.pp(set)).toEqual("Set( 1, 2 )");
|
24
|
+
});
|
25
|
+
|
26
|
+
it("should truncate sets with more elments than jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH", function() {
|
27
|
+
jasmine.getEnv().requireFunctioningSets();
|
28
|
+
var originalMaxSize = jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH;
|
29
|
+
|
30
|
+
try {
|
31
|
+
jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH = 2;
|
32
|
+
var set = new Set();
|
33
|
+
set.add('a');
|
34
|
+
set.add('b');
|
35
|
+
set.add('c');
|
36
|
+
expect(jasmineUnderTest.pp(set)).toEqual("Set( 'a', 'b', ... )");
|
37
|
+
} finally {
|
38
|
+
jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH = originalMaxSize;
|
39
|
+
}
|
40
|
+
})
|
41
|
+
});
|
42
|
+
|
43
|
+
describe('stringify maps', function() {
|
44
|
+
it("should stringify maps properly", function() {
|
45
|
+
jasmine.getEnv().requireFunctioningMaps();
|
46
|
+
var map = new Map();
|
47
|
+
map.set(1,2);
|
48
|
+
expect(jasmineUnderTest.pp(map)).toEqual("Map( [ 1, 2 ] )");
|
49
|
+
});
|
50
|
+
|
51
|
+
it("should truncate maps with more elments than jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH", function() {
|
52
|
+
jasmine.getEnv().requireFunctioningMaps();
|
53
|
+
var originalMaxSize = jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH;
|
54
|
+
|
55
|
+
try {
|
56
|
+
jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH = 2;
|
57
|
+
var map = new Map();
|
58
|
+
map.set("a",1);
|
59
|
+
map.set("b",2);
|
60
|
+
map.set("c",3);
|
61
|
+
expect(jasmineUnderTest.pp(map)).toEqual("Map( [ 'a', 1 ], [ 'b', 2 ], ... )");
|
62
|
+
} finally {
|
63
|
+
jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH = originalMaxSize;
|
64
|
+
}
|
65
|
+
})
|
66
|
+
});
|
67
|
+
|
68
|
+
|
17
69
|
describe('stringify arrays', function() {
|
18
70
|
it("should stringify arrays properly", function() {
|
19
71
|
expect(jasmineUnderTest.pp([1, 2])).toEqual("[ 1, 2 ]");
|
@@ -80,6 +132,58 @@ describe("jasmineUnderTest.pp", function () {
|
|
80
132
|
}, bar: [1, 2, 3]})).toEqual("Object({ foo: Function, bar: [ 1, 2, 3 ] })");
|
81
133
|
});
|
82
134
|
|
135
|
+
it("should truncate objects with too many keys", function () {
|
136
|
+
var originalMaxLength = jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH;
|
137
|
+
var long = {a: 1, b: 2, c: 3};
|
138
|
+
|
139
|
+
try {
|
140
|
+
jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH = 2;
|
141
|
+
expect(jasmineUnderTest.pp(long)).toEqual("Object({ a: 1, b: 2, ... })");
|
142
|
+
} finally {
|
143
|
+
jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH = originalMaxLength;
|
144
|
+
}
|
145
|
+
});
|
146
|
+
|
147
|
+
function withMaxChars(maxChars, fn) {
|
148
|
+
var originalMaxChars = jasmineUnderTest.MAX_PRETTY_PRINT_CHARS;
|
149
|
+
|
150
|
+
try {
|
151
|
+
jasmineUnderTest.MAX_PRETTY_PRINT_CHARS = maxChars;
|
152
|
+
fn();
|
153
|
+
} finally {
|
154
|
+
jasmineUnderTest.MAX_PRETTY_PRINT_CHARS = originalMaxChars;
|
155
|
+
}
|
156
|
+
}
|
157
|
+
|
158
|
+
it("should truncate outputs that are too long", function() {
|
159
|
+
var big = [
|
160
|
+
{ a: 1, b: "a long string" },
|
161
|
+
{}
|
162
|
+
];
|
163
|
+
|
164
|
+
withMaxChars(34, function() {
|
165
|
+
expect(jasmineUnderTest.pp(big)).toEqual("[ Object({ a: 1, b: 'a long st ...");
|
166
|
+
});
|
167
|
+
});
|
168
|
+
|
169
|
+
it("should not serialize more objects after hitting MAX_PRETTY_PRINT_CHARS", function() {
|
170
|
+
var a = { jasmineToString: function() { return 'object a'; } },
|
171
|
+
b = { jasmineToString: function() { return 'object b'; } },
|
172
|
+
c = { jasmineToString: jasmine.createSpy('c jasmineToString').and.returnValue('') },
|
173
|
+
d = { jasmineToString: jasmine.createSpy('d jasmineToString').and.returnValue('') };
|
174
|
+
|
175
|
+
withMaxChars(30, function() {
|
176
|
+
jasmineUnderTest.pp([{a: a, b: b, c: c}, d]);
|
177
|
+
expect(c.jasmineToString).not.toHaveBeenCalled();
|
178
|
+
expect(d.jasmineToString).not.toHaveBeenCalled();
|
179
|
+
});
|
180
|
+
});
|
181
|
+
|
182
|
+
it("should print 'null' as the constructor of an object with its own constructor property", function() {
|
183
|
+
expect(jasmineUnderTest.pp({constructor: function() {}})).toContain("null({");
|
184
|
+
expect(jasmineUnderTest.pp({constructor: 'foo'})).toContain("null({");
|
185
|
+
});
|
186
|
+
|
83
187
|
it("should not include inherited properties when stringifying an object", function() {
|
84
188
|
var SomeClass = function SomeClass() {};
|
85
189
|
SomeClass.prototype.foo = "inherited foo";
|
@@ -145,7 +249,6 @@ describe("jasmineUnderTest.pp", function () {
|
|
145
249
|
}
|
146
250
|
});
|
147
251
|
|
148
|
-
|
149
252
|
it('should not do HTML escaping of strings', function() {
|
150
253
|
expect(jasmineUnderTest.pp('some <b>html string</b> &', false)).toEqual('\'some <b>html string</b> &\'');
|
151
254
|
});
|
@@ -161,9 +264,9 @@ describe("jasmineUnderTest.pp", function () {
|
|
161
264
|
|
162
265
|
it("should stringify spy objects properly", function() {
|
163
266
|
var TestObject = {
|
164
|
-
|
165
|
-
|
166
|
-
|
267
|
+
someFunction: function() {}
|
268
|
+
},
|
269
|
+
env = new jasmineUnderTest.Env();
|
167
270
|
|
168
271
|
var spyRegistry = new jasmineUnderTest.SpyRegistry({currentSpies: function() {return [];}});
|
169
272
|
|
@@ -187,6 +290,31 @@ describe("jasmineUnderTest.pp", function () {
|
|
187
290
|
};
|
188
291
|
|
189
292
|
expect(jasmineUnderTest.pp(obj)).toEqual("my toString");
|
293
|
+
|
294
|
+
// Simulate object from another global context (e.g. an iframe or Web Worker) that does not actually have a custom
|
295
|
+
// toString despite obj.toString !== Object.prototype.toString
|
296
|
+
var objFromOtherContext = {
|
297
|
+
foo: 'bar',
|
298
|
+
toString: function () { return Object.prototype.toString.call(this); }
|
299
|
+
};
|
300
|
+
|
301
|
+
if (jasmine.getEnv().ieVersion < 9) {
|
302
|
+
expect(jasmineUnderTest.pp(objFromOtherContext)).toEqual("Object({ foo: 'bar' })");
|
303
|
+
} else {
|
304
|
+
expect(jasmineUnderTest.pp(objFromOtherContext)).toEqual("Object({ foo: 'bar', toString: Function })");
|
305
|
+
}
|
306
|
+
});
|
307
|
+
|
308
|
+
it("should stringify objects have have a toString that isn't a function", function() {
|
309
|
+
var obj = {
|
310
|
+
toString: "foo"
|
311
|
+
};
|
312
|
+
|
313
|
+
if (jasmine.getEnv().ieVersion < 9) {
|
314
|
+
expect(jasmineUnderTest.pp(obj)).toEqual("Object({ })");
|
315
|
+
} else {
|
316
|
+
expect(jasmineUnderTest.pp(obj)).toEqual("Object({ toString: 'foo' })");
|
317
|
+
}
|
190
318
|
});
|
191
319
|
|
192
320
|
it("should stringify objects from anonymous constructors with custom toString", function () {
|
@@ -19,6 +19,26 @@ describe("QueueRunner", function() {
|
|
19
19
|
expect(calls).toEqual(['fn1', 'fn2']);
|
20
20
|
});
|
21
21
|
|
22
|
+
it("runs cleanup functions after the others", function() {
|
23
|
+
var calls = [],
|
24
|
+
queueableFn1 = { fn: jasmine.createSpy('fn1') },
|
25
|
+
queueableFn2 = { fn: jasmine.createSpy('fn2') },
|
26
|
+
queueRunner = new jasmineUnderTest.QueueRunner({
|
27
|
+
queueableFns: [queueableFn1],
|
28
|
+
cleanupFns: [queueableFn2]
|
29
|
+
});
|
30
|
+
queueableFn1.fn.and.callFake(function() {
|
31
|
+
calls.push('fn1');
|
32
|
+
});
|
33
|
+
queueableFn2.fn.and.callFake(function() {
|
34
|
+
calls.push('fn2');
|
35
|
+
});
|
36
|
+
|
37
|
+
queueRunner.execute();
|
38
|
+
|
39
|
+
expect(calls).toEqual(['fn1', 'fn2']);
|
40
|
+
});
|
41
|
+
|
22
42
|
it("calls each function with a consistent 'this'-- an empty object", function() {
|
23
43
|
var queueableFn1 = { fn: jasmine.createSpy('fn1') },
|
24
44
|
queueableFn2 = { fn: jasmine.createSpy('fn2') },
|
@@ -31,7 +51,7 @@ describe("QueueRunner", function() {
|
|
31
51
|
queueRunner.execute();
|
32
52
|
|
33
53
|
var context = queueableFn1.fn.calls.first().object;
|
34
|
-
expect(context).toEqual(
|
54
|
+
expect(context).toEqual(new jasmineUnderTest.UserContext());
|
35
55
|
expect(queueableFn2.fn.calls.first().object).toBe(context);
|
36
56
|
expect(asyncContext).toBe(context);
|
37
57
|
});
|
@@ -189,6 +209,7 @@ describe("QueueRunner", function() {
|
|
189
209
|
|
190
210
|
queueRunner.execute();
|
191
211
|
|
212
|
+
jasmine.clock().tick(1);
|
192
213
|
expect(onComplete).toHaveBeenCalled();
|
193
214
|
|
194
215
|
jasmine.clock().tick(jasmineUnderTest.DEFAULT_TIMEOUT_INTERVAL);
|
@@ -197,12 +218,13 @@ describe("QueueRunner", function() {
|
|
197
218
|
|
198
219
|
it("only moves to the next spec the first time you call done", function() {
|
199
220
|
var queueableFn = { fn: function(done) {done(); done();} },
|
200
|
-
nextQueueableFn = { fn: jasmine.createSpy('nextFn') }
|
201
|
-
|
202
|
-
|
203
|
-
|
221
|
+
nextQueueableFn = { fn: jasmine.createSpy('nextFn') },
|
222
|
+
queueRunner = new jasmineUnderTest.QueueRunner({
|
223
|
+
queueableFns: [queueableFn, nextQueueableFn]
|
224
|
+
});
|
204
225
|
|
205
226
|
queueRunner.execute();
|
227
|
+
jasmine.clock().tick(1);
|
206
228
|
expect(nextQueueableFn.fn.calls.count()).toEqual(1);
|
207
229
|
});
|
208
230
|
|
@@ -211,10 +233,10 @@ describe("QueueRunner", function() {
|
|
211
233
|
setTimeout(done, 1);
|
212
234
|
throw new Error('error!');
|
213
235
|
} },
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
236
|
+
nextQueueableFn = { fn: jasmine.createSpy('nextFn') },
|
237
|
+
queueRunner = new jasmineUnderTest.QueueRunner({
|
238
|
+
queueableFns: [queueableFn, nextQueueableFn]
|
239
|
+
});
|
218
240
|
|
219
241
|
queueRunner.execute();
|
220
242
|
jasmine.clock().tick(1);
|
@@ -234,6 +256,151 @@ describe("QueueRunner", function() {
|
|
234
256
|
queueRunner.execute();
|
235
257
|
expect(doneReturn).toBe(null);
|
236
258
|
});
|
259
|
+
|
260
|
+
it("continues running functions when an exception is thrown in async code without timing out", function() {
|
261
|
+
var queueableFn = { fn: function(done) { throwAsync(); }, timeout: function() { return 1; } },
|
262
|
+
nextQueueableFn = { fn: jasmine.createSpy("nextFunction") },
|
263
|
+
onException = jasmine.createSpy('onException'),
|
264
|
+
globalErrors = { pushListener: jasmine.createSpy('pushListener'), popListener: jasmine.createSpy('popListener') },
|
265
|
+
queueRunner = new jasmineUnderTest.QueueRunner({
|
266
|
+
queueableFns: [queueableFn, nextQueueableFn],
|
267
|
+
onException: onException,
|
268
|
+
globalErrors: globalErrors
|
269
|
+
}),
|
270
|
+
throwAsync = function() {
|
271
|
+
globalErrors.pushListener.calls.mostRecent().args[0](new Error('foo'));
|
272
|
+
jasmine.clock().tick(2);
|
273
|
+
};
|
274
|
+
|
275
|
+
nextQueueableFn.fn.and.callFake(function() {
|
276
|
+
// should remove the same function that was added
|
277
|
+
expect(globalErrors.popListener).toHaveBeenCalledWith(globalErrors.pushListener.calls.argsFor(1)[0]);
|
278
|
+
});
|
279
|
+
|
280
|
+
queueRunner.execute();
|
281
|
+
|
282
|
+
function errorWithMessage(message) {
|
283
|
+
return {
|
284
|
+
asymmetricMatch: function(other) {
|
285
|
+
return new RegExp(message).test(other.message);
|
286
|
+
},
|
287
|
+
toString: function() {
|
288
|
+
return '<Error with message like "' + message + '">';
|
289
|
+
}
|
290
|
+
};
|
291
|
+
}
|
292
|
+
expect(onException).not.toHaveBeenCalledWith(errorWithMessage(/DEFAULT_TIMEOUT_INTERVAL/));
|
293
|
+
expect(onException).toHaveBeenCalledWith(errorWithMessage(/^foo$/));
|
294
|
+
expect(nextQueueableFn.fn).toHaveBeenCalled();
|
295
|
+
});
|
296
|
+
|
297
|
+
it("handles exceptions thrown while waiting for the stack to clear", function() {
|
298
|
+
var queueableFn = { fn: function(done) { done() } },
|
299
|
+
global = {},
|
300
|
+
errorListeners = [],
|
301
|
+
globalErrors = {
|
302
|
+
pushListener: function(f) { errorListeners.push(f); },
|
303
|
+
popListener: function() { errorListeners.pop(); }
|
304
|
+
},
|
305
|
+
clearStack = jasmine.createSpy('clearStack'),
|
306
|
+
onException = jasmine.createSpy('onException'),
|
307
|
+
queueRunner = new jasmineUnderTest.QueueRunner({
|
308
|
+
queueableFns: [queueableFn],
|
309
|
+
globalErrors: globalErrors,
|
310
|
+
clearStack: clearStack,
|
311
|
+
onException: onException
|
312
|
+
}),
|
313
|
+
error = new Error('nope');
|
314
|
+
|
315
|
+
queueRunner.execute();
|
316
|
+
jasmine.clock().tick();
|
317
|
+
expect(clearStack).toHaveBeenCalled();
|
318
|
+
expect(errorListeners.length).toEqual(1);
|
319
|
+
errorListeners[0](error);
|
320
|
+
clearStack.calls.argsFor(0)[0]();
|
321
|
+
expect(onException).toHaveBeenCalledWith(error);
|
322
|
+
});
|
323
|
+
});
|
324
|
+
|
325
|
+
describe("with a function that returns a promise", function() {
|
326
|
+
function StubPromise() {}
|
327
|
+
|
328
|
+
StubPromise.prototype.then = function(resolve, reject) {
|
329
|
+
this.resolveHandler = resolve;
|
330
|
+
this.rejectHandler = reject;
|
331
|
+
};
|
332
|
+
|
333
|
+
beforeEach(function() {
|
334
|
+
jasmine.clock().install();
|
335
|
+
});
|
336
|
+
|
337
|
+
afterEach(function() {
|
338
|
+
jasmine.clock().uninstall();
|
339
|
+
});
|
340
|
+
|
341
|
+
it("runs the function asynchronously, advancing once the promise is settled", function() {
|
342
|
+
var onComplete = jasmine.createSpy('onComplete'),
|
343
|
+
fnCallback = jasmine.createSpy('fnCallback'),
|
344
|
+
p1 = new StubPromise(),
|
345
|
+
p2 = new StubPromise(),
|
346
|
+
queueableFn1 = { fn: function() {
|
347
|
+
setTimeout(function() {
|
348
|
+
p1.resolveHandler();
|
349
|
+
}, 100);
|
350
|
+
return p1;
|
351
|
+
} };
|
352
|
+
queueableFn2 = { fn: function() {
|
353
|
+
fnCallback();
|
354
|
+
setTimeout(function() {
|
355
|
+
p2.resolveHandler();
|
356
|
+
}, 100);
|
357
|
+
return p2;
|
358
|
+
} },
|
359
|
+
queueRunner = new jasmineUnderTest.QueueRunner({
|
360
|
+
queueableFns: [queueableFn1, queueableFn2],
|
361
|
+
onComplete: onComplete
|
362
|
+
});
|
363
|
+
|
364
|
+
queueRunner.execute();
|
365
|
+
expect(fnCallback).not.toHaveBeenCalled();
|
366
|
+
expect(onComplete).not.toHaveBeenCalled();
|
367
|
+
|
368
|
+
jasmine.clock().tick(100);
|
369
|
+
|
370
|
+
expect(fnCallback).toHaveBeenCalled();
|
371
|
+
expect(onComplete).not.toHaveBeenCalled();
|
372
|
+
|
373
|
+
jasmine.clock().tick(100);
|
374
|
+
|
375
|
+
expect(onComplete).toHaveBeenCalled();
|
376
|
+
});
|
377
|
+
|
378
|
+
it("handles a rejected promise like an unhandled exception", function() {
|
379
|
+
var promise = new StubPromise(),
|
380
|
+
queueableFn1 = { fn: function() {
|
381
|
+
setTimeout(function() {
|
382
|
+
promise.rejectHandler('foo')
|
383
|
+
}, 100);
|
384
|
+
return promise;
|
385
|
+
} },
|
386
|
+
queueableFn2 = { fn: jasmine.createSpy('fn2') },
|
387
|
+
failFn = jasmine.createSpy('fail'),
|
388
|
+
onExceptionCallback = jasmine.createSpy('on exception callback'),
|
389
|
+
queueRunner = new jasmineUnderTest.QueueRunner({
|
390
|
+
queueableFns: [queueableFn1, queueableFn2],
|
391
|
+
onException: onExceptionCallback
|
392
|
+
});
|
393
|
+
|
394
|
+
queueRunner.execute();
|
395
|
+
|
396
|
+
expect(onExceptionCallback).not.toHaveBeenCalled();
|
397
|
+
expect(queueableFn2.fn).not.toHaveBeenCalled();
|
398
|
+
|
399
|
+
jasmine.clock().tick(100);
|
400
|
+
|
401
|
+
expect(onExceptionCallback).toHaveBeenCalledWith('foo');
|
402
|
+
expect(queueableFn2.fn).toHaveBeenCalled();
|
403
|
+
});
|
237
404
|
});
|
238
405
|
|
239
406
|
it("calls exception handlers when an exception is thrown in a fn", function() {
|
@@ -277,6 +444,87 @@ describe("QueueRunner", function() {
|
|
277
444
|
expect(nextQueueableFn.fn).toHaveBeenCalled();
|
278
445
|
});
|
279
446
|
|
447
|
+
describe("When configured to complete on first error", function() {
|
448
|
+
it("skips to cleanup functions on the first exception", function() {
|
449
|
+
var queueableFn = { fn: function() { throw new Error("error"); } },
|
450
|
+
nextQueueableFn = { fn: jasmine.createSpy("nextFunction") },
|
451
|
+
cleanupFn = { fn: jasmine.createSpy("cleanup") },
|
452
|
+
queueRunner = new jasmineUnderTest.QueueRunner({
|
453
|
+
queueableFns: [queueableFn, nextQueueableFn],
|
454
|
+
cleanupFns: [cleanupFn],
|
455
|
+
completeOnFirstError: true
|
456
|
+
});
|
457
|
+
|
458
|
+
queueRunner.execute();
|
459
|
+
expect(nextQueueableFn.fn).not.toHaveBeenCalled();
|
460
|
+
expect(cleanupFn.fn).toHaveBeenCalled();
|
461
|
+
});
|
462
|
+
|
463
|
+
it("does not skip when a cleanup function throws", function() {
|
464
|
+
var queueableFn = { fn: function() { } },
|
465
|
+
cleanupFn1 = { fn: function() { throw new Error("error"); } },
|
466
|
+
cleanupFn2 = { fn: jasmine.createSpy("cleanupFn2") },
|
467
|
+
queueRunner = new jasmineUnderTest.QueueRunner({
|
468
|
+
queueableFns: [queueableFn],
|
469
|
+
cleanupFns: [cleanupFn1, cleanupFn2],
|
470
|
+
completeOnFirstError: true
|
471
|
+
});
|
472
|
+
|
473
|
+
queueRunner.execute();
|
474
|
+
expect(cleanupFn2.fn).toHaveBeenCalled();
|
475
|
+
});
|
476
|
+
|
477
|
+
describe("with an asynchronous function", function() {
|
478
|
+
beforeEach(function() {
|
479
|
+
jasmine.clock().install();
|
480
|
+
});
|
481
|
+
|
482
|
+
afterEach(function() {
|
483
|
+
jasmine.clock().uninstall();
|
484
|
+
});
|
485
|
+
|
486
|
+
|
487
|
+
it("skips to cleanup functions on the first exception", function() {
|
488
|
+
var errorListeners = [],
|
489
|
+
queueableFn = { fn: function(done) {} },
|
490
|
+
nextQueueableFn = { fn: jasmine.createSpy('nextFunction') },
|
491
|
+
cleanupFn = { fn: jasmine.createSpy('cleanup') },
|
492
|
+
queueRunner = new jasmineUnderTest.QueueRunner({
|
493
|
+
globalErrors: {
|
494
|
+
pushListener: function(f) { errorListeners.push(f); },
|
495
|
+
popListener: function() { errorListeners.pop(); },
|
496
|
+
},
|
497
|
+
queueableFns: [queueableFn, nextQueueableFn],
|
498
|
+
cleanupFns: [cleanupFn],
|
499
|
+
completeOnFirstError: true,
|
500
|
+
});
|
501
|
+
|
502
|
+
queueRunner.execute();
|
503
|
+
errorListeners[errorListeners.length - 1](new Error('error'));
|
504
|
+
expect(nextQueueableFn.fn).not.toHaveBeenCalled();
|
505
|
+
expect(cleanupFn.fn).toHaveBeenCalled();
|
506
|
+
});
|
507
|
+
|
508
|
+
it("skips to cleanup functions when next.fail is called", function() {
|
509
|
+
var queueableFn = { fn: function(done) {
|
510
|
+
done.fail('nope');
|
511
|
+
} },
|
512
|
+
nextQueueableFn = { fn: jasmine.createSpy('nextFunction') },
|
513
|
+
cleanupFn = { fn: jasmine.createSpy('cleanup') },
|
514
|
+
queueRunner = new jasmineUnderTest.QueueRunner({
|
515
|
+
queueableFns: [queueableFn, nextQueueableFn],
|
516
|
+
cleanupFns: [cleanupFn],
|
517
|
+
completeOnFirstError: true,
|
518
|
+
});
|
519
|
+
|
520
|
+
queueRunner.execute();
|
521
|
+
jasmine.clock().tick();
|
522
|
+
expect(nextQueueableFn.fn).not.toHaveBeenCalled();
|
523
|
+
expect(cleanupFn.fn).toHaveBeenCalled();
|
524
|
+
});
|
525
|
+
});
|
526
|
+
});
|
527
|
+
|
280
528
|
it("calls a provided complete callback when done", function() {
|
281
529
|
var queueableFn = { fn: jasmine.createSpy('fn') },
|
282
530
|
completeCallback = jasmine.createSpy('completeCallback'),
|
@@ -290,21 +538,83 @@ describe("QueueRunner", function() {
|
|
290
538
|
expect(completeCallback).toHaveBeenCalled();
|
291
539
|
});
|
292
540
|
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
clearStack = jasmine.createSpy('clearStack'),
|
298
|
-
queueRunner = new jasmineUnderTest.QueueRunner({
|
299
|
-
queueableFns: [asyncFn, afterFn],
|
300
|
-
clearStack: clearStack,
|
301
|
-
onComplete: completeCallback
|
302
|
-
});
|
541
|
+
describe("clearing the stack", function() {
|
542
|
+
beforeEach(function() {
|
543
|
+
jasmine.clock().install();
|
544
|
+
});
|
303
545
|
|
304
|
-
|
546
|
+
afterEach(function() {
|
547
|
+
jasmine.clock().uninstall();
|
548
|
+
});
|
305
549
|
|
306
|
-
|
307
|
-
|
308
|
-
|
550
|
+
it("calls a provided stack clearing function when done", function() {
|
551
|
+
var asyncFn = { fn: function(done) { done() } },
|
552
|
+
afterFn = { fn: jasmine.createSpy('afterFn') },
|
553
|
+
completeCallback = jasmine.createSpy('completeCallback'),
|
554
|
+
clearStack = jasmine.createSpy('clearStack'),
|
555
|
+
queueRunner = new jasmineUnderTest.QueueRunner({
|
556
|
+
queueableFns: [asyncFn, afterFn],
|
557
|
+
clearStack: clearStack,
|
558
|
+
onComplete: completeCallback
|
559
|
+
});
|
560
|
+
|
561
|
+
clearStack.and.callFake(function(fn) { fn(); });
|
562
|
+
|
563
|
+
queueRunner.execute();
|
564
|
+
jasmine.clock().tick();
|
565
|
+
expect(afterFn.fn).toHaveBeenCalled();
|
566
|
+
expect(clearStack).toHaveBeenCalled();
|
567
|
+
clearStack.calls.argsFor(0)[0]();
|
568
|
+
expect(completeCallback).toHaveBeenCalled();
|
569
|
+
});
|
570
|
+
});
|
571
|
+
|
572
|
+
describe('when user context has not been defined', function() {
|
573
|
+
beforeEach(function() {
|
574
|
+
var fn;
|
575
|
+
|
576
|
+
this.fn = fn = jasmine.createSpy('fn1');
|
577
|
+
this.queueRunner = new jasmineUnderTest.QueueRunner({
|
578
|
+
queueableFns: [{ fn: fn }]
|
579
|
+
});
|
580
|
+
});
|
581
|
+
|
582
|
+
it('runs the functions on the scope of a UserContext', function() {
|
583
|
+
var calls = [],
|
584
|
+
context;
|
585
|
+
|
586
|
+
this.fn.and.callFake(function() {
|
587
|
+
context = this;
|
588
|
+
});
|
589
|
+
|
590
|
+
this.queueRunner.execute();
|
591
|
+
|
592
|
+
expect(context.constructor).toBe(jasmineUnderTest.UserContext);
|
593
|
+
});
|
594
|
+
});
|
595
|
+
|
596
|
+
describe('when user context has been defined', function() {
|
597
|
+
beforeEach(function() {
|
598
|
+
var fn, context;
|
599
|
+
|
600
|
+
this.fn = fn = jasmine.createSpy('fn1');
|
601
|
+
this.context = context = new jasmineUnderTest.UserContext();
|
602
|
+
this.queueRunner = new jasmineUnderTest.QueueRunner({
|
603
|
+
queueableFns: [{ fn: fn }],
|
604
|
+
userContext: context
|
605
|
+
});
|
606
|
+
});
|
607
|
+
|
608
|
+
it('runs the functions on the scope of a UserContext', function() {
|
609
|
+
var calls = [],
|
610
|
+
context;
|
611
|
+
this.fn.and.callFake(function() {
|
612
|
+
context = this;
|
613
|
+
});
|
614
|
+
|
615
|
+
this.queueRunner.execute();
|
616
|
+
|
617
|
+
expect(context).toBe(this.context);
|
618
|
+
});
|
309
619
|
});
|
310
620
|
});
|