|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this file, |
|
3 * You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 /* |
|
5 * The Marionette object, passed to the script context. |
|
6 */ |
|
7 |
|
8 this.Marionette = function Marionette(scope, window, context, logObj, timeout, |
|
9 heartbeatCallback, testName) { |
|
10 this.scope = scope; |
|
11 this.window = window; |
|
12 this.tests = []; |
|
13 this.logObj = logObj; |
|
14 this.context = context; |
|
15 this.timeout = timeout; |
|
16 this.heartbeatCallback = heartbeatCallback; |
|
17 this.testName = testName; |
|
18 this.TEST_UNEXPECTED_FAIL = "TEST-UNEXPECTED-FAIL"; |
|
19 this.TEST_PASS = "TEST-PASS"; |
|
20 this.TEST_KNOWN_FAIL = "TEST-KNOWN-FAIL"; |
|
21 } |
|
22 |
|
23 Marionette.prototype = { |
|
24 exports: ['ok', 'is', 'isnot', 'log', 'getLogs', 'generate_results', 'waitFor', |
|
25 'runEmulatorCmd', 'runEmulatorShell', 'TEST_PASS', 'TEST_KNOWN_FAIL', |
|
26 'TEST_UNEXPECTED_FAIL'], |
|
27 |
|
28 ok: function Marionette__ok(condition, name, passString, failString, diag) { |
|
29 this.heartbeatCallback(); |
|
30 if (typeof(diag) == "undefined") { |
|
31 diag = this.repr(condition) + " was " + !!condition + ", expected true"; |
|
32 } |
|
33 let test = {'result': !!condition, 'name': name, 'diag': diag}; |
|
34 this.logResult(test, |
|
35 typeof(passString) == "undefined" ? this.TEST_PASS : passString, |
|
36 typeof(failString) == "undefined" ? this.TEST_UNEXPECTED_FAIL : failString); |
|
37 this.tests.push(test); |
|
38 }, |
|
39 |
|
40 is: function Marionette__is(a, b, name, passString, failString) { |
|
41 this.heartbeatCallback(); |
|
42 let pass = (a == b); |
|
43 let diag = pass ? this.repr(a) + " should equal " + this.repr(b) |
|
44 : "got " + this.repr(a) + ", expected " + this.repr(b); |
|
45 this.ok(pass, name, passString, failString, diag); |
|
46 }, |
|
47 |
|
48 isnot: function Marionette__isnot (a, b, name, passString, failString) { |
|
49 this.heartbeatCallback(); |
|
50 let pass = (a != b); |
|
51 let diag = pass ? this.repr(a) + " should not equal " + this.repr(b) |
|
52 : "didn't expect " + this.repr(a) + ", but got it"; |
|
53 this.ok(pass, name, passString, failString, diag); |
|
54 }, |
|
55 |
|
56 log: function Marionette__log(msg, level) { |
|
57 this.heartbeatCallback(); |
|
58 dump("MARIONETTE LOG: " + (level ? level : "INFO") + ": " + msg + "\n"); |
|
59 if (this.logObj != null) { |
|
60 this.logObj.log(msg, level); |
|
61 } |
|
62 }, |
|
63 |
|
64 getLogs: function Marionette__getLogs() { |
|
65 this.heartbeatCallback(); |
|
66 if (this.logObj != null) { |
|
67 this.logObj.getLogs(); |
|
68 } |
|
69 }, |
|
70 |
|
71 generate_results: function Marionette__generate_results() { |
|
72 this.heartbeatCallback(); |
|
73 let passed = 0; |
|
74 let failed = 0; |
|
75 let failures = []; |
|
76 for (let i in this.tests) { |
|
77 if(this.tests[i].result) { |
|
78 passed++; |
|
79 } |
|
80 else { |
|
81 failed++; |
|
82 failures.push({'name': this.tests[i].name, |
|
83 'diag': this.tests[i].diag}); |
|
84 } |
|
85 } |
|
86 // Reset state in case this object is reused for more tests. |
|
87 this.tests = []; |
|
88 return {"passed": passed, "failed": failed, "failures": failures}; |
|
89 }, |
|
90 |
|
91 logToFile: function Marionette__logToFile(file) { |
|
92 this.heartbeatCallback(); |
|
93 //TODO |
|
94 }, |
|
95 |
|
96 logResult: function Marionette__logResult(test, passString, failString) { |
|
97 this.heartbeatCallback(); |
|
98 //TODO: dump to file |
|
99 let resultString = test.result ? passString : failString; |
|
100 let diagnostic = test.name + (test.diag ? " - " + test.diag : ""); |
|
101 let msg = resultString + " | " + this.testName + " | " + diagnostic; |
|
102 dump("MARIONETTE TEST RESULT:" + msg + "\n"); |
|
103 }, |
|
104 |
|
105 repr: function Marionette__repr(o) { |
|
106 if (typeof(o) == "undefined") { |
|
107 return "undefined"; |
|
108 } else if (o === null) { |
|
109 return "null"; |
|
110 } |
|
111 try { |
|
112 if (typeof(o.__repr__) == 'function') { |
|
113 return o.__repr__(); |
|
114 } else if (typeof(o.repr) == 'function' && o.repr != arguments.callee) { |
|
115 return o.repr(); |
|
116 } |
|
117 } catch (e) { |
|
118 } |
|
119 try { |
|
120 if (typeof(o.NAME) == 'string' && ( |
|
121 o.toString == Function.prototype.toString || |
|
122 o.toString == Object.prototype.toString |
|
123 )) { |
|
124 return o.NAME; |
|
125 } |
|
126 } catch (e) { |
|
127 } |
|
128 let ostring; |
|
129 try { |
|
130 ostring = (o + ""); |
|
131 } catch (e) { |
|
132 return "[" + typeof(o) + "]"; |
|
133 } |
|
134 if (typeof(o) == "function") { |
|
135 o = ostring.replace(/^\s+/, ""); |
|
136 let idx = o.indexOf("{"); |
|
137 if (idx != -1) { |
|
138 o = o.substr(0, idx) + "{...}"; |
|
139 } |
|
140 } |
|
141 return ostring; |
|
142 }, |
|
143 |
|
144 waitFor: function test_waitFor(callback, test, timeout) { |
|
145 this.heartbeatCallback(); |
|
146 if (test()) { |
|
147 callback(); |
|
148 return; |
|
149 } |
|
150 var now = Date.now(); |
|
151 var deadline = now + (typeof(timeout) == "undefined" ? this.timeout : timeout); |
|
152 if (deadline <= now) { |
|
153 dump("waitFor timeout: " + test.toString() + "\n"); |
|
154 // the script will timeout here, so no need to raise a separate |
|
155 // timeout exception |
|
156 return; |
|
157 } |
|
158 this.window.setTimeout(this.waitFor.bind(this), 100, callback, test, deadline - now); |
|
159 }, |
|
160 |
|
161 runEmulatorCmd: function runEmulatorCmd(cmd, callback) { |
|
162 this.heartbeatCallback(); |
|
163 this.scope.runEmulatorCmd(cmd, callback); |
|
164 }, |
|
165 |
|
166 runEmulatorShell: function runEmulatorShell(args, callback) { |
|
167 this.heartbeatCallback(); |
|
168 this.scope.runEmulatorShell(args, callback); |
|
169 }, |
|
170 |
|
171 }; |
|
172 |