summaryrefslogtreecommitdiffstats
path: root/comm/mail/components/extensions/test/xpcshell/data/utils.js
blob: 9025982e3300da652b965b4ebab19c85b7e1b57e (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
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at http://mozilla.org/MPL/2.0/. */

// Functions for extensions to use, so that we avoid repeating ourselves.

function assertDeepEqual(
  expected,
  actual,
  description = "Values should be equal",
  options = {}
) {
  let ok;
  let strict = !!options?.strict;
  try {
    ok = assertDeepEqualNested(expected, actual, strict);
  } catch (e) {
    ok = false;
  }
  if (!ok) {
    browser.test.fail(
      `Deep equal test. \n Expected value: ${JSON.stringify(
        expected
      )} \n Actual value: ${JSON.stringify(actual)},
      ${description}`
    );
  }
}

function assertDeepEqualNested(expected, actual, strict) {
  if (expected === null) {
    browser.test.assertTrue(actual === null);
    return actual === null;
  }

  if (expected === undefined) {
    browser.test.assertTrue(actual === undefined);
    return actual === undefined;
  }

  if (["boolean", "number", "string"].includes(typeof expected)) {
    browser.test.assertEq(typeof expected, typeof actual);
    browser.test.assertEq(expected, actual);
    return typeof expected == typeof actual && expected == actual;
  }

  if (Array.isArray(expected)) {
    browser.test.assertTrue(Array.isArray(actual));
    browser.test.assertEq(expected.length, actual.length);
    let ok = 0;
    let all = 0;
    for (let i = 0; i < expected.length; i++) {
      all++;
      if (assertDeepEqualNested(expected[i], actual[i], strict)) {
        ok++;
      }
    }
    return (
      Array.isArray(actual) && expected.length == actual.length && all == ok
    );
  }

  let expectedKeys = Object.keys(expected);
  let actualKeys = Object.keys(actual);
  // Ignore any extra keys on the actual object in non-strict mode (default).
  let lengthOk = strict
    ? expectedKeys.length == actualKeys.length
    : expectedKeys.length <= actualKeys.length;
  browser.test.assertTrue(lengthOk);

  let ok = 0;
  let all = 0;
  for (let key of expectedKeys) {
    all++;
    browser.test.assertTrue(actualKeys.includes(key), `Key ${key} exists`);
    if (assertDeepEqualNested(expected[key], actual[key], strict)) {
      ok++;
    }
  }
  return all == ok && lengthOk;
}

function waitForMessage() {
  return waitForEvent("test.onMessage");
}

function waitForEvent(eventName) {
  let [namespace, name] = eventName.split(".");
  return new Promise(resolve => {
    browser[namespace][name].addListener(function listener(...args) {
      browser[namespace][name].removeListener(listener);
      resolve(args);
    });
  });
}

async function waitForCondition(condition, msg, interval = 100, maxTries = 50) {
  let conditionPassed = false;
  let tries = 0;
  for (; tries < maxTries && !conditionPassed; tries++) {
    await new Promise(resolve =>
      // eslint-disable-next-line mozilla/no-arbitrary-setTimeout
      window.setTimeout(resolve, interval)
    );
    try {
      conditionPassed = await condition();
    } catch (e) {
      throw Error(`${msg} - threw exception: ${e}`);
    }
  }
  if (conditionPassed) {
    browser.test.succeed(
      `waitForCondition succeeded after ${tries} retries - ${msg}`
    );
  } else {
    browser.test.fail(`${msg} - timed out after ${maxTries} retries`);
  }
}

function sendMessage(...args) {
  let replyPromise = waitForMessage();
  browser.test.sendMessage(...args);
  return replyPromise;
}