summaryrefslogtreecommitdiffstats
path: root/browser/base/content/test/tabPrompts/browser_multiplePrompts.js
blob: 597b7dfd6f829195f15082d6c378edd41746ad3c (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
"use strict";

const CONTENT_PROMPT_SUBDIALOG = Services.prefs.getBoolPref(
  "prompts.contentPromptSubDialog",
  false
);

/**
 * Goes through a stacked series of dialogs opened with
 * CONTENT_PROMPT_SUBDIALOG set to true, and ensures that
 * the oldest one is front-most and has the right type. It
 * then closes the oldest to newest dialog.
 *
 * @param {Element} tab The <tab> that has had content dialogs opened
 * for it.
 * @param {Number} promptCount How many dialogs we expected to have been
 * opened.
 *
 * @return {Promise}
 * @resolves {undefined} Once the dialogs have all been closed.
 */
async function closeDialogs(tab, dialogCount) {
  let dialogElementsCount = dialogCount;
  let dialogs =
    tab.linkedBrowser.tabDialogBox.getContentDialogManager().dialogs;

  is(
    dialogs.length,
    dialogElementsCount,
    "There should be " + dialogElementsCount + " dialog(s)."
  );

  let i = dialogElementsCount - 1;
  for (let dialog of dialogs) {
    dialog.focus(true);
    await dialog._dialogReady;

    let dialogWindow = dialog.frameContentWindow;
    let expectedType = ["alert", "prompt", "confirm"][i % 3];

    is(
      dialogWindow.Dialog.args.text,
      expectedType + " countdown #" + i,
      "The #" + i + " alert should be labelled as such."
    );
    i--;

    dialogWindow.Dialog.ui.button0.click();

    // The click is handled async; wait for an event loop turn for that to
    // happen.
    await new Promise(function (resolve) {
      Services.tm.dispatchToMainThread(resolve);
    });
  }

  dialogs = tab.linkedBrowser.tabDialogBox.getContentDialogManager().dialogs;
  is(dialogs.length, 0, "Dialogs should all be dismissed.");
}

/**
 * Goes through a stacked series of tabprompt modals opened with
 * CONTENT_PROMPT_SUBDIALOG set to false, and ensures that
 * the oldest one is front-most and has the right type. It also
 * ensures that the other tabprompt modals are hidden. It
 * then closes the oldest to newest dialog.
 *
 * @param {Element} tab The <tab> that has had tabprompt modals opened
 * for it.
 * @param {Number} promptCount How many modals we expected to have been
 * opened.
 *
 * @return {Promise}
 * @resolves {undefined} Once the modals have all been closed.
 */
async function closeTabModals(tab, promptCount) {
  let promptElementsCount = promptCount;
  while (promptElementsCount--) {
    let promptElements =
      tab.linkedBrowser.parentNode.querySelectorAll("tabmodalprompt");
    is(
      promptElements.length,
      promptElementsCount + 1,
      "There should be " + (promptElementsCount + 1) + " prompt(s)."
    );
    // The oldest should be the first.
    let i = 0;

    for (let promptElement of promptElements) {
      let prompt = tab.linkedBrowser.tabModalPromptBox.getPrompt(promptElement);
      let expectedType = ["alert", "prompt", "confirm"][i % 3];
      is(
        prompt.Dialog.args.text,
        expectedType + " countdown #" + i,
        "The #" + i + " alert should be labelled as such."
      );
      if (i !== promptElementsCount) {
        is(prompt.element.hidden, true, "This prompt should be hidden.");
        i++;
        continue;
      }

      is(prompt.element.hidden, false, "The last prompt should not be hidden.");
      prompt.onButtonClick(0);

      // The click is handled async; wait for an event loop turn for that to
      // happen.
      await new Promise(function (resolve) {
        Services.tm.dispatchToMainThread(resolve);
      });
    }
  }

  let promptElements =
    tab.linkedBrowser.parentNode.querySelectorAll("tabmodalprompt");
  is(promptElements.length, 0, "Prompts should all be dismissed.");
}

/*
 * This test triggers multiple alerts on one single tab, because it"s possible
 * for web content to do so. The behavior is described in bug 1266353.
 *
 * We assert the presentation of the multiple alerts, ensuring we show only
 * the oldest one.
 */
add_task(async function () {
  const PROMPTCOUNT = 9;

  let unopenedPromptCount = PROMPTCOUNT;

  let tab = await BrowserTestUtils.openNewForegroundTab(
    gBrowser,
    // eslint-disable-next-line @microsoft/sdl/no-insecure-url
    "http://example.com",
    true
  );
  info("Tab loaded");

  let promptsOpenedPromise = BrowserTestUtils.waitForEvent(
    tab.linkedBrowser,
    "DOMWillOpenModalDialog",
    false,
    () => {
      unopenedPromptCount--;
      return unopenedPromptCount == 0;
    }
  );

  await SpecialPowers.spawn(tab.linkedBrowser, [PROMPTCOUNT], maxPrompts => {
    var i = maxPrompts;
    let fns = ["alert", "prompt", "confirm"];
    function openDialog() {
      i--;
      if (i) {
        SpecialPowers.Services.tm.dispatchToMainThread(openDialog);
      }
      content[fns[i % 3]](fns[i % 3] + " countdown #" + i);
    }
    SpecialPowers.Services.tm.dispatchToMainThread(openDialog);
  });

  await promptsOpenedPromise;

  if (CONTENT_PROMPT_SUBDIALOG) {
    await closeDialogs(tab, PROMPTCOUNT);
  } else {
    await closeTabModals(tab, PROMPTCOUNT);
  }

  BrowserTestUtils.removeTab(tab);
});