OLD | NEW |
---|---|
1 /* | 1 /* |
2 * testharness-helpers contains various useful extensions to testharness.js to | 2 * testharness-helpers contains various useful extensions to testharness.js to |
3 * allow them to be used across multiple tests before they have been | 3 * allow them to be used across multiple tests before they have been |
4 * upstreamed. This file is intended to be usable from both document and worker | 4 * upstreamed. This file is intended to be usable from both document and worker |
5 * environments, so code should for example not rely on the DOM. | 5 * environments, so code should for example not rely on the DOM. |
6 */ | 6 */ |
7 | 7 |
8 // 'promise_test' is a new kind of testharness test that handles some | 8 // A testharness test that simplifies testing with promises. |
9 // boilerplate for testing with promises. | 9 // |
10 // * The |func| argument should be a reference to a function that optionally | |
11 // takes a test object as an argument and returns a Promise (or really any | |
12 // thenable object). | |
13 // | |
14 // * Resolution of the promise completes the test. A rejection causes the test | |
15 // to fail. The test harness waits for the promise to resolve. | |
16 // | |
17 // * Assertions can be made at any point in the promise handlers. Assertions | |
18 // only need to be wrapped in test.step()s if the promise chain contains | |
jsbell
2014/10/20 18:20:40
test.step_func() ?
asanka
2014/10/22 22:35:31
Done.
| |
19 // rejection handlers. | |
20 // | |
21 // E.g.: | |
22 // promise_test(function(t) { | |
23 // return method_that_returns_a_promise() | |
24 // .then(function(result) { | |
25 // assert_equals(result, expected_result, "Should be expected."); | |
26 // }); | |
27 // }, 'Promise based test'); | |
10 function promise_test(func, name, properties) { | 28 function promise_test(func, name, properties) { |
11 properties = properties || {}; | 29 properties = properties || {}; |
12 var test = async_test(name, properties); | 30 var test = async_test(name, properties); |
13 Promise.resolve(test.step(func, test, test)) | 31 Promise.resolve(test.step(func, test, test)) |
14 .then(function() { test.done(); }) | 32 .then(function() { test.done(); }) |
15 .catch(test.step_func(function(value) { | 33 .catch(test.step_func(function(value) { |
16 throw value; | 34 throw value; |
17 })); | 35 })); |
18 } | 36 } |
19 | 37 |
20 // Returns a promise that fulfills after the provided |promise| is fulfilled. | 38 // Returns a promise that fulfills after the provided |promise| is fulfilled. |
21 // The |test| succeeds only if |promise| rejects with an exception matching | 39 // The |test| succeeds only if |promise| rejects with an exception matching |
22 // |code|. Accepted values for |code| follow those accepted for assert_throws(). | 40 // |code|. Accepted values for |code| follow those accepted for assert_throws(). |
23 // The optional |description| describes the test being performed. | 41 // The optional |description| describes the test being performed. |
42 // | |
24 // E.g.: | 43 // E.g.: |
25 // assert_promise_rejects( | 44 // assert_promise_rejects( |
26 // new Promise(...), // something that should throw an exception. | 45 // new Promise(...), // something that should throw an exception. |
27 // 'NotFoundError', | 46 // 'NotFoundError', |
28 // 'Should throw NotFoundError.'); | 47 // 'Should throw NotFoundError.'); |
29 // | 48 // |
30 // assert_promise_rejects( | 49 // assert_promise_rejects( |
31 // new Promise(...), | 50 // new Promise(...), |
32 // new TypeError(), | 51 // new TypeError(), |
33 // 'Should throw TypeError'); | 52 // 'Should throw TypeError'); |
34 function assert_promise_rejects(promise, code, description) { | 53 function assert_promise_rejects(promise, code, description) { |
35 return promise.then( | 54 return promise.then( |
36 function() { | 55 function() { |
37 throw 'assert_promise_rejects: ' + description + ' Promise did not reject. '; | 56 throw 'assert_promise_rejects: ' + description + ' Promise did not reject. '; |
38 }, | 57 }, |
39 function(e) { | 58 function(e) { |
40 if (code !== undefined) { | 59 if (code !== undefined) { |
41 assert_throws(code, function() { throw e; }, description); | 60 assert_throws(code, function() { throw e; }, description); |
42 } | 61 } |
43 }); | 62 }); |
44 } | 63 } |
64 | |
65 // Asserts that two objects |actual| and |expected| are weakly equal under the | |
66 // following definition: | |
67 // | |
68 // |a| and |b| are weakly equal if any of the following are true: | |
69 // 1. If |a| is not an 'object', and |a| === |b|. | |
70 // 2. If |a| is an 'object', and all of the following are true: | |
71 // 2.1 |a.p| is weakly equal to |b.p| for all own properties |p| of |a|. | |
72 // 2.2 Every own property of |b| is an own property of |a|. | |
73 // | |
74 // This is a replacement for the the version of assert_object_equals() in | |
75 // testharness.js. The latter doesn't handle own properties correctly. I.e. if | |
76 // |a.p| is not an own property, it still requires that |b.p| be an own | |
77 // property. | |
78 // | |
79 // Note that |actual| must not contain cyclic references. | |
80 self.assert_object_equals = function(actual, expected, description) { | |
81 var object_stack = []; | |
82 | |
83 function _is_equal(actual, expected, prefix) { | |
84 if (typeof actual !== 'object') { | |
85 assert_equals(actual, expected, prefix); | |
86 return; | |
87 } | |
88 assert_true(typeof expected === 'object', prefix); | |
89 assert_equals(object_stack.indexOf(actual), -1, | |
90 prefix + ' must not contain cyclic references.'); | |
91 | |
92 object_stack.push(actual); | |
93 | |
94 Object.getOwnPropertyNames(expected).forEach(function(property) { | |
95 assert_own_property(actual, property, prefix); | |
96 _is_equal(actual[property], expected[property], | |
97 prefix + '.' + property); | |
98 }); | |
99 Object.getOwnPropertyNames(actual).forEach(function(property) { | |
100 assert_own_property(expected, property, prefix); | |
101 }); | |
102 | |
103 object_stack.pop(); | |
104 } | |
105 | |
106 _is_equal(actual, expected, | |
107 (description ? description + ' :' : '') + '[object]'); | |
108 }; | |
109 | |
110 // Equivalent to assert_in_array, but uses a weaker equivalence relation | |
111 // (assert_object_equals) than '==='. | |
112 function assert_object_in_array(actual, expected_array, description) { | |
113 assert_true(expected_array.some(function(element) { | |
114 try { | |
115 assert_object_equals(actual, element); | |
116 return true; | |
117 } catch (e) { | |
118 return false; | |
119 } | |
120 }), description); | |
121 } | |
122 | |
123 // Assert that the two arrays |actual| and |expected| contain the same set of | |
124 // elements as determined by assert_object_equals. The order is not significant. | |
125 // | |
126 // |expected| is assumed to not contain any duplicates as determined by | |
127 // assert_object_equals(). | |
128 function assert_array_equivalent(actual, expected, description) { | |
129 assert_true(Array.isArray(actual), description); | |
130 assert_equals(actual.length, expected.length, description); | |
131 expected.forEach(function(expected_element) { | |
132 // assert_in_array treats the first argument as being 'actual', and the | |
133 // second as being 'expected array'. We are switching them around becaus | |
134 // we want to be resilient against the |actual| array containing | |
135 // duplicates. | |
136 assert_object_in_array(expected_element, actual, description); | |
137 }); | |
138 } | |
139 | |
140 // Asserts that two arrays |actual| and |expected| contain the same set of | |
141 // elements as determined by assert_object_equals. The corresponding elements | |
142 // must occupy corresponding indices in their respective arrays. | |
143 function assert_array_objects_equals(actual, expected, description) { | |
144 assert_true(Array.isArray(actual), description); | |
145 assert_equals(actual.length, expected.length, description); | |
146 actual.forEach(function(value, index) { | |
147 assert_object_equals(value, expected[index], | |
148 description + ' : object[' + index + ']'); | |
149 }); | |
150 } | |
OLD | NEW |