summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/service-workers/service-worker/resources/testharness-helpers.js
blob: 4d7af1ff9ca77c85696f35368ff3a7a1c4b2480b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
/*
 * testharness-helpers contains various useful extensions to testharness.js to
 * allow them to be used across multiple tests before they have been
 * upstreamed. This file is intended to be usable from both document and worker
 * environments, so code should for example not rely on the DOM.
 */

// Returns a promise that fulfills after the provided |promise| is fulfilled.
// The |test| succeeds only if |promise| rejects with an exception matching
// |code|. Accepted values for |code| follow those accepted for assert_throws().
// The optional |description| describes the test being performed.
//
// E.g.:
//   assert_promise_rejects(
//       new Promise(...), // something that should throw an exception.
//       'NotFoundError',
//       'Should throw NotFoundError.');
//
//   assert_promise_rejects(
//       new Promise(...),
//       new TypeError(),
//       'Should throw TypeError');
function assert_promise_rejects(promise, code, description) {
  return promise.then(
    function() {
      throw 'assert_promise_rejects: ' + description + ' Promise did not reject.';
    },
    function(e) {
      if (code !== undefined) {
        assert_throws(code, function() { throw e; }, description);
      }
    });
}

// Asserts that two objects |actual| and |expected| are weakly equal under the
// following definition:
//
// |a| and |b| are weakly equal if any of the following are true:
//   1. If |a| is not an 'object', and |a| === |b|.
//   2. If |a| is an 'object', and all of the following are true:
//     2.1 |a.p| is weakly equal to |b.p| for all own properties |p| of |a|.
//     2.2 Every own property of |b| is an own property of |a|.
//
// This is a replacement for the the version of assert_object_equals() in
// testharness.js. The latter doesn't handle own properties correctly. I.e. if
// |a.p| is not an own property, it still requires that |b.p| be an own
// property.
//
// Note that |actual| must not contain cyclic references.
self.assert_object_equals = function(actual, expected, description) {
  var object_stack = [];

  function _is_equal(actual, expected, prefix) {
    if (typeof actual !== 'object') {
      assert_equals(actual, expected, prefix);
      return;
    }
    assert_true(typeof expected === 'object', prefix);
    assert_equals(object_stack.indexOf(actual), -1,
                  prefix + ' must not contain cyclic references.');

    object_stack.push(actual);

    Object.getOwnPropertyNames(expected).forEach(function(property) {
        assert_own_property(actual, property, prefix);
        _is_equal(actual[property], expected[property],
                  prefix + '.' + property);
      });
    Object.getOwnPropertyNames(actual).forEach(function(property) {
        assert_own_property(expected, property, prefix);
      });

    object_stack.pop();
  }

  function _brand(object) {
    return Object.prototype.toString.call(object).match(/^\[object (.*)\]$/)[1];
  }

  _is_equal(actual, expected,
            (description ? description + ': ' : '') + _brand(expected));
};

// Equivalent to assert_in_array, but uses a weaker equivalence relation
// (assert_object_equals) than '==='.
function assert_object_in_array(actual, expected_array, description) {
  assert_true(expected_array.some(function(element) {
      try {
        assert_object_equals(actual, element);
        return true;
      } catch (e) {
        return false;
      }
    }), description);
}

// Assert that the two arrays |actual| and |expected| contain the same set of
// elements as determined by assert_object_equals. The order is not significant.
//
// |expected| is assumed to not contain any duplicates as determined by
// assert_object_equals().
function assert_array_equivalent(actual, expected, description) {
  assert_true(Array.isArray(actual), description);
  assert_equals(actual.length, expected.length, description);
  expected.forEach(function(expected_element) {
      // assert_in_array treats the first argument as being 'actual', and the
      // second as being 'expected array'. We are switching them around because
      // we want to be resilient against the |actual| array containing
      // duplicates.
      assert_object_in_array(expected_element, actual, description);
    });
}

// Asserts that two arrays |actual| and |expected| contain the same set of
// elements as determined by assert_object_equals(). The corresponding elements
// must occupy corresponding indices in their respective arrays.
function assert_array_objects_equals(actual, expected, description) {
  assert_true(Array.isArray(actual), description);
  assert_equals(actual.length, expected.length, description);
  actual.forEach(function(value, index) {
      assert_object_equals(value, expected[index],
                           description + ' : object[' + index + ']');
    });
}

// Asserts that |object| that is an instance of some interface has the attribute
// |attribute_name| following the conditions specified by WebIDL, but it's
// acceptable that the attribute |attribute_name| is an own property of the
// object because we're in the middle of moving the attribute to a prototype
// chain.  Once we complete the transition to prototype chains,
// assert_will_be_idl_attribute must be replaced with assert_idl_attribute
// defined in testharness.js.
//
// FIXME: Remove assert_will_be_idl_attribute once we complete the transition
// of moving the DOM attributes to prototype chains.  (http://crbug.com/43394)
function assert_will_be_idl_attribute(object, attribute_name, description) {
  assert_true(typeof object === "object", description);

  assert_true("hasOwnProperty" in object, description);

  // Do not test if |attribute_name| is not an own property because
  // |attribute_name| is in the middle of the transition to a prototype
  // chain.  (http://crbug.com/43394)

  assert_true(attribute_name in object, description);
}

// Stringifies a DOM object.  This function stringifies not only own properties
// but also DOM attributes which are on a prototype chain.  Note that
// JSON.stringify only stringifies own properties.
function stringifyDOMObject(object)
{
    function deepCopy(src) {
        if (typeof src != "object")
            return src;
        var dst = Array.isArray(src) ? [] : {};
        for (var property in src) {
            dst[property] = deepCopy(src[property]);
        }
        return dst;
    }
    return JSON.stringify(deepCopy(object));
}