Passed
Pull Request — develop (#92)
by Felipe
06:19
created

tests/selenium/selenium-lib/core/scripts/selenium-testrunner.js   F

Complexity

Total Complexity 230
Complexity/F 1.7

Size

Lines of Code 1343
Function Count 135

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 0
nc 512
dl 0
loc 1343
rs 2.4
c 0
b 0
f 0
wmc 230
mnd 4
bc 237
fnc 135
bpm 1.7555
cpm 1.7037
noi 19

104 Functions

Rating   Name   Duplication   Size   Complexity  
A objectExtend.isAutomatedRun 0 3 1
A objectExtend.saveTestResults 0 15 2
A Selenium.assertErrorOnNext 0 15 2
A objectExtend._recordFailure 0 5 1
A objectExtend.getSingleTestName 0 3 1
A objectExtend.loadTestCase 0 19 3
B objectExtend._attachStylesheet 0 25 5
A objectExtend.runNextTestInSuite 0 10 2
A selenium-testrunner.js ➔ getTestFrame 0 8 2
A objectExtend._onLoad 0 2 1
A objectExtend._collectCommandRows 0 16 4
A objectExtend.load 0 7 2
A objectExtend.getResultsUrl 0 3 1
A objectExtend.setMessage 0 3 1
A objectExtend.unselect 0 3 1
A objectExtend.getTestSuite 0 3 1
B objectExtend._collectSuiteRows 0 20 5
A objectExtend.shouldSaveResultsToFile 0 3 1
A objectExtend.addErrorMessage 0 12 2
A selenium-testrunner.js ➔ onSeleniumLoad 0 5 1
A objectExtend.getDocument 0 3 1
A Selenium._doSetSpeed 0 6 2
A objectExtend.setToPauseAtNextCommand 0 3 1
A selenium-testrunner.js ➔ get_new_rows 0 16 2
A objectExtend._onClick 0 4 1
A Selenium.assertFailureOnNext 0 13 2
A Selenium.doEcho 0 7 1
A objectExtend.commandComplete 0 12 3
A objectExtend.pauseCurrentTest 0 4 1
A objectExtend.commandStarted 0 5 1
A objectExtend.getCommandInterval 0 3 1
A selenium-testrunner.js ➔ getSuiteFrame 0 8 2
A objectExtend.initialize 0 12 1
A objectExtend.printMetrics 0 17 1
A objectExtend._acquireQueryString 0 10 4
A objectExtend.hasMoreCommandRows 0 3 1
A objectExtend.isBreakpoint 0 6 3
A objectExtend._switchContinueButtonToPause 0 4 1
A Selenium.XXXdoModalDialogTest 0 3 1
A objectExtend._getSeparateApplicationWindow 0 6 2
A objectExtend.markFailed 0 4 1
A objectExtend._startSingleTest 0 5 1
A objectExtend.markPassed 0 3 1
A objectExtend.updateSuiteWithResultOfPreviousTest 0 5 2
A objectExtend._advanceToNextRow 0 12 3
A objectExtend.markDone 0 3 1
A objectExtend.onClick 0 9 2
B objectExtend._onloadTestSuite 0 20 5
A objectExtend.stepCurrentTest 0 4 1
A objectExtend.commandError 0 15 2
A objectExtend._addBreakpointSupport 0 6 2
A objectExtend.getCurrentTestSuite 0 6 2
A objectExtend.getDefaultLogLevel 0 3 1
B objectExtend.loadSuiteFrame 0 31 6
A objectExtend._parseQueryParameter 0 7 2
A objectExtend.doNextCommand 0 20 3
A objectExtend.getAutoUrl 0 3 1
A Selenium.assertSelected 0 17 2
A objectExtend.startTestSuite 0 7 1
A objectExtend.setStatus 0 7 2
A objectExtend.isAvailable 0 3 1
A objectExtend.getWindow 0 3 1
A objectExtend.getCommandRows 0 3 1
A Selenium._getSpeed 0 3 1
A objectExtend.getSuiteRows 0 3 1
A objectExtend._onTestSuiteComplete 0 4 1
A objectExtend.setRunInterval 0 3 1
A objectExtend.setHighlightOption 0 4 1
A Selenium.doStore 0 7 1
A objectExtend._startCurrentTestCase 0 3 1
A objectExtend.reset 0 4 1
A objectExtend.getTestNumber 0 3 1
A objectExtend.closeAfterTests 0 3 1
A objectExtend._setLocation 0 15 3
A objectExtend.pause 0 3 1
A objectExtend._switchPauseButtonToContinue 0 5 1
A objectExtend.select 0 4 1
C objectExtend._checkExpectedFailure 0 30 7
A objectExtend.startTest 0 12 1
A objectExtend.scrollToTop 0 3 1
A Selenium.doPause 0 7 1
A objectExtend.unselectCurrentRow 0 6 2
A objectExtend.isCommandRow 0 3 1
A objectExtend.getCommand 0 6 1
D objectExtend.post 0 88 11
A objectExtend._getApplicationWindow 0 6 2
A objectExtend._pad 0 3 2
A objectExtend.getNextCommandRow 0 6 2
A objectExtend.getCurrentRow 0 6 2
A objectExtend.testComplete 0 17 2
A objectExtend._handleLoad 0 7 2
A objectExtend.nextCommand 0 7 2
A objectExtend._registerCommandHandlers 0 4 1
A objectExtend.getCommandHandler 0 6 2
A objectExtend.runNextTest 0 7 2
A objectExtend.continueCurrentTest 0 4 1
A Selenium.doBreak 0 8 1
A objectExtend.addBreakpointSupport 0 6 1
A objectExtend.getTestTable 0 4 1
A objectExtend.getCurrentTestCase 0 3 1
A objectExtend.getTestSuiteName 0 3 1
A objectExtend.resetMetrics 0 8 1
B objectExtend._saveToFile 0 52 5
A objectExtend.runSingleTest 0 5 1

How to fix   Complexity   

Complexity

Complex classes like .tests/selenium/selenium-lib/core/scripts/selenium-testrunner.js often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
/*
2
* Copyright 2004 ThoughtWorks, Inc
3
*
4
*  Licensed under the Apache License, Version 2.0 (the "License");
5
*  you may not use this file except in compliance with the License.
6
*  You may obtain a copy of the License at
7
*
8
*      http://www.apache.org/licenses/LICENSE-2.0
9
*
10
*  Unless required by applicable law or agreed to in writing, software
11
*  distributed under the License is distributed on an "AS IS" BASIS,
12
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
*  See the License for the specific language governing permissions and
14
*  limitations under the License.
15
*
16
*/
17
18
// An object representing the current test, used external
19
var currentTest = null; // TODO: get rid of this global, which mirrors the htmlTestRunner.currentTest
20
var selenium = null;
21
22
var htmlTestRunner;
23
var HtmlTestRunner = classCreate();
24
objectExtend(HtmlTestRunner.prototype, {
25
    initialize: function() {
26
        this.metrics = new Metrics();
27
        this.controlPanel = new HtmlTestRunnerControlPanel();
28
        this.testFailed = false;
29
        this.currentTest = null;
30
        this.runAllTests = false;
31
        this.appWindow = null;
32
        // we use a timeout here to make sure the LOG has loaded first, so we can see _every_ error
33
        setTimeout(fnBind(function() {
34
            this.loadSuiteFrame();
35
        }, this), 500);
36
    },
37
38
    getTestSuite: function() {
39
        return suiteFrame.getCurrentTestSuite();
40
    },
41
42
    markFailed: function() {
43
        this.testFailed = true;
44
        this.getTestSuite().markFailed();
45
    },
46
47
    loadSuiteFrame: function() {
48
        var logLevel = this.controlPanel.getDefaultLogLevel();
49
        if (logLevel) {
50
            LOG.setLogLevelThreshold(logLevel);
51
        }
52
        if (selenium == null) {
53
            var appWindow = this._getApplicationWindow();
54
            try { appWindow.location; }
0 ignored issues
show
introduced by
The result of the property access to appWindow.location is not used.
Loading history...
55
            catch (e) { 
56
                // when reloading, we may be pointing at an old window (Perm Denied)
57
                setTimeout(fnBind(function() {
58
                    this.loadSuiteFrame();
59
                }, this), 50);
60
                return;
61
            }
62
            selenium = Selenium.createForWindow(appWindow);
63
            this._registerCommandHandlers();
64
        }
65
        this.controlPanel.setHighlightOption();
66
        var testSuiteName = this.controlPanel.getTestSuiteName();
67
        var self = this;
68
        if (testSuiteName) {
69
            suiteFrame.load(testSuiteName, function() {setTimeout(fnBind(self._onloadTestSuite, self), 50)} );
70
            selenium.browserbot.baseUrl = absolutify(testSuiteName, window.location.href);
71
        }
72
        // DGF or should we use the old default?
73
        // selenium.browserbot.baseUrl = window.location.href;
74
        if (this.controlPanel.getBaseUrl()) {
75
            selenium.browserbot.baseUrl = this.controlPanel.getBaseUrl();
76
        }
77
    },
78
79
    _getApplicationWindow: function () {
80
        if (this.controlPanel.isMultiWindowMode()) {
81
            return this._getSeparateApplicationWindow();
82
        }
83
        return sel$('selenium_myiframe').contentWindow;
84
    },
85
86
    _getSeparateApplicationWindow: function () {
87
        if (this.appWindow == null) {
88
            this.appWindow = openSeparateApplicationWindow('TestRunner-splash.html', this.controlPanel.isAutomatedRun());
89
        }
90
        return this.appWindow;
91
    },
92
93
    _onloadTestSuite:function () {
94
        suiteFrame = new HtmlTestSuiteFrame(getSuiteFrame());
95
        if (! this.getTestSuite().isAvailable()) {
96
            return;
97
        }
98
        if (this.controlPanel.isAutomatedRun()) {
99
            this.startTestSuite();
100
        } else if (this.controlPanel.getAutoUrl()) {
101
            //todo what is the autourl doing, left to check it out
102
            addLoadListener(this._getApplicationWindow(), fnBind(this._startSingleTest, this));
103
            this._getApplicationWindow().src = this.controlPanel.getAutoUrl();
104
        } else {
105
            var testCaseLoaded = fnBind(function(){this.testCaseLoaded=true;},this);
106
            var testNumber = 0;
107
            if (this.controlPanel.getTestNumber() != null){
108
                var testNumber = this.controlPanel.getTestNumber() - 1; 
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable testNumber already seems to be declared on line 106. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
109
            }
110
            this.getTestSuite().getSuiteRows()[testNumber].loadTestCase(testCaseLoaded);
111
        }
112
    },
113
114
    _startSingleTest:function () {
115
        removeLoadListener(getApplicationWindow(), fnBind(this._startSingleTest, this));
116
        var singleTestName = this.controlPanel.getSingleTestName();
117
        testFrame.load(singleTestName, fnBind(this.startTest, this));
118
    },
119
120
    _registerCommandHandlers: function () {
121
        this.commandFactory = new CommandHandlerFactory();
122
        this.commandFactory.registerAll(selenium);
123
    },
124
125
    startTestSuite: function() {
126
        this.controlPanel.reset();
127
        this.metrics.resetMetrics();
128
        this.getTestSuite().reset();
129
        this.runAllTests = true;
130
        this.runNextTest();
131
    },
132
133
    runNextTest: function () {
134
        this.getTestSuite().updateSuiteWithResultOfPreviousTest();
135
        if (!this.runAllTests) {
136
            return;
137
        }
138
        this.getTestSuite().runNextTestInSuite();
139
    },
140
141
    startTest: function () {
142
        this.controlPanel.reset();
143
        testFrame.scrollToTop();
144
        //todo: move testFailed and storedVars to TestCase
145
        this.testFailed = false;
146
        storedVars = new Object();
0 ignored issues
show
Bug introduced by
The variable storedVars seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.storedVars.
Loading history...
147
        storedVars.nbsp = String.fromCharCode(160);
148
        storedVars.space = ' ';
149
        this.currentTest = new HtmlRunnerTestLoop(testFrame.getCurrentTestCase(), this.metrics, this.commandFactory);
150
        currentTest = this.currentTest;
151
        this.currentTest.start();
152
    },
153
154
    runSingleTest:function() {
155
        this.runAllTests = false;
156
        this.metrics.resetMetrics();
157
        this.startTest();
158
    }
159
});
160
161
var runInterval = 0;
162
163
/** SeleniumFrame encapsulates an iframe element */
164
var SeleniumFrame = classCreate();
165
objectExtend(SeleniumFrame.prototype, {
166
167
    initialize : function(frame) {
168
        this.frame = frame;
169
        addLoadListener(this.frame, fnBind(this._handleLoad, this));
170
    },
171
172
    getWindow : function() {
173
        return this.frame.contentWindow;
174
    },
175
176
    getDocument : function() {
177
        return this.frame.contentWindow.document;
178
    },
179
180
    _handleLoad: function() {
181
        this._attachStylesheet();
182
        this._onLoad();
183
        if (this.loadCallback) {
184
            this.loadCallback();
185
        }
186
    },
187
188
    _attachStylesheet: function() {
189
        var d = this.getDocument();
190
        var head = d.getElementsByTagName('head').item(0);
191
        var styleLink = d.createElement("link");
192
        styleLink.rel = "stylesheet";
193
        styleLink.type = "text/css";
194
        if (browserVersion && browserVersion.isChrome) {
0 ignored issues
show
Best Practice introduced by
If you intend to check if the variable browserVersion is declared in the current environment, consider using typeof browserVersion === "undefined" instead. This is safe if the variable is not actually declared.
Loading history...
195
            // DGF We have to play a clever trick to get the right absolute path.
196
            // This trick works on most browsers, (not IE), but is only needed in
197
            // chrome
198
            var tempLink = window.document.createElement("link");
199
            tempLink.href = "selenium-test.css"; // this will become an absolute href
200
            styleLink.href = tempLink.href;
201
        } else {
202
            // this works in every browser (except Firefox in chrome mode)
203
            var styleSheetPath = window.location.pathname.replace(/[^\/\\]+$/, "selenium-test.css");
204
            if (browserVersion.isIE && window.location.protocol == "file:") {
0 ignored issues
show
Bug introduced by
The variable browserVersion does not seem to be initialized in case browserVersion && browserVersion.isChrome on line 194 is false. Are you sure this can never be the case?
Loading history...
205
                styleSheetPath = "file:///" + styleSheetPath;
206
            }
207
            styleLink.href = styleSheetPath;
208
        }
209
        // DGF You're only going to see this log message if you set defaultLogLevel=debug
210
        LOG.debug("styleLink.href="+styleLink.href);
211
        head.appendChild(styleLink);
212
    },
213
214
    _onLoad: function() {
215
    },
216
217
    scrollToTop : function() {
218
        this.frame.contentWindow.scrollTo(0, 0);
219
    },
220
221
    _setLocation: function(location) {
222
        var isChrome = browserVersion.isChrome || false;
223
        var isHTA = browserVersion.isHTA || false;
224
        // DGF TODO multiWindow
225
        location += (location.indexOf("?") == -1 ? "?" : "&");
226
        location += "thisIsChrome=" + isChrome + "&thisIsHTA=" + isHTA; 
227
        if (browserVersion.isSafari) {
228
            // safari doesn't reload the page when the location equals to current location.
229
            // hence, set the location to blank so that the page will reload automatically.
230
            this.frame.src = "about:blank";
231
            this.frame.src = location;
232
        } else {
233
            this.frame.contentWindow.location.replace(location);
234
        }
235
    },
236
237
    load: function(/* url, [callback] */) {
238
        if (arguments.length > 1) {
239
            this.loadCallback = arguments[1];
240
241
        }
242
        this._setLocation(arguments[0]);
243
    }
244
245
});
246
247
/** HtmlTestSuiteFrame - encapsulates the suite iframe element */
248
var HtmlTestSuiteFrame = classCreate();
249
objectExtend(HtmlTestSuiteFrame.prototype, SeleniumFrame.prototype);
250
objectExtend(HtmlTestSuiteFrame.prototype, {
251
252
    getCurrentTestSuite: function() {
253
        if (!this.currentTestSuite) {
254
            this.currentTestSuite = new HtmlTestSuite(this.getDocument());
255
        }
256
        return this.currentTestSuite;
257
    }
258
259
});
260
261
/** HtmlTestFrame - encapsulates the test-case iframe element */
262
var HtmlTestFrame = classCreate();
263
objectExtend(HtmlTestFrame.prototype, SeleniumFrame.prototype);
264
objectExtend(HtmlTestFrame.prototype, {
265
266
    _onLoad: function() {
267
        this.currentTestCase = new HtmlTestCase(this.getWindow(), htmlTestRunner.getTestSuite().getCurrentRow());
268
    },
269
270
    getCurrentTestCase: function() {
271
        return this.currentTestCase;
272
    }
273
274
});
275
276
function onSeleniumLoad() {
277
    suiteFrame = new HtmlTestSuiteFrame(getSuiteFrame());
278
    testFrame = new HtmlTestFrame(getTestFrame());
279
    htmlTestRunner = new HtmlTestRunner();
280
}
281
282
var suiteFrame;
283
var testFrame;
284
285
function getSuiteFrame() {
286
    var f = sel$('testSuiteFrame');
287
    if (f == null) {
288
        f = top;
289
        // proxyInjection mode does not set selenium_myiframe
290
    }
291
    return f;
292
}
293
294
function getTestFrame() {
295
    var f = sel$('testFrame');
296
    if (f == null) {
297
        f = top;
298
        // proxyInjection mode does not set selenium_myiframe
299
    }
300
    return f;
301
}
302
303
var HtmlTestRunnerControlPanel = classCreate();
304
objectExtend(HtmlTestRunnerControlPanel.prototype, URLConfiguration.prototype);
305
objectExtend(HtmlTestRunnerControlPanel.prototype, {
306
    initialize: function() {
307
        this._acquireQueryString();
308
309
        this.runInterval = 0;
310
311
        this.highlightOption = sel$('highlightOption');
312
        this.pauseButton = sel$('pauseTest');
313
        this.stepButton = sel$('stepTest');
314
315
        this.highlightOption.onclick = fnBindAsEventListener((function() {
316
            this.setHighlightOption();
317
        }), this);
318
        this.pauseButton.onclick = fnBindAsEventListener(this.pauseCurrentTest, this);
319
        this.stepButton.onclick = fnBindAsEventListener(this.stepCurrentTest, this);
320
321
322
        this.speedController = new Control.Slider('speedHandle', 'speedTrack', {
323
            range: $R(0, 1000),
324
            onSlide: fnBindAsEventListener(this.setRunInterval, this),
325
            onChange: fnBindAsEventListener(this.setRunInterval, this)
326
        });
327
328
        this._parseQueryParameter();
329
    },
330
331
    setHighlightOption: function () {
332
        var isHighlight = this.highlightOption.checked;
333
        selenium.browserbot.setShouldHighlightElement(isHighlight);
334
    },
335
336
    _parseQueryParameter: function() {
337
        var tempRunInterval = this._getQueryParameter("runInterval");
338
        if (tempRunInterval) {
339
            this.setRunInterval(tempRunInterval);
340
        }
341
        this.highlightOption.checked = this._getQueryParameter("highlight");
342
    },
343
344
    setRunInterval: function(runInterval) {
345
        this.runInterval = runInterval;
346
    },
347
348
    setToPauseAtNextCommand: function() {
349
        this.runInterval = -1;
350
    },
351
352
    pauseCurrentTest: function () {
353
        this.setToPauseAtNextCommand();
354
        this._switchPauseButtonToContinue();
355
    },
356
357
    continueCurrentTest: function () {
358
        this.reset();
359
        currentTest.resume();
360
    },
361
362
    reset: function() {
363
        this.runInterval = this.speedController.value;
364
        this._switchContinueButtonToPause();
365
    },
366
367
    _switchContinueButtonToPause: function() {
368
        this.pauseButton.className = "cssPauseTest";
369
        this.pauseButton.onclick = fnBindAsEventListener(this.pauseCurrentTest, this);
370
    },
371
372
    _switchPauseButtonToContinue: function() {
373
        sel$('stepTest').disabled = false;
374
        this.pauseButton.className = "cssContinueTest";
375
        this.pauseButton.onclick = fnBindAsEventListener(this.continueCurrentTest, this);
376
    },
377
378
    stepCurrentTest: function () {
379
        this.setToPauseAtNextCommand();
380
        currentTest.resume();
381
    },
382
383
    isAutomatedRun: function() {
384
        return this._isQueryParameterTrue("auto");
385
    },
386
387
    shouldSaveResultsToFile: function() {
388
        return this._isQueryParameterTrue("save");
389
    },
390
391
    closeAfterTests: function() {
392
        return this._isQueryParameterTrue("close");
393
    },
394
395
    getTestSuiteName: function() {
396
        return this._getQueryParameter("test");
397
    },
398
399
    getTestNumber: function() {
400
        return this._getQueryParameter("testNumber");
401
    },
402
403
    getSingleTestName: function() {
404
        return this._getQueryParameter("singletest");
405
    },
406
407
    getAutoUrl: function() {
408
        return this._getQueryParameter("autoURL");
409
    },
410
    
411
    getDefaultLogLevel: function() {
412
        return this._getQueryParameter("defaultLogLevel");
413
    },
414
415
    getResultsUrl: function() {
416
        return this._getQueryParameter("resultsUrl");
417
    },
418
419
    _acquireQueryString: function() {
420
        if (this.queryString) return;
421
        if (browserVersion.isHTA) {
422
            var args = this._extractArgs();
423
            if (args.length < 2) return null;
424
            this.queryString = args[1];
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
425
        } else {
426
            this.queryString = location.search.substr(1);
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
427
        }
428
    }
429
430
});
431
432
var AbstractResultAwareRow = classCreate();
433
objectExtend(AbstractResultAwareRow.prototype, {
434
435
    initialize: function(trElement) {
436
        this.trElement = trElement;
437
    },
438
439
    setStatus: function(status) {
440
        this.unselect();
441
        this.trElement.className = this.trElement.className.replace(/status_[a-z]+/, "");
442
        if (status) {
443
            addClassName(this.trElement, "status_" + status);
444
        }
445
    },
446
447
    select: function() {
448
        addClassName(this.trElement, "selected");
449
        safeScrollIntoView(this.trElement);
450
    },
451
452
    unselect: function() {
453
        removeClassName(this.trElement, "selected");
454
    },
455
456
    markPassed: function() {
457
        this.setStatus("passed");
458
    },
459
460
    markDone: function() {
461
        this.setStatus("done");
462
    },
463
464
    markFailed: function() {
465
        this.setStatus("failed");
466
    }
467
468
});
469
470
var TitleRow = classCreate();
471
objectExtend(TitleRow.prototype, AbstractResultAwareRow.prototype);
472
objectExtend(TitleRow.prototype, {
473
474
    initialize: function(trElement) {
475
        this.trElement = trElement;
476
        trElement.className = "title";
477
    }
478
479
});
480
481
var HtmlTestCaseRow = classCreate();
482
objectExtend(HtmlTestCaseRow.prototype, AbstractResultAwareRow.prototype);
483
objectExtend(HtmlTestCaseRow.prototype, {
484
485
    getCommand: function () {
486
        return new SeleniumCommand(getText(this.trElement.cells[0]),
487
                getText(this.trElement.cells[1]),
488
                getText(this.trElement.cells[2]),
489
                this.isBreakpoint());
490
    },
491
492
    markFailed: function(errorMsg) {
493
        AbstractResultAwareRow.prototype.markFailed.call(this, errorMsg);
494
        this.setMessage(errorMsg);
495
    },
496
497
    setMessage: function(message) {
498
        setText(this.trElement.cells[2], message);
499
    },
500
501
    reset: function() {
502
        this.setStatus(null);
503
        var thirdCell = this.trElement.cells[2];
504
        if (thirdCell) {
505
            if (thirdCell.originalHTML) {
506
                thirdCell.innerHTML = thirdCell.originalHTML;
507
            } else {
508
                thirdCell.originalHTML = thirdCell.innerHTML;
509
            }
510
        }
511
    },
512
513
    onClick: function() {
514
        if (this.trElement.isBreakpoint == undefined) {
515
            this.trElement.isBreakpoint = true;
516
            addClassName(this.trElement, "breakpoint");
517
        } else {
518
            this.trElement.isBreakpoint = undefined;
519
            removeClassName(this.trElement, "breakpoint");
520
        }
521
    },
522
523
    addBreakpointSupport: function() {
524
        elementSetStyle(this.trElement, {"cursor" : "pointer"});
525
        this.trElement.onclick = fnBindAsEventListener(function() {
526
            this.onClick();
527
        }, this);
528
    },
529
530
    isBreakpoint: function() {
531
        if (this.trElement.isBreakpoint == undefined || this.trElement.isBreakpoint == null) {
532
            return false
533
        }
534
        return this.trElement.isBreakpoint;
535
    }
536
});
537
538
var HtmlTestSuiteRow = classCreate();
539
objectExtend(HtmlTestSuiteRow.prototype, AbstractResultAwareRow.prototype);
540
objectExtend(HtmlTestSuiteRow.prototype, {
541
542
    initialize: function(trElement, testFrame, htmlTestSuite) {
543
        this.trElement = trElement;
544
        this.testFrame = testFrame;
545
        this.htmlTestSuite = htmlTestSuite;
546
        this.link = trElement.getElementsByTagName("a")[0];
547
        this.link.onclick = fnBindAsEventListener(this._onClick, this);
548
    },
549
550
    reset: function() {
551
        this.setStatus(null);
552
    },
553
554
    _onClick: function() {
555
        this.loadTestCase(null);
556
        return false;
557
    },
558
559
    loadTestCase: function(onloadFunction) {
560
        this.htmlTestSuite.unselectCurrentRow();
561
        this.select();
562
        this.htmlTestSuite.currentRowInSuite = this.trElement.rowIndex - 1;
563
        // If the row has a stored results table, use that
564
        var resultsFromPreviousRun = this.trElement.cells[1];
565
        if (resultsFromPreviousRun) {
566
            // todo: delegate to TestFrame, e.g.
567
            //   this.testFrame.restoreTestCase(resultsFromPreviousRun.innerHTML);
568
            var testBody = this.testFrame.getDocument().body;
569
            testBody.innerHTML = resultsFromPreviousRun.innerHTML;
570
            this.testFrame._onLoad();
571
            if (onloadFunction) {
572
                onloadFunction();
573
            }
574
        } else {
575
            this.testFrame.load(this.link.href, onloadFunction);
576
        }
577
    },
578
579
    saveTestResults: function() {
580
        // todo: GLOBAL ACCESS!
581
        var resultHTML = this.testFrame.getDocument().body.innerHTML;
582
        if (!resultHTML) return;
583
584
        // todo: why create this div?
585
        var divElement = this.trElement.ownerDocument.createElement("div");
586
        divElement.innerHTML = resultHTML;
587
588
        var hiddenCell = this.trElement.ownerDocument.createElement("td");
589
        hiddenCell.appendChild(divElement);
590
        hiddenCell.style.display = "none";
591
592
        this.trElement.appendChild(hiddenCell);
593
    }
594
595
});
596
597
var HtmlTestSuite = classCreate();
598
objectExtend(HtmlTestSuite.prototype, {
599
600
    initialize: function(suiteDocument) {
601
        this.suiteDocument = suiteDocument;
602
        this.suiteRows = this._collectSuiteRows();
603
        var testTable = this.getTestTable();
604
        if (!testTable) return;
605
        this.titleRow = new TitleRow(testTable.rows[0]);
606
        this.reset();
607
    },
608
609
    reset: function() {
610
        this.failed = false;
611
        this.currentRowInSuite = -1;
612
        this.titleRow.setStatus(null);
613
        for (var i = 0; i < this.suiteRows.length; i++) {
614
            var row = this.suiteRows[i];
615
            row.reset();
616
        }
617
    },
618
619
    getSuiteRows: function() {
620
        return this.suiteRows;
621
    },
622
623
    getTestTable: function() {
624
        var tables = sel$A(this.suiteDocument.getElementsByTagName("table"));
625
        return tables[0];
626
    },
627
628
    isAvailable: function() {
629
        return this.getTestTable() != null;
630
    },
631
632
    _collectSuiteRows: function () {
633
        var result = [];
634
        var tables = sel$A(this.suiteDocument.getElementsByTagName("table"));
635
        var testTable = tables[0];
636
        if (!testTable) return;
637
        for (rowNum = 1; rowNum < testTable.rows.length; rowNum++) {
0 ignored issues
show
Bug introduced by
The variable rowNum seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.rowNum.
Loading history...
638
            var rowElement = testTable.rows[rowNum];
639
            result.push(new HtmlTestSuiteRow(rowElement, testFrame, this));
640
        }
641
        
642
        // process the unsuited rows as well
643
        for (var tableNum = 1; tableNum < sel$A(this.suiteDocument.getElementsByTagName("table")).length; tableNum++) {
644
            testTable = tables[tableNum];
645
            for (rowNum = 1; rowNum < testTable.rows.length; rowNum++) {
646
                var rowElement = testTable.rows[rowNum];
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable rowElement already seems to be declared on line 638. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
647
                new HtmlTestSuiteRow(rowElement, testFrame, this);
0 ignored issues
show
Unused Code Best Practice introduced by
The object created with new HtmlTestSuiteRow(rowElement, testFrame, this) is not used but discarded. Consider invoking another function instead of a constructor if you are doing this purely for side effects.
Loading history...
648
            }
649
        }
650
        return result;
651
    },
652
653
    getCurrentRow: function() {
654
        if (this.currentRowInSuite == -1) {
655
            return null;
656
        }
657
        return this.suiteRows[this.currentRowInSuite];
658
    },
659
660
    unselectCurrentRow: function() {
661
        var currentRow = this.getCurrentRow()
662
        if (currentRow) {
663
            currentRow.unselect();
664
        }
665
    },
666
667
    markFailed: function() {
668
        this.failed = true;
669
        this.titleRow.markFailed();
670
    },
671
672
    markDone: function() {
673
        if (!this.failed) {
674
            this.titleRow.markPassed();
675
        }
676
    },
677
678
    _startCurrentTestCase: function() {
679
        this.getCurrentRow().loadTestCase(fnBind(htmlTestRunner.startTest, htmlTestRunner));
680
    },
681
682
    _onTestSuiteComplete: function() {
683
        this.markDone();
684
        new SeleniumTestResult(this.failed, this.getTestTable()).post();
685
    },
686
687
    updateSuiteWithResultOfPreviousTest: function() {
688
        if (this.currentRowInSuite >= 0) {
689
            this.getCurrentRow().saveTestResults();
690
        }
691
    },
692
693
    runNextTestInSuite: function() {
694
        this.currentRowInSuite++;
695
696
        // If we are done with all of the tests, set the title bar as pass or fail
697
        if (this.currentRowInSuite >= this.suiteRows.length) {
698
            this._onTestSuiteComplete();
699
        } else {
700
            this._startCurrentTestCase();
701
        }
702
    }
703
704
705
706
});
707
708
var SeleniumTestResult = classCreate();
709
objectExtend(SeleniumTestResult.prototype, {
710
711
// Post the results to a servlet, CGI-script, etc.  The URL of the
712
// results-handler defaults to "/postResults", but an alternative location
713
// can be specified by providing a "resultsUrl" query parameter.
714
//
715
// Parameters passed to the results-handler are:
716
//      result:         passed/failed depending on whether the suite passed or failed
717
//      totalTime:      the total running time in seconds for the suite.
718
//
719
//      numTestPasses:  the total number of tests which passed.
720
//      numTestFailures: the total number of tests which failed.
721
//
722
//      numCommandPasses: the total number of commands which passed.
723
//      numCommandFailures: the total number of commands which failed.
724
//      numCommandErrors: the total number of commands which errored.
725
//
726
//      suite:      the suite table, including the hidden column of test results
727
//      testTable.1 to testTable.N: the individual test tables
728
//
729
    initialize: function (suiteFailed, suiteTable) {
730
        this.controlPanel = htmlTestRunner.controlPanel;
731
        this.metrics = htmlTestRunner.metrics;
732
        this.suiteFailed = suiteFailed;
733
        this.suiteTable = suiteTable;
734
    },
735
736
    post: function () {
737
        if (!this.controlPanel.isAutomatedRun()) {
738
            return;
739
        }
740
        var form = document.createElement("form");
741
        document.body.appendChild(form);
742
743
        form.id = "resultsForm";
744
        form.method = "post";
745
        form.target = "selenium_myiframe";
746
747
        var resultsUrl = this.controlPanel.getResultsUrl();
748
        if (!resultsUrl) {
749
            resultsUrl = "./postResults";
750
        }
751
752
        var actionAndParameters = resultsUrl.split('?', 2);
753
        form.action = actionAndParameters[0];
754
        var resultsUrlQueryString = actionAndParameters[1];
755
756
        form.createHiddenField = function(name, value) {
757
            input = document.createElement("input");
0 ignored issues
show
Bug introduced by
The variable input seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.input.
Loading history...
758
            input.type = "hidden";
759
            input.name = name;
760
            input.value = value;
761
            this.appendChild(input);
762
        };
763
764
        if (resultsUrlQueryString) {
765
            var clauses = resultsUrlQueryString.split('&');
766
            for (var i = 0; i < clauses.length; i++) {
767
                var keyValuePair = clauses[i].split('=', 2);
768
                var key = unescape(keyValuePair[0]);
769
                var value = unescape(keyValuePair[1]);
770
                form.createHiddenField(key, value);
771
            }
772
        }
773
774
        form.createHiddenField("selenium.version", Selenium.version);
775
        form.createHiddenField("selenium.revision", Selenium.revision);
776
777
        form.createHiddenField("result", this.suiteFailed ? "failed" : "passed");
778
779
        form.createHiddenField("totalTime", Math.floor((this.metrics.currentTime - this.metrics.startTime) / 1000));
780
        form.createHiddenField("numTestPasses", this.metrics.numTestPasses);
781
        form.createHiddenField("numTestFailures", this.metrics.numTestFailures);
782
        form.createHiddenField("numCommandPasses", this.metrics.numCommandPasses);
783
        form.createHiddenField("numCommandFailures", this.metrics.numCommandFailures);
784
        form.createHiddenField("numCommandErrors", this.metrics.numCommandErrors);
785
786
        // Create an input for each test table.  The inputs are named
787
        // testTable.1, testTable.2, etc.
788
        for (rowNum = 1; rowNum < this.suiteTable.rows.length; rowNum++) {
0 ignored issues
show
Bug introduced by
The variable rowNum seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.rowNum.
Loading history...
789
            // If there is a second column, then add a new input
790
            if (this.suiteTable.rows[rowNum].cells.length > 1) {
791
                var resultCell = this.suiteTable.rows[rowNum].cells[1];
792
                form.createHiddenField("testTable." + rowNum, resultCell.innerHTML);
793
                // remove the resultCell, so it's not included in the suite HTML
794
                resultCell.parentNode.removeChild(resultCell);
795
            }
796
        }
797
798
        form.createHiddenField("numTestTotal", rowNum-1);
799
800
        // Add HTML for the suite itself
801
        form.createHiddenField("suite", this.suiteTable.parentNode.innerHTML);
802
803
        var logMessages = [];
804
        while (LOG.pendingMessages.length > 0) {
805
            var msg = LOG.pendingMessages.shift();
806
            logMessages.push(msg.type);
807
            logMessages.push(": ");
808
            logMessages.push(msg.msg);
809
            logMessages.push('\n');
810
        }
811
        var logOutput = logMessages.join("");
812
        form.createHiddenField("log", logOutput);
813
814
        if (this.controlPanel.shouldSaveResultsToFile()) {
815
            this._saveToFile(resultsUrl, form);
816
        } else {
817
            form.submit();
818
        }
819
        document.body.removeChild(form);
820
        if (this.controlPanel.closeAfterTests()) {
821
            window.top.close();
822
        }
823
    },
824
825
    _saveToFile: function (fileName, form) {
826
        // This only works when run as an IE HTA
827
        var inputs = new Object();
828
        for (var i = 0; i < form.elements.length; i++) {
829
            inputs[form.elements[i].name] = form.elements[i].value;
830
        }
831
        
832
        var objFSO = new ActiveXObject("Scripting.FileSystemObject")
833
        
834
        // DGF get CSS
835
        var styles = "";
836
        try {
837
            var styleSheetPath = window.location.pathname.replace(/[^\/\\]+$/, "selenium-test.css");
838
            if (window.location.protocol == "file:") {
839
                var stylesFile = objFSO.OpenTextFile(styleSheetPath, 1);
840
                styles = stylesFile.ReadAll();
841
            } else {
842
                var xhr = XmlHttp.create();
843
                xhr.open("GET", styleSheetPath, false);
844
                xhr.send("");
845
                styles = xhr.responseText;
846
            }
847
        } catch (e) {}
0 ignored issues
show
Coding Style Comprehensibility Best Practice introduced by
Empty catch clauses should be used with caution; consider adding a comment why this is needed.
Loading history...
848
        
849
        var scriptFile = objFSO.CreateTextFile(fileName);
850
        
851
        
852
        scriptFile.WriteLine("<html><head><title>Test suite results</title><style>");
853
        scriptFile.WriteLine(styles);
854
        scriptFile.WriteLine("</style>");
855
        scriptFile.WriteLine("<body>\n<h1>Test suite results</h1>" +
856
             "\n\n<table>\n<tr>\n<td>result:</td>\n<td>" + inputs["result"] + "</td>\n" +
857
             "</tr>\n<tr>\n<td>totalTime:</td>\n<td>" + inputs["totalTime"] + "</td>\n</tr>\n" +
858
             "<tr>\n<td>numTestTotal:</td>\n<td>" + inputs["numTestTotal"] + "</td>\n</tr>\n" +
859
             "<tr>\n<td>numTestPasses:</td>\n<td>" + inputs["numTestPasses"] + "</td>\n</tr>\n" +
860
             "<tr>\n<td>numTestFailures:</td>\n<td>" + inputs["numTestFailures"] + "</td>\n</tr>\n" +
861
             "<tr>\n<td>numCommandPasses:</td>\n<td>" + inputs["numCommandPasses"] + "</td>\n</tr>\n" +
862
             "<tr>\n<td>numCommandFailures:</td>\n<td>" + inputs["numCommandFailures"] + "</td>\n</tr>\n" +
863
             "<tr>\n<td>numCommandErrors:</td>\n<td>" + inputs["numCommandErrors"] + "</td>\n</tr>\n" +
864
             "<tr>\n<td>" + inputs["suite"] + "</td>\n<td>&nbsp;</td>\n</tr></table><table>");
865
        var testNum = inputs["numTestTotal"];
866
        
867
        for (var rowNum = 1; rowNum <= testNum; rowNum++) {
868
            scriptFile.WriteLine("<tr>\n<td>" + inputs["testTable." + rowNum] + "</td>\n<td>&nbsp;</td>\n</tr>");
869
        }
870
        scriptFile.WriteLine("</table><pre>");
871
        var log = inputs["log"];
872
        log=log.replace(/&/gm,"&amp;").replace(/</gm,"&lt;").replace(/>/gm,"&gt;").replace(/"/gm,"&quot;").replace(/'/gm,"&apos;");
873
        scriptFile.WriteLine(log);
874
        scriptFile.WriteLine("</pre></body></html>");
875
        scriptFile.Close();
876
    }
877
});
878
879
/** HtmlTestCase encapsulates an HTML test document */
880
var HtmlTestCase = classCreate();
881
objectExtend(HtmlTestCase.prototype, {
882
883
    initialize: function(testWindow, htmlTestSuiteRow) {
884
        if (testWindow == null) {
885
            throw "testWindow should not be null";
886
        }
887
        if (htmlTestSuiteRow == null) {
888
            throw "htmlTestSuiteRow should not be null";
889
        }
890
        this.testWindow = testWindow;
891
        this.testDocument = testWindow.document;
892
        this.pathname = "'unknown'";
893
        try {
894
            if (this.testWindow.location) {
895
                this.pathname = this.testWindow.location.pathname;
896
            }
897
        } catch (e) {}
0 ignored issues
show
Coding Style Comprehensibility Best Practice introduced by
Empty catch clauses should be used with caution; consider adding a comment why this is needed.
Loading history...
898
            
899
        this.htmlTestSuiteRow = htmlTestSuiteRow;
900
        this.headerRow = new TitleRow(this.testDocument.getElementsByTagName("tr")[0]);
901
        this.commandRows = this._collectCommandRows();
902
        this.nextCommandRowIndex = 0;
903
        this._addBreakpointSupport();
904
    },
905
906
    _collectCommandRows: function () {
907
        var commandRows = [];
908
        var tables = sel$A(this.testDocument.getElementsByTagName("table"));
909
        var self = this;
910
        for (var i = 0; i < tables.length; i++) {
911
            var table = tables[i];
912
            var tableRows = sel$A(table.rows);
913
            for (var j = 0; j < tableRows.length; j++) {
914
                var candidateRow = tableRows[j];
915
                if (self.isCommandRow(candidateRow)) {
916
                    commandRows.push(new HtmlTestCaseRow(candidateRow));
917
                }
918
            }
919
        }
920
        return commandRows;
921
    },
922
923
    isCommandRow:  function (row) {
924
        return row.cells.length >= 3;
925
    },
926
927
    reset: function() {
928
        /**
929
         * reset the test to runnable state
930
         */
931
        this.nextCommandRowIndex = 0;
932
933
        this.setStatus('');
934
        for (var i = 0; i < this.commandRows.length; i++) {
935
            var row = this.commandRows[i];
936
            row.reset();
937
        }
938
939
        // remove any additional fake "error" row added to the end of the document
940
        var errorElement = this.testDocument.getElementById('error');
941
        if (errorElement) {
942
            errorElement.parentNode.removeChild(errorElement);
943
        }
944
    },
945
946
    getCommandRows: function () {
947
        return this.commandRows;
948
    },
949
950
    setStatus: function(status) {
951
        this.headerRow.setStatus(status);
952
    },
953
954
    markFailed: function() {
955
        this.setStatus("failed");
956
        this.htmlTestSuiteRow.markFailed();
957
    },
958
959
    markPassed: function() {
960
        this.setStatus("passed");
961
        this.htmlTestSuiteRow.markPassed();
962
    },
963
964
    addErrorMessage: function(errorMsg, currentRow) {
965
        errorMsg = errorMsg.replace(/ /g, String.fromCharCode(160)).replace("\n", '\\n');
966
        if (currentRow) {
967
            currentRow.markFailed(errorMsg);
968
        } else {
969
            var errorElement = this.testDocument.createElement("p");
970
            errorElement.id = "error";
971
            setText(errorElement, errorMsg);
972
            this.testDocument.body.appendChild(errorElement);
973
            errorElement.className = "status_failed";
974
        }
975
    },
976
977
    _addBreakpointSupport: function() {
978
        for (var i = 0; i < this.commandRows.length; i++) {
979
            var row = this.commandRows[i];
980
            row.addBreakpointSupport();
981
        }
982
    },
983
984
    hasMoreCommandRows: function() {
985
        return this.nextCommandRowIndex < this.commandRows.length;
986
    },
987
988
    getNextCommandRow: function() {
989
        if (this.hasMoreCommandRows()) {
990
            return this.commandRows[this.nextCommandRowIndex++];
991
        }
992
        return null;
993
    }
994
995
});
996
997
998
// TODO: split out an JavascriptTestCase class to handle the "sejs" stuff
999
1000
var get_new_rows = function() {
1001
    var row_array = new Array();
0 ignored issues
show
Coding Style Best Practice introduced by
Using the Array constructor is generally discouraged. Consider using an array literal instead.
Loading history...
1002
    for (var i = 0; i < new_block.length; i++) {
1003
1004
        var new_source = (new_block[i][0].tokenizer.source.slice(new_block[i][0].start,
1005
                new_block[i][0].end));
1006
1007
        var row = '<td style="display:none;" class="js">getEval</td>' +
1008
                  '<td style="display:none;">currentTest.doNextCommand()</td>' +
1009
                  '<td style="white-space: pre;">' + new_source + '</td>' +
1010
                  '<td></td>'
1011
1012
        row_array.push(row);
1013
    }
1014
    return row_array;
1015
};
1016
1017
1018
var Metrics = classCreate();
1019
objectExtend(Metrics.prototype, {
1020
    initialize: function() {
1021
        // The number of tests run
1022
        this.numTestPasses = 0;
1023
        // The number of tests that have failed
1024
        this.numTestFailures = 0;
1025
        // The number of commands which have passed
1026
        this.numCommandPasses = 0;
1027
        // The number of commands which have failed
1028
        this.numCommandFailures = 0;
1029
        // The number of commands which have caused errors (element not found)
1030
        this.numCommandErrors = 0;
1031
        // The time that the test was started.
1032
        this.startTime = null;
1033
        // The current time.
1034
        this.currentTime = null;
1035
    },
1036
1037
    printMetrics: function() {
1038
        setText(sel$('commandPasses'), this.numCommandPasses);
1039
        setText(sel$('commandFailures'), this.numCommandFailures);
1040
        setText(sel$('commandErrors'), this.numCommandErrors);
1041
        setText(sel$('testRuns'), this.numTestPasses + this.numTestFailures);
1042
        setText(sel$('testFailures'), this.numTestFailures);
1043
1044
        this.currentTime = new Date().getTime();
1045
1046
        var timeDiff = this.currentTime - this.startTime;
1047
        var totalSecs = Math.floor(timeDiff / 1000);
1048
1049
        var minutes = Math.floor(totalSecs / 60);
1050
        var seconds = totalSecs % 60;
1051
1052
        setText(sel$('elapsedTime'), this._pad(minutes) + ":" + this._pad(seconds));
1053
    },
1054
1055
// Puts a leading 0 on num if it is less than 10
1056
    _pad: function(num) {
1057
        return (num > 9) ? num : "0" + num;
1058
    },
1059
1060
    resetMetrics: function() {
1061
        this.numTestPasses = 0;
1062
        this.numTestFailures = 0;
1063
        this.numCommandPasses = 0;
1064
        this.numCommandFailures = 0;
1065
        this.numCommandErrors = 0;
1066
        this.startTime = new Date().getTime();
1067
    }
1068
1069
});
1070
1071
var HtmlRunnerCommandFactory = classCreate();
1072
objectExtend(HtmlRunnerCommandFactory.prototype, {
1073
1074
    initialize: function(seleniumCommandFactory, testLoop) {
1075
        this.seleniumCommandFactory = seleniumCommandFactory;
1076
        this.testLoop = testLoop;
1077
        this.handlers = {};
1078
        //todo: register commands
1079
    },
1080
1081
    getCommandHandler: function(command) {
1082
        if (this.handlers[command]) {
1083
            return this.handlers[command];
1084
        }
1085
        return this.seleniumCommandFactory.getCommandHandler(command);
1086
    }
1087
1088
});
1089
1090
var HtmlRunnerTestLoop = classCreate();
1091
objectExtend(HtmlRunnerTestLoop.prototype, new TestLoop());
1092
objectExtend(HtmlRunnerTestLoop.prototype, {
1093
    initialize: function(htmlTestCase, metrics, seleniumCommandFactory) {
1094
1095
        this.commandFactory = new HtmlRunnerCommandFactory(seleniumCommandFactory, this);
1096
        this.metrics = metrics;
1097
1098
        this.htmlTestCase = htmlTestCase;
1099
        LOG.info("Starting test " + htmlTestCase.pathname);
1100
1101
        this.currentRow = null;
1102
        this.currentRowIndex = 0;
1103
1104
        // used for selenium tests in javascript
1105
        this.currentItem = null;
1106
        this.commandAgenda = new Array();
0 ignored issues
show
Coding Style Best Practice introduced by
Using the Array constructor is generally discouraged. Consider using an array literal instead.
Loading history...
1107
        this.expectedFailure = null;
1108
        this.expectedFailureType = null;
1109
1110
        this.htmlTestCase.reset();
1111
    },
1112
1113
    _advanceToNextRow: function() {
1114
        if (this.htmlTestCase.hasMoreCommandRows()) {
1115
            this.currentRow = this.htmlTestCase.getNextCommandRow();
1116
            if (this.sejsElement) {
1117
                this.currentItem = agenda.pop();
1118
                this.currentRowIndex++;
1119
            }
1120
        } else {
1121
            this.currentRow = null;
1122
            this.currentItem = null;
1123
        }
1124
    },
1125
1126
    nextCommand : function() {
1127
        this._advanceToNextRow();
1128
        if (this.currentRow == null) {
1129
            return null;
1130
        }
1131
        return this.currentRow.getCommand();
1132
    },
1133
1134
    commandStarted : function() {
1135
        sel$('pauseTest').disabled = false;
1136
        this.currentRow.select();
1137
        this.metrics.printMetrics();
1138
    },
1139
1140
    commandComplete : function(result) {
1141
        this._checkExpectedFailure(result);
1142
        if (result.failed) {
1143
            this.metrics.numCommandFailures += 1;
1144
            this._recordFailure(result.failureMessage);
1145
        } else if (result.passed) {
1146
            this.metrics.numCommandPasses += 1;
1147
            this.currentRow.markPassed();
1148
        } else {
1149
            this.currentRow.markDone();
1150
        }
1151
    },
1152
1153
    _checkExpectedFailure : function(result) {
1154
        if (this.expectedFailure != null) {
1155
            if (this.expectedFailureJustSet) {
1156
                this.expectedFailureJustSet = false;
1157
                return;
1158
            }
1159
            if (!result.failed) {
1160
                result.passed = false;
1161
                result.failed = true;
1162
                result.failureMessage = "Expected " + this.expectedFailureType + " did not occur.";
1163
            } else {
1164
                if (PatternMatcher.matches(this.expectedFailure, result.failureMessage)) {
1165
                    var failureType = result.error ? "error" : "failure";
1166
                    if (failureType == this.expectedFailureType) {
1167
                        result.failed = false;
1168
                        result.passed = true;
1169
                    } else {
1170
                        result.failed = true;
1171
                        result.failureMessage = "Expected "+this.expectedFailureType+", but "+failureType+" occurred instead";
1172
                    }
1173
                } else {
1174
                    result.failed = true;
1175
                    result.failureMessage = "Expected " + this.expectedFailureType + " message '" + this.expectedFailure
1176
                                            + "' but was '" + result.failureMessage + "'";
1177
                }
1178
            }
1179
            this.expectedFailure = null;
1180
            this.expectedFailureType = null;
1181
        }
1182
    },
1183
1184
    commandError : function(errorMessage) {
1185
        var tempResult = {};
1186
        tempResult.passed = false;
1187
        tempResult.failed = true;
1188
        tempResult.error = true;
1189
        tempResult.failureMessage = errorMessage;
1190
        this._checkExpectedFailure(tempResult);
1191
        if (tempResult.passed) {
1192
            this.currentRow.markDone();
1193
            return true;
1194
        }
1195
        errorMessage = tempResult.failureMessage;
1196
        this.metrics.numCommandErrors += 1;
1197
        this._recordFailure(errorMessage);
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
1198
    },
1199
1200
    _recordFailure : function(errorMsg) {
1201
        LOG.warn("currentTest.recordFailure: " + errorMsg);
1202
        htmlTestRunner.markFailed();
1203
        this.htmlTestCase.addErrorMessage(errorMsg, this.currentRow);
1204
    },
1205
1206
    testComplete : function() {
1207
        sel$('pauseTest').disabled = true;
1208
        sel$('stepTest').disabled = true;
1209
        if (htmlTestRunner.testFailed) {
1210
            this.htmlTestCase.markFailed();
1211
            this.metrics.numTestFailures += 1;
1212
        } else {
1213
            this.htmlTestCase.markPassed();
1214
            this.metrics.numTestPasses += 1;
1215
        }
1216
1217
        this.metrics.printMetrics();
1218
1219
        window.setTimeout(function() {
1220
            htmlTestRunner.runNextTest();
1221
        }, 1);
1222
    },
1223
1224
    getCommandInterval : function() {
1225
        return htmlTestRunner.controlPanel.runInterval;
1226
    },
1227
1228
    pause : function() {
1229
        htmlTestRunner.controlPanel.pauseCurrentTest();
1230
    },
1231
1232
    doNextCommand: function() {
1233
        var _n = this.currentItem[0];
1234
        var _x = this.currentItem[1];
1235
1236
        new_block = new Array()
0 ignored issues
show
Coding Style Best Practice introduced by
Using the Array constructor is generally discouraged. Consider using an array literal instead.
Loading history...
Bug introduced by
The variable new_block seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.new_block.
Loading history...
1237
        execute(_n, _x);
1238
        if (new_block.length > 0) {
1239
            var the_table = this.htmlTestCase.testDocument.getElementById("se-js-table")
1240
            var loc = this.currentRowIndex
1241
            var new_rows = get_new_rows()
1242
1243
            // make the new statements visible on screen...
1244
            for (var i = 0; i < new_rows.length; i++) {
1245
                the_table.insertRow(loc + 1);
1246
                the_table.rows[loc + 1].innerHTML = new_rows[i];
1247
                this.commandRows.unshift(the_table.rows[loc + 1])
1248
            }
1249
1250
        }
1251
    }
1252
1253
});
1254
1255
Selenium.prototype.doPause = function(waitTime) {
1256
    /** Wait for the specified amount of time (in milliseconds)
1257
     * @param waitTime the amount of time to sleep (in milliseconds)
1258
     */
1259
    // todo: should not refer to currentTest directly
1260
    currentTest.pauseInterval = waitTime;
1261
};
1262
1263
Selenium.prototype.doBreak = function() {
1264
    /** Halt the currently running test, and wait for the user to press the Continue button.
1265
     * This command is useful for debugging, but be careful when using it, because it will
1266
     * force automated tests to hang until a user intervenes manually.
1267
     */
1268
    // todo: should not refer to controlPanel directly
1269
    htmlTestRunner.controlPanel.setToPauseAtNextCommand();
1270
};
1271
1272
Selenium.prototype.doStore = function(expression, variableName) {
1273
    /** This command is a synonym for storeExpression.
1274
     * @param expression the value to store
1275
     * @param variableName the name of a <a href="#storedVars">variable</a> in which the result is to be stored.
1276
     */
1277
    storedVars[variableName] = expression;
1278
}
1279
1280
/*
1281
 * Click on the located element, and attach a callback to notify
1282
 * when the page is reloaded.
1283
 */
1284
// DGF TODO this code has been broken for some time... what is it trying to accomplish?
1285
Selenium.prototype.XXXdoModalDialogTest = function(returnValue) {
1286
    this.browserbot.doModalDialogTest(returnValue);
1287
};
1288
1289
Selenium.prototype.doEcho = function(message) {
1290
    /** Prints the specified message into the third table cell in your Selenese tables.
1291
     * Useful for debugging.
1292
     * @param message the message to print
1293
     */
1294
    currentTest.currentRow.setMessage(message);
1295
}
1296
1297
/*
1298
 * doSetSpeed and getSpeed are already defined in selenium-api.js,
1299
 * so we're defining these functions in a tricky way so that doc.js doesn't
1300
 * try to read API doc from the function definitions here.
1301
 */
1302
Selenium.prototype._doSetSpeed = function(value) {
1303
    var milliseconds = parseInt(value);
1304
    if (milliseconds < 0) milliseconds = 0;
1305
    htmlTestRunner.controlPanel.speedController.setValue(milliseconds);
1306
    htmlTestRunner.controlPanel.setRunInterval(milliseconds);
1307
}
1308
Selenium.prototype.doSetSpeed = Selenium.prototype._doSetSpeed;
1309
1310
Selenium.prototype._getSpeed = function() {
1311
    return htmlTestRunner.controlPanel.runInterval;
1312
}
1313
Selenium.prototype.getSpeed = Selenium.prototype._getSpeed;
1314
1315
Selenium.prototype.assertSelected = function(selectLocator, optionLocator) {
1316
    /**
1317
     * Verifies that the selected option of a drop-down satisfies the optionSpecifier.  <i>Note that this command is deprecated; you should use assertSelectedLabel, assertSelectedValue, assertSelectedIndex, or assertSelectedId instead.</i>
1318
     *
1319
     * <p>See the select command for more information about option locators.</p>
1320
     *
1321
     * @param selectLocator an <a href="#locators">element locator</a> identifying a drop-down menu
1322
     * @param optionLocator an option locator, typically just an option label (e.g. "John Smith")
1323
     */
1324
    var element = this.page().findElement(selectLocator);
1325
    var locator = this.optionLocatorFactory.fromLocatorString(optionLocator);
1326
    if (element.selectedIndex == -1)
1327
    {
1328
        Assert.fail("No option selected");
1329
    }
1330
    locator.assertSelected(element);
1331
};
1332
1333
Selenium.prototype.assertFailureOnNext = function(message) {
1334
    /**
1335
     * Tell Selenium to expect a failure on the next command execution. 
1336
     * @param message The failure message we should expect.  This command will fail if the wrong failure message appears.
1337
     */
1338
    if (!message) {
1339
        throw new SeleniumError("Message must be provided");
1340
    }
1341
1342
    currentTest.expectedFailure = message;
1343
    currentTest.expectedFailureType = "failure";
1344
    currentTest.expectedFailureJustSet = true;
1345
};
1346
1347
Selenium.prototype.assertErrorOnNext = function(message) {
1348
    /**
1349
     * Tell Selenium to expect an error on the next command execution. 
1350
     * @param message The error message we should expect.  This command will fail if the wrong error message appears.
1351
     */
1352
     // This command temporarily installs a CommandFactory that generates
1353
     // CommandHandlers that expect an error.
1354
    if (!message) {
1355
        throw new SeleniumError("Message must be provided");
1356
    }
1357
1358
    currentTest.expectedFailure = message;
1359
    currentTest.expectedFailureType = "error";
1360
    currentTest.expectedFailureJustSet = true;
1361
};
1362
1363