File: test_bug430392.html

package info (click to toggle)
firefox 147.0.2-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 4,683,484 kB
  • sloc: cpp: 7,607,246; javascript: 6,533,185; ansic: 3,775,227; python: 1,415,393; xml: 634,561; asm: 438,951; java: 186,241; sh: 62,752; makefile: 18,079; objc: 13,092; perl: 12,808; yacc: 4,583; cs: 3,846; pascal: 3,448; lex: 1,720; ruby: 1,003; php: 436; lisp: 258; awk: 247; sql: 66; sed: 54; csh: 10; exp: 6
file content (229 lines) | stat: -rw-r--r-- 10,001 bytes parent folder | download | duplicates (2)
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
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=430392
-->
<head>
  <title>Test for Bug 430392</title>
  <script src="/tests/SimpleTest/SimpleTest.js"></script>
  <script src="/tests/SimpleTest/EventUtils.js"></script>
  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=430392">Mozilla Bug 430392</a>
<p id="display"></p>
<div id="content">
  <div contenteditable="true" id="edit"> <span contenteditable="false">A</span> ; <span contenteditable="false">B</span> ; <span contenteditable="false">C</span> </div>
</div>
<pre id="test">
<script class="testbody" type="text/javascript">

/** Test for Bug 430392 */

function test() {
  var edit = document.getElementById("edit");
  var html = edit.innerHTML;
  var expectedText = edit.textContent;
  document.getElementById("edit").focus();

  // Each test is [desc, callback, inputType of `beforeinput`, inputType of `input`].
  // callback() is called and we check that the textContent didn't change.
  // For expected failures, the format is
  // [desc, callback, undefined, inputType of `beforeinput`, inputType of `input`, expectedValue],
  // and the test will be marked as an expected fail if the textContent changes
  // to expectedValue, and an unexpected fail if it's neither the original value
  // nor expectedValue.
  let tests = [
    [
      "adding returns",
      () => {
        getSelection().collapse(edit.firstChild, 0); // [] <span contenteditable=false>A</span> ; <span
        synthesizeKey("KEY_ArrowRight");             //  <span contenteditable=false>A</span>[] ; <span
        synthesizeKey("KEY_Enter");
        info(`1st Enter: "${edit.innerHTML}"`);
        // " <div><span contenteditable="false">A</span></div><div>[]&nbsp;; <span contenteditable="false">B</span> ; <span contenteditable="false">C</span></div> "
        synthesizeKey("KEY_Enter");
        info(`2nd Enter: "${edit.innerHTML}"`);
        // " <div><span contenteditable="false">A</span></div><div><br></div><div>[]&nbsp;; <span contenteditable="false">B</span> ; <span contenteditable="false">C</span></div> "
        synthesizeKey("KEY_Backspace");
        info(`1st Backspace: "${edit.innerHTML}"`);
        // " <div><span contenteditable="false">A</span></div><div>[]&nbsp;; <span contenteditable="false">B</span> ; <span contenteditable="false">C</span></div> "
        synthesizeKey("KEY_Backspace");
        info(`2nd Backspace: "${edit.innerHTML}"`);
        // " &nbsp;; <span contenteditable="false">B</span> ; <span contenteditable="false">C</span><div><span contenteditable="false">A</span></div> "
      }, [
        "insertParagraph",
        "insertParagraph",
        "deleteContentBackward",
        "deleteContentBackward",
      ],
      [
        "insertParagraph",
        "insertParagraph",
        "deleteContentBackward",
        "deleteContentBackward",
      ],
      aSeparator => {
        switch (aSeparator) {
          case "div":
          case "p":
            // The following white-space of "A" should be converted to an
            // NBSP when it's wrapped in a new paragraph.  Then, it'll stay
            // the start of the `Text` after `Backspace`es.  Therefore, it
            // won't be back to an ASCII white-space.
            return " &nbsp;; B ; CA ";
          case "br":
            // After insertLineBreak, the first white-space should be replaced
            // with &nbsp; and it should not be reconverted at Backspace.
            // Therefore, the actual expected result is " A&nbsp;; B ; C ".
            return " A\u00A0; B ; C ";
        }
        throw new Error("handle all cases!");
      },
    ],
    [
      "adding shift-returns",
      () => {
        getSelection().collapse(edit.firstChild, 0); // [] <span contenteditable=false>A</span> ; <span
        synthesizeKey("KEY_ArrowRight");             //  <span contenteditable=false>A</span>[] ; <span
        synthesizeKey("KEY_Enter", {shiftKey: true});
        info(`1st Shift+Enter: "${edit.innerHTML}"`);
        // " <span contenteditable="false">A</span><br>[]&nbsp;; <span contenteditable="false">B</span> ; <span contenteditable="false">C</span> "
        synthesizeKey("KEY_Enter", {shiftKey: true});
        info(`2nd Shift+Enter: "${edit.innerHTML}"`);
        // " <span contenteditable="false">A</span><br><br>[]&nbsp;; <span contenteditable="false">B</span> ; <span contenteditable="false">C</span> "
        synthesizeKey("KEY_Backspace");
        info(`1st Backspace: "${edit.innerHTML}"`);
        // " <span contenteditable="false">A</span><br>[]&nbsp;; <span contenteditable="false">B</span> ; <span contenteditable="false">C</span> "
        synthesizeKey("KEY_Backspace");
        info(`2nd Backspace: "${edit.innerHTML}"`);
        // " []&nbsp;; <span contenteditable="false">A</span><span contenteditable="false">B</span> ; <span contenteditable="false">C</span> "
      }, [
        "insertLineBreak",
        "insertLineBreak",
        "deleteContentBackward",
        "deleteContentBackward",
      ], [
        "insertLineBreak",
        "insertLineBreak",
        "deleteContentBackward",
        "deleteContentBackward",
      ],
      // Actual expected result should be "A&nbsp;; B ; C " because when first
      // <br> is inserted, the following white-space should be preserved as
      // an &nbsp;.  Then, it should not be reconverted to a white-space after
      // Backspace.
      " \u00A0; AB ; C ",
    ],
  ];

  [
    ["insertorderedlist", "insertOrderedList"],
    ["insertunorderedlist", "insertUnorderedList"],
    ["formatblock", "", "p"],
  ].forEach(item => {
    let cmd = item[0];
    let param = item[2];
    let inputType = item[1];
    tests.push([cmd, () => { document.execCommand(cmd, false, param); },
                [/* execCommand shouldn't cause beforeinput event */],
                [inputType]]);
  });

  // These are all TODO -- they don't move the non-editable elements
  [
    ["bold", "formatBold"],
    ["italic", "formatItalic"],
    ["underline", "formatUnderline"],
    ["strikethrough", "formatStrikeThrough"],
    ["subscript", "formatSubscript"],
    ["superscript", "formatSuperscript"],
    ["forecolor", "formatFontColor", "blue"],
    ["backcolor", "formatBackColor", "blue"],
    ["hilitecolor", "formatBackColor", "blue"],
    ["fontname", "formatFontName", "monospace"],
    ["fontsize", "", "1"],
    ["justifyright", "formatJustifyRight"],
    ["justifycenter", "formatJustifyCenter"],
    ["justifyfull", "formatJustifyFull"],
  ].forEach(item => {
    let cmd = item[0];
    let param = item[2];
    let inputType = item[1];
    tests.push([cmd, () => { document.execCommand(cmd, false, param); },
                [/* execCommand shouldn't cause beforeinput event */],
                [inputType],
                " A ;  ; BC "]);
   });

  tests.push(["indent", () => { document.execCommand("indent"); },
              [/* execCommand shouldn't cause beforeinput event */],
              ["formatIndent"],
              "  ;  ;  ABC"]);

  let beforeinputTypes = [];
  let inputTypes = [];
  edit.addEventListener("beforeinput", event => { beforeinputTypes.push(event.inputType); });
  edit.addEventListener("input", event => { inputTypes.push(event.inputType); });
  tests.forEach(arr => {
    ["div", "br", "p"].forEach(sep => {
      document.execCommand("defaultParagraphSeparator", false, sep);

      let expectedFailText = typeof arr[4] == "function" ? arr[4](sep) : arr[4];

      edit.innerHTML = html;
      edit.focus();
      getSelection().selectAllChildren(edit);
      beforeinputTypes = [];
      inputTypes = [];
      arr[1]();
      const resultText = edit.textContent;
      if (expectedFailText !== undefined) {
        todo_is(resultText, expectedText, `${arr[0]} should not change text (${sep})`);
        if (resultText !== expectedText && resultText !== expectedFailText) {
          is(
            resultText.replaceAll(/\u00A0/g, "&nbsp;"),
            expectedFailText.replaceAll(/\u00A0/g, "&nbsp;"),
            `${arr[0]} changed to different failure (${sep})`
          );
        }
      } else {
        is(
          resultText.replaceAll(/\u00A0/g, "&nbsp;"),
          expectedText.replaceAll(/\u00A0/g, "&nbsp;"),
          `${arr[0]} should not change text (${sep})`
        );
      }
      is(beforeinputTypes.length, arr[2].length, `${arr[0]}: number of beforeinput events should be ${arr[2].length} (${sep})`);
      for (let i = 0; i < Math.max(beforeinputTypes.length, arr[2].length); i++) {
        if (i < beforeinputTypes.length && i < arr[2].length) {
          is(beforeinputTypes[i], arr[2][i], `${arr[0]}: ${i + 1}th inputType of beforeinput event should be "${arr[2][i]}" (${sep})`);
        } else if (i < beforeinputTypes.length) {
          ok(false, `${arr[0]}: Redundant beforeinput event shouldn't be fired, its inputType was "${beforeinputTypes[i]}" (${sep})`);
        } else {
          ok(false, `${arr[0]}: beforeinput event whose inputType is "${arr[2][i]}" should be fired, but not fired (${sep})`);
        }
      }
      is(inputTypes.length, arr[3].length, `${arr[0]}: number of input events is unexpected (${sep})`);
      for (let i = 0; i < Math.max(inputTypes.length, arr[3].length); i++) {
        if (i < inputTypes.length && i < arr[3].length) {
          is(inputTypes[i], arr[3][i], `${arr[0]}: ${i + 1}th inputType of input event should be "${arr[3][i]}" (${sep})`);
        } else if (i < inputTypes.length) {
          ok(false, `${arr[0]}: Redundant input event shouldn't be fired, its inputType was "${inputTypes[i]}" (${sep})`);
        } else {
          ok(false, `${arr[0]}: input event whose inputType is "${arr[3][i]}" should be fired, but not fired (${sep})`);
        }
      }
    });
  });

  SimpleTest.finish();
}

SimpleTest.waitForExplicitFinish();
SimpleTest.waitForFocus(test);

</script>
</pre>
</body>
</html>