summaryrefslogtreecommitdiffstats
path: root/browser/components/sessionstore/test/browser_formdata_face.js
blob: 5c383388714eb50f70237d035b19d930447ed775 (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
/* Any copyright is dedicated to the Public Domain.
 * http://creativecommons.org/publicdomain/zero/1.0/ */

"use strict";

/**
 * This test ensures that collecting form data for form-associated custom
 * elements works as expected.
 */
add_task(async function test_face_restore() {
  const URL = `data:text/html;charset=utf-8,<!DOCTYPE html>
    <h1>mozilla</h1>
    <script>
      restoredStates = {};
      customElements.define("c-e", class extends HTMLElement {
        static formAssociated = true;
        constructor() {
          super();
          this.internals = this.attachInternals();
        }
        formStateRestoreCallback(state, reason) {
          if (reason == "restore") {
            restoredStates[this.id] = state;
          }
        }
      });
    </script>
    <form>
      <c-e id="test1"></c-e>
      <c-e id="test2"></c-e>
      <c-e id="test3"></c-e>
      <c-e id="test4"></c-e>
      <c-e id="test5"></c-e>
      <c-e id="test6"></c-e>
    </form>`;

  // Load a tab with a FACE.
  let tab = (gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, URL));
  let browser = tab.linkedBrowser;
  await promiseBrowserLoaded(browser);

  // Set the FACE state and value.
  await SpecialPowers.spawn(browser, ["c-e"], selector => {
    function formDataWith(...entries) {
      const formData = new content.FormData();
      for (let [key, value] of entries) {
        formData.append(key, value);
      }
      return formData;
    }
    const states = [
      "test state",
      new content.File(["state"], "state.txt"),
      formDataWith(["1", "state"], ["2", new content.Blob(["state_blob"])]),
      null,
      undefined,
      null,
    ];
    const values = [
      "test value",
      new content.File(["value"], "value.txt"),
      formDataWith(["1", "value"], ["2", new content.Blob(["value_blob"])]),
      "null state",
      "both value and state",
      null,
    ];

    [...content.document.querySelectorAll(selector)].forEach((node, i) => {
      node.internals.setFormValue(values[i], states[i]);
    });
  });

  // Close and restore the tab.
  await promiseRemoveTabAndSessionState(tab);

  {
    let [
      {
        state: { formdata },
      },
    ] = ss.getClosedTabDataForWindow(window);

    is(formdata.id.test1.value, "test value", "String value should be stored");
    is(formdata.id.test1.state, "test state", "String state should be stored");

    let storedFile = formdata.id.test2.value;
    is(storedFile.name, "value.txt", "File value name should be stored");
    is(await storedFile.text(), "value", "File value text should be stored");
    storedFile = formdata.id.test2.state;
    is(storedFile.name, "state.txt", "File state name should be stored");
    is(await storedFile.text(), "state", "File state text should be stored");

    let storedFormData = formdata.id.test3.value;
    is(
      storedFormData.get("1"),
      "value",
      "FormData value string should be stored"
    );
    is(
      await storedFormData.get("2").text(),
      "value_blob",
      "Form value blob should be stored"
    );
    storedFormData = formdata.id.test3.state;
    is(
      storedFormData.get("1"),
      "state",
      "FormData state string should be stored"
    );
    is(
      await storedFormData.get("2").text(),
      "state_blob",
      "Form state blob should be stored"
    );

    is(formdata.id.test4.state, null, "Null state stored");
    is(formdata.id.test4.value, "null state", "Value with null state stored");

    is(
      formdata.id.test5.value,
      "both value and state",
      "Undefined state should be set to value"
    );
    is(
      formdata.id.test5.state,
      "both value and state",
      "Undefined state should be set to value"
    );

    ok(
      !("test6" in formdata.id),
      "Completely null values should not be stored"
    );
  }

  tab = ss.undoCloseTab(window, 0);
  browser = tab.linkedBrowser;
  await promiseTabRestored(tab);

  // Check that the FACE state was restored.
  await SpecialPowers.spawn(browser, ["restoredStates"], async prop => {
    let restoredStates = content.wrappedJSObject[prop];
    is(restoredStates.test1, "test state", "String should be stored");

    let storedFile = restoredStates.test2;
    is(storedFile.name, "state.txt", "File name should be stored");
    is(await storedFile.text(), "state", "File text should be stored");

    const storedFormData = restoredStates.test3;
    is(storedFormData.get("1"), "state", "Form data string should be stored");
    is(
      await storedFormData.get("2").text(),
      "state_blob",
      "Form data blob should be stored"
    );

    ok(!("test4" in restoredStates), "Null values don't get restored");

    is(
      restoredStates.test5,
      "both value and state",
      "Undefined state should be set to value"
    );
  });

  // Cleanup.
  gBrowser.removeTab(tab);
});