Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
seleniumhq
GitHub Repository: seleniumhq/selenium
Path: blob/trunk/javascript/webdriver/test/stacktrace_test.js
2868 views
1
// Licensed to the Software Freedom Conservancy (SFC) under one
2
// or more contributor license agreements. See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership. The SFC licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License. You may obtain a copy of the License at
8
//
9
// http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied. See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
18
goog.require('bot.Error');
19
goog.require('bot.ErrorCode');
20
goog.require('goog.string');
21
goog.require('goog.testing.JsUnitException');
22
goog.require('goog.testing.PropertyReplacer');
23
goog.require('goog.testing.StrictMock');
24
goog.require('goog.testing.jsunit');
25
goog.require('goog.testing.stacktrace');
26
goog.require('webdriver.stacktrace');
27
goog.require('webdriver.test.testutil');
28
29
var stubs;
30
31
function setUpPage() {
32
stubs = new goog.testing.PropertyReplacer();
33
}
34
35
function tearDown() {
36
stubs.reset();
37
}
38
39
40
function assertStackFrame(message, frameOrFrameString, expectedFrame) {
41
var frame = frameOrFrameString;
42
if (goog.isString(frame)) {
43
frame = webdriver.stacktrace.parseStackFrame_(frame);
44
assertNotNull(message + '\nunable to parse frame: ' + frameOrFrameString,
45
frame);
46
}
47
var diff = [];
48
for (var prop in expectedFrame) {
49
if (goog.isString(expectedFrame[prop]) &&
50
frame[prop] !== expectedFrame[prop]) {
51
diff.push([
52
prop, ': <', expectedFrame[prop], '> !== <', frame[prop], '>'
53
].join(''));
54
}
55
}
56
if (diff.length) {
57
fail(message +
58
'\nfor: <' + frameOrFrameString + '>' +
59
'\nexpected: <' + expectedFrame + '>' +
60
'\nbut was: <' + frame + '>' +
61
'\n ' +
62
diff.join('\n '));
63
}
64
}
65
66
function assertFrame(frame, file, line) {
67
// Normalize path for when run through Node.js on Windows.
68
var url = frame.getUrl().replace(/\\/g, '/');
69
assertContains('/' + file, url);
70
assertEquals(line, frame.getLine());
71
}
72
73
function testGetStacktraceFromFile() {
74
if (!webdriver.stacktrace.BROWSER_SUPPORTED) {
75
return false;
76
}
77
78
var stacktrace = webdriver.test.testutil.getStackTrace();
79
assertFrame(stacktrace[0], 'testutil.js', 50);
80
assertFrame(stacktrace[1], 'stacktrace_test.js', 78);
81
}
82
83
function testGetStacktraceWithUrlOnLine() {
84
if (!webdriver.stacktrace.BROWSER_SUPPORTED) {
85
return false;
86
}
87
88
// The url argument is intentionally ignored here.
89
function getStacktraceWithUrlArgument(url) {
90
return webdriver.stacktrace.get();
91
}
92
93
var stacktrace = getStacktraceWithUrlArgument('http://www.google.com');
94
assertFrame(stacktrace[0], 'stacktrace_test.js', 90);
95
96
stacktrace = getStacktraceWithUrlArgument('http://www.google.com/search');
97
assertFrame(stacktrace[0], 'stacktrace_test.js', 90);
98
}
99
100
function testParseStackFrameInV8() {
101
assertStackFrame('exception name only (node v0.8)',
102
' at Error (unknown source)',
103
new webdriver.stacktrace.Frame('', 'Error', '', 'unknown source'));
104
105
assertStackFrame('exception name only (chrome v22)',
106
' at Error (<anonymous>)',
107
new webdriver.stacktrace.Frame('', 'Error', '', '<anonymous>'));
108
109
assertStackFrame('context object + function name + url',
110
' at Object.assert (file:///.../asserts.js:29:10)',
111
new webdriver.stacktrace.Frame('Object', 'assert', '',
112
'file:///.../asserts.js:29:10'));
113
114
assertStackFrame('context object + function name + file',
115
' at Object.assert (asserts.js:29:10)',
116
new webdriver.stacktrace.Frame('Object', 'assert', '',
117
'asserts.js:29:10'));
118
119
assertStackFrame('context object + anonymous function + file',
120
' at Interface.<anonymous> (repl.js:182:12)',
121
new webdriver.stacktrace.Frame('Interface', '<anonymous>', '',
122
'repl.js:182:12'));
123
124
assertStackFrame('url only',
125
' at http://www.example.com/jsunit.js:117:13',
126
new webdriver.stacktrace.Frame('', '', '',
127
'http://www.example.com/jsunit.js:117:13'));
128
129
assertStackFrame('file only',
130
' at repl:1:57',
131
new webdriver.stacktrace.Frame('', '', '', 'repl:1:57'));
132
133
assertStackFrame('function alias',
134
' at [object Object].exec [as execute] (file:///foo)',
135
new webdriver.stacktrace.Frame('[object Object]', 'exec',
136
'execute', 'file:///foo'));
137
138
assertStackFrame('constructor call',
139
' at new Class (file:///foo)',
140
new webdriver.stacktrace.Frame('new ', 'Class', '', 'file:///foo'));
141
142
assertStackFrame('object property constructor call',
143
' at new [object Object].foo (repl:1:2)',
144
new webdriver.stacktrace.Frame('new [object Object]', 'foo', '',
145
'repl:1:2'));
146
147
assertStackFrame('namespaced constructor call',
148
' at new foo.bar.Class (foo:1:2)',
149
new webdriver.stacktrace.Frame('new foo.bar', 'Class', '', 'foo:1:2'));
150
151
assertStackFrame('anonymous constructor call',
152
' at new <anonymous> (file:///foo)',
153
new webdriver.stacktrace.Frame('new ', '<anonymous>', '',
154
'file:///foo'));
155
156
assertStackFrame('native function call',
157
' at Array.forEach (native)',
158
new webdriver.stacktrace.Frame('Array', 'forEach', '', 'native'));
159
160
assertStackFrame('eval',
161
' at foo (eval at file://bar)',
162
new webdriver.stacktrace.Frame('', 'foo', '', 'eval at file://bar'));
163
164
assertStackFrame('nested anonymous eval',
165
' at eval (eval at <anonymous> (unknown source), <anonymous>:2:7)',
166
new webdriver.stacktrace.Frame('', 'eval', '',
167
'eval at <anonymous> (unknown source), <anonymous>:2:7'));
168
169
assertStackFrame('Url containing parentheses',
170
' at Object.assert (http://bar:4000/bar.js?value=(a):150:3)',
171
new webdriver.stacktrace.Frame('Object', 'assert', '',
172
'http://bar:4000/bar.js?value=(a):150:3'));
173
174
assertStackFrame('Frame with non-standard leading whitespace (issue 7994)',
175
' at module.exports.runCucumber (/local/dir/path)',
176
new webdriver.stacktrace.Frame('module.exports', 'runCucumber', '',
177
'/local/dir/path'));
178
}
179
180
function testParseClosureCanonicalStackFrame() {
181
assertStackFrame('unknown frame', '> (unknown)',
182
webdriver.stacktrace.ANONYMOUS_FRAME_);
183
assertStackFrame('anonymous frame', '> anonymous',
184
webdriver.stacktrace.ANONYMOUS_FRAME_);
185
186
assertStackFrame('name only', '> foo',
187
new webdriver.stacktrace.Frame('', 'foo', '', ''));
188
189
assertStackFrame('name and path', '> foo at http://x:123',
190
new webdriver.stacktrace.Frame('', 'foo', '', 'http://x:123'));
191
192
assertStackFrame('anonymous function with path',
193
'> anonymous at file:///x/y/z',
194
new webdriver.stacktrace.Frame('', 'anonymous', '', 'file:///x/y/z'));
195
196
assertStackFrame('anonymous function with v8 path',
197
'> anonymous at /x/y/z:12:34',
198
new webdriver.stacktrace.Frame('', 'anonymous', '', '/x/y/z:12:34'));
199
200
assertStackFrame('context and name only',
201
'> foo.bar', new webdriver.stacktrace.Frame('foo', 'bar', '', ''));
202
203
assertStackFrame('name and alias',
204
'> foo [as bar]', new webdriver.stacktrace.Frame('', 'foo', 'bar', ''));
205
206
assertStackFrame('context, name, and alias',
207
'> foo.bar [as baz]',
208
new webdriver.stacktrace.Frame('foo', 'bar', 'baz', ''));
209
210
assertStackFrame('path only', '> http://x:123',
211
new webdriver.stacktrace.Frame('', '', '', 'http://x:123'));
212
213
assertStackFrame('name and arguments',
214
'> foo(arguments)', new webdriver.stacktrace.Frame('', 'foo', '', ''));
215
216
assertStackFrame('full frame',
217
'> foo.bar(123, "abc") [as baz] at http://x:123',
218
new webdriver.stacktrace.Frame('foo', 'bar', 'baz', 'http://x:123'));
219
220
assertStackFrame('name and url with sub-domain',
221
'> foo at http://x.y.z:80/path:1:2',
222
new webdriver.stacktrace.Frame('', 'foo', '',
223
'http://x.y.z:80/path:1:2'));
224
225
assertStackFrame('name and url with sub-domain',
226
'> foo.bar.baz at http://x.y.z:80/path:1:2',
227
new webdriver.stacktrace.Frame('foo.bar', 'baz', '',
228
'http://x.y.z:80/path:1:2'));
229
}
230
231
// All test strings are parsed with the conventional and long
232
// frame algorithms.
233
function testParseStackFrameInFirefox() {
234
var frameString = 'Error("Assertion failed")@:0';
235
var frame = webdriver.stacktrace.parseStackFrame_(frameString);
236
var expected = new webdriver.stacktrace.Frame('', 'Error', '', '');
237
assertObjectEquals('function name + arguments', expected, frame);
238
239
frame = webdriver.stacktrace.parseLongFirefoxFrame_(frameString);
240
assertObjectEquals('function name + arguments', expected, frame);
241
242
frameString = '()@file:///foo:42';
243
frame = webdriver.stacktrace.parseStackFrame_(frameString);
244
expected = new webdriver.stacktrace.Frame('', '', '', 'file:///foo:42');
245
assertObjectEquals('anonymous function', expected, frame);
246
247
frame = webdriver.stacktrace.parseLongFirefoxFrame_(frameString);
248
assertObjectEquals('anonymous function', expected, frame);
249
250
frameString = '@javascript:alert(0)';
251
frame = webdriver.stacktrace.parseStackFrame_(frameString);
252
expected = new webdriver.stacktrace.Frame('', '', '', 'javascript:alert(0)');
253
assertObjectEquals('anonymous function', expected, frame);
254
255
frame = webdriver.stacktrace.parseLongFirefoxFrame_(frameString);
256
assertObjectEquals('anonymous function', expected, frame);
257
}
258
259
function testStringRepresentation() {
260
var frame = new webdriver.stacktrace.Frame('window', 'foo', 'bar',
261
'http://x?a=1&b=2:1');
262
assertEquals(' at window.foo [as bar] (http://x?a=1&b=2:1)',
263
frame.toString());
264
265
frame = new webdriver.stacktrace.Frame('', 'Error', '', '');
266
assertEquals(' at Error (<anonymous>)', frame.toString());
267
268
assertEquals(' at <anonymous>',
269
webdriver.stacktrace.ANONYMOUS_FRAME_.toString());
270
271
frame = new webdriver.stacktrace.Frame('', '', '', 'http://x:123');
272
assertEquals(' at http://x:123', frame.toString());
273
274
frame = new webdriver.stacktrace.Frame('foo', 'bar', '', 'http://x:123');
275
assertEquals(' at foo.bar (http://x:123)', frame.toString());
276
277
frame = new webdriver.stacktrace.Frame('new ', 'Foo', '', 'http://x:123');
278
assertEquals(' at new Foo (http://x:123)', frame.toString());
279
280
frame = new webdriver.stacktrace.Frame('new foo', 'Bar', '', '');
281
assertEquals(' at new foo.Bar (<anonymous>)', frame.toString());
282
}
283
284
// Create a stack trace string with one modest record and one long record,
285
// Verify that all frames are parsed. The length of the long arg is set
286
// to blow Firefox 3x's stack if put through a RegExp.
287
function testParsingLongStackTrace() {
288
var longArg = goog.string.buildString(
289
'(', goog.string.repeat('x', 1000000), ')');
290
var stackTrace = goog.string.buildString(
291
'shortFrame()@:0\n',
292
'longFrame',
293
longArg,
294
'@http://google.com/somescript:0\n');
295
var frames = webdriver.stacktrace.parse_(stackTrace);
296
assertEquals('number of returned frames', 2, frames.length);
297
var expected = new webdriver.stacktrace.Frame('', 'shortFrame', '', '');
298
assertStackFrame('short frame', frames[0], expected);
299
300
expected = new webdriver.stacktrace.Frame(
301
'', 'longFrame', '', 'http://google.com/somescript:0');
302
assertStackFrame('exception name only', frames[1], expected);
303
}
304
305
function testRemovesV8MessageHeaderBeforeParsingStack() {
306
var stack =
307
' at Color.red (http://x:1234)\n' +
308
' at Foo.bar (http://y:5678)';
309
310
var frames = webdriver.stacktrace.parse_(stack);
311
assertEquals(2, frames.length);
312
assertEquals(' at Color.red (http://x:1234)', frames[0].toString());
313
assertEquals(' at Foo.bar (http://y:5678)', frames[1].toString());
314
}
315
316
function testCanParseClosureJsUnitExceptions() {
317
stubs.set(goog.testing.stacktrace, 'get', function() {
318
return '> Color.red at http://x:1234\n' +
319
'> Foo.bar at http://y:5678';
320
});
321
322
var error = new goog.testing.JsUnitException('stub');
323
stubs.reset();
324
325
var frames = webdriver.stacktrace.parse_(error.stackTrace);
326
assertEquals(2, frames.length);
327
assertEquals(' at Color.red (http://x:1234)', frames[0].toString());
328
assertEquals(' at Foo.bar (http://y:5678)', frames[1].toString());
329
}
330
331
function testFormattingAV8StyleError() {
332
var errorStub = {
333
name: 'Error',
334
message: 'foo',
335
toString: function() { return 'Error: foo'; },
336
stack:
337
'Error: foo\n' +
338
' at Color.red (http://x:1234)\n' +
339
' at Foo.bar (http://y:5678)'
340
};
341
342
var ret = webdriver.stacktrace.format(errorStub);
343
assertEquals(errorStub, ret);
344
assertEquals([
345
'Error: foo',
346
' at Color.red (http://x:1234)',
347
' at Foo.bar (http://y:5678)'
348
].join('\n'), ret.stack);
349
}
350
351
function testFormattingAFirefoxStyleError() {
352
var errorStub = {
353
name: 'Error',
354
message: 'boom',
355
toString: function() { return 'Error: boom'; },
356
stack:
357
'foo@file:///foo/foo.js:1\n' +
358
'@file:///bar/bar.js:1'
359
};
360
361
var ret = webdriver.stacktrace.format(errorStub);
362
assertEquals(errorStub, ret);
363
assertEquals([
364
'Error: boom',
365
' at foo (file:///foo/foo.js:1)',
366
' at file:///bar/bar.js:1'
367
].join('\n'), ret.stack);
368
}
369
370
function testInsertsAnAnonymousFrameWhenUnableToParse() {
371
var errorStub = {
372
name: 'Error',
373
message: 'boom',
374
toString: function() { return 'Error: boom'; },
375
stack:
376
'foo@file:///foo/foo.js:1\n' +
377
'this is unparsable garbage\n' +
378
'@file:///bar/bar.js:1'
379
};
380
381
var ret = webdriver.stacktrace.format(errorStub);
382
assertEquals(errorStub, ret);
383
assertEquals([
384
'Error: boom',
385
' at foo (file:///foo/foo.js:1)',
386
' at <anonymous>',
387
' at file:///bar/bar.js:1'
388
].join('\n'), ret.stack);
389
}
390
391
function testFormattingBotErrors() {
392
var error = new bot.Error(bot.ErrorCode.NO_SUCH_ELEMENT, 'boom');
393
var expectedStack = [
394
'NoSuchElementError: boom',
395
' at Color.red (http://x:1234)',
396
' at Foo.bar (http://y:5678)'
397
].join('\n');
398
error.stack = expectedStack;
399
400
var ret = webdriver.stacktrace.format(error);
401
assertEquals(ret, error);
402
assertEquals(expectedStack, error.stack);
403
}
404
405
function testFormatsUsingNameAndMessageIfAvailable() {
406
var ret = webdriver.stacktrace.format({
407
name: 'TypeError',
408
message: 'boom'
409
});
410
assertEquals('TypeError: boom\n', ret.stack);
411
412
ret = webdriver.stacktrace.format({
413
message: 'boom'
414
});
415
assertEquals('boom\n', ret.stack);
416
417
ret = webdriver.stacktrace.format({
418
toString: function() {
419
return 'Hello world'
420
}
421
});
422
assertEquals('Hello world\n', ret.stack);
423
424
ret = webdriver.stacktrace.format({
425
name: 'TypeError',
426
message: 'boom',
427
toString: function() {
428
return 'Should not use this'
429
}
430
});
431
assertEquals('TypeError: boom\n', ret.stack);
432
}
433
434
function testDoesNotFormatErrorIfOriginalStacktraceIsInAnUnexpectedFormat() {
435
var error = Error('testing');
436
var stack = error.stack = [
437
'Error: testing',
438
'..> at Color.red (http://x:1234)',
439
'..> at Foo.bar (http://y:5678)'
440
].join('\n');
441
442
var ret = webdriver.stacktrace.format(error);
443
assertEquals(ret, error);
444
assertEquals(stack, error.stack);
445
}
446
447
function testParseStackFrameInIE10() {
448
assertStackFrame('name and path',
449
' at foo (http://bar:4000/bar.js:150:3)',
450
new webdriver.stacktrace.Frame('', 'foo', '',
451
'http://bar:4000/bar.js:150:3'));
452
453
assertStackFrame('Anonymous function',
454
' at Anonymous function (http://bar:4000/bar.js:150:3)',
455
new webdriver.stacktrace.Frame('', 'Anonymous function', '',
456
'http://bar:4000/bar.js:150:3'));
457
458
assertStackFrame('Global code',
459
' at Global code (http://bar:4000/bar.js:150:3)',
460
new webdriver.stacktrace.Frame('', 'Global code', '',
461
'http://bar:4000/bar.js:150:3'));
462
463
assertStackFrame('eval code',
464
' at foo (eval code:150:3)',
465
new webdriver.stacktrace.Frame('', 'foo', '', 'eval code:150:3'));
466
467
assertStackFrame('nested eval',
468
' at eval code (eval code:150:3)',
469
new webdriver.stacktrace.Frame('', 'eval code', '', 'eval code:150:3'));
470
471
assertStackFrame('Url containing parentheses',
472
' at foo (http://bar:4000/bar.js?value=(a):150:3)',
473
new webdriver.stacktrace.Frame('', 'foo', '',
474
'http://bar:4000/bar.js?value=(a):150:3'));
475
476
assertStackFrame('Url ending with parentheses',
477
' at foo (http://bar:4000/bar.js?a=))',
478
new webdriver.stacktrace.Frame('', 'foo', '',
479
'http://bar:4000/bar.js?a=)'));
480
}
481
482