summaryrefslogtreecommitdiffstats
path: root/editor/libeditor/tests/test_paste_no_formatting.html
blob: 384510e4056646dd1adf114a317c7916cd5f6c3f (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
203
204
205
206
207
208
209
210
211
212
213
214
<!DOCTYPE HTML>
<html>
<head>
  <meta charset="utf-8">
  <title>Test pasting formatted test into various fields</title>
  <script src="/tests/SimpleTest/SimpleTest.js"></script>
  <script src="/tests/SimpleTest/EventUtils.js"></script>
  <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
</head>
<body>

<input id="input">
<textarea id="textarea"></textarea>
<div id="editable" contenteditable="true"></div>
<div id="noneditable">Text</div>

<div id="source">Some <b>Bold</b> Text</div>
<script>

const expectedText = "Some Bold Text";
const expectedHTML = "<div id=\"source\">Some <b>Bold</b> Text</div>";

const htmlPrefix = navigator.platform.includes("Win")
  ? "<html><body>\n<!--StartFragment-->"
  : "";
const htmlPostfix = navigator.platform.includes("Win")
  ? "<!--EndFragment-->\n</body>\n</html>"
  : "";

add_task(async function test_paste_formatted() {
  window.getSelection().selectAllChildren(document.getElementById("source"));
  synthesizeKey("c", { accelKey: true });

  function doKey(element, withShiftKey)
  {
    let inputEventPromise = new Promise(resolve => {
      element.addEventListener("input", event => {
        is(event.inputType, "insertFromPaste", "correct inputType");
        resolve();
      }, { once: true });
    });
    synthesizeKey("v", { accelKey: true, shiftKey: withShiftKey });
    return inputEventPromise;
  }

  function cancelEvent(event) {
    event.preventDefault();
  }

  // Paste into input and textarea
  for (let fieldid of ["input", "textarea"]) {
    const field = document.getElementById(fieldid);
    field.focus();

    field.addEventListener("paste", cancelEvent);
    doKey(field, false);
    is(
      field.value,
      "",
      `Nothing should be pasted into <${field.tagName.toLowerCase()}> when paste event is canceled (shift key is not pressed)`
    );

    doKey(field, true);
    is(
      field.value,
      "",
      `Nothing should be pasted into <${field.tagName.toLowerCase()}> when paste event is canceled (shift key is pressed)`
    );
    field.removeEventListener("paste", cancelEvent);

    doKey(field, false);
    is(field.value, expectedText, "paste into " + fieldid);

    doKey(field, true);
    is(field.value, expectedText + expectedText, "paste unformatted into " + field);
  }

  const selection = window.getSelection();

  const editable = document.getElementById("editable");
  const innerHTMLBeforeTest = editable.innerHTML;

  (function test_pasteWithFormatIntoEditableArea() {
    selection.selectAllChildren(editable);
    selection.collapseToStart();
    editable.addEventListener("paste", cancelEvent);
    doKey(editable, false);
    is(
      editable.innerHTML,
      "",
      "test_pasteWithFormatIntoEditableArea: Nothing should be pasted when paste event is canceled"
    );
    editable.removeEventListener("paste", cancelEvent);

    doKey(editable, false);
    is(
      editable.innerHTML,
      expectedHTML,
      "test_pasteWithFormatIntoEditableArea: Pasting with format should work as expected"
    );
    editable.innerHTML = innerHTMLBeforeTest;
  }());

  (function test_pasteWithoutFormatIntoEditableArea() {
    selection.selectAllChildren(editable);
    selection.collapseToEnd();
    doKey(editable, true);
    is(
      editable.innerHTML,
      expectedText,
      "test_pasteWithoutFormatIntoEditableArea: Pasting without format should work as expected",
    );
    editable.innerHTML = innerHTMLBeforeTest;
  })();

  (function test_pasteWithFormatIntoEditableAreaWhenHTMLEditorIsInReadonlyMode() {
    getEditor().flags |= SpecialPowers.Ci.nsIEditor.eEditorReadonlyMask;
    selection.selectAllChildren(editable);
    selection.collapseToStart();
    let beforeInputEvents = [];
    function onBeforeInput(aEvent) {
      beforeInputEvents.push(aEvent);
    }
    editable.addEventListener("beforeinput", onBeforeInput);
    doKey(editable, false);
    const description = "test_pasteWithFormatIntoEditableAreaWhenHTMLEditorIsInReadonlyMode";
    is(
      editable.innerHTML,
      innerHTMLBeforeTest,
      `${description}: Pasting with format should not work`
    );
    is(
      beforeInputEvents.length,
      0,
      `${description}: Pasting with format should not cause "beforeinput", but fired "${
        beforeInputEvents[0]?.inputType
      }"`
    );
    editable.removeEventListener("beforeinput", onBeforeInput);
    editable.innerHTML = innerHTMLBeforeTest;
    getEditor().flags &= ~SpecialPowers.Ci.nsIEditor.eEditorReadonlyMask;
  })();

  (function test_pasteWithoutFormatIntoEditableAreaWhenHTMLEditorIsInReadonlyMode() {
    getEditor().flags |= SpecialPowers.Ci.nsIEditor.eEditorReadonlyMask;
    selection.selectAllChildren(editable);
    selection.collapseToStart();
    let beforeInputEvents = [];
    function onBeforeInput(aEvent) {
      beforeInputEvents.push(aEvent);
    }
    editable.addEventListener("beforeinput", onBeforeInput);
    doKey(editable, false);
    const description = "test_pasteWithoutFormatIntoEditableAreaWhenHTMLEditorIsInReadonlyMode";
    is(
      editable.innerHTML,
      innerHTMLBeforeTest,
      `${description}: Pasting with format should not work`
    );
    is(
      beforeInputEvents.length,
      0,
      `${description}: Pasting with format should not cause "beforeinput", but fired "${
        beforeInputEvents[0]?.inputType
      }"`
    );
    editable.removeEventListener("beforeinput", onBeforeInput);
    editable.innerHTML = innerHTMLBeforeTest;
    getEditor().flags &= ~SpecialPowers.Ci.nsIEditor.eEditorReadonlyMask;
  })();

  let noneditable = document.getElementById("noneditable");
  selection.selectAllChildren(noneditable);
  selection.collapseToStart();

  function getPasteResult() {
    return new Promise(resolve => {
      noneditable.addEventListener("paste", event => {
        resolve({
          text: event.clipboardData.getData("text/plain"),
          html: event.clipboardData.getData("text/html"),
        });
      }, { once: true});
    });
  }

  // Normal paste into non-editable area
  let pastePromise = getPasteResult();
  doKey(noneditable, false);
  is(noneditable.innerHTML, "Text", "paste into non-editable");

  let result = await pastePromise;
  is(result.text, expectedText, "paste text into non-editable");
  is(result.html,
     htmlPrefix + expectedHTML + htmlPostfix,
     "paste html into non-editable");

  // Unformatted paste into non-editable area
  pastePromise = getPasteResult();
  doKey(noneditable, true);
  is(noneditable.innerHTML, "Text", "paste unformatted into non-editable");

  result = await pastePromise;
  is(result.text, expectedText, "paste unformatted text into non-editable");
  // Formatted HTML text should not exist when pasting unformatted.
  is(result.html, "", "paste unformatted html into non-editable");
});

function getEditor() {
  const editingSession = SpecialPowers.wrap(window).docShell.editingSession;
  return editingSession.getEditorForWindow(window);
}
</script>
</body>