summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/html/rendering/widgets
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/html/rendering/widgets')
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/appearance/appearance-animation-001.html23
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/appearance/appearance-animation-002-ref.html3
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/appearance/appearance-animation-002.html20
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/appearance/appearance-transition-001-ref.html7
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/appearance/appearance-transition-001.html21
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/appearance/appearance-transition-002-ref.html6
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/appearance/appearance-transition-002.html19
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/appearance/appearance-transition-003.html19
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/appearance/default-styles.html96
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/baseline-alignment-and-overflow.tentative.html237
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/button-layout/anonymous-button-content-box-ref.html31
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/button-layout/anonymous-button-content-box.html31
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/button-layout/computed-style.html52
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/button-layout/display-other.html52
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/button-layout/flex.html61
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/button-layout/grid.html30
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/button-layout/inline-level-ref.html10
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/button-layout/inline-level.html25
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/button-layout/input-type-button-clip-ref.html9
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/button-layout/input-type-button-clip.html15
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/button-layout/input-type-button-newline-2-mismatch.html2
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/button-layout/input-type-button-newline-2.html6
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/button-layout/input-type-button-newline-mismatch.html2
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/button-layout/input-type-button-newline.html6
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/button-layout/propagate-text-decoration-ref.html9
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/button-layout/propagate-text-decoration.html13
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/button-layout/shrink-wrap.html42
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/field-sizing-input-number.html149
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/field-sizing-input-text.html154
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/field-sizing-select.html87
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/field-sizing-textarea.html141
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/input-checkbox-disabled-checked-notref.html2
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/input-checkbox-disabled-checked.html5
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/input-checkbox-no-centering.html19
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/input-checkbox-switch-indeterminate-ref.html2
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/input-checkbox-switch-indeterminate.tentative.html7
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/input-checkbox-switch-notref.html4
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/input-checkbox-switch-ref.html4
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/input-checkbox-switch-rtl-notref.html1
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/input-checkbox-switch-rtl.tentative.html3
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/input-checkbox-switch.tentative.html14
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/input-checkbox-switch.tentative.window.js34
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/input-date-baseline-min-height-ref.html6
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/input-date-baseline-min-height.html10
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/input-date-baseline-print.html25
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/input-date-baseline-ref.html16
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/input-date-baseline.html25
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/input-date-content-size-ref.html9
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/input-date-content-size.html11
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/input-date-no-resize-on-hover.html35
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/input-no-centering-ref.html2
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/input-radio-disabled-checked-notref.html2
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/input-radio-disabled-checked.html5
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/input-radio-no-centering.html19
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/input-text-size.html45
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/input-time-content-size-ref.html9
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/input-time-content-size.html11
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/select-wrap-no-spill.optional.html23
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/textarea-cols-rows.html64
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/the-select-element/option-add-label-quirks.html20
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/the-select-element/option-add-label.html21
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/the-select-element/option-checked-styling-ref.html21
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/the-select-element/option-checked-styling.html21
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/the-select-element/option-empty-label-to-empty-string.html21
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/the-select-element/option-empty-label.html14
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/the-select-element/option-label-and-text.html14
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/the-select-element/option-label-ref.html12
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/the-select-element/option-only-label.html14
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/the-select-element/option-rm-label.html21
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/the-select-element/select-as-listbox-default-styles.tentative.html113
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/the-select-element/select-invalidation-ref.html15
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/the-select-element/select-invalidation.html31
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/the-select-element/select-size-001.html11
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/the-select-element/select-size-002.html11
-rw-r--r--testing/web-platform/tests/html/rendering/widgets/the-select-element/select-size-ref.html7
75 files changed, 2157 insertions, 0 deletions
diff --git a/testing/web-platform/tests/html/rendering/widgets/appearance/appearance-animation-001.html b/testing/web-platform/tests/html/rendering/widgets/appearance/appearance-animation-001.html
new file mode 100644
index 0000000000..7d7474e0a4
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/appearance/appearance-animation-001.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>compute the kind of widget: author origin and animation origin</title>
+<link rel="match" href="appearance-transition-001-ref.html">
+<style>
+ input {
+ background-color: rgb(0, 0, 0);
+ }
+ .bg200 {
+ animation: 1e10s steps(2, start) animate-bg;
+ }
+ @keyframes animate-bg {
+ to {
+ background-color: rgb(0, 200, 0);
+ }
+ }
+</style>
+<input value="text" id=input>
+<script>
+ document.documentElement.offsetTop;
+ input.classList.toggle('bg200');
+</script>
+<p>PASS if the input field has a dark green background</p>
diff --git a/testing/web-platform/tests/html/rendering/widgets/appearance/appearance-animation-002-ref.html b/testing/web-platform/tests/html/rendering/widgets/appearance/appearance-animation-002-ref.html
new file mode 100644
index 0000000000..fab70234d2
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/appearance/appearance-animation-002-ref.html
@@ -0,0 +1,3 @@
+<!DOCTYPE html>
+<input value="text">
+<p>PASS if the input field does not have a red background</p>
diff --git a/testing/web-platform/tests/html/rendering/widgets/appearance/appearance-animation-002.html b/testing/web-platform/tests/html/rendering/widgets/appearance/appearance-animation-002.html
new file mode 100644
index 0000000000..acca93eae7
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/appearance/appearance-animation-002.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>compute the kind of widget: animation origin only</title>
+<link rel="match" href="appearance-animation-002-ref.html">
+<style>
+ .bg200 {
+ animation: 1e10s steps(2, start) animate-bg;
+ }
+ @keyframes animate-bg {
+ to {
+ background-color: rgb(255, 0, 0);
+ }
+ }
+</style>
+<input value="text" id=input>
+<script>
+ document.documentElement.offsetTop;
+ input.classList.toggle('bg200');
+</script>
+<p>PASS if the input field does not have a red background</p>
diff --git a/testing/web-platform/tests/html/rendering/widgets/appearance/appearance-transition-001-ref.html b/testing/web-platform/tests/html/rendering/widgets/appearance/appearance-transition-001-ref.html
new file mode 100644
index 0000000000..69726c6cd2
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/appearance/appearance-transition-001-ref.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<style>
+ input { background-color: rgb(0, 100, 0); }
+</style>
+<input value="text">
+<p>PASS if the input field has a dark green background</p>
diff --git a/testing/web-platform/tests/html/rendering/widgets/appearance/appearance-transition-001.html b/testing/web-platform/tests/html/rendering/widgets/appearance/appearance-transition-001.html
new file mode 100644
index 0000000000..ec51cf9be5
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/appearance/appearance-transition-001.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>compute the kind of widget: author origin and transition origin</title>
+<link rel="help" href="https://crbug.com/1086732">
+<link rel="match" href="appearance-transition-001-ref.html">
+<style>
+ input {
+ background-color: rgb(0, 0, 0);
+ transition: background-color 1e10s steps(2, start);
+ }
+
+ .bg200 {
+ background-color: rgb(0, 200, 0);
+ }
+</style>
+<input value="text" id=input>
+<script>
+ document.documentElement.offsetTop;
+ input.classList.toggle('bg200');
+</script>
+<p>PASS if the input field has a dark green background</p>
diff --git a/testing/web-platform/tests/html/rendering/widgets/appearance/appearance-transition-002-ref.html b/testing/web-platform/tests/html/rendering/widgets/appearance/appearance-transition-002-ref.html
new file mode 100644
index 0000000000..febd6c55aa
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/appearance/appearance-transition-002-ref.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<style>
+ input { background-color: rgb(128, 228, 128); }
+</style>
+<input value="text">
+<p>PASS if the input field has a light green background</p>
diff --git a/testing/web-platform/tests/html/rendering/widgets/appearance/appearance-transition-002.html b/testing/web-platform/tests/html/rendering/widgets/appearance/appearance-transition-002.html
new file mode 100644
index 0000000000..b6c2a3dcad
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/appearance/appearance-transition-002.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>compute the kind of widget: transition origin without author origin style before the transition</title>
+<link rel="match" href="appearance-transition-002-ref.html">
+<style>
+ input {
+ transition: background-color 1e10s steps(2, start);
+ }
+
+ .bg200 {
+ background-color: rgb(0, 200, 0);
+ }
+</style>
+<input value="text" id=input>
+<script>
+ document.documentElement.offsetTop;
+ input.classList.toggle('bg200');
+</script>
+<p>PASS if the input field has a light green background</p>
diff --git a/testing/web-platform/tests/html/rendering/widgets/appearance/appearance-transition-003.html b/testing/web-platform/tests/html/rendering/widgets/appearance/appearance-transition-003.html
new file mode 100644
index 0000000000..109617b7b7
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/appearance/appearance-transition-003.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>compute the kind of widget: transition origin without author origin style after the transition</title>
+<link rel="match" href="appearance-animation-002-ref.html">
+<style>
+ input {
+ transition: background-color 1e10s steps(2, start);
+ }
+
+ .bg200 {
+ background-color: rgb(255, 0, 0);
+ }
+</style>
+<input value="text" id=input class=bg200>
+<script>
+ document.documentElement.offsetTop;
+ input.classList.toggle('bg200');
+</script>
+<p>PASS if the input field does not have a red background</p>
diff --git a/testing/web-platform/tests/html/rendering/widgets/appearance/default-styles.html b/testing/web-platform/tests/html/rendering/widgets/appearance/default-styles.html
new file mode 100644
index 0000000000..8869808696
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/appearance/default-styles.html
@@ -0,0 +1,96 @@
+<!doctype html>
+<title>HTML: default style for 'appearance'</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<script>
+// namespaces
+const htmlns = 'http://www.w3.org/1999/xhtml';
+const svgns = 'http://www.w3.org/2000/svg';
+
+// auto
+testAppearance(htmlns, 'input', null, 'auto');
+testAppearance(htmlns, 'input', {type: 'text'}, 'auto');
+testAppearance(htmlns, 'input', {type: 'TEXT'}, 'auto');
+testAppearance(htmlns, 'input', {type: 'search'}, 'auto');
+testAppearance(htmlns, 'input', {type: 'tel'}, 'auto');
+testAppearance(htmlns, 'input', {type: 'url'}, 'auto');
+testAppearance(htmlns, 'input', {type: 'email'}, 'auto');
+testAppearance(htmlns, 'input', {type: 'password'}, 'auto');
+testAppearance(htmlns, 'input', {type: 'date'}, 'auto');
+testAppearance(htmlns, 'input', {type: 'month'}, 'auto');
+testAppearance(htmlns, 'input', {type: 'week'}, 'auto');
+testAppearance(htmlns, 'input', {type: 'time'}, 'auto');
+testAppearance(htmlns, 'input', {type: 'datetime-local'}, 'auto');
+testAppearance(htmlns, 'input', {type: 'number'}, 'auto');
+testAppearance(htmlns, 'input', {type: 'range'}, 'auto');
+testAppearance(htmlns, 'input', {type: 'color'}, 'auto');
+testAppearance(htmlns, 'input', {type: 'checkbox'}, 'auto');
+testAppearance(htmlns, 'input', {type: 'radio'}, 'auto');
+testAppearance(htmlns, 'input', {type: 'submit'}, 'auto');
+testAppearance(htmlns, 'input', {type: 'reset'}, 'auto');
+testAppearance(htmlns, 'input', {type: 'button'}, 'auto');
+testAppearance(htmlns, 'input', {type: 'unknowntype'}, 'auto');
+testAppearance(htmlns, 'select', null, 'auto');
+testAppearance(htmlns, 'select', {multiple: ''}, 'auto');
+testAppearance(htmlns, 'select', {size: '2'}, 'auto');
+testAppearance(htmlns, 'button', null, 'auto');
+testAppearance(htmlns, 'textarea', null, 'auto');
+testAppearance(htmlns, 'meter', null, 'auto');
+testAppearance(htmlns, 'progress', null, 'auto');
+
+// none
+testAppearance(htmlns, 'input', {type: 'hidden'}, 'none');
+testAppearance(htmlns, 'input', {type: 'HIDDEN'}, 'none');
+testAppearance(htmlns, 'input', {type: 'file'}, 'none');
+testAppearance(htmlns, 'input', {type: 'image'}, 'none');
+testAppearance(htmlns, 'div', null, 'none');
+testAppearance(htmlns, 'details', null, 'none');
+testAppearance(htmlns, 'summary', null, 'none');
+testAppearance(htmlns, 'video', null, 'none');
+testAppearance(htmlns, 'video', {controls: ''}, 'none');
+testAppearance(htmlns, 'menuitem', null, 'none');
+testAppearance(htmlns, 'marquee', null, 'none');
+testAppearance(htmlns, 'keygen', null, 'none');
+testAppearance(null, 'input', null, 'none');
+testAppearance(svgns, 'input', null, 'none');
+
+test(t => {
+ assertAppearance(document.documentElement, 'none');
+}, 'The html element');
+
+test(t => {
+ assertAppearance(document.body, 'none');
+}, 'The body element');
+
+
+function testAppearance(ns, tag, attributes, expected) {
+ test(t => {
+ const elm = document.createElementNS(ns, tag);
+ for (const att in attributes) {
+ elm.setAttribute(att, attributes[att]);
+ }
+ document.body.appendChild(elm);
+ t.add_cleanup(() => elm.remove());
+ assertAppearance(elm, expected);
+ }, formatTestName(ns, tag, attributes));
+}
+
+function assertAppearance(elm, expected) {
+ const computedStyle = getComputedStyle(elm);
+ assert_equals(computedStyle.getPropertyValue('-webkit-appearance'), expected, '-webkit-appearance');
+ assert_equals(computedStyle.getPropertyValue('appearance'), expected, 'appearance (no prefix)');
+}
+
+function formatTestName(ns, tag, attributes) {
+ let s = `<${tag}`;
+ for (const att in attributes) {
+ s += ` ${att}="${attributes[att]}"`;
+ }
+ s += '>';
+ if (ns !== htmlns) {
+ s += ` (namespace: ${ns})`;
+ }
+ return s;
+}
+</script>
diff --git a/testing/web-platform/tests/html/rendering/widgets/baseline-alignment-and-overflow.tentative.html b/testing/web-platform/tests/html/rendering/widgets/baseline-alignment-and-overflow.tentative.html
new file mode 100644
index 0000000000..45ac762bd1
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/baseline-alignment-and-overflow.tentative.html
@@ -0,0 +1,237 @@
+<!DOCTYPE html>
+<title>HTML: widgets' baseline alignment and interaction with 'overflow'</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<!--
+This test tests where the baseline is for different widgets.
+This isn't yet specified, see https://github.com/whatwg/html/issues/5065
+
+Where the baseline is affects where *other* things on the same linebox are positioned. So this test
+makes assertions about the offsetTop for a previous sibling <span>, and compares it to a reference
+that has equivalent setup but using a styled <span> instead of an actual widget (where possible) so
+we can control where its baseline will be (assuming a correct CSS implementation).
+
+CSS has the following behavior regarding baselines (this is non-normative, also read the spec):
+
+* for a normal inline containing text, the baseline is the same as the text's baseline.
+* for replaced elements (like images), the baseline is at the bottom margin-box edge.
+* for an inline-block, it depends on its 'overflow':
+ - 'visible': the baseline is the same as the baseline for the last line box in the inline-block.
+ - otherwise: the baseline is like replaced elements.
+
+The baselines for different widgets, as implemented in Firefox, are as follows:
+
+<input type=text>
+<input type=search>
+<input type=tel>
+<input type=email>
+<input type=password>
+<input type=date>
+<input type=month>
+<input type=week>
+<input type=time>
+<input type=datetime-local>
+<input type=number>
+<input type=submit>
+<input type=reset>
+<input type=button>
+ Like inline-block but 'overflow' is forced to 'visible' and text inside is vertically centered.
+
+<input type=checkbox> with 'appearance: auto'
+<input type=radio> with 'appearance: auto'
+ At the bottom of the content-box edge (and whether there's a border depends
+ on the platform).
+
+ This is not usually how CSS works so we fake it with a negative margin-bottom.
+
+<input type=color>
+ At the content-box edge.
+
+<input type=file>
+ Like inline-block but 'overflow' is forced to to 'visible' and it contains a button; the button
+ can affect where the baseline is.
+
+<input type=image> showing alt text, with 'overflow: visible'
+ Like inline-block.
+
+<input type=image> showing an image
+<input type=image> showing alt text, with 'overflow' something other than 'visible'
+<input type=range>
+<input type=checkbox> with 'appearance: none'
+<input type=radio> with 'appearance: none'
+ Like replaced elements.
+
+-->
+<style>
+.test {
+ border-collapse: collapse;
+ font-size: 10px;
+}
+.test td {
+ border: none;
+ padding: 0;
+ margin:0;
+ outline: 1px solid silver;
+}
+
+.test td > input,
+.ref td > .fake-input-text,
+.ref td > .inline-block,
+.ref td > img,
+.ref td > button {
+ font: inherit;
+ height: 60px;
+ width: 60px;
+ padding: 10px;
+ box-sizing: border-box;
+ margin: 10px 0;
+ /* Note: a border is not specified because that would imply 'appearance: none' for some widgets */
+}
+
+.ref button img {
+ height: 100%;
+ width: 100%;
+ display: block;
+}
+
+/* Use inline-grid instead of inline-block here to more easily center the text inside */
+.ref .fake-input-text {
+ display: inline-grid;
+ border: 2px solid; /* 2px matches UA default style */
+ align-items: center;
+}
+.ref .inline-block {
+ display: inline-block;
+}
+
+.ref-file-input-like button {
+ font-size: unset;
+}
+
+[style*="appearance: none;"] {
+ -webkit-appearance: none; /* TODO(zcorpan) remove this when unprefixed appearance is supported */
+}
+</style>
+<div id="log"></div>
+<h2>refs</h2>
+<!--
+The first span's offsetTop is what we want to compare with the corresponding test's span's offsetTop.
+The sibling element is there to control where the baseline for the line box will be.
+-->
+<table class="test ref">
+ <tr class="ref-text-input-like"><td><span>ref-text-input-like</span> <span class=fake-input-text>x</span>
+ <tr class="ref-checkbox-input-appearance-auto-like"><td><span>ref-checkbox-input-appearance-auto-like</span> <img class=auto-checkbox src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAMCAIAAAD3UuoiAAAAGklEQVQoz2Nk%2BP%2BfgRqAiYFKYNSgUYOGp0EA%2BQMCFrJdTgsAAAAASUVORK5CYII%3D">
+ <tr class="ref-color-input-like"><td><span>ref-color-input-like</span> <button><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAMCAIAAAD3UuoiAAAAGklEQVQoz2Nk%2BP%2BfgRqAiYFKYNSgUYOGp0EA%2BQMCFrJdTgsAAAAASUVORK5CYII%3D"></button>
+ <tr class="ref-file-input-like"><td><span>ref-file-input-like</span> <span class=inline-block><button>x</button></span>
+ <tr class="ref-image-input-showing-alt-overflow-visible-like"><td><span>ref-image-input-showing-alt-overflow-visible-like</span> <span class=inline-block>x</span>
+ <tr class="ref-image-input-showing-image-like"><td><span>ref-image-input-showing-image-like</span> <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAMCAIAAAD3UuoiAAAAGklEQVQoz2Nk%2BP%2BfgRqAiYFKYNSgUYOGp0EA%2BQMCFrJdTgsAAAAASUVORK5CYII%3D">
+</table>
+<h2>template table</h2>
+<!--
+Each row in this table will be cloned into #test-table for each combination of styles to test.
+-->
+<table id="template-table">
+ <tr><td><span>text</span> <input type=text value=x></td></tr>
+ <tr><td><span>search</span> <input type=search value=x></td></tr>
+ <tr><td><span>tel</span> <input type=tel value=x></td></tr>
+ <tr><td><span>url</span> <input type=url value="data:,x"></td></tr>
+ <tr><td><span>email</span> <input type=email value=x></td></tr>
+ <tr><td><span>password</span> <input type=password value=x></td></tr>
+ <tr><td><span>date</span> <input type=date value="2020-01-01"></td></tr>
+ <tr><td><span>month</span> <input type=month value="2020-01"></td></tr>
+ <tr><td><span>week</span> <input type=week value="2020-W01"></td></tr>
+ <tr><td><span>time</span> <input type=time value="00:00"></td></tr>
+ <tr><td><span>datetime-local</span> <input type=datetime-local value="2020-01-01T00:00"></td></tr>
+ <tr><td><span>number</span> <input type=number value=0></td></tr>
+ <tr><td><span>range</span> <input type=range></td></tr>
+ <tr><td><span>color</span> <input type=color value=#000000></td></tr>
+ <tr><td><span>checkbox</span> <input type=checkbox></td></tr>
+ <tr><td><span>radio</span> <input type=radio></td></tr>
+ <tr><td><span>file</span> <input type=file></td></tr>
+ <tr><td><span>submit</span> <input type=submit value=x></td></tr>
+ <tr><td><span>image</span> <input type=image src="data:,broken" alt="x"></td></tr>
+ <tr><td><span>image-with-src</span> <input type=image src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAMCAIAAAD3UuoiAAAAGklEQVQoz2Nk%2BP%2BfgRqAiYFKYNSgUYOGp0EA%2BQMCFrJdTgsAAAAASUVORK5CYII%3D" alt="x"></td></tr>
+ <tr><td><span>reset</span> <input type=reset value=x></td></tr>
+ <tr><td><span>button</span> <input type=button value=x></td></tr>
+</table>
+<h2>tests</h2>
+<!--
+This table gets populated by the script.
+-->
+<table class="test" id="test-table"><tbody></tbody></table>
+<script>
+ "use strict";
+
+ promise_setup(async () => {
+ const templateTable = document.querySelector('#template-table');
+ const testTBody = document.querySelector('#test-table tbody');
+
+ {
+ const checkboxBorder = getComputedStyle(document.querySelector("input[type=checkbox]")).borderTopWidth;
+ const checkboxLike = document.querySelector(".auto-checkbox");
+ checkboxLike.style.border = checkboxBorder + " solid";
+ checkboxLike.style.marginBottom = "-" + checkboxBorder;
+ }
+
+ const templateRows = templateTable.querySelectorAll('tr');
+ for (const templateRow of templateRows) {
+ for (const appearanceValue of ["auto", "none"]) {
+ for (const overflowValue of ['visible', 'hidden', 'scroll']) {
+ const clonedRow = templateRow.cloneNode(true);
+ clonedRow.querySelector('input').setAttribute('style', `overflow: ${overflowValue}; appearance: ${appearanceValue};`);
+ testTBody.append(clonedRow);
+ }
+ }
+ }
+
+ // wait for images to load
+ await new Promise(resolve => window.onload = e => resolve());
+ for (const img of document.images) {
+ assert_true(img.complete); // either error state or loaded
+ }
+
+ // get layout info from refs
+ const refTextInputLikeOffsetTop = document.querySelector('.ref-text-input-like span').offsetTop;
+ const refCheckboxInputAppearanceAutoLikeOffsetTop = document.querySelector('.ref-checkbox-input-appearance-auto-like span').offsetTop;
+ const refColorInputLikeOffsetTop = document.querySelector('.ref-color-input-like span').offsetTop;
+ const refFileInputLikeOffsetTop = document.querySelector('.ref-file-input-like span').offsetTop;
+ const refImageInputShowingAltOverflowVisibleLikeOffsetTop = document.querySelector('.ref-image-input-showing-alt-overflow-visible-like span').offsetTop;
+ const refImageInputShowingImageLikeOffsetTop = document.querySelector('.ref-image-input-showing-image-like span').offsetTop;
+
+ function expectedOffsetTop(input) {
+ // TODO(zcorpan) https://github.com/whatwg/html/issues/5065
+ // for now this is intended to match Firefox
+ const style = input.getAttribute('style');
+ const src = input.getAttribute('src');
+ switch (input.type) {
+ case 'file':
+ return refFileInputLikeOffsetTop;
+ case 'range':
+ return refImageInputShowingImageLikeOffsetTop;
+ case 'color':
+ return refColorInputLikeOffsetTop;
+ case 'checkbox':
+ case 'radio':
+ return (style.includes('appearance: none;')) ? refImageInputShowingImageLikeOffsetTop : refCheckboxInputAppearanceAutoLikeOffsetTop;
+ case 'image':
+ return (src === 'data:,broken' && style.includes('overflow: visible;')) ? refImageInputShowingAltOverflowVisibleLikeOffsetTop : refImageInputShowingImageLikeOffsetTop;
+ default:
+ return refTextInputLikeOffsetTop;
+ }
+ }
+
+ function testName(markup) {
+ return markup.replace(/data:image\/png[^"]+/, 'data:(png)');
+ }
+
+ for (const row of testTBody.children) {
+ const input = row.firstChild.lastElementChild;
+ // This is not using test() because promise_setup() only allows promise_test().
+ promise_test(async () => {
+ assert_equals(input.type, input.getAttribute('type'), 'input type should be supported')
+ const offsetTopActual = row.firstChild.firstChild.offsetTop;
+ assert_equals(offsetTopActual, expectedOffsetTop(input), '<span>.offsetTop');
+ }, testName(input.outerHTML));
+ }
+ });
+</script>
diff --git a/testing/web-platform/tests/html/rendering/widgets/button-layout/anonymous-button-content-box-ref.html b/testing/web-platform/tests/html/rendering/widgets/button-layout/anonymous-button-content-box-ref.html
new file mode 100644
index 0000000000..243f0add0d
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/button-layout/anonymous-button-content-box-ref.html
@@ -0,0 +1,31 @@
+<!doctype html>
+<title>Reference for Anonymous button content box</title>
+<style>
+body { margin: 0 }
+.button { width: 124px; height: 124px; background: papayawhip; border: 2px solid; display: table-cell; vertical-align: middle; text-align: center; box-sizing: border-box; }
+.top { vertical-align: top }
+.left { text-align: left }
+.float { display: block; float: left; }
+body > div { clear: left; }
+.button > div { width: 50px; height: 50px; border: solid }
+.button > .tall { height: 150px }
+.button > .wide { width: 150px; margin-top: 32px }
+</style>
+<div>
+ <div class=button>input</div>
+ <div class="button">input grid</div>
+ <div class="button">input flex</div>
+ <div class=button>button</div>
+</div>
+<div>
+ <div class=button style="text-align: left">button left</div>
+ <div class=button><div>div</div></div>
+ <div class="button top">grid</div>
+ <div class="button top"><div>grid</div></div>
+</div>
+<div>
+ <div class="button top left float">flex</div>
+ <div class="button top float"><div>flex</div></div>
+ <div class="button float"><div class=tall>tall</div></div>
+ <div class="button float"><div class=wide>wide</div></div>
+</div>
diff --git a/testing/web-platform/tests/html/rendering/widgets/button-layout/anonymous-button-content-box.html b/testing/web-platform/tests/html/rendering/widgets/button-layout/anonymous-button-content-box.html
new file mode 100644
index 0000000000..07c7b8e366
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/button-layout/anonymous-button-content-box.html
@@ -0,0 +1,31 @@
+<!doctype html>
+<title>Anonymous button content box</title>
+<link rel=match href=anonymous-button-content-box-ref.html>
+<style>
+body { margin: 0 }
+button, input { width: 124px; height: 124px; background: papayawhip; border: 2px solid; margin: 0; padding: 0; float: left; font: inherit }
+body > div { clear: left; }
+button > div { width: 50px; height: 50px; border: solid }
+.grid { display: grid }
+.flex { display: flex }
+.tall { height: 150px }
+.wide { width: 150px }
+</style>
+<div>
+ <input type=button value=input>
+ <input type=button value="input grid" class=grid>
+ <input type=button value="input flex" class=flex>
+ <button>button</button>
+</div>
+<div>
+ <button style="text-align: left">button left</button>
+ <button><div>div</div></button>
+ <button class=grid>grid</button>
+ <button class=grid><div>grid</div></button>
+</div>
+<div>
+ <button class=flex>flex</button>
+ <button class=flex><div>flex</div></button>
+ <button><div class=tall>tall</div></button>
+ <button><div class=wide>wide</div></button>
+</div>
diff --git a/testing/web-platform/tests/html/rendering/widgets/button-layout/computed-style.html b/testing/web-platform/tests/html/rendering/widgets/button-layout/computed-style.html
new file mode 100644
index 0000000000..d18e5d365d
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/button-layout/computed-style.html
@@ -0,0 +1,52 @@
+<!doctype html>
+<title>computed style on buttons</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div class="tests">
+ <input type="reset">
+ <input type="button">
+ <input type="submit">
+ <input type="color">
+ <input type="image">
+ <button></button>
+</div>
+<script>
+// "behave as" doesn't change computed value.
+const displayValues = ['inline', 'block', 'list-item', 'inline-block', 'table', 'inline-table', 'table-row-group', 'table-header-group', 'table-footer-group', 'table-row', 'table-column-group', 'table-column', 'table-cell', 'table-caption', 'none', 'contents', 'flow', 'flow-root', 'flex', 'grid', 'ruby', 'ruby-base', 'ruby-text', 'ruby-base-container', 'ruby-text-container', 'inline-flex', 'inline-grid'];
+for (const val of displayValues) {
+ [].slice.call(document.querySelectorAll('.tests > *')).forEach(el => {
+ el.style.display = ''
+ el.style.display = val;
+ const attrs = el.type ? ` type=${el.type}` : '';
+ const tag = `<${el.localName}${attrs}>`;
+ test(() => {
+ assert_not_equals(el.style.display, '', `display: ${val} is not supported`)
+ let expectedVal = val;
+ if (el instanceof HTMLInputElement && val === 'contents') {
+ expectedVal = 'none'; // https://drafts.csswg.org/css-display/#unbox-html
+ }
+ if (val == 'flow') {
+ // Use the more backwards-compatible form, `block` is better than `flow`
+ // https://drafts.csswg.org/cssom/#serializing-css-values
+ expectedVal = 'block';
+ }
+ assert_equals(getComputedStyle(el).display, expectedVal);
+ }, `computed display of ${tag} with display: ${val}`);
+ });
+}
+
+for (let input of document.querySelectorAll("input")) {
+ test(() => {
+ if (input.type == "image") {
+ assert_equals(getComputedStyle(input).overflow, "visible", "Should not be clip by default");
+ return;
+ }
+ assert_equals(getComputedStyle(input).overflow, "clip", "Should be clip by default");
+ assert_equals(getComputedStyle(input).overflowClipMargin, "0px", "Should use 0 margin");
+ input.style.overflow = "visible";
+ input.style.overflowClipMargin = "10px";
+ assert_equals(getComputedStyle(input).overflow, "clip", "Clip be !important");
+ assert_equals(getComputedStyle(input).overflowClipMargin, "0px", "Clip margin should be !important too");
+ }, `<input type=${input.type}> overflow/overflow-clip-margin`);
+}
+</script>
diff --git a/testing/web-platform/tests/html/rendering/widgets/button-layout/display-other.html b/testing/web-platform/tests/html/rendering/widgets/button-layout/display-other.html
new file mode 100644
index 0000000000..6ed3f5894a
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/button-layout/display-other.html
@@ -0,0 +1,52 @@
+<!doctype html>
+<title>button with other display values</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<style>
+body { margin: 0 }
+.float { width: 100px; height: 100px; float: left; background: blue; margin: 10px }
+</style>
+<div class=float></div>
+<button id=button style="display: block;"><div class=float></div></button><span id=after>after</span>
+<script>
+// These should all behave as flow-root.
+const displayValues = ['run-in', 'flow', 'flow-root', 'table', 'list-item',
+ 'table-row-group', 'table-header-group', 'table-footer-group',
+ 'table-row', 'table-cell', 'table-column-group', 'table-column',
+ 'table-caption', 'ruby-base', 'ruby-text', 'ruby-base-container',
+ 'ruby-text-container'];
+const button = document.getElementById('button');
+const after = document.getElementById('after');
+function getValues() {
+ return {
+ buttonLeft: button.offsetLeft,
+ buttonTop: button.offsetTop,
+ buttonWidth: button.clientWidth,
+ buttonHeight: button.clientHeight,
+ afterLeft: after.offsetLeft,
+ afterTop: after.offsetTop,
+ };
+}
+const expected = getValues();
+test(t => {
+ assert_equals(expected.buttonLeft, 120, 'buttonLeft');
+ assert_equals(expected.buttonTop, 0, 'buttonTop');
+ assert_greater_than_equal(expected.buttonWidth, 120, 'buttonWidth');
+ assert_greater_than_equal(expected.buttonHeight, 120, 'buttonHeight');
+ assert_equals(expected.afterLeft, 0, 'afterLeft');
+ assert_greater_than_equal(expected.afterTop, 120, 'afterTop');
+}, 'display: block');
+for (const val of displayValues) {
+ test(t => {
+ t.add_cleanup(() => {
+ button.style.display = 'block';
+ });
+ assert_true(CSS.supports(`display: ${val}`), `display: ${val} is not supported`);
+ button.style.display = val;
+ const values = getValues();
+ for (const prop in values) {
+ assert_equals(values[prop], expected[prop], prop);
+ }
+ }, `display: ${val}`);
+}
+</script>
diff --git a/testing/web-platform/tests/html/rendering/widgets/button-layout/flex.html b/testing/web-platform/tests/html/rendering/widgets/button-layout/flex.html
new file mode 100644
index 0000000000..7f159fc232
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/button-layout/flex.html
@@ -0,0 +1,61 @@
+<!doctype html>
+<title>button with flex/inline-flex</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<style>
+#inline-flex { display: inline-flex }
+#flex { display: flex }
+#ref > div { display: flex }
+
+#flexstart {
+ border: none;
+ padding: 0;
+ display: flex;
+ align-items: flex-start;
+ height: 3em;
+}
+
+#stretch {
+ border: none;
+ padding: 0;
+ display: flex;
+ align-items: stretch;
+ height: 3em;
+}
+</style>
+<button id=inline-flex><div>1</div><div>2</div><div>3</div><div>4</div></button>
+<button id=flex><div>1</div><div>2</div><div>3</div><div>4</div></button>
+<button id=ref><div><div>1</div><div>2</div><div>3</div><div>4</div></div></button>
+
+<div><button id="flexstart"><span id="flexstart-item">abc</span></button></div>
+
+<div><button id="stretch"><span id="stretch-item">abc</span></button></div>
+<script>
+const ref = document.getElementById('ref');
+const expectedWidth = ref.clientWidth;
+const expectedHeight = ref.clientHeight;
+for (const elm of [document.getElementById('inline-flex'),
+ document.getElementById('flex')]) {
+ test(() => {
+ // check that flex is supported
+ const flexValue = elm.id;
+ assert_equals(getComputedStyle(elm).display, flexValue, `${flexValue} is not supported`);
+ const width = elm.clientWidth;
+ const height = elm.clientHeight;
+ assert_equals(width, expectedWidth, 'clientWidth');
+ assert_equals(height, expectedHeight, 'clientHeight');
+ }, elm.id);
+}
+
+// crbug.com/700029
+test(() => {
+ assert_equals(document.getElementById('flexstart').offsetTop,
+ document.getElementById('flexstart-item').offsetTop);
+}, 'align-items:flex-start should work');
+
+// crbug.com/1004163
+test(() => {
+ assert_equals(document.getElementById('stretch').offsetHeight,
+ document.getElementById('stretch-item').offsetHeight);
+}, 'align-items:stretch should work');
+</script>
diff --git a/testing/web-platform/tests/html/rendering/widgets/button-layout/grid.html b/testing/web-platform/tests/html/rendering/widgets/button-layout/grid.html
new file mode 100644
index 0000000000..7c2a467099
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/button-layout/grid.html
@@ -0,0 +1,30 @@
+<!doctype html>
+<title>button with grid/inline-grid</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<style>
+#inline-grid { display: inline-grid }
+#grid { display: grid }
+#ref > div { display: grid }
+#inline-grid, #grid, #ref > div { grid-template: auto auto / auto auto }
+</style>
+<button id=inline-grid><div>1</div><div>2</div><div>3</div><div>4</div></button>
+<button id=grid><div>1</div><div>2</div><div>3</div><div>4</div></button>
+<button id=ref><div><div>1</div><div>2</div><div>3</div><div>4</div></div></button>
+<script>
+const ref = document.getElementById('ref');
+const expectedWidth = ref.clientWidth;
+const expectedHeight = ref.clientHeight;
+for (const elm of [document.getElementById('inline-grid'),
+ document.getElementById('grid')]) {
+ test(() => {
+ // check that grid is supported
+ const gridValue = elm.id;
+ assert_equals(getComputedStyle(elm).display, gridValue, `${gridValue} is not supported`);
+ const width = elm.clientWidth;
+ const height = elm.clientHeight;
+ assert_equals(width, expectedWidth, 'clientWidth');
+ assert_equals(height, expectedHeight, 'clientHeight');
+ }, elm.id);
+}
+</script>
diff --git a/testing/web-platform/tests/html/rendering/widgets/button-layout/inline-level-ref.html b/testing/web-platform/tests/html/rendering/widgets/button-layout/inline-level-ref.html
new file mode 100644
index 0000000000..3784cc30db
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/button-layout/inline-level-ref.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>Reference for button with inline-level display</title>
+<style>
+button { font: inherit }
+</style>
+<p>There should be three buttons below containing "1" and "2" on separate lines, and "a" and "b" before and after on the same baseline as the "2".</p>
+<p>a<button>1<br>2</button>b</p>
+<p>a<button>1<br>2</button>b</p>
+<p>a<button>1<br>2</button>b</p>
+<p>a<button>1<br>2</button>b</p>
diff --git a/testing/web-platform/tests/html/rendering/widgets/button-layout/inline-level.html b/testing/web-platform/tests/html/rendering/widgets/button-layout/inline-level.html
new file mode 100644
index 0000000000..e23aba731c
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/button-layout/inline-level.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<title>button with inline-level display</title>
+<link rel=match href=inline-level-ref.html>
+<style>
+button, input { font: inherit }
+.inline { display: inline }
+.inline-block { display: inline-block }
+.inline-table { display: inline-table }
+</style>
+<p>There should be three buttons below containing "1" and "2" on separate lines, and "a" and "b" before and after on the same baseline as the "2".</p>
+<p>a<button class=inline>1<br><span class=check-baseline>2</span></button><span class=ref-baseline>b</span></p>
+<p>a<button class=inline-block>1<br><span class=check-baseline>2</span></button><span class=ref-baseline>b</span></p>
+<p>a<button class=inline-table>1<br><span class=check-baseline>2</span></button><span class=ref-baseline>b</span></p>
+<p>a<input type=button class=inline-table value="1&#10;2">b</p>
+<script>
+const spans = document.querySelectorAll('.check-baseline');
+for (const span of [].slice.call(spans)) {
+ const baseline = span.offsetTop + span.offsetHeight;
+ const refSpan = span.parentNode.nextSibling;
+ const refBaseline = refSpan.offsetTop + refSpan.offsetHeight;
+ if (baseline !== refBaseline) {
+ refSpan.textContent += " (wrong baseline)";
+ }
+}
+</script>
diff --git a/testing/web-platform/tests/html/rendering/widgets/button-layout/input-type-button-clip-ref.html b/testing/web-platform/tests/html/rendering/widgets/button-layout/input-type-button-clip-ref.html
new file mode 100644
index 0000000000..8f956d36f5
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/button-layout/input-type-button-clip-ref.html
@@ -0,0 +1,9 @@
+<!doctype html>
+<style>
+ button {
+ width: 10ch;
+ overflow: clip;
+ text-overflow: ellipsis;
+ }
+</style>
+<button>aaaaaaaaaaaaaaaaaaaaaa</button>
diff --git a/testing/web-platform/tests/html/rendering/widgets/button-layout/input-type-button-clip.html b/testing/web-platform/tests/html/rendering/widgets/button-layout/input-type-button-clip.html
new file mode 100644
index 0000000000..db1ad35cce
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/button-layout/input-type-button-clip.html
@@ -0,0 +1,15 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>button input is clipped by default, and text-overflow: ellipsis works</title>
+<link rel="help" href="https://github.com/whatwg/html/issues/9976">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1800077">
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="author" title="Mozilla" href="https://mozilla.org">
+<link rel="match" href="input-type-button-clip-ref.html">
+<style>
+ input {
+ width: 10ch;
+ text-overflow: ellipsis;
+ }
+</style>
+<input type="button" value="aaaaaaaaaaaaaaaaaaaaaa">
diff --git a/testing/web-platform/tests/html/rendering/widgets/button-layout/input-type-button-newline-2-mismatch.html b/testing/web-platform/tests/html/rendering/widgets/button-layout/input-type-button-newline-2-mismatch.html
new file mode 100644
index 0000000000..19930b947b
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/button-layout/input-type-button-newline-2-mismatch.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<input type=button value="1">
diff --git a/testing/web-platform/tests/html/rendering/widgets/button-layout/input-type-button-newline-2.html b/testing/web-platform/tests/html/rendering/widgets/button-layout/input-type-button-newline-2.html
new file mode 100644
index 0000000000..6e21c9e98e
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/button-layout/input-type-button-newline-2.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<link rel=author href="mailto:jarhar@chromium.org">
+<link rel=help href="https://bugs.chromium.org/p/chromium/issues/detail?id=922011">
+<link rel=mismatch href="input-type-button-newline-2-mismatch.html">
+
+<input type=button value="1&#10;2">
diff --git a/testing/web-platform/tests/html/rendering/widgets/button-layout/input-type-button-newline-mismatch.html b/testing/web-platform/tests/html/rendering/widgets/button-layout/input-type-button-newline-mismatch.html
new file mode 100644
index 0000000000..3d6495de66
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/button-layout/input-type-button-newline-mismatch.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<input type=button value="12">
diff --git a/testing/web-platform/tests/html/rendering/widgets/button-layout/input-type-button-newline.html b/testing/web-platform/tests/html/rendering/widgets/button-layout/input-type-button-newline.html
new file mode 100644
index 0000000000..139893ed42
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/button-layout/input-type-button-newline.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<link rel=author href="mailto:jarhar@chromium.org">
+<link rel=help href="https://bugs.chromium.org/p/chromium/issues/detail?id=922011">
+<link rel=mismatch href="input-type-button-newline-mismatch.html">
+
+<input type=button value="1&#10;2">
diff --git a/testing/web-platform/tests/html/rendering/widgets/button-layout/propagate-text-decoration-ref.html b/testing/web-platform/tests/html/rendering/widgets/button-layout/propagate-text-decoration-ref.html
new file mode 100644
index 0000000000..f33a011a20
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/button-layout/propagate-text-decoration-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<title>Reference for propagating text-decoration into buttons</title>
+<style>
+button { font: inherit }
+</style>
+<p>The text in the following buttons should be underlined.</p>
+<p><button><u>foo</u></button><button><u>foo</u></button></p>
+<p>The text in the following buttons should NOT be underlined.</p>
+<p><button>foo</button><button>foo</button></p>
diff --git a/testing/web-platform/tests/html/rendering/widgets/button-layout/propagate-text-decoration.html b/testing/web-platform/tests/html/rendering/widgets/button-layout/propagate-text-decoration.html
new file mode 100644
index 0000000000..83608402c1
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/button-layout/propagate-text-decoration.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<title>propagating text-decoration into buttons</title>
+<link rel=match href=propagate-text-decoration-ref.html>
+<meta name=fuzzy content="maxDifference=0-40;totalPixels=0-50">
+<style>
+button, input { font: inherit }
+.inline > u > * { display: inline }
+.inline-block > u > * { display: inline-block }
+</style>
+<p>The text in the following buttons should be underlined.</p>
+<p class=inline><u><button>foo</button><input type=button value=foo></u></p>
+<p>The text in the following buttons should NOT be underlined.</p>
+<p class=inline-block><u><button>foo</button><input type=button value=foo></u></p>
diff --git a/testing/web-platform/tests/html/rendering/widgets/button-layout/shrink-wrap.html b/testing/web-platform/tests/html/rendering/widgets/button-layout/shrink-wrap.html
new file mode 100644
index 0000000000..6d61102608
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/button-layout/shrink-wrap.html
@@ -0,0 +1,42 @@
+<!doctype html>
+<title>shrink-wrap button</title>
+<link rel=help href=https://html.spec.whatwg.org/multipage/rendering.html#button-layout>
+<link rel=help href=https://drafts.csswg.org/css2/visudet.html#shrink-to-fit-float>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<!--
+ minimum preferred width 100px
+ preferred width 250px
+ available width vary
+-->
+<style>
+div.available-width { border: thin dotted red; margin: 1em 0; padding: 1em 0 }
+button { border: none; margin: 0; padding: 0; background: papayawhip; }
+button > span.minimum-preferred-width { width: 100px }
+button > span { width: 50px; display: inline-block; outline: thin dotted blue }
+</style>
+<div class="available-width" style="width: 50px">
+ <button data-expected="100"><span class="minimum-preferred-width">x</span><span>x</span><span>x</span><span>x</span></button>
+</div>
+
+<div class="available-width" style="width: 200px">
+ <button data-expected="200"><span class="minimum-preferred-width">x</span><span>x</span><span>x</span><span>x</span></button>
+</div>
+
+<div class="available-width" style="width: 300px">
+ <button data-expected="250"><span class="minimum-preferred-width">x</span><span>x</span><span>x</span><span>x</span></button>
+</div>
+
+<script>
+const styles = ['display: block', 'display: inline', 'display: inline-block',
+ 'display: list-item', 'display: table', 'display: table-row',
+ 'display: table-cell', 'float: left'];
+for (const style of styles) {
+ for (const button of [].slice.call(document.querySelectorAll('button'))) {
+ test(() => {
+ button.setAttribute('style', style);
+ assert_equals(button.clientWidth, parseInt(button.dataset.expected, 10));
+ }, `${style} - available ${button.parentNode.getAttribute('style')}`);
+ }
+}
+</script>
diff --git a/testing/web-platform/tests/html/rendering/widgets/field-sizing-input-number.html b/testing/web-platform/tests/html/rendering/widgets/field-sizing-input-number.html
new file mode 100644
index 0000000000..859d35197b
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/field-sizing-input-number.html
@@ -0,0 +1,149 @@
+<!DOCTYPE html>
+<link rel="help" href="https://drafts.csswg.org/css-ui-4/#field-sizing">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+.disable-default {
+ field-sizing: content;
+}
+
+.small-placeholder {
+ font-size: 32px;
+}
+.small-placeholder::placeholder {
+ font-size: 16px;
+}
+
+.large-placeholder {
+ font-size: 20px;
+}
+.large-placeholder::placeholder {
+ font-size: 40px;
+}
+</style>
+<body>
+<div id="container"></div>
+<script>
+const DISABLE = 'class="disable-default"';
+const LONG_VALUE = '12345678901234567890.123';
+const LONG_TEXT = 'The quick brown fox jumps over the lazy dog.';
+
+function addElements(source) {
+ const container = document.querySelector('#container');
+ container.innerHTML = source + source;
+ container.lastElementChild.classList.add('disable-default');
+ return {
+ fixed: container.firstElementChild,
+ content: container.lastElementChild
+ };
+}
+
+function addTwoElements(source1, source2) {
+ const container = document.querySelector('#container');
+ container.innerHTML = source1 + source2;
+ return {
+ e1: container.firstElementChild,
+ e2: container.lastElementChild
+ };
+}
+
+['number'].forEach(type => {
+ test(() => {
+ let pair = addElements(`<input type=${type}>`);
+ // A text <input> has approximately 20ch width by default.
+ // A text <input> with field-sizing:content must be shorter than the default.
+ assert_less_than(pair.content.offsetWidth, pair.fixed.offsetWidth);
+ assert_equals(pair.content.offsetHeight, pair.fixed.offsetHeight);
+
+ pair = addTwoElements(`<input type=${type} ${DISABLE}>`,
+ `<input type=${type} ${DISABLE} value="123">`);
+ assert_less_than(pair.e1.offsetWidth, pair.e2.offsetWidth);
+ assert_equals(pair.e1.offsetHeight, pair.e2.offsetHeight);
+ }, `${type}: Empty value`);
+
+ test(() => {
+ let pair = addElements(`<input type=${type} value="${LONG_VALUE}">`);
+ assert_greater_than(pair.content.offsetWidth, pair.fixed.offsetWidth);
+ pair = addElements(`<input type=${type} placeholder="${LONG_TEXT}">`);
+ assert_greater_than(pair.content.offsetWidth, pair.fixed.offsetWidth);
+ }, `${type}: Auto width and auto height with a long text`);
+
+ test(() => {
+ let pair = addElements(`<input type=${type} style="width:20ch; height:2lh">`);
+ assert_equals(pair.content.offsetWidth, pair.fixed.offsetWidth);
+ assert_equals(pair.content.offsetHeight, pair.fixed.offsetHeight);
+
+ pair = addElements(`<input type=${type} style="width:20ch; height:2lh" value="${LONG_VALUE}">`);
+ assert_equals(pair.content.offsetWidth, pair.fixed.offsetWidth);
+ assert_equals(pair.content.offsetHeight, pair.fixed.offsetHeight);
+
+ pair = addElements(`<input type=${type} style="width:20ch; height:2lh" placeholder="${LONG_TEXT}">`);
+ assert_equals(pair.content.offsetWidth, pair.fixed.offsetWidth);
+ assert_equals(pair.content.offsetHeight, pair.fixed.offsetHeight);
+ }, `${type}: Explicit width and heigth`);
+
+ test(() => {
+ let pair = addElements(`<input type=${type} style="width:20ch">`);
+ assert_equals(pair.content.offsetWidth, pair.fixed.offsetWidth);
+ assert_equals(pair.content.offsetHeight, pair.fixed.offsetHeight);
+
+ pair = addElements(`<input type=${type} style="width:20ch" value="${LONG_VALUE}">`);
+ assert_equals(pair.content.offsetWidth, pair.fixed.offsetWidth);
+ assert_equals(pair.content.offsetHeight, pair.fixed.offsetHeight);
+
+ pair = addElements(`<input type=${type} style="width:20ch" placeholder="${LONG_TEXT}">`);
+ assert_equals(pair.content.offsetWidth, pair.fixed.offsetWidth);
+ assert_equals(pair.content.offsetHeight, pair.fixed.offsetHeight);
+ }, `${type}: Explicit width and auto height`);
+
+ test(() => {
+ let pair = addElements(`<input type=${type} style="height:2lh">`);
+ assert_less_than(pair.content.offsetWidth, pair.fixed.offsetWidth);
+ assert_equals(pair.content.offsetHeight, pair.fixed.offsetHeight);
+
+ pair = addElements(`<input type=${type} style="height:2lh" value="${LONG_VALUE}">`);
+ assert_greater_than(pair.content.offsetWidth, pair.fixed.offsetWidth);
+ assert_equals(pair.content.offsetHeight, pair.fixed.offsetHeight);
+
+ pair = addElements(`<input type=${type} style="height:2lh" placeholder="${LONG_TEXT}">`);
+ assert_greater_than(pair.content.offsetWidth, pair.fixed.offsetWidth);
+ assert_equals(pair.content.offsetHeight, pair.fixed.offsetHeight);
+ }, `${type}: Explicit height and auto width`);
+
+ test(() => {
+ let pair = addTwoElements(
+ `<input type=${type} class="disable-default small-placeholder">`,
+ `<input type=${type} class="disable-default small-placeholder" placeholder="foo bar">`);
+ assert_less_than(pair.e1.offsetWidth, pair.e2.offsetWidth);
+ assert_equals(pair.e1.offsetHeight, pair.e2.offsetHeight);
+ }, `${type}: Text caret is taller than the placeholder`);
+
+ test(() => {
+ let pair = addTwoElements(
+ `<input type=${type} class="disable-default large-placeholder">`,
+ `<input type=${type} class="disable-default large-placeholder" placeholder="foo bar">`);
+ assert_less_than(pair.e1.offsetWidth, pair.e2.offsetWidth);
+ assert_less_than(pair.e1.offsetHeight, pair.e2.offsetHeight);
+
+ pair = addTwoElements(
+ `<input type=${type} class="disable-default" style="font-size:40px; padding:16px">`,
+ `<input type=${type} class="disable-default large-placeholder"
+ placeholder="foo bar" style="font-size:40px; padding:16px">`);
+ assert_equals(pair.e1.offsetHeight, pair.e2.offsetHeight);
+ assert_equals(pair.e1.offsetTop, pair.e2.offsetTop);
+ }, `${type}: Text caret is shorter than the placeholder`);
+
+ test(() => {
+ const container = document.querySelector('#container');
+ container.innerHTML = `<input type=${type}>`;
+ const element = container.firstChild;
+ const w = element.offsetWidth;
+ const h = element.offsetHeight;
+ element.classList.add('disable-default');
+ assert_less_than(element.offsetWidth, w);
+ assert_equals(element.offsetHeight, h);
+ }, `${type}: Update field-sizing property dynamically`);
+
+});
+</script>
+</body>
diff --git a/testing/web-platform/tests/html/rendering/widgets/field-sizing-input-text.html b/testing/web-platform/tests/html/rendering/widgets/field-sizing-input-text.html
new file mode 100644
index 0000000000..f421ad602c
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/field-sizing-input-text.html
@@ -0,0 +1,154 @@
+<!DOCTYPE html>
+<link rel="help" href="https://drafts.csswg.org/css-ui-4/#field-sizing">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+.disable-default {
+ field-sizing: content;
+}
+
+.small-placeholder {
+ font-size: 32px;
+}
+.small-placeholder::placeholder {
+ font-size: 16px;
+}
+
+.large-placeholder {
+ font-size: 20px;
+}
+.large-placeholder::placeholder {
+ font-size: 40px;
+}
+</style>
+<body>
+<div id="container"></div>
+<script>
+const DISABLE = 'class="disable-default"';
+const LONG_TEXT = 'The quick brown fox jumps over the lazy dog.';
+
+function addElements(source) {
+ const container = document.querySelector('#container');
+ container.innerHTML = source + source;
+ container.lastElementChild.classList.add('disable-default');
+ return {
+ fixed: container.firstElementChild,
+ content: container.lastElementChild
+ };
+}
+
+function addTwoElements(source1, source2) {
+ const container = document.querySelector('#container');
+ container.innerHTML = source1 + source2;
+ return {
+ e1: container.firstElementChild,
+ e2: container.lastElementChild
+ };
+}
+
+['text', 'search', 'tel', 'url', 'email', 'password'].forEach(type => {
+ test(() => {
+ let pair = addElements(`<input type=${type}>`);
+ // A text <input> has approximately 20ch width by default.
+ // A text <input> with field-sizing:content must be shorter than the default.
+ assert_less_than(pair.content.offsetWidth, pair.fixed.offsetWidth);
+ assert_equals(pair.content.offsetHeight, pair.fixed.offsetHeight);
+
+ pair = addTwoElements(`<input type=${type} ${DISABLE}>`,
+ `<input type=${type} ${DISABLE} value="foo">`);
+ assert_less_than(pair.e1.offsetWidth, pair.e2.offsetWidth);
+ assert_equals(pair.e1.offsetHeight, pair.e2.offsetHeight);
+ }, `${type}: Empty value`);
+
+ test(() => {
+ let pair = addElements(`<input type=${type} size="10">`);
+ assert_less_than(pair.content.offsetWidth, pair.fixed.offsetWidth);
+ assert_equals(pair.content.offsetHeight, pair.fixed.offsetHeight);
+ }, `${type}: Empty value with a size atttribute`);
+
+ test(() => {
+ let pair = addElements(`<input type=${type} value="${LONG_TEXT}">`);
+ assert_greater_than(pair.content.offsetWidth, pair.fixed.offsetWidth);
+ pair = addElements(`<input type=${type} placeholder="${LONG_TEXT}">`);
+ assert_greater_than(pair.content.offsetWidth, pair.fixed.offsetWidth);
+ }, `${type}: Auto width and auto height with a long text`);
+
+ test(() => {
+ let pair = addElements(`<input type=${type} style="width:20ch; height:2lh">`);
+ assert_equals(pair.content.offsetWidth, pair.fixed.offsetWidth);
+ assert_equals(pair.content.offsetHeight, pair.fixed.offsetHeight);
+
+ pair = addElements(`<input type=${type} style="width:20ch; height:2lh" value="${LONG_TEXT}">`);
+ assert_equals(pair.content.offsetWidth, pair.fixed.offsetWidth);
+ assert_equals(pair.content.offsetHeight, pair.fixed.offsetHeight);
+
+ pair = addElements(`<input type=${type} style="width:20ch; height:2lh" placeholder="${LONG_TEXT}">`);
+ assert_equals(pair.content.offsetWidth, pair.fixed.offsetWidth);
+ assert_equals(pair.content.offsetHeight, pair.fixed.offsetHeight);
+ }, `${type}: Explicit width and heigth`);
+
+ test(() => {
+ let pair = addElements(`<input type=${type} style="width:20ch">`);
+ assert_equals(pair.content.offsetWidth, pair.fixed.offsetWidth);
+ assert_equals(pair.content.offsetHeight, pair.fixed.offsetHeight);
+
+ pair = addElements(`<input type=${type} style="width:20ch" value="${LONG_TEXT}">`);
+ assert_equals(pair.content.offsetWidth, pair.fixed.offsetWidth);
+ assert_equals(pair.content.offsetHeight, pair.fixed.offsetHeight);
+
+ pair = addElements(`<input type=${type} style="width:20ch" placeholder="${LONG_TEXT}">`);
+ assert_equals(pair.content.offsetWidth, pair.fixed.offsetWidth);
+ assert_equals(pair.content.offsetHeight, pair.fixed.offsetHeight);
+ }, `${type}: Explicit width and auto height`);
+
+ test(() => {
+ let pair = addElements(`<input type=${type} style="height:2lh">`);
+ assert_less_than(pair.content.offsetWidth, pair.fixed.offsetWidth);
+ assert_equals(pair.content.offsetHeight, pair.fixed.offsetHeight);
+
+ pair = addElements(`<input type=${type} style="height:2lh" value="${LONG_TEXT}">`);
+ assert_greater_than(pair.content.offsetWidth, pair.fixed.offsetWidth);
+ assert_equals(pair.content.offsetHeight, pair.fixed.offsetHeight);
+
+ pair = addElements(`<input type=${type} style="height:2lh" placeholder="${LONG_TEXT}">`);
+ assert_greater_than(pair.content.offsetWidth, pair.fixed.offsetWidth);
+ assert_equals(pair.content.offsetHeight, pair.fixed.offsetHeight);
+ }, `${type}: Explicit height and auto width`);
+
+ test(() => {
+ let pair = addTwoElements(
+ `<input type=${type} class="disable-default small-placeholder">`,
+ `<input type=${type} class="disable-default small-placeholder" placeholder="foo bar">`);
+ assert_less_than(pair.e1.offsetWidth, pair.e2.offsetWidth);
+ assert_equals(pair.e1.offsetHeight, pair.e2.offsetHeight);
+ }, `${type}: Text caret is taller than the placeholder`);
+
+ test(() => {
+ let pair = addTwoElements(
+ `<input type=${type} class="disable-default large-placeholder">`,
+ `<input type=${type} class="disable-default large-placeholder" placeholder="foo bar">`);
+ assert_less_than(pair.e1.offsetWidth, pair.e2.offsetWidth);
+ assert_less_than(pair.e1.offsetHeight, pair.e2.offsetHeight);
+
+ pair = addTwoElements(
+ `<input type=${type} class="disable-default" style="font-size:40px; padding:16px">`,
+ `<input type=${type} class="disable-default large-placeholder"
+ placeholder="foo bar" style="font-size:40px; padding:16px">`);
+ assert_equals(pair.e1.offsetHeight, pair.e2.offsetHeight);
+ assert_equals(pair.e1.offsetTop, pair.e2.offsetTop);
+ }, `${type}: Text caret is shorter than the placeholder`);
+
+ test(() => {
+ const container = document.querySelector('#container');
+ container.innerHTML = `<input type=${type}>`;
+ const element = container.firstChild;
+ const w = element.offsetWidth;
+ const h = element.offsetHeight;
+ element.classList.add('disable-default');
+ assert_less_than(element.offsetWidth, w);
+ assert_equals(element.offsetHeight, h);
+ }, `${type}: Update field-sizing property dynamically`);
+
+});
+</script>
+</body>
diff --git a/testing/web-platform/tests/html/rendering/widgets/field-sizing-select.html b/testing/web-platform/tests/html/rendering/widgets/field-sizing-select.html
new file mode 100644
index 0000000000..d55898105e
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/field-sizing-select.html
@@ -0,0 +1,87 @@
+<!DOCTYPE html>
+<link rel="help" href="https://drafts.csswg.org/css-ui-4/#field-sizing">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<style>
+.disable-default {
+ field-sizing: content;
+}
+</style>
+<div id="container"></div>
+<script>
+const container = document.querySelector('#container');
+const DISABLE = 'class="disable-default"';
+
+// Tests for drop-down box ====================================================
+
+test(() => {
+ const s = '<select>><option>1<option>quick brown<option>fox</select>';
+ container.innerHTML = s + s;
+ container.lastElementChild.style.fieldSizing = 'content';
+ const widthForContent1 = container.lastElementChild.offsetWidth;
+ assert_greater_than(container.firstElementChild.offsetWidth,
+ widthForContent1);
+ container.lastElementChild.selectedIndex = 1;
+ const widthForContentQuickBrown = container.lastElementChild.offsetWidth;
+ assert_greater_than(widthForContentQuickBrown, widthForContent1);
+}, 'dropdown: The width should depend on the selected OPTION');
+
+test(() => {
+ container.innerHTML = '<select><option>foo<option>quick brown fox</select>';
+ const select = container.firstElementChild;
+ const initialWidth = select.offsetWidth;
+ select.style.fieldSizing = 'content';
+ assert_less_than(select.offsetWidth, initialWidth);
+ select.style.fieldSizing = 'fixed';
+ assert_equals(select.offsetWidth, initialWidth);
+}, 'dropdown: Change the field-sizing value dynamically');
+
+// Tests for list box =========================================================
+
+// Some paltforms don't support list box rendering.
+container.innerHTML = '<select></select><select multiple></select>';
+if (container.firstElementChild.offsetHeight != container.lastElementChild.offsetHeight) {
+
+ test(() => {
+ container.innerHTML = `<select multiple><option>fox</select>` +
+ `<select multiple ${DISABLE}><option>fox</select>`;
+ const former = container.firstElementChild;
+ const latter = container.lastElementChild;
+ const widthForOneItem = latter.offsetWidth;
+ const heightForOneItem = latter.offsetHeight;
+ assert_equals(former.offsetWidth, widthForOneItem);
+ assert_greater_than(former.offsetHeight, heightForOneItem);
+
+ latter.add(new Option('quick brown'));
+ assert_greater_than(latter.offsetWidth, widthForOneItem);
+ assert_greater_than(latter.offsetHeight, heightForOneItem);
+ }, 'listbox: The size depend on the content');
+
+ test(() => {
+ container.innerHTML = `<select size="4"></select><select size="4" ${DISABLE}></select>`;
+ const former = container.firstElementChild;
+ const latter = container.lastElementChild;
+ const widthForZeroItem = latter.offsetWidth;
+ const heightForZeroItem = latter.offsetHeight;
+ assert_equals(former.offsetWidth, widthForZeroItem);
+ assert_greater_than(former.offsetHeight, heightForZeroItem);
+
+ latter.add(new Option('quick brown'));
+ assert_greater_than(latter.offsetWidth, widthForZeroItem);
+ assert_greater_than(latter.offsetHeight, heightForZeroItem);
+ }, 'listbox: The size attribute value is ignored');
+
+ test(() => {
+ container.innerHTML = '<select multiple><option>foo<option>quick brown fox</select>';
+ const select = container.firstElementChild;
+ const initialHeight = select.offsetHeight;
+ select.style.fieldSizing = 'content';
+ assert_less_than(select.offsetHeight, initialHeight);
+ select.style.fieldSizing = 'fixed';
+ assert_equals(select.offsetHeight, initialHeight);
+ }, 'listbox: Change the field-sizing value dynamically');
+
+}
+</script>
+</body>
diff --git a/testing/web-platform/tests/html/rendering/widgets/field-sizing-textarea.html b/testing/web-platform/tests/html/rendering/widgets/field-sizing-textarea.html
new file mode 100644
index 0000000000..f8d90dc659
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/field-sizing-textarea.html
@@ -0,0 +1,141 @@
+<!DOCTYPE html>
+<link rel="help" href="https://drafts.csswg.org/css-ui-4/#field-sizing">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+.disable-default {
+ field-sizing: content;
+}
+
+.small-placeholder {
+ font-size: 32px;
+}
+.small-placeholder::placeholder {
+ font-size: 16px;
+}
+
+.large-placeholder {
+ font-size: 20px;
+}
+.large-placeholder::placeholder {
+ font-size: 40px;
+}
+</style>
+<body>
+<div id="container"></div>
+<script>
+const DISABLE = 'class="disable-default"';
+const LONG_TEXT = 'The quick brown fox jumps over the lazy dog.';
+
+function addElements(source) {
+ const container = document.querySelector('#container');
+ container.innerHTML = source + source;
+ container.lastElementChild.classList.add('disable-default');
+ return {
+ fixed: container.firstElementChild,
+ content: container.lastElementChild
+ };
+}
+
+function addTwoElements(source1, source2) {
+ const container = document.querySelector('#container');
+ container.innerHTML = source1 + source2;
+ return {
+ e1: container.firstElementChild,
+ e2: container.lastElementChild
+ };
+}
+
+test(() => {
+ let pair = addElements('<textarea></textarea>');
+ // Historically a <textarea> has approximately 20ch x 2lh size by default.
+ // A <textarea> with field-sizing:content must be samller than the default.
+ assert_less_than(pair.content.offsetWidth, pair.fixed.offsetWidth);
+ assert_less_than(pair.content.offsetHeight, pair.fixed.offsetHeight);
+
+ pair = addTwoElements(`<textarea ${DISABLE}></textarea>`, `<textarea ${DISABLE}>foo</textarea>`);
+ assert_less_than(pair.e1.offsetWidth, pair.e2.offsetWidth);
+ assert_equals(pair.e1.offsetHeight, pair.e2.offsetHeight);
+}, 'Empty value');
+
+test(() => {
+ let pair = addElements('<textarea cols="10" rows="3"></textarea>');
+ assert_less_than(pair.content.offsetWidth, pair.fixed.offsetWidth);
+ assert_less_than(pair.content.offsetHeight, pair.fixed.offsetHeight);
+}, 'Empty value with cols/rows');
+
+test(() => {
+ let pair = addElements(`<textarea>${LONG_TEXT}</textarea>`);
+ assert_greater_than(pair.content.offsetWidth, pair.fixed.offsetWidth);
+ pair = addElements(`<textarea placeholder="${LONG_TEXT}"></textarea>`);
+ assert_greater_than(pair.content.offsetWidth, pair.fixed.offsetWidth);
+}, 'Auto width and auto height with a long text');
+
+test(() => {
+ let pair = addElements('<textarea style="width:20ch; height:2lh"></textarea>');
+ assert_equals(pair.content.offsetWidth, pair.fixed.offsetWidth);
+ assert_equals(pair.content.offsetHeight, pair.fixed.offsetHeight);
+
+ pair = addElements(`<textarea style="width:20ch; height:2lh">${LONG_TEXT}</textarea>`);
+ assert_equals(pair.content.offsetWidth, pair.fixed.offsetWidth);
+ assert_equals(pair.content.offsetHeight, pair.fixed.offsetHeight);
+
+ pair = addElements(`<textarea style="width:20ch; height:2lh" placeholder="${LONG_TEXT}"></textarea>`);
+ assert_equals(pair.content.offsetWidth, pair.fixed.offsetWidth);
+ assert_equals(pair.content.offsetHeight, pair.fixed.offsetHeight);
+}, 'Explicit width and heigth');
+
+test(() => {
+ let pair = addElements('<textarea style="width:20ch"></textarea>');
+ assert_equals(pair.content.offsetWidth, pair.fixed.offsetWidth);
+ assert_less_than(pair.content.offsetHeight, pair.fixed.offsetHeight);
+
+ pair = addElements(`<textarea style="width:20ch">${LONG_TEXT}</textarea>`);
+ assert_equals(pair.content.offsetWidth, pair.fixed.offsetWidth);
+ assert_greater_than(pair.content.offsetHeight, pair.fixed.offsetHeight);
+
+ pair = addElements(`<textarea style="width:20ch" placeholder="${LONG_TEXT}"></textarea>`);
+ assert_equals(pair.content.offsetWidth, pair.fixed.offsetWidth);
+ assert_greater_than(pair.content.offsetHeight, pair.fixed.offsetHeight);
+}, 'Explicit width and auto height');
+
+test(() => {
+ let pair = addElements('<textarea style="height:2lh"></textarea>');
+ assert_less_than(pair.content.offsetWidth, pair.fixed.offsetWidth);
+ assert_equals(pair.content.offsetHeight, pair.fixed.offsetHeight);
+
+ pair = addElements(`<textarea style="height:2lh">${LONG_TEXT}</textarea>`);
+ assert_greater_than(pair.content.offsetWidth, pair.fixed.offsetWidth);
+ assert_equals(pair.content.offsetHeight, pair.fixed.offsetHeight);
+
+ pair = addElements(`<textarea style="height:2lh" placeholder="${LONG_TEXT}"></textarea>`);
+ assert_greater_than(pair.content.offsetWidth, pair.fixed.offsetWidth);
+ assert_equals(pair.content.offsetHeight, pair.fixed.offsetHeight);
+}, 'Explicit height and auto width');
+
+test(() => {
+ let pair = addTwoElements(`<textarea class="disable-default small-placeholder"></textarea>`,
+ `<textarea class="disable-default small-placeholder" placeholder="foo"></textarea>`);
+ assert_less_than(pair.e1.offsetWidth, pair.e2.offsetWidth);
+ assert_equals(pair.e1.offsetHeight, pair.e2.offsetHeight);
+}, 'Text caret is taller than the placeholder');
+
+test(() => {
+ let pair = addTwoElements(`<textarea class="disable-default large-placeholder"></textarea>`,
+ `<textarea class="disable-default large-placeholder" placeholder="foo"></textarea>`);
+ assert_less_than(pair.e1.offsetWidth, pair.e2.offsetWidth, 'width');
+ assert_less_than(pair.e1.offsetHeight, pair.e2.offsetHeight, 'height');
+}, 'Text caret is shorter than the placeholder');
+
+test(() => {
+ const container = document.querySelector('#container');
+ container.innerHTML = '<textarea></textarea>';
+ const element = container.firstChild;
+ const w = element.offsetWidth;
+ const h = element.offsetHeight;
+ element.classList.add('disable-default');
+ assert_less_than(element.offsetWidth, w);
+ assert_less_than(element.offsetHeight, h);
+}, 'Update field-sizing property dynamically');
+</script>
+</body>
diff --git a/testing/web-platform/tests/html/rendering/widgets/input-checkbox-disabled-checked-notref.html b/testing/web-platform/tests/html/rendering/widgets/input-checkbox-disabled-checked-notref.html
new file mode 100644
index 0000000000..8caced027a
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/input-checkbox-disabled-checked-notref.html
@@ -0,0 +1,2 @@
+<!doctype html>
+<input type=checkbox disabled>
diff --git a/testing/web-platform/tests/html/rendering/widgets/input-checkbox-disabled-checked.html b/testing/web-platform/tests/html/rendering/widgets/input-checkbox-disabled-checked.html
new file mode 100644
index 0000000000..f72fdf62fd
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/input-checkbox-disabled-checked.html
@@ -0,0 +1,5 @@
+<!doctype html>
+<title>checkbox with disabled and checked attributes renders differently than unchecked</title>
+<link rel=help href="https://bugzilla.mozilla.org/show_bug.cgi?id=1735077">
+<link rel=mismatch href="input-checkbox-disabled-checked-notref.html">
+<input type=checkbox disabled checked>
diff --git a/testing/web-platform/tests/html/rendering/widgets/input-checkbox-no-centering.html b/testing/web-platform/tests/html/rendering/widgets/input-checkbox-no-centering.html
new file mode 100644
index 0000000000..7dba149c75
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/input-checkbox-no-centering.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=1441341">
+<link rel="match" href="input-no-centering-ref.html">
+<style>
+input {
+ appearance: none;
+ margin: 0;
+ width: 200px;
+ height: 200px;
+}
+input:before {
+ content: "";
+ display: block;
+ width: 100px;
+ height: 100px;
+ background: green;
+}
+</style>
+<input type="checkbox">
diff --git a/testing/web-platform/tests/html/rendering/widgets/input-checkbox-switch-indeterminate-ref.html b/testing/web-platform/tests/html/rendering/widgets/input-checkbox-switch-indeterminate-ref.html
new file mode 100644
index 0000000000..cb9a76aa21
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/input-checkbox-switch-indeterminate-ref.html
@@ -0,0 +1,2 @@
+<!doctype html>
+<input type=checkbox switch>
diff --git a/testing/web-platform/tests/html/rendering/widgets/input-checkbox-switch-indeterminate.tentative.html b/testing/web-platform/tests/html/rendering/widgets/input-checkbox-switch-indeterminate.tentative.html
new file mode 100644
index 0000000000..bd4137c1b5
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/input-checkbox-switch-indeterminate.tentative.html
@@ -0,0 +1,7 @@
+<!doctype html>
+<title>Checkbox with switch attribute set does not render differently when the indeterminate attribute is set</title>
+<link rel=match href="input-checkbox-switch-indeterminate-ref.html">
+<input id="input" type=checkbox switch>
+<script>
+ input.indeterminate = true;
+</script>
diff --git a/testing/web-platform/tests/html/rendering/widgets/input-checkbox-switch-notref.html b/testing/web-platform/tests/html/rendering/widgets/input-checkbox-switch-notref.html
new file mode 100644
index 0000000000..75fff5d94f
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/input-checkbox-switch-notref.html
@@ -0,0 +1,4 @@
+<!doctype html>
+<input type=checkbox>
+<input type=checkbox>
+<input type=checkbox switch>
diff --git a/testing/web-platform/tests/html/rendering/widgets/input-checkbox-switch-ref.html b/testing/web-platform/tests/html/rendering/widgets/input-checkbox-switch-ref.html
new file mode 100644
index 0000000000..94aa1b7ecd
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/input-checkbox-switch-ref.html
@@ -0,0 +1,4 @@
+<!doctype html>
+<input type=checkbox switch>
+<input type=checkbox switch>
+<input type=checkbox>
diff --git a/testing/web-platform/tests/html/rendering/widgets/input-checkbox-switch-rtl-notref.html b/testing/web-platform/tests/html/rendering/widgets/input-checkbox-switch-rtl-notref.html
new file mode 100644
index 0000000000..02d57baf43
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/input-checkbox-switch-rtl-notref.html
@@ -0,0 +1 @@
+<input type=checkbox switch>
diff --git a/testing/web-platform/tests/html/rendering/widgets/input-checkbox-switch-rtl.tentative.html b/testing/web-platform/tests/html/rendering/widgets/input-checkbox-switch-rtl.tentative.html
new file mode 100644
index 0000000000..3e0c5d44c9
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/input-checkbox-switch-rtl.tentative.html
@@ -0,0 +1,3 @@
+<!doctype html>
+<link rel=mismatch href=input-checkbox-switch-rtl-notref.html>
+<input type=checkbox switch dir=rtl>
diff --git a/testing/web-platform/tests/html/rendering/widgets/input-checkbox-switch.tentative.html b/testing/web-platform/tests/html/rendering/widgets/input-checkbox-switch.tentative.html
new file mode 100644
index 0000000000..315728d539
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/input-checkbox-switch.tentative.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<html class="reftest-wait">
+<title>Checkbox with switch attribute set renders differently than a checkbox without switch attribute</title>
+<link rel=match href="input-checkbox-switch-ref.html">
+<link rel=mismatch href="input-checkbox-switch-notref.html">
+<input type=checkbox switch>
+<input id='input2' type=checkbox>
+<input id='input3' type=checkbox switch>
+<script>
+ input2.setAttribute('switch','');
+ input3.removeAttribute('switch');
+ document.documentElement.classList.remove("reftest-wait");
+</script>
+</html>
diff --git a/testing/web-platform/tests/html/rendering/widgets/input-checkbox-switch.tentative.window.js b/testing/web-platform/tests/html/rendering/widgets/input-checkbox-switch.tentative.window.js
new file mode 100644
index 0000000000..84198eda10
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/input-checkbox-switch.tentative.window.js
@@ -0,0 +1,34 @@
+test(t => {
+ const input = document.body.appendChild(document.createElement("input"));
+ t.add_cleanup(() => input.remove());
+ input.type = "checkbox";
+ input.switch = true;
+ assert_equals(getComputedStyle(input).appearance, "auto");
+}, "Default appearance value");
+
+test(t => {
+ const input = document.body.appendChild(document.createElement("input"));
+ t.add_cleanup(() => input.remove());
+ input.type = "checkbox";
+ input.switch = true;
+ input.style.display = "none"
+ assert_equals(getComputedStyle(input).display, "none");
+}, "Default appearance value: display:none");
+
+test(t => {
+ const input = document.body.appendChild(document.createElement("input"));
+ t.add_cleanup(() => input.remove());
+ input.type = "checkbox";
+ input.switch = true;
+ input.style.appearance = "none";
+ assert_equals(getComputedStyle(input).appearance, "none");
+}, "appearance:none should work");
+
+test(t => {
+ const input = document.body.appendChild(document.createElement("input"));
+ t.add_cleanup(() => input.remove());
+ input.type = "checkbox";
+ input.switch = true;
+ input.style.appearance = "none";
+ assert_equals(getComputedStyle(input).display, "inline");
+}, "appearance:none should work: display gets its initial value");
diff --git a/testing/web-platform/tests/html/rendering/widgets/input-date-baseline-min-height-ref.html b/testing/web-platform/tests/html/rendering/widgets/input-date-baseline-min-height-ref.html
new file mode 100644
index 0000000000..249076a5b7
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/input-date-baseline-min-height-ref.html
@@ -0,0 +1,6 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>CSS Test Reference</title>
+<div>
+ abc <input type=date style="height: 40px"> def
+</div>
diff --git a/testing/web-platform/tests/html/rendering/widgets/input-date-baseline-min-height.html b/testing/web-platform/tests/html/rendering/widgets/input-date-baseline-min-height.html
new file mode 100644
index 0000000000..86b552ab80
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/input-date-baseline-min-height.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>date input baseline should account for min-height</title>
+<link rel="match" href="input-date-baseline-min-height-ref.html">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1825709">
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="author" title="Mozilla" href="https://mozilla.org">
+<div>
+ abc <input type=date style="min-height: 40px"> def
+</div>
diff --git a/testing/web-platform/tests/html/rendering/widgets/input-date-baseline-print.html b/testing/web-platform/tests/html/rendering/widgets/input-date-baseline-print.html
new file mode 100644
index 0000000000..dda06c69fb
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/input-date-baseline-print.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<title>date input baseline shouldn't be insane when printing</title>
+<link rel="match" href="input-date-baseline-ref.html">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1667510">
+<link rel="stylesheet" href="/fonts/ahem.css">
+<style>
+ div {
+ border: 1px solid black;
+ line-height: 0;
+ }
+
+ input {
+ height: 20px;
+ font: 20px/1 Ahem;
+ box-sizing: border-box;
+ padding: 1px; /* Needed to trigger the bug */
+ border: 0;
+ visibility: hidden;
+ -webkit-appearance: none;
+ appearance: none;
+ }
+</style>
+<div>
+ <input type="date">
+</div>
diff --git a/testing/web-platform/tests/html/rendering/widgets/input-date-baseline-ref.html b/testing/web-platform/tests/html/rendering/widgets/input-date-baseline-ref.html
new file mode 100644
index 0000000000..dcef656bad
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/input-date-baseline-ref.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<title>Test reference</title>
+<link rel="stylesheet" href="/fonts/ahem.css">
+<style>
+ div {
+ border: 1px solid black;
+ line-height: 0;
+ }
+ span {
+ font: 20px/1 Ahem;
+ visibility: hidden;
+ }
+</style>
+<div>
+ <span>A</span>
+</div>
diff --git a/testing/web-platform/tests/html/rendering/widgets/input-date-baseline.html b/testing/web-platform/tests/html/rendering/widgets/input-date-baseline.html
new file mode 100644
index 0000000000..0d8f46c064
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/input-date-baseline.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<title>date input baseline shouldn't be insane</title>
+<link rel="match" href="input-date-baseline-ref.html">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1667510">
+<link rel="stylesheet" href="/fonts/ahem.css">
+<style>
+ div {
+ border: 1px solid black;
+ line-height: 0;
+ }
+
+ input {
+ height: 20px;
+ font: 20px/1 Ahem;
+ box-sizing: border-box;
+ padding: 1px; /* needed to trigger the bug */
+ border: 0;
+ visibility: hidden;
+ -webkit-appearance: none;
+ appearance: none;
+ }
+</style>
+<div>
+ <input type="date">
+</div>
diff --git a/testing/web-platform/tests/html/rendering/widgets/input-date-content-size-ref.html b/testing/web-platform/tests/html/rendering/widgets/input-date-content-size-ref.html
new file mode 100644
index 0000000000..18019c56b1
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/input-date-content-size-ref.html
@@ -0,0 +1,9 @@
+<!doctype html>
+<title>Test reference</title>
+<link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
+<link rel="author" href="https://mozilla.org" title="Mozilla">
+<body>
+ <input type="date">
+ <br>
+ <input type="date">
+</body>
diff --git a/testing/web-platform/tests/html/rendering/widgets/input-date-content-size.html b/testing/web-platform/tests/html/rendering/widgets/input-date-content-size.html
new file mode 100644
index 0000000000..d026771f3c
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/input-date-content-size.html
@@ -0,0 +1,11 @@
+<!doctype html>
+<title>Test: the date field's min-content and max-content sizes should be the same as its automatic size</title>
+<link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
+<link rel="author" href="https://mozilla.org" title="Mozilla">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1695578">
+<link rel="match" href="input-date-content-size-ref.html">
+<body>
+ <input type="date" style="width: min-content">
+ <br>
+ <input type="date" style="width: max-content">
+</body>
diff --git a/testing/web-platform/tests/html/rendering/widgets/input-date-no-resize-on-hover.html b/testing/web-platform/tests/html/rendering/widgets/input-date-no-resize-on-hover.html
new file mode 100644
index 0000000000..74952ca239
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/input-date-no-resize-on-hover.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Date input should not resize on hover when using web fonts</title>
+<link rel="help" href="https://crbug.com/1167555">
+<link rel="author" href="mailto:xiaochengh@chromium.org">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+
+<input id="target" type="date" style="font-family: custom-font">
+
+<script>
+function mouseMoveToTarget(target) {
+ return new test_driver.Actions().pointerMove(0, 0, {origin: target}).send();
+}
+
+promise_test(async () => {
+ // Update layout before font loads
+ document.body.offsetWidth;
+
+ const font_sheet = document.createElement('style');
+ font_sheet.textContent = '@font-face { font-family: custom-font; src: url(/fonts/Revalia.woff) }';
+ document.body.appendChild(font_sheet);
+
+ await document.fonts.ready;
+
+ const target = document.getElementById('target');
+ const width_before_hover = target.offsetWidth;
+ await mouseMoveToTarget(target);
+ const width_after_hover = target.offsetWidth;
+ assert_equals(width_before_hover, width_after_hover);
+});
+</script>
diff --git a/testing/web-platform/tests/html/rendering/widgets/input-no-centering-ref.html b/testing/web-platform/tests/html/rendering/widgets/input-no-centering-ref.html
new file mode 100644
index 0000000000..5b2ea91fe5
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/input-no-centering-ref.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<div style="width: 100px; height: 100px; background: green;"></div>
diff --git a/testing/web-platform/tests/html/rendering/widgets/input-radio-disabled-checked-notref.html b/testing/web-platform/tests/html/rendering/widgets/input-radio-disabled-checked-notref.html
new file mode 100644
index 0000000000..987e03cd92
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/input-radio-disabled-checked-notref.html
@@ -0,0 +1,2 @@
+<!doctype html>
+<input type=radio disabled>
diff --git a/testing/web-platform/tests/html/rendering/widgets/input-radio-disabled-checked.html b/testing/web-platform/tests/html/rendering/widgets/input-radio-disabled-checked.html
new file mode 100644
index 0000000000..3ac2a37199
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/input-radio-disabled-checked.html
@@ -0,0 +1,5 @@
+<!doctype html>
+<title>radio with disabled and checked attributes renders differently than unchecked</title>
+<link rel=help href="https://bugzilla.mozilla.org/show_bug.cgi?id=1735077">
+<link rel=mismatch href="input-radio-disabled-checked-notref.html">
+<input type=radio disabled checked>
diff --git a/testing/web-platform/tests/html/rendering/widgets/input-radio-no-centering.html b/testing/web-platform/tests/html/rendering/widgets/input-radio-no-centering.html
new file mode 100644
index 0000000000..6a714f8460
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/input-radio-no-centering.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=1441341">
+<link rel="match" href="input-no-centering-ref.html">
+<style>
+input {
+ appearance: none;
+ margin: 0;
+ width: 200px;
+ height: 200px;
+}
+input:before {
+ content: "";
+ display: block;
+ width: 100px;
+ height: 100px;
+ background: green;
+}
+</style>
+<input type="radio">
diff --git a/testing/web-platform/tests/html/rendering/widgets/input-text-size.html b/testing/web-platform/tests/html/rendering/widgets/input-text-size.html
new file mode 100644
index 0000000000..fb3008df08
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/input-text-size.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<link rel="help" href="https://html.spec.whatwg.org/C/#the-input-element-as-a-text-entry-widget">
+<title>Test `size` attribute behaivor</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+
+<input id="missing">
+<input id="invalid" size="-1">
+<input id="size0" size="0">
+<input id="size1" size="1">
+<input id="size10" size="10">
+<input id="size20" size="20">
+<input id="size21" size="21">
+<input id="computed" style="border:none; padding:0;" size="19">
+<input id="computedNone" style="display:none" size="17">
+
+<script>
+test(() => {
+ assert_equals(missing.offsetWidth, size20.offsetWidth);
+}, 'A misssing attribute is equivalent to size=20');
+
+test(() => {
+ assert_equals(invalid.offsetWidth, size20.offsetWidth, 'size="-1"');
+ assert_equals(size0.offsetWidth, size20.offsetWidth, 'size="0"');
+}, 'An invalid attribute value is equivalent to size=20');
+
+test(() => {
+ assert_less_than(size1.offsetWidth, size10.offsetWidth, '1 < 10');
+ assert_less_than(size10.offsetWidth, size20.offsetWidth, '10 < 20');
+ assert_less_than(size20.offsetWidth, size21.offsetWidth, '20 < 21');
+}, 'The width depends on a size attribute');
+
+test(() => {
+ const computedString = getComputedStyle(computed).width;
+ assert_equals(computed.offsetWidth,
+ parseInt(computedString.substring(0, computedString.length - 2)));
+}, 'Size attribute value affects layout-dependent computed style');
+
+test(() => {
+ const computedString = getComputedStyle(computedNone).width;
+ assert_equals(computedString, 'auto');
+}, 'Size attribute value is not a presentational hint');
+</script>
+
diff --git a/testing/web-platform/tests/html/rendering/widgets/input-time-content-size-ref.html b/testing/web-platform/tests/html/rendering/widgets/input-time-content-size-ref.html
new file mode 100644
index 0000000000..938d2659a8
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/input-time-content-size-ref.html
@@ -0,0 +1,9 @@
+<!doctype html>
+<title>Test reference</title>
+<link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
+<link rel="author" href="https://mozilla.org" title="Mozilla">
+<body>
+ <input type="time">
+ <br>
+ <input type="time">
+</body>
diff --git a/testing/web-platform/tests/html/rendering/widgets/input-time-content-size.html b/testing/web-platform/tests/html/rendering/widgets/input-time-content-size.html
new file mode 100644
index 0000000000..4a378f6923
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/input-time-content-size.html
@@ -0,0 +1,11 @@
+<!doctype html>
+<title>Test: the time field's min-content and max-content sizes should be the same as its automatic size</title>
+<link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
+<link rel="author" href="https://mozilla.org" title="Mozilla">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1695578">
+<link rel="match" href="input-time-content-size-ref.html">
+<body>
+ <input type="time" style="width: min-content">
+ <br>
+ <input type="time" style="width: max-content">
+</body>
diff --git a/testing/web-platform/tests/html/rendering/widgets/select-wrap-no-spill.optional.html b/testing/web-platform/tests/html/rendering/widgets/select-wrap-no-spill.optional.html
new file mode 100644
index 0000000000..84aa5602ac
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/select-wrap-no-spill.optional.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<table>
+<tr><td id="target">
+<select style="width:80px; white-space:pre-wrap;">
+<option>ab option with a very long text that does not fit but should not spill</option>
+</select>
+<tr><td id="reference"><select style="width:80px;">
+<option>ab option with a very long text that does not fit but should not spill</option>
+</select>
+</table>
+<script>
+// crbug.com/924929
+test(() => {
+ assert_equals(document.querySelector('#target').offsetHeight,
+ document.querySelector('#reference').offsetHeight);
+}, 'Selected OPTION label with white-space:pre-wrap should not spill out.');
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/html/rendering/widgets/textarea-cols-rows.html b/testing/web-platform/tests/html/rendering/widgets/textarea-cols-rows.html
new file mode 100644
index 0000000000..6ad24a2eb8
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/textarea-cols-rows.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<link rel="help" href="https://html.spec.whatwg.org/C/#the-textarea-element-2">
+<title>Test `cols` `rows` attributes behaivor</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+
+<textarea id="missing"></textarea>
+<textarea id="invalid" cols="-1" rows="-1"></textarea>
+<textarea id="computed" style="border:none; padding:0;" cols="19" rows="5"></textarea>
+<textarea id="computedNone" style="display:none" cols="17" rows="7"></textarea>
+
+<textarea id="cols0" cols="0"></textarea>
+<textarea id="cols1" cols="1"></textarea>
+<textarea id="cols10" cols="10"></textarea>
+<textarea id="cols20" cols="20"></textarea>
+<textarea id="cols21" cols="21"></textarea>
+
+<textarea id="rows0" rows="0"></textarea>
+<textarea id="rows1" rows="1"></textarea>
+<textarea id="rows2" rows="2"></textarea>
+<textarea id="rows3" rows="3"></textarea>
+
+<script>
+test(() => {
+ assert_equals(missing.offsetWidth, cols20.offsetWidth);
+ assert_equals(missing.offsetHeight, rows2.offsetHeight);
+}, 'A misssing attribute is equivalent to cols=20 rows=2');
+
+test(() => {
+ assert_equals(invalid.offsetWidth, cols20.offsetWidth);
+ assert_equals(invalid.offsetHeight, rows2.offsetHeight);
+ assert_equals(cols0.offsetWidth, cols20.offsetWidth);
+ assert_equals(rows0.offsetHeight, rows2.offsetHeight);
+}, 'An invalid attribute value is equivalent to cols=20 rows=2');
+
+test(() => {
+ assert_less_than(cols1.offsetWidth, cols10.offsetWidth, '1 < 10');
+ assert_less_than(cols10.offsetWidth, cols20.offsetWidth, '10 < 20');
+ assert_less_than(cols20.offsetWidth, cols21.offsetWidth, '20 < 21');
+}, 'The width depends on a cols attribute');
+
+test(() => {
+ assert_less_than(rows1.offsetHeight, rows2.offsetHeight, '1 < 2');
+ assert_less_than(rows2.offsetHeight, rows3.offsetHeight, '2 < 3');
+}, 'The height depends on a rows attribute');
+
+test(() => {
+ const computedWidth = getComputedStyle(computed).width;
+ assert_equals(computed.offsetWidth,
+ parseInt(computedWidth.substring(0, computedWidth.length - 2)));
+
+ const computedHeight = getComputedStyle(computed).height;
+ assert_equals(computed.offsetHeight,
+ parseInt(computedHeight.substring(0, computedHeight.length - 2)));
+}, 'Cols/rows attribute values affect layout-dependent computed style');
+
+test(() => {
+ const computedNoneStyle = getComputedStyle(computedNone);
+ assert_equals(computedNoneStyle.width, 'auto');
+ assert_equals(computedNoneStyle.height, 'auto');
+}, 'Cols/rows attribute values are not presentational hints');
+</script>
+
diff --git a/testing/web-platform/tests/html/rendering/widgets/the-select-element/option-add-label-quirks.html b/testing/web-platform/tests/html/rendering/widgets/the-select-element/option-add-label-quirks.html
new file mode 100644
index 0000000000..2c3c8093e2
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/the-select-element/option-add-label-quirks.html
@@ -0,0 +1,20 @@
+<meta charset="utf-8">
+<title>OPTION's label attribute in SELECT -- Adding a label (quirks)</title>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/rendering.html#the-select-element-2">
+<link rel="match" href="option-label-ref.html">
+<meta name="assert" content="An option element is expected to be rendered by displaying the element's label.">
+
+<select>
+ <option>Element Text</option>
+</select>
+<br/>
+<select size="4">
+ <option>Element Text</option>
+</select>
+<script>
+let options = document.querySelectorAll("option");
+options[0].getBoundingClientRect(); // force layout.
+for (let option of options) {
+ option.setAttribute("label", "Label Text");
+}
+</script>
diff --git a/testing/web-platform/tests/html/rendering/widgets/the-select-element/option-add-label.html b/testing/web-platform/tests/html/rendering/widgets/the-select-element/option-add-label.html
new file mode 100644
index 0000000000..5110164c31
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/the-select-element/option-add-label.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>OPTION's label attribute in SELECT -- Adding a label</title>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/rendering.html#the-select-element-2">
+<link rel="match" href="option-label-ref.html">
+<meta name="assert" content="An option element is expected to be rendered by displaying the element's label.">
+
+<select>
+ <option>Element Text</option>
+</select>
+<br/>
+<select size="4">
+ <option>Element Text</option>
+</select>
+<script>
+let options = document.querySelectorAll("option");
+options[0].getBoundingClientRect(); // force layout.
+for (let option of options) {
+ option.setAttribute("label", "Label Text");
+}
+</script>
diff --git a/testing/web-platform/tests/html/rendering/widgets/the-select-element/option-checked-styling-ref.html b/testing/web-platform/tests/html/rendering/widgets/the-select-element/option-checked-styling-ref.html
new file mode 100644
index 0000000000..92504a47b5
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/the-select-element/option-checked-styling-ref.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Stylability of select>option with :checked pseudo</title>
+<link rel="author" href="mailto:masonf@chromium.org">
+
+<style>
+ option {
+ color: black;
+ }
+ #option2 {
+ background-color: red;
+ }
+ #option1 {
+ background: green;
+ }
+</style>
+
+<select id=select size=3 multiple>
+ <option id=option1>Option #1 (should be green)</option>
+ <option id=option2>Option #2 (should be red)</option>
+</select>
diff --git a/testing/web-platform/tests/html/rendering/widgets/the-select-element/option-checked-styling.html b/testing/web-platform/tests/html/rendering/widgets/the-select-element/option-checked-styling.html
new file mode 100644
index 0000000000..216b03a88a
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/the-select-element/option-checked-styling.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Stylability of select>option with :checked pseudo</title>
+<link rel="author" href="mailto:masonf@chromium.org">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/form-elements.html#the-select-element">
+<link rel="match" href="option-checked-styling-ref.html">
+
+<style>
+ option {
+ color: black;
+ background-color: red;
+ }
+ option:checked {
+ background: green;
+ }
+</style>
+
+<select id=select size=3 multiple>
+ <option id=option1 selected>Option #1 (should be green)</option>
+ <option id=option2>Option #2 (should be red)</option>
+</select>
diff --git a/testing/web-platform/tests/html/rendering/widgets/the-select-element/option-empty-label-to-empty-string.html b/testing/web-platform/tests/html/rendering/widgets/the-select-element/option-empty-label-to-empty-string.html
new file mode 100644
index 0000000000..c8aa4d20b2
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/the-select-element/option-empty-label-to-empty-string.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>OPTION's label attribute in SELECT -- Adding a label</title>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/rendering.html#the-select-element-2">
+<link rel="match" href="option-label-ref.html">
+<meta name="assert" content="An option element is expected to be rendered by displaying the element's label.">
+
+<select>
+ <option label="Element Text">Label Text</option>
+</select>
+<br/>
+<select size="4">
+ <option label="Element Text">Label Text</option>
+</select>
+<script>
+let options = document.querySelectorAll("option");
+options[0].getBoundingClientRect(); // force layout.
+for (let option of options) {
+ option.setAttribute("label", "");
+}
+</script>
diff --git a/testing/web-platform/tests/html/rendering/widgets/the-select-element/option-empty-label.html b/testing/web-platform/tests/html/rendering/widgets/the-select-element/option-empty-label.html
new file mode 100644
index 0000000000..a34c41d299
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/the-select-element/option-empty-label.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>OPTION's label attribute in SELECT -- Empty label uses Element text</title>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/rendering.html#the-select-element-2">
+<link rel="match" href="option-label-ref.html">
+<meta name="assert" content="An option element is expected to be rendered by displaying the element's label.">
+
+<select>
+ <option label>Label Text</option>
+</select>
+<br/>
+<select size="4">
+ <option label>Label Text</option>
+</select>
diff --git a/testing/web-platform/tests/html/rendering/widgets/the-select-element/option-label-and-text.html b/testing/web-platform/tests/html/rendering/widgets/the-select-element/option-label-and-text.html
new file mode 100644
index 0000000000..152bfdcb6a
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/the-select-element/option-label-and-text.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>OPTION's label attribute in SELECT - Prefers label over element text</title>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/rendering.html#the-select-element-2">
+<link rel="match" href="option-label-ref.html">
+<meta name="assert" content="An option element is expected to be rendered by displaying the element's label.">
+
+<select>
+ <option label="Label Text">Element Text</option>
+</select>
+<br/>
+<select size="4">
+ <option label="Label Text">Element Text</option>
+</select>
diff --git a/testing/web-platform/tests/html/rendering/widgets/the-select-element/option-label-ref.html b/testing/web-platform/tests/html/rendering/widgets/the-select-element/option-label-ref.html
new file mode 100644
index 0000000000..3dd07b8dc2
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/the-select-element/option-label-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>OPTION's label attribute in SELECT (reference)</title>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/rendering.html#the-select-element-2">
+
+<select>
+ <option>Label Text</option>
+</select>
+<br/>
+<select size="4">
+ <option>Label Text</option>
+</select>
diff --git a/testing/web-platform/tests/html/rendering/widgets/the-select-element/option-only-label.html b/testing/web-platform/tests/html/rendering/widgets/the-select-element/option-only-label.html
new file mode 100644
index 0000000000..5e3c06cd66
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/the-select-element/option-only-label.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>OPTION's label attribute in SELECT -- Only a label</title>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/rendering.html#the-select-element-2">
+<link rel="match" href="option-label-ref.html">
+<meta name="assert" content="An option element is expected to be rendered by displaying the element's label.">
+
+<select>
+ <option label="Label Text"></option>
+</select>
+<br/>
+<select size="4">
+ <option label="Label Text"></option>
+</select>
diff --git a/testing/web-platform/tests/html/rendering/widgets/the-select-element/option-rm-label.html b/testing/web-platform/tests/html/rendering/widgets/the-select-element/option-rm-label.html
new file mode 100644
index 0000000000..a5272cf6f1
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/the-select-element/option-rm-label.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>OPTION's label attribute in SELECT -- Removing the label</title>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/rendering.html#the-select-element-2">
+<link rel="match" href="option-label-ref.html">
+<meta name="assert" content="An option element is expected to be rendered by displaying the element's label.">
+
+<select>
+ <option label="Bad Label Text">Label Text</option>
+</select>
+<br/>
+<select size="4">
+ <option label="Bad Label Text">Label Text</option>
+</select>
+<script>
+let options = document.querySelectorAll("option");
+options[0].getBoundingClientRect(); // force layout.
+for (let option of options) {
+ option.removeAttribute("label");
+}
+</script>
diff --git a/testing/web-platform/tests/html/rendering/widgets/the-select-element/select-as-listbox-default-styles.tentative.html b/testing/web-platform/tests/html/rendering/widgets/the-select-element/select-as-listbox-default-styles.tentative.html
new file mode 100644
index 0000000000..3e9b001f99
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/the-select-element/select-as-listbox-default-styles.tentative.html
@@ -0,0 +1,113 @@
+<!doctype html>
+<title>default styles for select as a listbox</title>
+<meta name="viewport" content="width=device-width">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/rendering/support/test-ua-stylesheet.js"></script>
+<style>
+/* Specify this bogus namespace, so the rules in this stylesheet only apply to the `fakeClone`d elements in #refs, not the HTML elements in #tests. */
+@namespace url(urn:not-html);
+
+select {
+ letter-spacing: initial;
+ word-spacing: initial;
+ line-height: initial;
+ text-transform: initial;
+ text-indent: initial;
+ text-shadow: initial;
+ appearance: auto;
+}
+
+select {
+ text-align: initial;
+}
+
+select {
+ box-sizing: border-box;
+}
+
+/* When the element renders as a list box, it is a devolvable widget expected to render as an 'inline-block' box whose 'height' is the height necessary to contain as many rows for items as given by the element's display size, or four rows if the attribute is absent, and whose 'width' is the width of the select's labels plus the width of a scrollbar. */
+select {
+ display: inline-block;
+}
+
+</style>
+
+<style>
+/* non-initial styles on parent to test 'initial' in UA stylesheet */
+#tests, #refs {
+ letter-spacing: 1px;
+ word-spacing: 1px;
+ line-height: 20px;
+ text-transform: lowercase;
+ text-indent: 1px;
+ text-shadow: 0px 0px;
+ text-align: justify;
+}
+</style>
+
+<div id="log"></div>
+
+<div id="tests">
+
+ <select multiple><option>1</option><optgroup label=2><option>3</select>
+
+</div>
+
+<div id="refs"></div>
+
+<script>
+ const props = [
+ 'display',
+ 'margin-top',
+ 'margin-right',
+ 'margin-bottom',
+ 'margin-left',
+ 'padding-top',
+ 'padding-right',
+ 'padding-bottom',
+ 'padding-left',
+ 'letter-spacing',
+ 'word-spacing',
+ 'text-transform',
+ 'text-indent',
+ 'text-shadow',
+ 'appearance',
+ 'box-sizing',
+ 'border-top-width',
+ 'border-right-width',
+ 'border-bottom-width',
+ 'border-left-width',
+ 'border-top-style',
+ 'border-right-style',
+ 'border-bottom-style',
+ 'border-left-style',
+ 'border-top-color',
+ 'border-right-color',
+ 'border-bottom-color',
+ 'border-left-color',
+ 'align-items',
+ 'white-space',
+ 'color',
+ 'background-color',
+ 'cursor',
+ 'font-style',
+ 'font-weight',
+ 'font-size',
+ 'font-family',
+ 'writing-mode',
+ 'scrollbar-width',
+ 'overflow',
+ 'vertical-align',
+ 'user-select',
+ 'page-break-inside',
+ 'overflow-clip-box',
+ 'font-variant-ligatures',
+ 'font-variant-caps',
+ 'font-variant-numeric',
+ 'font-variant-east-asian',
+ 'text-rendering',
+ ];
+ runUAStyleTests(props);
+
+</script>
diff --git a/testing/web-platform/tests/html/rendering/widgets/the-select-element/select-invalidation-ref.html b/testing/web-platform/tests/html/rendering/widgets/the-select-element/select-invalidation-ref.html
new file mode 100644
index 0000000000..7a3dd1d50d
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/the-select-element/select-invalidation-ref.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Select rendering invalidation</title>
+<link rel="author" href="mailto:masonf@chromium.org">
+
+<style>
+ select {
+ color: lime;
+ }
+</style>
+
+<select id=select>
+ <option>The down arrow should be green</option>
+ <option>value B</option>
+</select>
diff --git a/testing/web-platform/tests/html/rendering/widgets/the-select-element/select-invalidation.html b/testing/web-platform/tests/html/rendering/widgets/the-select-element/select-invalidation.html
new file mode 100644
index 0000000000..199db0b7aa
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/the-select-element/select-invalidation.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<meta charset="utf-8">
+<title>Select rendering invalidation</title>
+<link rel="author" href="mailto:masonf@chromium.org">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/form-elements.html#the-select-element">
+<link rel="match" href="select-invalidation-ref.html">
+
+<style>
+ select {
+ color: red;
+ }
+</style>
+
+<select id=select>
+ <option>The down arrow should be green</option>
+ <option>value B</option>
+</select>
+
+<script>
+ requestAnimationFrame(() => {
+ requestAnimationFrame(() => {
+ select.style.color = "lime";
+ requestAnimationFrame(() => {
+ requestAnimationFrame(() => {
+ document.documentElement.classList.remove("reftest-wait");
+ });
+ });
+ });
+ });
+</script>
diff --git a/testing/web-platform/tests/html/rendering/widgets/the-select-element/select-size-001.html b/testing/web-platform/tests/html/rendering/widgets/the-select-element/select-size-001.html
new file mode 100644
index 0000000000..ad4055415d
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/the-select-element/select-size-001.html
@@ -0,0 +1,11 @@
+<!doctype html>
+<title>select size=1 renders the same as plain select</title>
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1643279">
+<link rel="author" title="Mozilla" href="https://mozilla.org">
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="match" href="select-size-ref.html">
+<select size="1">
+ <option value ="1">1</option>
+ <option value ="2">2</option>
+ <option value ="3">3</option>
+</select>
diff --git a/testing/web-platform/tests/html/rendering/widgets/the-select-element/select-size-002.html b/testing/web-platform/tests/html/rendering/widgets/the-select-element/select-size-002.html
new file mode 100644
index 0000000000..0838e7a3c6
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/the-select-element/select-size-002.html
@@ -0,0 +1,11 @@
+<!doctype html>
+<title>select size=0 renders the same as plain select</title>
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1643279">
+<link rel="author" title="Mozilla" href="https://mozilla.org">
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="match" href="select-size-ref.html">
+<select size="0">
+ <option value ="1">1</option>
+ <option value ="2">2</option>
+ <option value ="3">3</option>
+</select>
diff --git a/testing/web-platform/tests/html/rendering/widgets/the-select-element/select-size-ref.html b/testing/web-platform/tests/html/rendering/widgets/the-select-element/select-size-ref.html
new file mode 100644
index 0000000000..fc3b3be6e5
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/widgets/the-select-element/select-size-ref.html
@@ -0,0 +1,7 @@
+<!doctype html>
+<title>Test reference.</title>
+<select>
+ <option value ="1">1</option>
+ <option value ="2">2</option>
+ <option value ="3">3</option>
+</select>