|
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 |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 "use strict"; |
|
6 |
|
7 var BaseAssert = require("sdk/test/assert").Assert; |
|
8 |
|
9 /** |
|
10 * Whether or not given property descriptors are equivalent. They are |
|
11 * equivalent either if both are marked as "conflict" or "required" property |
|
12 * or if all the properties of descriptors are equal. |
|
13 * @param {Object} actual |
|
14 * @param {Object} expected |
|
15 */ |
|
16 function equivalentDescriptors(actual, expected) { |
|
17 return (actual.conflict && expected.conflict) || |
|
18 (actual.required && expected.required) || |
|
19 equalDescriptors(actual, expected); |
|
20 } |
|
21 |
|
22 function equalDescriptors(actual, expected) { |
|
23 return actual.get === expected.get && |
|
24 actual.set === expected.set && |
|
25 actual.value === expected.value && |
|
26 !!actual.enumerable === !!expected.enumerable && |
|
27 !!actual.configurable === !!expected.configurable && |
|
28 !!actual.writable === !!expected.writable; |
|
29 } |
|
30 |
|
31 /** |
|
32 * Whether or not given `target` array contains all the element |
|
33 * from a given `source` array. |
|
34 */ |
|
35 function containsSet(source, target) { |
|
36 return source.some(function(element) { |
|
37 return 0 > target.indexOf(element); |
|
38 }); |
|
39 } |
|
40 |
|
41 /** |
|
42 * Whether or not given two arrays contain all elements from another. |
|
43 */ |
|
44 function equivalentSets(source, target) { |
|
45 return containsSet(source, target) && containsSet(target, source); |
|
46 } |
|
47 |
|
48 /** |
|
49 * Finds name of the property from `source` property descriptor map, that |
|
50 * is not equivalent of the name named property in the `target` property |
|
51 * descriptor map. If not found `null` is returned instead. |
|
52 */ |
|
53 function findNonEquivalentPropertyName(source, target) { |
|
54 var value = null; |
|
55 Object.getOwnPropertyNames(source).some(function(key) { |
|
56 var areEquivalent = false; |
|
57 if (!equivalentDescriptors(source[key], target[key])) { |
|
58 value = key; |
|
59 areEquivalent = true; |
|
60 } |
|
61 return areEquivalent; |
|
62 }); |
|
63 return value; |
|
64 } |
|
65 |
|
66 var AssertDescriptor = { |
|
67 equalTraits: { |
|
68 value: function equivalentTraits(actual, expected, message) { |
|
69 var difference; |
|
70 var actualKeys = Object.getOwnPropertyNames(actual); |
|
71 var expectedKeys = Object.getOwnPropertyNames(expected); |
|
72 |
|
73 if (equivalentSets(actualKeys, expectedKeys)) { |
|
74 this.fail({ |
|
75 operator: "equalTraits", |
|
76 message: "Traits define different properties", |
|
77 actual: actualKeys.sort().join(","), |
|
78 expected: expectedKeys.sort().join(","), |
|
79 }); |
|
80 } |
|
81 else if ((difference = findNonEquivalentPropertyName(actual, expected))) { |
|
82 this.fail({ |
|
83 operator: "equalTraits", |
|
84 message: "Traits define non-equivalent property `" + difference + "`", |
|
85 actual: actual[difference], |
|
86 expected: expected[difference] |
|
87 }); |
|
88 } |
|
89 else { |
|
90 this.pass(message || "Traits are equivalent."); |
|
91 } |
|
92 } |
|
93 } |
|
94 }; |
|
95 |
|
96 exports.Assert = function Assert() { |
|
97 return Object.create(BaseAssert.apply(null, arguments), AssertDescriptor); |
|
98 }; |