summaryrefslogtreecommitdiffstats
path: root/devtools/startup/tests/xpcshell/test_devtools_shim.js
blob: 6e0ef2789dd21a4804fe3ebd61548b8d790a274f (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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
/* Any copyright is dedicated to the Public Domain.
   http://creativecommons.org/publicdomain/zero/1.0/ */

"use strict";

const { DevToolsShim } = ChromeUtils.importESModule(
  "chrome://devtools-startup/content/DevToolsShim.sys.mjs"
);

// Test the DevToolsShim

/**
 * Create a mocked version of DevTools that records all calls made to methods expected
 * to be called by DevToolsShim.
 */
function createMockDevTools() {
  const methods = [
    "on",
    "off",
    "emit",
    "saveDevToolsSession",
    "restoreDevToolsSession",
  ];

  const mock = {
    callLog: {},
  };

  for (const method of methods) {
    // Create a stub for method, that only pushes its arguments in the inner callLog
    mock[method] = function (...args) {
      mock.callLog[method].push(args);
    };
    mock.callLog[method] = [];
  }

  return mock;
}

/**
 * Check if a given method was called an expected number of times, and finally check the
 * arguments provided to the last call, if appropriate.
 */
function checkCalls(mock, method, length, lastArgs) {
  Assert.strictEqual(
    mock.callLog[method].length,
    length,
    "Devtools.on was called the expected number of times"
  );

  // If we don't want to check the last call or if the method was never called, bail out.
  if (!lastArgs || length === 0) {
    return;
  }

  for (let i = 0; i < lastArgs.length; i++) {
    const expectedArg = lastArgs[i];
    Assert.strictEqual(
      mock.callLog[method][length - 1][i],
      expectedArg,
      `Devtools.${method} was called with the expected argument (index ${i})`
    );
  }
}

function test_register_unregister() {
  ok(!DevToolsShim.isInitialized(), "DevTools are not initialized");

  DevToolsShim.register(createMockDevTools());
  ok(DevToolsShim.isInitialized(), "DevTools are initialized");

  DevToolsShim.unregister();
  ok(!DevToolsShim.isInitialized(), "DevTools are not initialized");
}

function test_on_is_forwarded_to_devtools() {
  ok(!DevToolsShim.isInitialized(), "DevTools are not initialized");

  function cb1() {}
  function cb2() {}
  const mock = createMockDevTools();

  DevToolsShim.on("test_event", cb1);
  DevToolsShim.register(mock);
  checkCalls(mock, "on", 1, ["test_event", cb1]);

  DevToolsShim.on("other_event", cb2);
  checkCalls(mock, "on", 2, ["other_event", cb2]);
}

function test_off_called_before_registering_devtools() {
  ok(!DevToolsShim.isInitialized(), "DevTools are not initialized");

  function cb1() {}
  const mock = createMockDevTools();

  DevToolsShim.on("test_event", cb1);
  DevToolsShim.off("test_event", cb1);

  DevToolsShim.register(mock);
  checkCalls(mock, "on", 0);
}

function test_off_called_before_with_bad_callback() {
  ok(!DevToolsShim.isInitialized(), "DevTools are not initialized");

  function cb1() {}
  function cb2() {}
  const mock = createMockDevTools();

  DevToolsShim.on("test_event", cb1);
  DevToolsShim.off("test_event", cb2);

  DevToolsShim.register(mock);
  // on should still be called
  checkCalls(mock, "on", 1, ["test_event", cb1]);
  // Calls to off should not be held and forwarded.
  checkCalls(mock, "off", 0);
}

function test_events() {
  ok(!DevToolsShim.isInitialized(), "DevTools are not initialized");

  const mock = createMockDevTools();
  // Check emit was not called.
  checkCalls(mock, "emit", 0);

  // Check emit is called once with the devtools-registered event.
  DevToolsShim.register(mock);
  checkCalls(mock, "emit", 1, ["devtools-registered"]);

  // Check emit is called once with the devtools-unregistered event.
  DevToolsShim.unregister();
  checkCalls(mock, "emit", 2, ["devtools-unregistered"]);
}

function test_restore_session_apis() {
  // Backup method that will be updated for the test.
  const initDevToolsBackup = DevToolsShim.initDevTools;

  // Create fake session objects to restore.
  const sessionWithoutDevTools = {};
  const sessionWithDevTools = {
    browserConsole: true,
  };

  Services.prefs.setBoolPref("devtools.policy.disabled", true);
  ok(!DevToolsShim.isInitialized(), "DevTools are not initialized");
  ok(!DevToolsShim.isEnabled(), "DevTools are not enabled");

  // Check that save & restore DevToolsSession don't initialize the tools and don't
  // crash.
  DevToolsShim.saveDevToolsSession({});
  DevToolsShim.restoreDevToolsSession(sessionWithDevTools);
  ok(!DevToolsShim.isInitialized(), "DevTools are still not initialized");

  Services.prefs.setBoolPref("devtools.policy.disabled", false);
  ok(DevToolsShim.isEnabled(), "DevTools are enabled");
  ok(!DevToolsShim.isInitialized(), "DevTools are not initialized");

  // Check that DevTools are not initialized when calling restoreDevToolsSession without
  // DevTools related data.
  DevToolsShim.restoreDevToolsSession(sessionWithoutDevTools);
  ok(!DevToolsShim.isInitialized(), "DevTools are still not initialized");

  const mock = createMockDevTools();
  DevToolsShim.initDevTools = () => {
    // Next call to restoreDevToolsSession is expected to initialize DevTools, which we
    // simulate here by registering our mock.
    DevToolsShim.register(mock);
  };

  DevToolsShim.restoreDevToolsSession(sessionWithDevTools);
  checkCalls(mock, "restoreDevToolsSession", 1, [sessionWithDevTools]);

  ok(DevToolsShim.isInitialized(), "DevTools are initialized");

  DevToolsShim.saveDevToolsSession({});
  checkCalls(mock, "saveDevToolsSession", 1, []);

  // Restore initDevTools backup.
  DevToolsShim.initDevTools = initDevToolsBackup;
}

function run_test() {
  test_register_unregister();
  DevToolsShim.unregister();

  test_on_is_forwarded_to_devtools();
  DevToolsShim.unregister();

  test_off_called_before_registering_devtools();
  DevToolsShim.unregister();

  test_off_called_before_with_bad_callback();
  DevToolsShim.unregister();

  test_restore_session_apis();
  DevToolsShim.unregister();

  test_events();
}