summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/html/editing/editing-0
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /testing/web-platform/tests/html/editing/editing-0
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/html/editing/editing-0')
-rw-r--r--testing/web-platform/tests/html/editing/editing-0/autocapitalization/autocapitalize.html688
-rw-r--r--testing/web-platform/tests/html/editing/editing-0/contenteditable/contentEditable-slotted-inherit.html37
-rw-r--r--testing/web-platform/tests/html/editing/editing-0/contenteditable/contenteditable-enumerated-ascii-case-insensitive.html45
-rw-r--r--testing/web-platform/tests/html/editing/editing-0/contenteditable/contenteditable-overflow-height-ref.html9
-rw-r--r--testing/web-platform/tests/html/editing/editing-0/contenteditable/contenteditable-overflow-height.html14
-rw-r--r--testing/web-platform/tests/html/editing/editing-0/contenteditable/contenteditable-with-empty-block-ref.html7
-rw-r--r--testing/web-platform/tests/html/editing/editing-0/contenteditable/contenteditable-with-empty-block.html11
-rw-r--r--testing/web-platform/tests/html/editing/editing-0/contenteditable/selection-in-contentEditable-at-turning-designMode-on-off.tentative.html31
-rw-r--r--testing/web-platform/tests/html/editing/editing-0/contenteditable/user-interaction-editing-contenteditable.html68
-rw-r--r--testing/web-platform/tests/html/editing/editing-0/making-entire-documents-editable-the-designmode-idl-attribute/original-id.json1
-rw-r--r--testing/web-platform/tests/html/editing/editing-0/making-entire-documents-editable-the-designmode-idl-attribute/user-interaction-editing-designMode-svg.svg34
-rw-r--r--testing/web-platform/tests/html/editing/editing-0/making-entire-documents-editable-the-designmode-idl-attribute/user-interaction-editing-designMode-xml.xml32
-rw-r--r--testing/web-platform/tests/html/editing/editing-0/making-entire-documents-editable-the-designmode-idl-attribute/user-interaction-editing-designMode.html32
-rw-r--r--testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/references/spelling-markers-001-ref.html7
-rw-r--r--testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spellcheck-enumerated-ascii-case-insensitive.html27
-rw-r--r--testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-001.html17
-rw-r--r--testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-002.html18
-rw-r--r--testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-003.html17
-rw-r--r--testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-004.html18
-rw-r--r--testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-005.html18
-rw-r--r--testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-006.html20
-rw-r--r--testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-007.html27
-rw-r--r--testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-008.html27
-rw-r--r--testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-009.html27
-rw-r--r--testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-010.html27
-rw-r--r--testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/user-interaction-editing-spellcheck.html35
-rw-r--r--testing/web-platform/tests/html/editing/editing-0/writing-suggestions/writingsuggestions.html457
27 files changed, 1751 insertions, 0 deletions
diff --git a/testing/web-platform/tests/html/editing/editing-0/autocapitalization/autocapitalize.html b/testing/web-platform/tests/html/editing/editing-0/autocapitalization/autocapitalize.html
new file mode 100644
index 0000000000..49ee14329c
--- /dev/null
+++ b/testing/web-platform/tests/html/editing/editing-0/autocapitalization/autocapitalize.html
@@ -0,0 +1,688 @@
+<!DOCTYPE html>
+<html>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/interaction.html#autocapitalization">
+<body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+
+test(function() {
+ assert_true('autocapitalize' in document.createElement('input'));
+}, "Test that the autocapitalize is available on HTMLInputElement.")
+
+test(function() {
+ assert_true('autocapitalize' in document.createElement('textarea'));
+}, "Test that the autocapitalize is available on HTMLTextAreaElement.")
+
+test(function() {
+ assert_true('autocapitalize' in document.createElement('div'));
+}, "Test that the autocapitalize is available on div.")
+
+test(function() {
+ var elements = [ document.createElement('input'),
+ document.createElement('textarea'),
+ document.createElement('div') ];
+
+ elements.forEach(function(e) {
+ e.autocapitalize = 'on';
+ assert_equals(e.autocapitalize, 'sentences');
+
+ e.autocapitalize = 'off';
+ assert_equals(e.autocapitalize, 'none');
+ });
+}, "Test deprecated values of autocapitalize.");
+
+test(function() {
+ var elements = [ document.createElement('input'),
+ document.createElement('textarea'),
+ document.createElement('div') ];
+ var knownValues = [ 'none', 'characters', 'words', 'sentences' ];
+
+ elements.forEach(function(e) {
+ // Default value.
+ assert_equals(e.autocapitalize, '');
+
+ // Empty value.
+ e.autocapitalize = '';
+ assert_equals(e.autocapitalize, '');
+ assert_equals(e.getAttribute('autocapitalize'), '');
+ e.setAttribute('autocapitalize', '');
+ assert_equals(e.autocapitalize, '');
+ assert_equals(e.getAttribute('autocapitalize'), '');
+ assert_equals(e.autocapitalize, '');
+
+ // Invalid value.
+ e.autocapitalize = 'foo';
+ assert_equals(e.autocapitalize, 'sentences');
+ assert_equals(e.getAttribute('autocapitalize'), 'foo');
+ e.setAttribute('autocapitalize', 'bar');
+ assert_equals(e.autocapitalize, 'sentences');
+ assert_equals(e.getAttribute('autocapitalize'), 'bar');
+
+ // Default value.
+ e.removeAttribute('autocapitalize');
+ assert_equals(e.autocapitalize, '');
+ assert_equals(e.getAttribute('autocapitalize'), null);
+
+ // Case insensitive.
+ e.setAttribute('autocapitalize', 'NoNe');
+ assert_equals(e.autocapitalize, 'none');
+ assert_equals(e.getAttribute('autocapitalize'), 'NoNe');
+ e.autocapitalize = 'WORDS';
+ assert_equals(e.autocapitalize, 'words');
+ assert_equals(e.getAttribute('autocapitalize'), 'WORDS');
+
+ knownValues.forEach(function(value) {
+ e.setAttribute('autocapitalize', value);
+ assert_equals(e.autocapitalize, value);
+ assert_equals(e.getAttribute('autocapitalize'), value);
+
+ e.removeAttribute('autocapitalize');
+
+ e.autocapitalize = value;
+ assert_equals(e.autocapitalize, value);
+ assert_equals(e.getAttribute('autocapitalize'), value);
+
+ e.removeAttribute('autocapitalize');
+ });
+ });
+}, "Test reflection of autocapitalize.");
+
+test(function() {
+var testData = [ 'text',
+ 'search',
+ 'email',
+ 'url',
+ 'tel',
+ 'number',
+ 'date',
+ 'color',
+ 'password' ];
+
+ testData.forEach(function(data) {
+ const input = document.createElement('input');
+ input.type = data;
+ assert_equals(input.autocapitalize, '');
+
+ // Verify that wrapping the input element in a form doesn't change the
+ // defaults.
+ const form = document.createElement('form');
+ form.appendChild(input);
+ assert_equals(input.autocapitalize, '');
+ });
+}, "Test that the IDL attribute returns the empty string if the content "
++ "attribute is not set.")
+
+test(function() {
+ const testData = [
+ {
+ formValue: null,
+ formElementValue: null,
+ inheritedResult: '',
+ uninheritedResult: '',
+ },
+ {
+ formValue: null,
+ formElementValue: '',
+ inheritedResult: '',
+ uninheritedResult: '',
+ },
+ {
+ formValue: null,
+ formElementValue: 'on',
+ inheritedResult: 'sentences',
+ uninheritedResult: 'sentences',
+ },
+ {
+ formValue: null,
+ formElementValue: 'off',
+ inheritedResult: 'none',
+ uninheritedResult: 'none',
+ },
+ {
+ formValue: null,
+ formElementValue: 'none',
+ inheritedResult: 'none',
+ uninheritedResult: 'none',
+ },
+ {
+ formValue: null,
+ formElementValue: 'characters',
+ inheritedResult: 'characters',
+ uninheritedResult: 'characters',
+ },
+ {
+ formValue: null,
+ formElementValue: 'words',
+ inheritedResult: 'words',
+ uninheritedResult: 'words',
+ },
+ {
+ formValue: null,
+ formElementValue: 'sentences',
+ inheritedResult: 'sentences',
+ uninheritedResult: 'sentences',
+ },
+ {
+ formValue: null,
+ formElementValue: 'foo',
+ inheritedResult: 'sentences',
+ uninheritedResult: 'sentences',
+ },
+ {
+ formValue: '',
+ formElementValue: null,
+ inheritedResult: '',
+ uninheritedResult: '',
+ },
+ {
+ formValue: '',
+ formElementValue: '',
+ inheritedResult: '',
+ uninheritedResult: '',
+ },
+ {
+ formValue: '',
+ formElementValue: 'on',
+ inheritedResult: 'sentences',
+ uninheritedResult: 'sentences',
+ },
+ {
+ formValue: '',
+ formElementValue: 'off',
+ inheritedResult: 'none',
+ uninheritedResult: 'none',
+ },
+ {
+ formValue: '',
+ formElementValue: 'none',
+ inheritedResult: 'none',
+ uninheritedResult: 'none',
+ },
+ {
+ formValue: '',
+ formElementValue: 'characters',
+ inheritedResult: 'characters',
+ uninheritedResult: 'characters',
+ },
+ {
+ formValue: '',
+ formElementValue: 'words',
+ inheritedResult: 'words',
+ uninheritedResult: 'words',
+ },
+ {
+ formValue: '',
+ formElementValue: 'sentences',
+ inheritedResult: 'sentences',
+ uninheritedResult: 'sentences',
+ },
+ {
+ formValue: '',
+ formElementValue: 'foo',
+ inheritedResult: 'sentences',
+ uninheritedResult: 'sentences',
+ },
+ {
+ formValue: 'on',
+ formElementValue: null,
+ inheritedResult: 'sentences',
+ uninheritedResult: '',
+ },
+ {
+ formValue: 'on',
+ formElementValue: '',
+ inheritedResult: 'sentences',
+ uninheritedResult: '',
+ },
+ {
+ formValue: 'on',
+ formElementValue: 'on',
+ inheritedResult: 'sentences',
+ uninheritedResult: 'sentences',
+ },
+ {
+ formValue: 'on',
+ formElementValue: 'off',
+ inheritedResult: 'none',
+ uninheritedResult: 'none',
+ },
+ {
+ formValue: 'on',
+ formElementValue: 'none',
+ inheritedResult: 'none',
+ uninheritedResult: 'none',
+ },
+ {
+ formValue: 'on',
+ formElementValue: 'characters',
+ inheritedResult: 'characters',
+ uninheritedResult: 'characters',
+ },
+ {
+ formValue: 'on',
+ formElementValue: 'words',
+ inheritedResult: 'words',
+ uninheritedResult: 'words',
+ },
+ {
+ formValue: 'on',
+ formElementValue: 'sentences',
+ inheritedResult: 'sentences',
+ uninheritedResult: 'sentences',
+ },
+ {
+ formValue: 'on',
+ formElementValue: 'foo',
+ inheritedResult: 'sentences',
+ uninheritedResult: 'sentences',
+ },
+ {
+ formValue: 'off',
+ formElementValue: null,
+ inheritedResult: 'none',
+ uninheritedResult: '',
+ },
+ {
+ formValue: 'off',
+ formElementValue: '',
+ inheritedResult: 'none',
+ uninheritedResult: '',
+ },
+ {
+ formValue: 'off',
+ formElementValue: 'on',
+ inheritedResult: 'sentences',
+ uninheritedResult: 'sentences',
+ },
+ {
+ formValue: 'off',
+ formElementValue: 'off',
+ inheritedResult: 'none',
+ uninheritedResult: 'none',
+ },
+ {
+ formValue: 'off',
+ formElementValue: 'none',
+ inheritedResult: 'none',
+ uninheritedResult: 'none',
+ },
+ {
+ formValue: 'off',
+ formElementValue: 'characters',
+ inheritedResult: 'characters',
+ uninheritedResult: 'characters',
+ },
+ {
+ formValue: 'off',
+ formElementValue: 'words',
+ inheritedResult: 'words',
+ uninheritedResult: 'words',
+ },
+ {
+ formValue: 'off',
+ formElementValue: 'sentences',
+ inheritedResult: 'sentences',
+ uninheritedResult: 'sentences',
+ },
+ {
+ formValue: 'off',
+ formElementValue: 'foo',
+ inheritedResult: 'sentences',
+ uninheritedResult: 'sentences',
+ },
+ {
+ formValue: 'none',
+ formElementValue: null,
+ inheritedResult: 'none',
+ uninheritedResult: '',
+ },
+ {
+ formValue: 'none',
+ formElementValue: '',
+ inheritedResult: 'none',
+ uninheritedResult: '',
+ },
+ {
+ formValue: 'none',
+ formElementValue: 'on',
+ inheritedResult: 'sentences',
+ uninheritedResult: 'sentences',
+ },
+ {
+ formValue: 'none',
+ formElementValue: 'off',
+ inheritedResult: 'none',
+ uninheritedResult: 'none',
+ },
+ {
+ formValue: 'none',
+ formElementValue: 'none',
+ inheritedResult: 'none',
+ uninheritedResult: 'none',
+ },
+ {
+ formValue: 'none',
+ formElementValue: 'characters',
+ inheritedResult: 'characters',
+ uninheritedResult: 'characters',
+ },
+ {
+ formValue: 'none',
+ formElementValue: 'words',
+ inheritedResult: 'words',
+ uninheritedResult: 'words',
+ },
+ {
+ formValue: 'none',
+ formElementValue: 'sentences',
+ inheritedResult: 'sentences',
+ uninheritedResult: 'sentences',
+ },
+ {
+ formValue: 'none',
+ formElementValue: 'foo',
+ inheritedResult: 'sentences',
+ uninheritedResult: 'sentences',
+ },
+ {
+ formValue: 'characters',
+ formElementValue: null,
+ inheritedResult: 'characters',
+ uninheritedResult: '',
+ },
+ {
+ formValue: 'characters',
+ formElementValue: '',
+ inheritedResult: 'characters',
+ uninheritedResult: '',
+ },
+ {
+ formValue: 'characters',
+ formElementValue: 'on',
+ inheritedResult: 'sentences',
+ uninheritedResult: 'sentences',
+ },
+ {
+ formValue: 'characters',
+ formElementValue: 'off',
+ inheritedResult: 'none',
+ uninheritedResult: 'none',
+ },
+ {
+ formValue: 'characters',
+ formElementValue: 'none',
+ inheritedResult: 'none',
+ uninheritedResult: 'none',
+ },
+ {
+ formValue: 'characters',
+ formElementValue: 'characters',
+ inheritedResult: 'characters',
+ uninheritedResult: 'characters',
+ },
+ {
+ formValue: 'characters',
+ formElementValue: 'words',
+ inheritedResult: 'words',
+ uninheritedResult: 'words',
+ },
+ {
+ formValue: 'characters',
+ formElementValue: 'sentences',
+ inheritedResult: 'sentences',
+ uninheritedResult: 'sentences',
+ },
+ {
+ formValue: 'characters',
+ formElementValue: 'foo',
+ inheritedResult: 'sentences',
+ uninheritedResult: 'sentences',
+ },
+ {
+ formValue: 'words',
+ formElementValue: null,
+ inheritedResult: 'words',
+ uninheritedResult: '',
+ },
+ {
+ formValue: 'words',
+ formElementValue: '',
+ inheritedResult: 'words',
+ uninheritedResult: '',
+ },
+ {
+ formValue: 'words',
+ formElementValue: 'on',
+ inheritedResult: 'sentences',
+ uninheritedResult: 'sentences',
+ },
+ {
+ formValue: 'words',
+ formElementValue: 'off',
+ inheritedResult: 'none',
+ uninheritedResult: 'none',
+ },
+ {
+ formValue: 'words',
+ formElementValue: 'none',
+ inheritedResult: 'none',
+ uninheritedResult: 'none',
+ },
+ {
+ formValue: 'words',
+ formElementValue: 'characters',
+ inheritedResult: 'characters',
+ uninheritedResult: 'characters',
+ },
+ {
+ formValue: 'words',
+ formElementValue: 'words',
+ inheritedResult: 'words',
+ uninheritedResult: 'words',
+ },
+ {
+ formValue: 'words',
+ formElementValue: 'sentences',
+ inheritedResult: 'sentences',
+ uninheritedResult: 'sentences',
+ },
+ {
+ formValue: 'words',
+ formElementValue: 'foo',
+ inheritedResult: 'sentences',
+ uninheritedResult: 'sentences',
+ },
+ {
+ formValue: 'sentences',
+ formElementValue: null,
+ inheritedResult: 'sentences',
+ uninheritedResult: '',
+ },
+ {
+ formValue: 'sentences',
+ formElementValue: '',
+ inheritedResult: 'sentences',
+ uninheritedResult: '',
+ },
+ {
+ formValue: 'sentences',
+ formElementValue: 'on',
+ inheritedResult: 'sentences',
+ uninheritedResult: 'sentences',
+ },
+ {
+ formValue: 'sentences',
+ formElementValue: 'off',
+ inheritedResult: 'none',
+ uninheritedResult: 'none',
+ },
+ {
+ formValue: 'sentences',
+ formElementValue: 'none',
+ inheritedResult: 'none',
+ uninheritedResult: 'none',
+ },
+ {
+ formValue: 'sentences',
+ formElementValue: 'characters',
+ inheritedResult: 'characters',
+ uninheritedResult: 'characters',
+ },
+ {
+ formValue: 'sentences',
+ formElementValue: 'words',
+ inheritedResult: 'words',
+ uninheritedResult: 'words',
+ },
+ {
+ formValue: 'sentences',
+ formElementValue: 'sentences',
+ inheritedResult: 'sentences',
+ uninheritedResult: 'sentences',
+ },
+ {
+ formValue: 'sentences',
+ formElementValue: 'foo',
+ inheritedResult: 'sentences',
+ uninheritedResult: 'sentences',
+ },
+ {
+ formValue: 'foo',
+ formElementValue: null,
+ inheritedResult: 'sentences',
+ uninheritedResult: '',
+ },
+ {
+ formValue: 'foo',
+ formElementValue: '',
+ inheritedResult: 'sentences',
+ uninheritedResult: '',
+ },
+ {
+ formValue: 'foo',
+ formElementValue: 'on',
+ inheritedResult: 'sentences',
+ uninheritedResult: 'sentences',
+ },
+ {
+ formValue: 'foo',
+ formElementValue: 'off',
+ inheritedResult: 'none',
+ uninheritedResult: 'none',
+ },
+ {
+ formValue: 'foo',
+ formElementValue: 'none',
+ inheritedResult: 'none',
+ uninheritedResult: 'none',
+ },
+ {
+ formValue: 'foo',
+ formElementValue: 'characters',
+ inheritedResult: 'characters',
+ uninheritedResult: 'characters',
+ },
+ {
+ formValue: 'foo',
+ formElementValue: 'words',
+ inheritedResult: 'words',
+ uninheritedResult: 'words',
+ },
+ {
+ formValue: 'foo',
+ formElementValue: 'sentences',
+ inheritedResult: 'sentences',
+ uninheritedResult: 'sentences',
+ },
+ {
+ formValue: 'foo',
+ formElementValue: 'foo',
+ inheritedResult: 'sentences',
+ uninheritedResult: 'sentences',
+ },
+ ];
+
+ const formElements = [
+ {element: 'button', inherits: true},
+ {element: 'fieldset', inherits: true},
+ {element: 'img', inherits: false},
+ {element: 'input', inherits: true},
+ {element: 'object', inherits: false},
+ {element: 'output', inherits: true},
+ {element: 'select', inherits: true},
+ {element: 'textarea', inherits: true},
+ ];
+
+ const form = document.createElement('form');
+ form.id = 'form';
+ document.body.appendChild(form);
+
+ testData.forEach(data => {
+ form.removeAttribute('autocapitalize');
+
+ if (data.formValue !== null) {
+ form.setAttribute('autocapitalize', data.formValue);
+ }
+
+ formElements.forEach(elementData => {
+ const element = document.createElement(elementData.element);
+ form.appendChild(element);
+
+ const element2 = document.createElement(elementData.element);
+ element2.setAttribute('form', 'form');
+ document.body.appendChild(element2);
+
+ if (data.formElementValue !== null) {
+ element.setAttribute('autocapitalize', data.formElementValue);
+ element2.setAttribute('autocapitalize', data.formElementValue);
+ }
+
+ const descriptionSuffix = 'with "' + data.formValue
+ + '" and form element with "'+ data.formElementValue + '"';
+
+ if (elementData.inherits) {
+ assert_equals(element.autocapitalize, data.inheritedResult,
+ `${elementData.element} element with form parent `
+ + `${descriptionSuffix}`);
+ assert_equals(element2.autocapitalize, data.inheritedResult,
+ `${elementData.element} element with form owner attribute`
+ + ` set ${descriptionSuffix}`);
+ } else {
+ assert_equals(element.autocapitalize, data.uninheritedResult,
+ `${elementData.element} element with form parent `
+ + `${descriptionSuffix}`);
+ assert_equals(element2.autocapitalize, data.uninheritedResult,
+ `${elementData.element} element with form owner attribute`
+ + `set ${descriptionSuffix}`);
+ }
+ });
+ });
+}, "Test inheriting values from a form.")
+
+test(function() {
+ const testData = [ 'text',
+ 'search',
+ 'email',
+ 'url',
+ 'tel',
+ 'number',
+ 'date',
+ 'color',
+ 'password' ];
+
+ testData.forEach(function(data) {
+ const form = document.createElement('form');
+ form.setAttribute('autocapitalize', 'sentences');
+ const input = document.createElement('input');
+ input.setAttribute('type', data);
+ form.appendChild(input);
+
+ assert_equals(input.autocapitalize, 'sentences');
+ });
+}, "Verify that even input types that are never autocapitalized support the "
++ "IDL interface.")
+
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/html/editing/editing-0/contenteditable/contentEditable-slotted-inherit.html b/testing/web-platform/tests/html/editing/editing-0/contenteditable/contentEditable-slotted-inherit.html
new file mode 100644
index 0000000000..42da515920
--- /dev/null
+++ b/testing/web-platform/tests/html/editing/editing-0/contenteditable/contentEditable-slotted-inherit.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>contentEditable inherit from light tree parent</title>
+<link rel="author" title="Rune Lillesveen" href="mailto:futhark@chromium.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#contenteditable">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<p>You should see the word PASS two times below and no FAIL.</p>
+<div id="host1" contenteditable><div>FAILPASS</div></div>
+<div id="host2" contenteditable><div>FAILPASS</div></div>
+<script>
+ test(() => {
+ const root = host1.attachShadow({mode:"open"});
+ root.innerHTML = "<slot></slot>";
+ const text = host1.firstChild.firstChild;
+ const selection = window.getSelection();
+ selection.collapse(text, 0);
+ selection.extend(text, 4);
+ host1.focus();
+ document.execCommand("delete");
+ host1.blur();
+ assert_equals(text.data, "PASS", "Text should be PASS after FAIL is deleted");
+ }, "Slotted child of contenteditable host should be editable - slot direct child of shadow root");
+
+ test(() => {
+ const root = host2.attachShadow({mode:"open"});
+ root.innerHTML = "<div><slot></slot></div>";
+ const text = host2.firstChild.firstChild;
+ const selection = window.getSelection();
+ selection.collapse(text, 0);
+ selection.extend(text, 4);
+ host2.focus();
+ document.execCommand("delete");
+ host2.blur();
+ assert_equals(text.data, "PASS", "Text should be PASS after FAIL is deleted");
+ }, "Slotted child of contenteditable host should be editable - slot wrapped in shadow tree ancestor");
+</script>
diff --git a/testing/web-platform/tests/html/editing/editing-0/contenteditable/contenteditable-enumerated-ascii-case-insensitive.html b/testing/web-platform/tests/html/editing/editing-0/contenteditable/contenteditable-enumerated-ascii-case-insensitive.html
new file mode 100644
index 0000000000..0125b95667
--- /dev/null
+++ b/testing/web-platform/tests/html/editing/editing-0/contenteditable/contenteditable-enumerated-ascii-case-insensitive.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<link rel="help" href="https://html.spec.whatwg.org/#attr-contenteditable">
+<link rel="help" href="https://html.spec.whatwg.org/#enumerated-attribute">
+<meta name="assert" content="@contenteditable values are ASCII case-insensitive">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<script>
+function testValue(value, isValid) {
+ const valueLower = value.toLowerCase();
+
+ test(() => {
+ const el = document.createElement('div');
+ if (valueLower !== "inherit") {
+ el.setAttribute('contenteditable', value);
+ }
+ assert_equals(el.contentEditable, isValid ? valueLower : "inherit");
+ }, `IDL attribute getter for attribute value "${value}"`);
+
+ test(() => {
+ const el = document.createElement('div');
+ if (isValid) {
+ el.contentEditable = value;
+ assert_equals(el.getAttribute('contenteditable'), valueLower === "inherit" ? null : valueLower);
+ } else {
+ assert_throws_dom("SyntaxError", () => {
+ el.contentEditable = value;
+ });
+ }
+ }, `IDL attribute setter for value "${value}"`);
+}
+
+const valid = ["true", "false", "inherit", "plaintext-only"]; // "inherit" is treated specially
+const invalid = ["foobar", "falſe", "plaıntext-only", "plaİntext-only"];
+
+for (const value of valid) {
+ testValue(value, true);
+ testValue(value.toUpperCase(), true);
+}
+
+for (const value of invalid) {
+ testValue(value, false);
+}
+</script>
diff --git a/testing/web-platform/tests/html/editing/editing-0/contenteditable/contenteditable-overflow-height-ref.html b/testing/web-platform/tests/html/editing/editing-0/contenteditable/contenteditable-overflow-height-ref.html
new file mode 100644
index 0000000000..e88e904f96
--- /dev/null
+++ b/testing/web-platform/tests/html/editing/editing-0/contenteditable/contenteditable-overflow-height-ref.html
@@ -0,0 +1,9 @@
+<!doctype html>
+<title>CSS test reference</title>
+<style>
+ [contenteditable] {
+ outline: 1px solid black;
+ outline-offset: -1px;
+ }
+</style>
+<div contenteditable></div>
diff --git a/testing/web-platform/tests/html/editing/editing-0/contenteditable/contenteditable-overflow-height.html b/testing/web-platform/tests/html/editing/editing-0/contenteditable/contenteditable-overflow-height.html
new file mode 100644
index 0000000000..8470b02c2b
--- /dev/null
+++ b/testing/web-platform/tests/html/editing/editing-0/contenteditable/contenteditable-overflow-height.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<title>Overflow still allows contenteditable elements to have height</title>
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="author" title="Mozilla" href="https://mozilla.org">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1681375">
+<link rel="match" href="contenteditable-overflow-height-ref.html">
+<style>
+ [contenteditable] {
+ outline: 1px solid black;
+ outline-offset: -1px;
+ overflow: hidden;
+ }
+</style>
+<div contenteditable></div>
diff --git a/testing/web-platform/tests/html/editing/editing-0/contenteditable/contenteditable-with-empty-block-ref.html b/testing/web-platform/tests/html/editing/editing-0/contenteditable/contenteditable-with-empty-block-ref.html
new file mode 100644
index 0000000000..fe68571013
--- /dev/null
+++ b/testing/web-platform/tests/html/editing/editing-0/contenteditable/contenteditable-with-empty-block-ref.html
@@ -0,0 +1,7 @@
+<!doctype html>
+<title>Test reference</title>
+<div>
+ Foo
+ <div></div>
+ Bar
+</div>
diff --git a/testing/web-platform/tests/html/editing/editing-0/contenteditable/contenteditable-with-empty-block.html b/testing/web-platform/tests/html/editing/editing-0/contenteditable/contenteditable-with-empty-block.html
new file mode 100644
index 0000000000..7bcc611072
--- /dev/null
+++ b/testing/web-platform/tests/html/editing/editing-0/contenteditable/contenteditable-with-empty-block.html
@@ -0,0 +1,11 @@
+<!doctype html>
+<title>contenteditable doesn't cause inner empty blocks to grow.</title>
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="author" title="Mozilla" href="https://mozilla.org">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1628770">
+<link rel="match" href="contenteditable-with-empty-block-ref.html">
+<div contenteditable>
+ Foo
+ <div></div>
+ Bar
+</div>
diff --git a/testing/web-platform/tests/html/editing/editing-0/contenteditable/selection-in-contentEditable-at-turning-designMode-on-off.tentative.html b/testing/web-platform/tests/html/editing/editing-0/contenteditable/selection-in-contentEditable-at-turning-designMode-on-off.tentative.html
new file mode 100644
index 0000000000..4ef9d9003d
--- /dev/null
+++ b/testing/web-platform/tests/html/editing/editing-0/contenteditable/selection-in-contentEditable-at-turning-designMode-on-off.tentative.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>selection in contenteditable should not be changed when designMode is turned on/off</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<iframe srcdoc="<body contenteditable>abc</body>"></iframe>
+<script>
+ const test_load = async_test("Selection in contenteditable shouldn't be reinitialized when changing designMode");
+ window.addEventListener("load", test_load.step_func_done(() => {
+ let iframe = document.querySelector("iframe");
+ let iframeSelection = iframe.contentDocument.getSelection();
+ iframe.focus();
+ iframeSelection.collapse(iframe.contentDocument.body, 1);
+ function summariseRange(range) {
+ if (!range) {
+ return "null";
+ }
+ return `(${range.startContainer.nodeName}, ${range.startOffset}) - (${range.endContainer.nodeName}, ${range.endOffset})`;
+ }
+ let maybeNormalizedRangeSummary = summariseRange(iframeSelection.getRangeAt(0));
+ assert_in_array(maybeNormalizedRangeSummary, ["(BODY, 1) - (BODY, 1)", "(#text, 3) - (#text, 3)"],
+ "Selection collapsed at end of <body> can be either as-is or normalized to the end of the text node");
+ iframe.contentDocument.designMode = "on";
+ assert_equals(summariseRange(iframeSelection.getRangeAt(0)), maybeNormalizedRangeSummary,
+ "Turning designMode on at load event shouldn't change selection in contenteditable");
+ iframe.contentDocument.designMode = "off";
+ assert_equals(summariseRange(iframeSelection.getRangeAt(0)), maybeNormalizedRangeSummary,
+ "Turning designMode off at load event shouldn't change selection in contenteditable");
+ }));
+</script>
diff --git a/testing/web-platform/tests/html/editing/editing-0/contenteditable/user-interaction-editing-contenteditable.html b/testing/web-platform/tests/html/editing/editing-0/contenteditable/user-interaction-editing-contenteditable.html
new file mode 100644
index 0000000000..19b21863e0
--- /dev/null
+++ b/testing/web-platform/tests/html/editing/editing-0/contenteditable/user-interaction-editing-contenteditable.html
@@ -0,0 +1,68 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Editing: contentEditable attribute test</title>
+ <link rel="author" title="Baidu" href="mailto: guopengcheng@baidu.com" />
+ <link
+ rel="help"
+ href="https://html.spec.whatwg.org/multipage/#contenteditable"
+ />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <div id="log"></div>
+ </head>
+ <body>
+ <script>
+ function testContentEditable(variationFunc, title, expectIsContentEditable, expectContentEditable) {
+ test(() => {
+ const div = document.createElement("div");
+ variationFunc(div);
+ assert_equals(div.isContentEditable, expectIsContentEditable, 'isContentEditable');
+ assert_equals(div.contentEditable, expectContentEditable, 'contentEditable');
+ }, title);
+ }
+
+ testContentEditable(el => {
+ }, "no contenteditable attribute", false, "inherit");
+
+ testContentEditable(el => {
+ el.setAttribute("contenteditable", "");
+ }, "empty contentEditable attribute", true, "true");
+
+ testContentEditable(el => {
+ el.contentEditable = "true";
+ }, 'set contentEditable = "true"', true, "true");
+
+ testContentEditable(el => {
+ el.contentEditable = "false";
+ }, 'set contentEditable = "false"', false, "false");
+
+ testContentEditable(el => {
+ const parent = document.createElement("div");
+ parent.appendChild(el);
+ parent.contentEditable = "true";
+ }, 'set parent element contentEditable = "true"', true, "inherit");
+
+ testContentEditable(el => {
+ const parent = document.createElement("div");
+ parent.appendChild(el);
+ parent.contentEditable = "false";
+ }, 'set parent element contentEditable = "false"', false, "inherit");
+
+ testContentEditable(el => {
+ el.contentEditable = "true";
+ el.removeAttribute("contenteditable");
+ }, 'set contentEditable = "true" and then remove contenteditable attribute', false, "inherit");
+
+ testContentEditable(el => {
+ el.setAttribute("contenteditable", "plaintext-only");
+ }, "contentEditable=plaintext-only attribute", true, "plaintext-only");
+
+ testContentEditable(el => {
+ const parent = document.createElement("div");
+ parent.appendChild(el);
+ parent.contentEditable = "plaintext-only";
+ }, 'set parent element contentEditable = "plaintext-only"', true, "inherit");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/editing/editing-0/making-entire-documents-editable-the-designmode-idl-attribute/original-id.json b/testing/web-platform/tests/html/editing/editing-0/making-entire-documents-editable-the-designmode-idl-attribute/original-id.json
new file mode 100644
index 0000000000..8b7c4b838c
--- /dev/null
+++ b/testing/web-platform/tests/html/editing/editing-0/making-entire-documents-editable-the-designmode-idl-attribute/original-id.json
@@ -0,0 +1 @@
+{"original_id":"making-entire-documents-editable:-the-designmode-idl-attribute"} \ No newline at end of file
diff --git a/testing/web-platform/tests/html/editing/editing-0/making-entire-documents-editable-the-designmode-idl-attribute/user-interaction-editing-designMode-svg.svg b/testing/web-platform/tests/html/editing/editing-0/making-entire-documents-editable-the-designmode-idl-attribute/user-interaction-editing-designMode-svg.svg
new file mode 100644
index 0000000000..fd2fde0fbe
--- /dev/null
+++ b/testing/web-platform/tests/html/editing/editing-0/making-entire-documents-editable-the-designmode-idl-attribute/user-interaction-editing-designMode-svg.svg
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg:svg xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/1999/xhtml"
+ width="100%" height="100%" viewBox="0 0 800 600">
+ <svg:title>Editing: designMode attribute test</svg:title>
+ <head>
+ <link rel="author" title="Baidu" href="mailto: guopengcheng@baidu.com"/>
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#making-entire-documents-editable:-the-designmode-idl-attribute"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <div id="log"></div>
+ </head>
+ <body>
+ <script type="text/javascript"><![CDATA[
+ test(function() {
+ assert_equals(document.designMode, "off", "check for designMode value");
+ assert_throws_dom("InvalidStateError", function() { document.queryCommandSupported("delete") });
+ assert_throws_dom("InvalidStateError", function() { document.queryCommandEnabled("delete") });
+ }, "initial designMode attribute");
+ document.designMode="on";
+ test(function() {
+ assert_equals(document.designMode, "on", "check for designMode value");
+ assert_throws_dom("InvalidStateError", function() { document.queryCommandSupported("delete") });
+ assert_throws_dom("InvalidStateError", function() { document.queryCommandEnabled("delete") });
+ }, "set designMode = \"on\"");
+ document.designMode="off";
+ test(function() {
+ assert_equals(document.designMode,"off", "check for designMode value");
+ assert_throws_dom("InvalidStateError", function() { document.queryCommandSupported("delete") });
+ assert_throws_dom("InvalidStateError", function() { document.queryCommandEnabled("delete") });
+ }, "set designMode = \"off\"");
+ ]]></script>
+ </body>
+</svg:svg>
diff --git a/testing/web-platform/tests/html/editing/editing-0/making-entire-documents-editable-the-designmode-idl-attribute/user-interaction-editing-designMode-xml.xml b/testing/web-platform/tests/html/editing/editing-0/making-entire-documents-editable-the-designmode-idl-attribute/user-interaction-editing-designMode-xml.xml
new file mode 100644
index 0000000000..f26cd56453
--- /dev/null
+++ b/testing/web-platform/tests/html/editing/editing-0/making-entire-documents-editable-the-designmode-idl-attribute/user-interaction-editing-designMode-xml.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Editing: designMode attribute test</title>
+ <link rel="author" title="Baidu" href="mailto: guopengcheng@baidu.com"/>
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#making-entire-documents-editable:-the-designmode-idl-attribute"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <div id="log"></div>
+ </head>
+ <body>
+ <script type="text/javascript"><![CDATA[
+ test(function() {
+ assert_equals(document.designMode, "off", "check for designMode value");
+ assert_throws_dom("InvalidStateError", function() { document.queryCommandSupported("delete") });
+ assert_throws_dom("InvalidStateError", function() { document.queryCommandEnabled("delete") });
+ }, "initial designMode attribute");
+ document.designMode="on";
+ test(function() {
+ assert_equals(document.designMode, "on", "check for designMode value");
+ assert_throws_dom("InvalidStateError", function() { document.queryCommandSupported("delete") });
+ assert_throws_dom("InvalidStateError", function() { document.queryCommandEnabled("delete") });
+ }, "set designMode = \"on\"");
+ document.designMode="off";
+ test(function() {
+ assert_equals(document.designMode,"off", "check for designMode value");
+ assert_throws_dom("InvalidStateError", function() { document.queryCommandSupported("delete") });
+ assert_throws_dom("InvalidStateError", function() { document.queryCommandEnabled("delete") });
+ }, "set designMode = \"off\"");
+ ]]></script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/editing/editing-0/making-entire-documents-editable-the-designmode-idl-attribute/user-interaction-editing-designMode.html b/testing/web-platform/tests/html/editing/editing-0/making-entire-documents-editable-the-designmode-idl-attribute/user-interaction-editing-designMode.html
new file mode 100644
index 0000000000..79d2dc8ba0
--- /dev/null
+++ b/testing/web-platform/tests/html/editing/editing-0/making-entire-documents-editable-the-designmode-idl-attribute/user-interaction-editing-designMode.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Editing: designMode attribute test</title>
+ <link rel="author" title="Baidu" href="mailto: guopengcheng@baidu.com"/>
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#making-entire-documents-editable:-the-designmode-idl-attribute"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <div id="log"></div>
+ </head>
+ <body>
+ <script type="text/javascript">
+ test(function() {
+ assert_equals(document.designMode, "off", "check for designMode value");
+ assert_true(document.queryCommandSupported("delete"));
+ assert_false(document.queryCommandEnabled("delete"));
+ }, "initial designMode attribute");
+ document.designMode="on";
+ test(function() {
+ assert_equals(document.designMode, "on", "check for designMode value");
+ assert_true(document.queryCommandSupported("delete"));
+ assert_true(document.queryCommandEnabled("delete"));
+ }, "set designMode = \"on\"");
+ document.designMode="off";
+ test(function() {
+ assert_equals(document.designMode,"off", "check for designMode value");
+ assert_true(document.queryCommandSupported("delete"));
+ assert_false(document.queryCommandEnabled("delete"));
+ }, "set designMode = \"off\"");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/references/spelling-markers-001-ref.html b/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/references/spelling-markers-001-ref.html
new file mode 100644
index 0000000000..68dcc54702
--- /dev/null
+++ b/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/references/spelling-markers-001-ref.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta charset="utf-8">
+<title>Reference file for spellcheck tests</title>
+
+<div>This test passes if there is no visual marker indicating the spellinnnnnggg mistake in this sentence, and fails otherwise.</div>
+
diff --git a/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spellcheck-enumerated-ascii-case-insensitive.html b/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spellcheck-enumerated-ascii-case-insensitive.html
new file mode 100644
index 0000000000..9f00f1dff1
--- /dev/null
+++ b/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spellcheck-enumerated-ascii-case-insensitive.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<link rel="help" href="https://html.spec.whatwg.org/#attr-spellcheck">
+<link rel="help" href="https://html.spec.whatwg.org/#enumerated-attribute">
+<meta name="assert" content="@spellcheck values are ASCII case-insensitive">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<!--
+ While <div> and <span> aren’t defined as “checkable for the purposes of this
+ feature”, this has no effect on the attribute’s state.
+
+ We wrap the <span> elements under test with <div> elements so the checking
+ enabled algorithm stops at step 4 (ancestor content attribute), before steps
+ relying on user-agent-defined behavior (see [#concept-spellcheck-default]).
+-->
+<div spellcheck="true"><span spellcheck="false"></span></div>
+<div spellcheck="true"><span spellcheck="FaLsE"></span></div>
+<div spellcheck="true"><span spellcheck="falſe"></span></div>
+<script>
+const span = document.querySelectorAll("span");
+
+test(() => {
+ assert_equals(span[0].spellcheck, false, "lowercase valid");
+ assert_equals(span[1].spellcheck, false, "mixed case valid");
+ assert_equals(span[2].spellcheck, true, "non-ASCII invalid");
+}, "keyword false");
+</script>
diff --git a/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-001.html b/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-001.html
new file mode 100644
index 0000000000..7dd891374b
--- /dev/null
+++ b/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-001.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta charset="utf-8">
+<title>Turning off spellcheck on editing hosts</title>
+<link rel=match href="references/spelling-markers-001-ref.html">
+<link rel=help href="https://html.spec.whatwg.org/multipage/interaction.html#spelling-and-grammar-checking">
+<meta name=assert content="Spellchecking stops applying to editing hosts when they become non editable">
+
+<div id="test" contenteditable=true>This test passes if there is no visual marker indicating the spellinnnnnggg mistake in this sentence, and fails otherwise.</div>
+
+<script>
+ var test = document.getElementById("test");
+ // Force spellcheck by focus and then blur
+ test.focus();
+ test.blur();
+ test.removeAttribute("contenteditable");
+</script>
diff --git a/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-002.html b/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-002.html
new file mode 100644
index 0000000000..b361b93040
--- /dev/null
+++ b/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-002.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta charset="utf-8">
+<title>Turning off spellcheck on editable elements</title>
+<link rel=match href="references/spelling-markers-001-ref.html">
+<link rel=help href="https://html.spec.whatwg.org/multipage/interaction.html#spelling-and-grammar-checking">
+<meta name=assert content="Spellchecking stops applying to editable elements when they become non editable">
+
+<div id="test" contenteditable=true>This test passes if there is no visual marker indicating the <span id=child>spellinnnnnggg</span> mistake in this sentence, and fails otherwise.</div>
+
+<script>
+ var test = document.getElementById("test");
+ // Force spellcheck by focus and then blur
+ test.focus();
+ test.blur();
+ var child = document.getElementById("child");
+ child.setAttribute("contenteditable", false);
+</script>
diff --git a/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-003.html b/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-003.html
new file mode 100644
index 0000000000..d1a6aa3a9b
--- /dev/null
+++ b/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-003.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta charset="utf-8">
+<title>Turning off spellcheck on editing hosts while keeping them editable</title>
+<link rel=match href="references/spelling-markers-001-ref.html">
+<link rel=help href="https://html.spec.whatwg.org/multipage/interaction.html#spelling-and-grammar-checking">
+<meta name=assert content="Spellchecking stops applying to editing hosts when the spellcheck attribute becomes false">
+
+<div id="test" spellcheck=true contenteditable=true>This test passes if there is no visual marker indicating the spellinnnnnggg mistake in this sentence, and fails otherwise.</div>
+
+<script>
+ var test = document.getElementById("test");
+ // Force spellcheck by focus and then blur
+ test.focus();
+ test.blur();
+ test.setAttribute("spellcheck", false);
+</script>
diff --git a/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-004.html b/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-004.html
new file mode 100644
index 0000000000..c718e77bb8
--- /dev/null
+++ b/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-004.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta charset="utf-8">
+<title>Turning off spellcheck on editable elements while keeping them editable</title>
+<link rel=match href="references/spelling-markers-001-ref.html">
+<link rel=help href="https://html.spec.whatwg.org/multipage/interaction.html#spelling-and-grammar-checking">
+<meta name=assert content="Spellchecking stops applying to editable elements when the spellcheck attribute becomes false">
+
+<div id="test" spellcheck=true contenteditable=true>This test passes if there is no visual marker indicating the <span id=child>spellinnnnnggg</span> mistake in this sentence, and fails otherwise.</div>
+
+<script>
+ var test = document.getElementById("test");
+ // Force spellcheck by focus then blur
+ test.focus();
+ test.blur();
+ var child = document.getElementById("child");
+ child.setAttribute("spellcheck", false);
+</script>
diff --git a/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-005.html b/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-005.html
new file mode 100644
index 0000000000..705ee7b67f
--- /dev/null
+++ b/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-005.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta charset="utf-8">
+<title>Turning off spellcheck on editable elements via an ancestor</title>
+<link rel=match href="references/spelling-markers-001-ref.html">
+<link rel=help href="https://html.spec.whatwg.org/multipage/interaction.html#spelling-and-grammar-checking">
+<meta name=assert content="Spellchecking stops applying to editable elements when the spellcheck attribute becomes false on an ancestor">
+
+<div id="test" contenteditable=true>This test passes if there is no visual marker indicating the <span id=child><span>spellinnnnnggg</span></span> mistake in this sentence, and fails otherwise.</div>
+
+<script>
+ var test = document.getElementById("test");
+ // Force spellcheck by focus then blur
+ test.focus();
+ test.blur();
+ var child = document.getElementById("child");
+ child.setAttribute("spellcheck", false);
+</script>
diff --git a/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-006.html b/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-006.html
new file mode 100644
index 0000000000..512d473f13
--- /dev/null
+++ b/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-006.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta charset="utf-8">
+<title>Turning off spellcheck via an ancestor of the editing host</title>
+<link rel=match href="references/spelling-markers-001-ref.html">
+<link rel=help href="https://html.spec.whatwg.org/multipage/interaction.html#spelling-and-grammar-checking">
+<meta name=assert content="Spellchecking stops applying when the spellcheck attribute becomes false on an ancestor, without restrcting the search to the nearest editing host">
+
+<div id=parent>
+ <div id=test contenteditable=true>This test passes if there is no visual marker indicating the spellinnnnnggg mistake in this sentence, and fails otherwise.</div>
+</div>
+
+<script>
+ var test = document.getElementById("test");
+ // Force spellcheck by focus then blur
+ test.focus();
+ test.blur();
+ var p = document.getElementById("parent");
+ p.setAttribute("spellcheck", false);
+</script>
diff --git a/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-007.html b/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-007.html
new file mode 100644
index 0000000000..31b3755f3a
--- /dev/null
+++ b/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-007.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta charset="utf-8">
+<title>Turning off spellcheck by making textareas readonly</title>
+<link rel=match href="references/spelling-markers-001-ref.html">
+<link rel=help href="https://html.spec.whatwg.org/multipage/interaction.html#spelling-and-grammar-checking">
+<meta name=assert content="Spellchecking stops applying to textareas when they become readonly">
+
+<style>
+#test {
+ /* Match the ref */
+ all: initial;
+ width: 100%;
+ display: block;
+ font-family: inherit;
+}
+</style>
+
+<textarea id=test>This test passes if there is no visual marker indicating the spellinnnnnggg mistake in this sentence, and fails otherwise.</textarea>
+
+<script>
+ var test = document.getElementById("test");
+ // Force spellcheck by focus then blur
+ test.focus();
+ test.blur();
+ test.setAttribute("readonly", true);
+</script>
diff --git a/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-008.html b/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-008.html
new file mode 100644
index 0000000000..f891acff42
--- /dev/null
+++ b/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-008.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta charset="utf-8">
+<title>Turning off spellcheck by making textareas disabled</title>
+<link rel=match href="references/spelling-markers-001-ref.html">
+<link rel=help href="https://html.spec.whatwg.org/multipage/interaction.html#spelling-and-grammar-checking">
+<meta name=assert content="Spellchecking stops applying to textareas when they become disabled">
+
+<style>
+#test {
+ /* Match the ref */
+ all: initial;
+ width: 100%;
+ display: block;
+ font-family: inherit;
+}
+</style>
+
+<textarea id=test>This test passes if there is no visual marker indicating the spellinnnnnggg mistake in this sentence, and fails otherwise.</textarea>
+
+<script>
+ var test = document.getElementById("test");
+ // Force spellcheck by focus then blur
+ test.focus();
+ test.blur();
+ test.setAttribute("disabled", true);
+</script>
diff --git a/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-009.html b/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-009.html
new file mode 100644
index 0000000000..96eb87d2f4
--- /dev/null
+++ b/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-009.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta charset="utf-8">
+<title>Turning off spellcheck by making input elements readonly</title>
+<link rel=match href="references/spelling-markers-001-ref.html">
+<link rel=help href="https://html.spec.whatwg.org/multipage/interaction.html#spelling-and-grammar-checking">
+<meta name=assert content="Spellchecking stops applying to input elements when they become readonly">
+
+<style>
+#test {
+ /* Match the ref */
+ all: initial;
+ width: 100%;
+ display: block;
+ font-family: inherit;
+}
+</style>
+
+<input type=text id=test value="This test passes if there is no visual marker indicating the spellinnnnnggg mistake in this sentence, and fails otherwise.">
+
+<script>
+ var test = document.getElementById("test");
+ // Force spellcheck by focus then blur
+ test.focus();
+ test.blur();
+ test.setAttribute("readonly", true);
+</script>
diff --git a/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-010.html b/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-010.html
new file mode 100644
index 0000000000..16275f10e9
--- /dev/null
+++ b/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/spelling-markers-010.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta charset="utf-8">
+<title>Turning off spellcheck by making input elements disabled</title>
+<link rel=match href="references/spelling-markers-001-ref.html">
+<link rel=help href="https://html.spec.whatwg.org/multipage/interaction.html#spelling-and-grammar-checking">
+<meta name=assert content="Spellchecking stops applying to input elements when they become disabled">
+
+<style>
+#test {
+ /* Match the ref */
+ all: initial;
+ width: 100%;
+ display: block;
+ font-family: inherit;
+}
+</style>
+
+<input type=text id=test value="This test passes if there is no visual marker indicating the spellinnnnnggg mistake in this sentence, and fails otherwise.">
+
+<script>
+ var test = document.getElementById("test");
+ // Force spellcheck by focus then blur
+ test.focus();
+ test.blur();
+ test.setAttribute("disabled", true);
+</script>
diff --git a/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/user-interaction-editing-spellcheck.html b/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/user-interaction-editing-spellcheck.html
new file mode 100644
index 0000000000..c8bdaafdb8
--- /dev/null
+++ b/testing/web-platform/tests/html/editing/editing-0/spelling-and-grammar-checking/user-interaction-editing-spellcheck.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Editing: spellcheck attribute test</title>
+ <link rel="author" title="Baidu" href="mailto: guopengcheng@baidu.com"/>
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#spelling-and-grammar-checking"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <textarea id="testText1" spellcheck="true">Test textarea with spellcheck is true</textarea>
+ <textarea id="testText2" spellcheck="false">Test textarea with spellcheck is false</textarea>
+ <script type="text/javascript">
+ test(function() {
+ assert_true(document.getElementById("testText1").spellcheck, "check for testText1 spellcheck value");
+ assert_false(document.getElementById("testText2").spellcheck, "check for testText2 spellcheck value");
+ }, "Getting spellcheck IDL attribute");
+ test(function() {
+ var testElement = document.createElement("testElement");
+ testElement.contentEditable = true;
+ testElement.spellcheck = true;
+ assert_true(testElement.spellcheck, "check for testElement.spellcheck value");
+ assert_equals(testElement.getAttribute("spellcheck"), "true");
+ }, "Setting spellcheck IDL attribute to true");
+ test(function() {
+ var testElement = document.createElement("testElement");
+ testElement.contentEditable = true;
+ testElement.spellcheck = false;
+ assert_false(testElement.spellcheck, "check for testText2 spellcheck value");
+ assert_equals(testElement.getAttribute("spellcheck"), "false");
+ }, "Setting spellcheck IDL attribute to false");
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/editing/editing-0/writing-suggestions/writingsuggestions.html b/testing/web-platform/tests/html/editing/editing-0/writing-suggestions/writingsuggestions.html
new file mode 100644
index 0000000000..49e75000d3
--- /dev/null
+++ b/testing/web-platform/tests/html/editing/editing-0/writing-suggestions/writingsuggestions.html
@@ -0,0 +1,457 @@
+<!DOCTYPE html>
+<title>Tests for the writingsuggestions attribute</title>
+<link rel='author' title='Sanket Joshi' href='mailto:sajos@microsoft.com'>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/interaction.html#writingsuggestions">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+'use strict';
+
+customElements.define('test-custom-element', class extends HTMLElement {});
+
+test(function() {
+ assert_true('writingSuggestions' in document.createElement('input'));
+}, 'Test that the writingsuggestions attribute is available on HTMLInputElement.');
+
+test(function() {
+ assert_true('writingSuggestions' in document.createElement('textarea'));
+}, 'Test that the writingsuggestions attribute is available on HTMLTextAreaElement.');
+
+test(function() {
+ assert_true('writingSuggestions' in document.createElement('div'));
+}, 'Test that the writingsuggestions attribute is available on HTMLDivElement.');
+
+test(function() {
+ assert_true('writingSuggestions' in document.createElement('span'));
+}, 'Test that the writingsuggestions attribute is available on HTMLSpanElement.');
+
+test(function() {
+ assert_true('writingSuggestions' in document.createElement('test-custom-element'));
+}, 'Test that the writingsuggestions attribute is available on custom elements.');
+
+function testSetAttributeDirectly(IDLValue, contentValue, expectedIDLValue, expectedContentValue, testDescription) {
+ test(function() {
+ const elements = [document.createElement('input'),
+ document.createElement('textarea'),
+ document.createElement('div'),
+ document.createElement('span'),
+ document.createElement('test-custom-element') ];
+
+ elements.forEach(function(element) {
+ if (IDLValue != undefined) {
+ element.writingSuggestions = IDLValue;
+ }
+ if (contentValue != undefined) {
+ element.setAttribute('writingsuggestions', contentValue);
+ }
+ assert_equals(element.writingSuggestions, expectedIDLValue);
+ assert_equals(element.getAttribute('writingsuggestions'), expectedContentValue);
+ });
+ }, testDescription);
+}
+
+// Test setting either the `writingsuggestions` IDL or content attribute to some variation of 'true' directly on the target element.
+testSetAttributeDirectly('true', undefined, 'true', 'true', 'Test setting the `writingsuggestions` IDL attribute to `true` directly on the target element.');
+testSetAttributeDirectly(undefined, 'true', 'true', 'true', 'Test setting the `writingsuggestions` content attribute to `true` directly on the target element.');
+testSetAttributeDirectly(true, undefined, 'true', 'true', 'Test setting the `writingsuggestions` IDL attribute to boolean `true` directly on the target element.');
+testSetAttributeDirectly(undefined, true, 'true', 'true', 'Test setting the `writingsuggestions` content attribute to boolean `true` directly on the target element.');
+testSetAttributeDirectly('TrUe', undefined, 'true', 'true', 'Test setting the `writingsuggestions` IDL attribute to `TrUe` directly on the target element.');
+testSetAttributeDirectly(undefined, 'TrUe', 'true', 'TrUe', 'Test setting the `writingsuggestions` content attribute to `TrUe` directly on the target element.');
+
+// Test setting either the `writingsuggestions` IDL or content attribute to some variation of 'false' directly on the target element.
+testSetAttributeDirectly('false', undefined, 'false', 'false', 'Test setting the `writingsuggestions` IDL attribute to `false` directly on the target element.');
+testSetAttributeDirectly(undefined, 'false', 'false', 'false', 'Test setting the `writingsuggestions` content attribute to `false` directly on the target element.');
+testSetAttributeDirectly(false, undefined, 'false', 'false', 'Test setting the `writingsuggestions` IDL attribute to boolean `false` directly on the target element.');
+testSetAttributeDirectly(undefined, false, 'false', 'false', 'Test setting the `writingsuggestions` content attribute to boolean `false` directly on the target element.');
+testSetAttributeDirectly('FaLsE', undefined, 'false', 'false', 'Test setting the `writingsuggestions` IDL attribute to `FaLsE` directly on the target element.');
+testSetAttributeDirectly(undefined, 'FaLsE', 'false', 'FaLsE', 'Test setting the `writingsuggestions` content attribute to `FaLsE` directly on the target element.');
+
+// Test setting either the `writingsuggestions` IDL or content attribute to the empty string directly on the target element.
+testSetAttributeDirectly('', undefined, 'true', 'true', 'Test setting the `writingsuggestions` IDL attribute to the empty string directly on the target element.');
+testSetAttributeDirectly(undefined, '', 'true', '', 'Test setting the `writingsuggestions` content attribute to the empty string directly on the target element.');
+
+// Test setting either the `writingsuggestions` IDL or content attribute to an invalid value directly on the target element.
+testSetAttributeDirectly('foo', undefined, 'true', 'true', 'Test setting the `writingsuggestions` IDL attribute to an invalid value directly on the target element.');
+testSetAttributeDirectly(undefined, 'foo', 'true', 'foo', 'Test setting the `writingsuggestions` content attribute to an invalid value directly on the target element.');
+
+// Test setting neither the `writingsuggestions` IDL nor content attribute directly on the target element.
+testSetAttributeDirectly(undefined, undefined, 'true', null, 'Test the writing suggestions state when the `writingsuggestions` attribute is missing.');
+
+// Test setting the content attribute after the IDL attribute and making sure the IDL and content attributes are properly reflected.
+testSetAttributeDirectly('true', 'false', 'false', 'false', 'Test setting the `writingsuggestions` content attribute to `false` after the IDL attribute was set to `true`.');
+testSetAttributeDirectly('true', '', 'true', '', 'Test setting the `writingsuggestions` content attribute to the empty string after the IDL attribute was set to `true`.');
+testSetAttributeDirectly('true', 'foo', 'true', 'foo', 'Test setting the `writingsuggestions` content attribute to an invalid value after the IDL attribute was set to `true`.');
+testSetAttributeDirectly('true', 'TrUe', 'true', 'TrUe', 'Test setting the `writingsuggestions` content attribute to `TrUe` after the IDL attribute was set to `true`.');
+testSetAttributeDirectly('true', 'FaLsE', 'false', 'FaLsE', 'Test setting the `writingsuggestions` content attribute to `FaLsE` after the IDL attribute was set to `true`.');
+testSetAttributeDirectly('true', true, 'true', 'true', 'Test setting the `writingsuggestions` content attribute to boolean `true` after the IDL attribute was set to `true`.');
+testSetAttributeDirectly('true', false, 'false', 'false', 'Test setting the `writingsuggestions` content attribute to boolean `false` after the IDL attribute was set to `true`.');
+
+testSetAttributeDirectly('false', 'true', 'true', 'true', 'Test setting the `writingsuggestions` content attribute to `true` after the IDL attribute was set to `false`.');
+testSetAttributeDirectly('false', '', 'true', '', 'Test setting the `writingsuggestions` content attribute to the empty string after the IDL attribute was set to `false`.');
+testSetAttributeDirectly('false', 'foo', 'true', 'foo', 'Test setting the `writingsuggestions` content attribute to an invalid value after the IDL attribute was set to `false`.');
+testSetAttributeDirectly('false', 'TrUe', 'true', 'TrUe', 'Test setting the `writingsuggestions` content attribute to `TrUe` after the IDL attribute was set to `false`.');
+testSetAttributeDirectly('false', 'FaLsE', 'false', 'FaLsE', 'Test setting the `writingsuggestions` content attribute to `FaLsE` after the IDL attribute was set to `false`.');
+testSetAttributeDirectly('false', true, 'true', 'true', 'Test setting the `writingsuggestions` content attribute to boolean `true` after the IDL attribute was set to `false`.');
+testSetAttributeDirectly('false', false, 'false', 'false', 'Test setting the `writingsuggestions` content attribute to boolean `false` after the IDL attribute was set to `false`.');
+
+test(function() {
+ const elements = [ new DOMParser().parseFromString('<input writingsuggestions />', 'text/html').body.firstElementChild,
+ new DOMParser().parseFromString('<textarea writingsuggestions></textarea>', 'text/html').body.firstElementChild,
+ new DOMParser().parseFromString('<div writingsuggestions></div>', 'text/html').body.firstElementChild,
+ new DOMParser().parseFromString('<span writingsuggestions></span>', 'text/html').body.firstElementChild ];
+
+ elements.forEach(function(element) {
+ assert_equals(element.writingSuggestions, 'true');
+ assert_equals(element.getAttribute('writingsuggestions'), '');
+ });
+}, 'Test setting the `writingsuggestions` attribute with a missing value directly on the target element.');
+
+test(function() {
+ const elements = [ new DOMParser().parseFromString('<html><body writingsuggestions="true"><input /></body></html>', 'text/html').body.firstElementChild,
+ new DOMParser().parseFromString('<html><body writingsuggestions="true"><textarea></textarea></body></html>', 'text/html').body.firstElementChild,
+ new DOMParser().parseFromString('<html><body writingsuggestions="true"><div></div></body></html>', 'text/html').body.firstElementChild,
+ new DOMParser().parseFromString('<html><body writingsuggestions="true"><span></span></body></html>', 'text/html').body.firstElementChild ];
+
+ elements.forEach(function(element) {
+ assert_equals(element.parentElement.writingSuggestions, 'true');
+ assert_equals(element.parentElement.getAttribute('writingsuggestions'), 'true');
+ assert_equals(element.writingSuggestions, 'true');
+ assert_equals(element.getAttribute('writingsuggestions'), null);
+ });
+}, 'Test setting the `writingsuggestions` attribute to "true" on a parent element.');
+
+test(function() {
+ const elements = [ new DOMParser().parseFromString('<html><body writingsuggestions=""><input /></body></html>', 'text/html').body.firstElementChild,
+ new DOMParser().parseFromString('<html><body writingsuggestions=""><textarea></textarea></body></html>', 'text/html').body.firstElementChild,
+ new DOMParser().parseFromString('<html><body writingsuggestions=""><div></div></body></html>', 'text/html').body.firstElementChild,
+ new DOMParser().parseFromString('<html><body writingsuggestions=""><span></span></body></html>', 'text/html').body.firstElementChild ];
+
+ elements.forEach(function(element) {
+ assert_equals(element.parentElement.writingSuggestions, 'true');
+ assert_equals(element.parentElement.getAttribute('writingsuggestions'), '');
+ assert_equals(element.writingSuggestions, 'true');
+ assert_equals(element.getAttribute('writingsuggestions'), null);
+ });
+}, 'Test setting the `writingsuggestions` attribute to an empty string on a parent element.');
+
+test(function() {
+ const elements = [ new DOMParser().parseFromString('<html><body writingsuggestions="false"><input /></body></html>', 'text/html').body.firstElementChild,
+ new DOMParser().parseFromString('<html><body writingsuggestions="false"><textarea></textarea></body></html>', 'text/html').body.firstElementChild,
+ new DOMParser().parseFromString('<html><body writingsuggestions="false"><div></div></body></html>', 'text/html').body.firstElementChild,
+ new DOMParser().parseFromString('<html><body writingsuggestions="false"><span></span></body></html>', 'text/html').body.firstElementChild ];
+
+ elements.forEach(function(element) {
+ assert_equals(element.parentElement.writingSuggestions, 'false');
+ assert_equals(element.parentElement.getAttribute('writingsuggestions'), 'false');
+ assert_equals(element.writingSuggestions, 'false');
+ assert_equals(element.getAttribute('writingsuggestions'), null);
+ });
+}, 'Test setting the `writingsuggestions` attribute to "false" on a parent element.');
+
+test(function() {
+ const elements = [ new DOMParser().parseFromString('<html><body writingsuggestions="foo"><input /></body></html>', 'text/html').body.firstElementChild,
+ new DOMParser().parseFromString('<html><body writingsuggestions="foo"><textarea></textarea></body></html>', 'text/html').body.firstElementChild,
+ new DOMParser().parseFromString('<html><body writingsuggestions="foo"><div></div></body></html>', 'text/html').body.firstElementChild,
+ new DOMParser().parseFromString('<html><body writingsuggestions="foo"><span></span></body></html>', 'text/html').body.firstElementChild ];
+
+ elements.forEach(function(element) {
+ assert_equals(element.parentElement.writingSuggestions, 'true');
+ assert_equals(element.parentElement.getAttribute('writingsuggestions'), 'foo');
+ assert_equals(element.writingSuggestions, 'true');
+ assert_equals(element.getAttribute('writingsuggestions'), null);
+ });
+}, 'Test setting the `writingsuggestions` attribute to an invalid value on a parent element.');
+
+test(function() {
+ const elements = [ new DOMParser().parseFromString('<html><body writingsuggestions="true"><input writingsuggestions="false" /></body></html>', 'text/html').body.firstElementChild,
+ new DOMParser().parseFromString('<html><body writingsuggestions="true"><textarea writingsuggestions="false"></textarea></body></html>', 'text/html').body.firstElementChild,
+ new DOMParser().parseFromString('<html><body writingsuggestions="true"><div writingsuggestions="false"></div></body></html>', 'text/html').body.firstElementChild,
+ new DOMParser().parseFromString('<html><body writingsuggestions="true"><span writingsuggestions="false"></span></body></html>', 'text/html').body.firstElementChild ];
+
+ elements.forEach(function(element) {
+ assert_equals(element.parentElement.writingSuggestions, 'true');
+ assert_equals(element.parentElement.getAttribute('writingsuggestions'), 'true');
+ assert_equals(element.writingSuggestions, 'false');
+ assert_equals(element.getAttribute('writingsuggestions'), 'false');
+ });
+}, 'Test overriding the parent element\'s `writingsuggestions` attribute from "true" to "false".');
+
+test(function() {
+ const elements = [ new DOMParser().parseFromString('<html><body writingsuggestions=""><input writingsuggestions="false" /></body></html>', 'text/html').body.firstElementChild,
+ new DOMParser().parseFromString('<html><body writingsuggestions=""><textarea writingsuggestions="false"></textarea></body></html>', 'text/html').body.firstElementChild,
+ new DOMParser().parseFromString('<html><body writingsuggestions=""><div writingsuggestions="false"></div></body></html>', 'text/html').body.firstElementChild,
+ new DOMParser().parseFromString('<html><body writingsuggestions=""><span writingsuggestions="false"></span></body></html>', 'text/html').body.firstElementChild ];
+
+ elements.forEach(function(element) {
+ assert_equals(element.parentElement.writingSuggestions, 'true');
+ assert_equals(element.parentElement.getAttribute('writingsuggestions'), '');
+ assert_equals(element.writingSuggestions, 'false');
+ assert_equals(element.getAttribute('writingsuggestions'), 'false');
+ });
+}, 'Test overriding the parent element\'s `writingsuggestions` attribute from the empty string to "false".');
+
+test(function() {
+ const elements = [ new DOMParser().parseFromString('<html><body writingsuggestions="false"><input writingsuggestions="true" /></body></html>', 'text/html').body.firstElementChild,
+ new DOMParser().parseFromString('<html><body writingsuggestions="false"><textarea writingsuggestions="true"></textarea></body></html>', 'text/html').body.firstElementChild,
+ new DOMParser().parseFromString('<html><body writingsuggestions="false"><div writingsuggestions="true"></div></body></html>', 'text/html').body.firstElementChild,
+ new DOMParser().parseFromString('<html><body writingsuggestions="false"><span writingsuggestions="true"></span></body></html>', 'text/html').body.firstElementChild ];
+
+ elements.forEach(function(element) {
+ assert_equals(element.parentElement.writingSuggestions, 'false');
+ assert_equals(element.parentElement.getAttribute('writingsuggestions'), 'false');
+ assert_equals(element.writingSuggestions, 'true');
+ assert_equals(element.getAttribute('writingsuggestions'), 'true');
+ });
+}, 'Test overriding the parent element\'s `writingsuggestions` attribute from "false" to "true".');
+
+test(function() {
+ const elements = [ new DOMParser().parseFromString('<html><body writingsuggestions="false"><input writingsuggestions="foo" /></body></html>', 'text/html').body.firstElementChild,
+ new DOMParser().parseFromString('<html><body writingsuggestions="false"><textarea writingsuggestions="foo"></textarea></body></html>', 'text/html').body.firstElementChild,
+ new DOMParser().parseFromString('<html><body writingsuggestions="false"><div writingsuggestions="foo"></div></body></html>', 'text/html').body.firstElementChild,
+ new DOMParser().parseFromString('<html><body writingsuggestions="false"><span writingsuggestions="foo"></span></body></html>', 'text/html').body.firstElementChild ];
+
+ elements.forEach(function(element) {
+ assert_equals(element.parentElement.writingSuggestions, 'false');
+ assert_equals(element.parentElement.getAttribute('writingsuggestions'), 'false');
+ assert_equals(element.writingSuggestions, 'true');
+ assert_equals(element.getAttribute('writingsuggestions'), 'foo');
+ });
+}, 'Test overriding the parent element\'s `writingsuggestions` attribute from "false" to an invalid value.');
+
+test(function() {
+ const elements = [ new DOMParser().parseFromString('<html><body writingsuggestions="false"><input writingsuggestions="" /></body></html>', 'text/html').body.firstElementChild,
+ new DOMParser().parseFromString('<html><body writingsuggestions="false"><textarea writingsuggestions=""></textarea></body></html>', 'text/html').body.firstElementChild,
+ new DOMParser().parseFromString('<html><body writingsuggestions="false"><div writingsuggestions=""></div></body></html>', 'text/html').body.firstElementChild,
+ new DOMParser().parseFromString('<html><body writingsuggestions="false"><span writingsuggestions=""></span></body></html>', 'text/html').body.firstElementChild ];
+
+ elements.forEach(function(element) {
+ assert_equals(element.parentElement.writingSuggestions, 'false');
+ assert_equals(element.parentElement.getAttribute('writingsuggestions'), 'false');
+ assert_equals(element.writingSuggestions, 'true');
+ assert_equals(element.getAttribute('writingsuggestions'), '');
+ });
+}, 'Test overriding the parent element\'s `writingsuggestions` attribute from "false" to the empty string.');
+
+test(function() {
+ const doc = new DOMParser().parseFromString('<html writingsuggestions="false"><body><input /><textarea></textarea><div></div><span></span></body></html>', 'text/html');
+ assert_equals(doc.documentElement.writingSuggestions, 'false');
+ assert_equals(doc.body.writingSuggestions, 'false');
+ assert_equals(doc.querySelector('input').writingSuggestions, 'false');
+ assert_equals(doc.querySelector('textarea').writingSuggestions, 'false');
+ assert_equals(doc.querySelector('div').writingSuggestions, 'false');
+ assert_equals(doc.querySelector('span').writingSuggestions, 'false');
+}, 'Test turning off writing suggestions for an entire document.');
+
+test(function() {
+ const doc = new DOMParser().parseFromString('<html writingsuggestions="false"><body><input writingsuggestions="true" /><textarea></textarea><div></div><span></span></body></html>', 'text/html');
+ assert_equals(doc.documentElement.writingSuggestions, 'false');
+ assert_equals(doc.body.writingSuggestions, 'false');
+ assert_equals(doc.querySelector('input').writingSuggestions, 'true');
+ assert_equals(doc.querySelector('textarea').writingSuggestions, 'false');
+ assert_equals(doc.querySelector('div').writingSuggestions, 'false');
+ assert_equals(doc.querySelector('span').writingSuggestions, 'false');
+}, 'Test overriding a non-parent ancestor element\'s `writingsuggestions` attribute on an input element from "false" to "true".');
+
+test(function() {
+ const doc = new DOMParser().parseFromString('<html writingsuggestions="false"><body><input /><textarea writingsuggestions="true"></textarea><div></div><span></span></body></html>', 'text/html');
+ assert_equals(doc.documentElement.writingSuggestions, 'false');
+ assert_equals(doc.body.writingSuggestions, 'false');
+ assert_equals(doc.querySelector('input').writingSuggestions, 'false');
+ assert_equals(doc.querySelector('textarea').writingSuggestions, 'true');
+ assert_equals(doc.querySelector('div').writingSuggestions, 'false');
+ assert_equals(doc.querySelector('span').writingSuggestions, 'false');
+}, 'Test overriding a non-parent ancestor element\'s `writingsuggestions` attribute on a textarea element from "false" to "true".');
+
+test(function() {
+ const doc = new DOMParser().parseFromString('<html writingsuggestions="false"><body><input /><textarea></textarea><div writingsuggestions="true"></div><span></span></body></html>', 'text/html');
+ assert_equals(doc.documentElement.writingSuggestions, 'false');
+ assert_equals(doc.body.writingSuggestions, 'false');
+ assert_equals(doc.querySelector('input').writingSuggestions, 'false');
+ assert_equals(doc.querySelector('textarea').writingSuggestions, 'false');
+ assert_equals(doc.querySelector('div').writingSuggestions, 'true');
+ assert_equals(doc.querySelector('span').writingSuggestions, 'false');
+}, 'Test overriding a non-parent ancestor element\'s `writingsuggestions` attribute on a div element from "false" to "true".');
+
+test(function() {
+ const doc = new DOMParser().parseFromString('<html writingsuggestions="false"><body><input /><textarea></textarea><div></div><span writingsuggestions="true"></span></body></html>', 'text/html');
+ assert_equals(doc.documentElement.writingSuggestions, 'false');
+ assert_equals(doc.body.writingSuggestions, 'false');
+ assert_equals(doc.querySelector('input').writingSuggestions, 'false');
+ assert_equals(doc.querySelector('textarea').writingSuggestions, 'false');
+ assert_equals(doc.querySelector('div').writingSuggestions, 'false');
+ assert_equals(doc.querySelector('span').writingSuggestions, 'true');
+}, 'Test overriding a non-parent ancestor element\'s `writingsuggestions` attribute on a span element from "false" to "true".');
+
+test(function() {
+ const doc = new DOMParser().parseFromString('<html writingsuggestions="false"><body><input writingsuggestions=""><textarea></textarea><div></div><span></span></body></html>', 'text/html');
+ assert_equals(doc.documentElement.writingSuggestions, 'false');
+ assert_equals(doc.body.writingSuggestions, 'false');
+ assert_equals(doc.querySelector('input').writingSuggestions, 'true');
+ assert_equals(doc.querySelector('textarea').writingSuggestions, 'false');
+ assert_equals(doc.querySelector('div').writingSuggestions, 'false');
+ assert_equals(doc.querySelector('span').writingSuggestions, 'false');
+}, 'Test overriding a non-parent ancestor element\'s `writingsuggestions` attribute on an input element from "false" to the empty string.');
+
+test(function() {
+ const doc = new DOMParser().parseFromString('<html writingsuggestions="false"><body><input><textarea writingsuggestions=""></textarea><div></div><span></span></body></html>', 'text/html');
+ assert_equals(doc.documentElement.writingSuggestions, 'false');
+ assert_equals(doc.body.writingSuggestions, 'false');
+ assert_equals(doc.querySelector('input').writingSuggestions, 'false');
+ assert_equals(doc.querySelector('textarea').writingSuggestions, 'true');
+ assert_equals(doc.querySelector('div').writingSuggestions, 'false');
+ assert_equals(doc.querySelector('span').writingSuggestions, 'false');
+}, 'Test overriding a non-parent ancestor element\'s `writingsuggestions` attribute on a textarea element from "false" to the empty string.');
+
+test(function() {
+ const doc = new DOMParser().parseFromString('<html writingsuggestions="false"><body><input><textarea></textarea><div writingsuggestions=""></div><span></span></body></html>', 'text/html');
+ assert_equals(doc.documentElement.writingSuggestions, 'false');
+ assert_equals(doc.body.writingSuggestions, 'false');
+ assert_equals(doc.querySelector('input').writingSuggestions, 'false');
+ assert_equals(doc.querySelector('textarea').writingSuggestions, 'false');
+ assert_equals(doc.querySelector('div').writingSuggestions, 'true');
+ assert_equals(doc.querySelector('span').writingSuggestions, 'false');
+}, 'Test overriding a non-parent ancestor element\'s `writingsuggestions` attribute on a div element from "false" to the empty string.');
+
+test(function() {
+ const doc = new DOMParser().parseFromString('<html writingsuggestions="false"><body><input><textarea></textarea><div></div><span writingsuggestions=""></span></body></html>', 'text/html');
+ assert_equals(doc.documentElement.writingSuggestions, 'false');
+ assert_equals(doc.body.writingSuggestions, 'false');
+ assert_equals(doc.querySelector('input').writingSuggestions, 'false');
+ assert_equals(doc.querySelector('textarea').writingSuggestions, 'false');
+ assert_equals(doc.querySelector('div').writingSuggestions, 'false');
+ assert_equals(doc.querySelector('span').writingSuggestions, 'true');
+}, 'Test overriding a non-parent ancestor element\'s `writingsuggestions` attribute on a span element from "false" to the empty string.');
+
+test(function() {
+ const doc = new DOMParser().parseFromString('<html writingsuggestions="false"><body><input writingsuggestions="foo"><textarea></textarea><div></div><span></span></body></html>', 'text/html');
+ assert_equals(doc.documentElement.writingSuggestions, 'false');
+ assert_equals(doc.body.writingSuggestions, 'false');
+ assert_equals(doc.querySelector('input').writingSuggestions, 'true');
+ assert_equals(doc.querySelector('textarea').writingSuggestions, 'false');
+ assert_equals(doc.querySelector('div').writingSuggestions, 'false');
+ assert_equals(doc.querySelector('span').writingSuggestions, 'false');
+}, 'Test overriding a non-parent ancestor element\'s `writingsuggestions` attribute on an input element from "false" to an invalid value.');
+
+test(function() {
+ const doc = new DOMParser().parseFromString('<html writingsuggestions="false"><body><input><textarea writingsuggestions="foo"></textarea><div></div><span></span></body></html>', 'text/html');
+ assert_equals(doc.documentElement.writingSuggestions, 'false');
+ assert_equals(doc.body.writingSuggestions, 'false');
+ assert_equals(doc.querySelector('input').writingSuggestions, 'false');
+ assert_equals(doc.querySelector('textarea').writingSuggestions, 'true');
+ assert_equals(doc.querySelector('div').writingSuggestions, 'false');
+ assert_equals(doc.querySelector('span').writingSuggestions, 'false');
+}, 'Test overriding a non-parent ancestor element\'s `writingsuggestions` attribute on a textarea element from "false" to an invalid value.');
+
+test(function() {
+ const doc = new DOMParser().parseFromString('<html writingsuggestions="false"><body><input><textarea></textarea><div writingsuggestions="foo"></div><span></span></body></html>', 'text/html');
+ assert_equals(doc.documentElement.writingSuggestions, 'false');
+ assert_equals(doc.body.writingSuggestions, 'false');
+ assert_equals(doc.querySelector('input').writingSuggestions, 'false');
+ assert_equals(doc.querySelector('textarea').writingSuggestions, 'false');
+ assert_equals(doc.querySelector('div').writingSuggestions, 'true');
+ assert_equals(doc.querySelector('span').writingSuggestions, 'false');
+}, 'Test overriding a non-parent ancestor element\'s `writingsuggestions` attribute on a div element from "false" to an invalid value.');
+
+test(function() {
+ const doc = new DOMParser().parseFromString('<html writingsuggestions="false"><body><input><textarea></textarea><div></div><span writingsuggestions="foo"></span></body></html>', 'text/html');
+ assert_equals(doc.documentElement.writingSuggestions, 'false');
+ assert_equals(doc.body.writingSuggestions, 'false');
+ assert_equals(doc.querySelector('input').writingSuggestions, 'false');
+ assert_equals(doc.querySelector('textarea').writingSuggestions, 'false');
+ assert_equals(doc.querySelector('div').writingSuggestions, 'false');
+ assert_equals(doc.querySelector('span').writingSuggestions, 'true');
+}, 'Test overriding a non-parent ancestor element\'s `writingsuggestions` attribute on a span element from "false" to an invalid value.');
+
+test(function() {
+ const doc = new DOMParser().parseFromString('<html writingsuggestions="true"><body><input writingsuggestions="false"><textarea></textarea><div></div><span></span></body></html>', 'text/html');
+ assert_equals(doc.documentElement.writingSuggestions, 'true');
+ assert_equals(doc.body.writingSuggestions, 'true');
+ assert_equals(doc.querySelector('input').writingSuggestions, 'false');
+ assert_equals(doc.querySelector('textarea').writingSuggestions, 'true');
+ assert_equals(doc.querySelector('div').writingSuggestions, 'true');
+ assert_equals(doc.querySelector('span').writingSuggestions, 'true');
+}, 'Test overriding a non-parent ancestor element\'s `writingsuggestions` attribute on an input element from "true" to "false".');
+
+test(function() {
+ const doc = new DOMParser().parseFromString('<html writingsuggestions="true"><body><input><textarea writingsuggestions="false"></textarea><div></div><span></span></body></html>', 'text/html');
+ assert_equals(doc.documentElement.writingSuggestions, 'true');
+ assert_equals(doc.body.writingSuggestions, 'true');
+ assert_equals(doc.querySelector('input').writingSuggestions, 'true');
+ assert_equals(doc.querySelector('textarea').writingSuggestions, 'false');
+ assert_equals(doc.querySelector('div').writingSuggestions, 'true');
+ assert_equals(doc.querySelector('span').writingSuggestions, 'true');
+}, 'Test overriding a non-parent ancestor element\'s `writingsuggestions` attribute on a textarea element from "true" to "false".');
+
+test(function() {
+ const doc = new DOMParser().parseFromString('<html writingsuggestions="true"><body><input><textarea></textarea><div writingsuggestions="false"></div><span></span></body></html>', 'text/html');
+ assert_equals(doc.documentElement.writingSuggestions, 'true');
+ assert_equals(doc.body.writingSuggestions, 'true');
+ assert_equals(doc.querySelector('input').writingSuggestions, 'true');
+ assert_equals(doc.querySelector('textarea').writingSuggestions, 'true');
+ assert_equals(doc.querySelector('div').writingSuggestions, 'false');
+ assert_equals(doc.querySelector('span').writingSuggestions, 'true');
+}, 'Test overriding a non-parent ancestor element\'s `writingsuggestions` attribute on a div element from "true" to "false".');
+
+test(function() {
+ const doc = new DOMParser().parseFromString('<html writingsuggestions="true"><body><input><textarea></textarea><div></div><span writingsuggestions="false"></span></body></html>', 'text/html');
+ assert_equals(doc.documentElement.writingSuggestions, 'true');
+ assert_equals(doc.body.writingSuggestions, 'true');
+ assert_equals(doc.querySelector('input').writingSuggestions, 'true');
+ assert_equals(doc.querySelector('textarea').writingSuggestions, 'true');
+ assert_equals(doc.querySelector('div').writingSuggestions, 'true');
+ assert_equals(doc.querySelector('span').writingSuggestions, 'false');
+}, 'Test overriding a non-parent ancestor element\'s `writingsuggestions` attribute on a span element from "true" to "false".');
+
+test(function() {
+ const doc = new DOMParser().parseFromString('<html writingsuggestions=""><body><input writingsuggestions="false"><textarea></textarea><div></div><span></span></body></html>', 'text/html');
+ assert_equals(doc.documentElement.writingSuggestions, 'true');
+ assert_equals(doc.body.writingSuggestions, 'true');
+ assert_equals(doc.querySelector('input').writingSuggestions, 'false');
+ assert_equals(doc.querySelector('textarea').writingSuggestions, 'true');
+ assert_equals(doc.querySelector('div').writingSuggestions, 'true');
+ assert_equals(doc.querySelector('span').writingSuggestions, 'true');
+}, 'Test overriding a non-parent ancestor element\'s `writingsuggestions` attribute on an input element from the empty string to "false".');
+
+test(function() {
+ const doc = new DOMParser().parseFromString('<html writingsuggestions=""><body><input><textarea writingsuggestions="false"></textarea><div></div><span></span></body></html>', 'text/html');
+ assert_equals(doc.documentElement.writingSuggestions, 'true');
+ assert_equals(doc.body.writingSuggestions, 'true');
+ assert_equals(doc.querySelector('input').writingSuggestions, 'true');
+ assert_equals(doc.querySelector('textarea').writingSuggestions, 'false');
+ assert_equals(doc.querySelector('div').writingSuggestions, 'true');
+ assert_equals(doc.querySelector('span').writingSuggestions, 'true');
+}, 'Test overriding a non-parent ancestor element\'s `writingsuggestions` attribute on a textarea element from the empty string to "false".');
+
+test(function() {
+ const doc = new DOMParser().parseFromString('<html writingsuggestions=""><body><input><textarea></textarea><div writingsuggestions="false"></div><span></span></body></html>', 'text/html');
+ assert_equals(doc.documentElement.writingSuggestions, 'true');
+ assert_equals(doc.body.writingSuggestions, 'true');
+ assert_equals(doc.querySelector('input').writingSuggestions, 'true');
+ assert_equals(doc.querySelector('textarea').writingSuggestions, 'true');
+ assert_equals(doc.querySelector('div').writingSuggestions, 'false');
+ assert_equals(doc.querySelector('span').writingSuggestions, 'true');
+}, 'Test overriding a non-parent ancestor element\'s `writingsuggestions` attribute on a div element from the empty string to "false".');
+
+test(function() {
+ const doc = new DOMParser().parseFromString('<html writingsuggestions=""><body><input><textarea></textarea><div></div><span writingsuggestions="false"></span></body></html>', 'text/html');
+ assert_equals(doc.documentElement.writingSuggestions, 'true');
+ assert_equals(doc.body.writingSuggestions, 'true');
+ assert_equals(doc.querySelector('input').writingSuggestions, 'true');
+ assert_equals(doc.querySelector('textarea').writingSuggestions, 'true');
+ assert_equals(doc.querySelector('div').writingSuggestions, 'true');
+ assert_equals(doc.querySelector('span').writingSuggestions, 'false');
+}, 'Test overriding a non-parent ancestor element\'s `writingsuggestions` attribute on a span element from the empty string to "false".');
+
+test(function() {
+ const doc = new DOMParser().parseFromString('<html writingsuggestions="true"><body><div contenteditable="true"><span>Writing suggestions allowed.</span> <span writingsuggestions="false">Writing suggestions not allowed.</span></div></body></html>', 'text/html');
+ const div = doc.querySelector('div');
+ const span1 = doc.querySelector('span');
+ const span2 = doc.querySelector('span:last-child');
+ assert_equals(div.writingSuggestions, 'true');
+ assert_equals(span1.writingSuggestions, 'true');
+ assert_equals(span2.writingSuggestions, 'false');
+}, 'Test that for continuous text on the screen, writing suggestions may be allowed in one part but not another.');
+
+</script>
+</body>
+</html> \ No newline at end of file