Skip to content

Commit 79645bf

Browse files
committed
Bug 1965855 [wpt PR 52476] - Add MutationObserver tests for <selectedcontent>,
Automatic update from web-platform-tests Add MutationObserver tests for <selectedcontent> These were requested here: whatwg/html#10633 (comment) There are failing test expectations added for the virtual test suites where CustomizableSelect is disabled, where the <selectedcontent> element is not enabled. Change-Id: Ib2906a5c8d70ae5ea5cccb6d899c79b29ea45e5e Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6471702 Commit-Queue: Joey Arhar <jarharchromium.org> Reviewed-by: Dominic Farolino <domchromium.org> Cr-Commit-Position: refs/heads/main{#1458866} -- wpt-commits: 23b9c427c9115a1b40b95e4e4099c353a985c958 wpt-pr: 52476 Differential Revision: https://phabricator.services.mozilla.com/D249370 UltraBlame original commit: c92c496cf3b9513fb0279fdb8afa468388d866ff
1 parent a3ff74f commit 79645bf

File tree

2 files changed

+149
-3
lines changed

2 files changed

+149
-3
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
<!DOCTYPE html>
2+
<link rel=author href="mailto:[email protected]">
3+
<link rel=help href="https://github.com/whatwg/html/issues/9799">
4+
<script src="/resources/testharness.js"></script>
5+
<script src="/resources/testharnessreport.js"></script>
6+
7+
<style>
8+
select, ::picker(select) {
9+
appearance: base-select;
10+
}
11+
</style>
12+
13+
<div id=target>
14+
<script>
15+
window.selectedcontentRecords = [];
16+
window.selectedcontentObserver = new MutationObserver(mutations => {
17+
window.selectedcontentRecords = window.selectedcontentRecords.concat(mutations);
18+
});
19+
const config = {attributes: true, childList: true, subtree: true};
20+
window.selectedcontentObserver.observe(document.getElementById('target'), config);
21+
</script>
22+
23+
<select>
24+
<button>
25+
<selectedcontent></selectedcontent>
26+
</button>
27+
<option><span>span</span> one</option>
28+
<option><span>span</span> two</option>
29+
<option selected><span>span</option> three</option>
30+
</select>
31+
</div>
32+
33+
<script>
34+
function getNodeRepresentation(node) {
35+
if (!node) {
36+
return 'null';
37+
}
38+
switch (node.nodeType) {
39+
case Node.ELEMENT_NODE:
40+
let representation = node.tagName.toLowerCase();
41+
if (node.id) {
42+
representation += `#${node.id}`;
43+
}
44+
if (node.classList && node.classList.length > 0) {
45+
representation += `.${Array.from(node.classList).join('.')}`;
46+
}
47+
return representation;
48+
case Node.TEXT_NODE:
49+
const text = node.textContent.trim();
50+
return `#text: "${text.length > 50 ? text.substring(0, 47) + '...' : text}"`;
51+
case Node.COMMENT_NODE:
52+
return '';
53+
default:
54+
return `[Node type ${node.nodeType}]`;
55+
}
56+
}
57+
58+
function mutationRecordToString(record) {
59+
if (!record) {
60+
return '[Invalid MutationRecord]';
61+
}
62+
63+
const targetStr = getNodeRepresentation(record.target);
64+
let summary = `Type: ${record.type} | Target: ${targetStr}`;
65+
66+
switch (record.type) {
67+
case 'attributes':
68+
const attrName = record.attributeName;
69+
const oldValue = record.oldValue !== null ? `"${record.oldValue}"` : 'null';
70+
const newValue = record.target.getAttribute(attrName);
71+
const newValueStr = newValue !== null ? `"${newValue}"` : 'null';
72+
summary += ` | Attribute: '${attrName}' changed from ${oldValue} to ${newValueStr}`;
73+
if (record.attributeNamespace) {
74+
summary += ` (Namespace: ${record.attributeNamespace})`;
75+
}
76+
break;
77+
78+
case 'characterData':
79+
const oldText = record.oldValue !== null ? `"${record.oldValue}"` : 'null';
80+
const newText = record.target.textContent !== null ? `"${record.target.textContent}"` : 'null';
81+
summary += ` | Data changed from ${oldText} to ${newText}`;
82+
break;
83+
84+
case 'childList':
85+
if (record.addedNodes.length > 0) {
86+
const added = Array.from(record.addedNodes).map(getNodeRepresentation).join(', ');
87+
summary += ` | Added: [${added}]`;
88+
}
89+
if (record.removedNodes.length > 0) {
90+
const removed = Array.from(record.removedNodes).map(getNodeRepresentation).join(', ');
91+
summary += ` | Removed: [${removed}]`;
92+
}
93+
if (record.previousSibling) {
94+
summary += ` | After: ${getNodeRepresentation(record.previousSibling)}`;
95+
}
96+
if (record.nextSibling) {
97+
summary += ` | Before: ${getNodeRepresentation(record.nextSibling)}`;
98+
}
99+
break;
100+
101+
default:
102+
summary += ' | [Unknown mutation type]';
103+
break;
104+
}
105+
106+
return summary;
107+
}
108+
109+
function convertMutationRecords(records) {
110+
const output = [];
111+
for (const record of records) {
112+
output.push(mutationRecordToString(record));
113+
}
114+
return output;
115+
}
116+
117+
test(() => {
118+
const expectedMutations = [
119+
"Type: childList | Target: div#target | Added: [#text: \"\"] | After: script",
120+
"Type: childList | Target: div#target | Added: [select] | After: #text: \"\"",
121+
"Type: childList | Target: select | Added: [#text: \"\"]",
122+
"Type: childList | Target: select | Added: [button] | After: #text: \"\"",
123+
"Type: childList | Target: button | Added: [#text: \"\"]",
124+
"Type: childList | Target: button | Added: [selectedcontent] | After: #text: \"\"",
125+
"Type: childList | Target: button | Added: [#text: \"\"] | After: selectedcontent",
126+
"Type: childList | Target: select | Added: [#text: \"\"] | After: button",
127+
"Type: childList | Target: select | Added: [option] | After: #text: \"\"",
128+
"Type: childList | Target: option | Added: [span]",
129+
"Type: childList | Target: span | Added: [#text: \"span\"]",
130+
"Type: childList | Target: option | Added: [#text: \"one\"] | After: span",
131+
"Type: childList | Target: selectedcontent | Added: [span, #text: \"one\"]",
132+
"Type: childList | Target: select | Added: [#text: \"\"] | After: option",
133+
"Type: childList | Target: select | Added: [option] | After: #text: \"\"",
134+
"Type: childList | Target: option | Added: [span]",
135+
"Type: childList | Target: span | Added: [#text: \"span\"]",
136+
"Type: childList | Target: option | Added: [#text: \"two\"] | After: span",
137+
"Type: childList | Target: select | Added: [#text: \"\"] | After: option",
138+
"Type: childList | Target: select | Added: [option] | After: #text: \"\"",
139+
"Type: childList | Target: selectedcontent | Removed: [span, #text: \"one\"]",
140+
"Type: childList | Target: option | Added: [span]",
141+
"Type: childList | Target: span | Added: [#text: \"span\"]",
142+
"Type: childList | Target: selectedcontent | Added: [span]",
143+
"Type: childList | Target: select | Added: [#text: \"three\"] | After: option",
144+
"Type: childList | Target: div#target | Added: [#text: \"\"] | After: select"
145+
];
146+
assert_array_equals(convertMutationRecords(window.selectedcontentRecords), expectedMutations);
147+
}, 'MutationObserver records during parsing of <select> with <selectedcontent>');
148+
</script>

testing/web-platform/tests/html/semantics/forms/the-select-element/customizable-select/selectedcontent.tentative.html

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<script src="/resources/testdriver-vendor.js"></script>
88

99
<style>
10-
select, select::picker(select) {
10+
select, ::picker(select) {
1111
appearance: base-select;
1212
}
1313
</style>
@@ -92,8 +92,6 @@
9292
optionOne.remove();
9393
assert_equals(selectedcontent.innerHTML, '',
9494
'The content of <selectedcontent> should be cleared if there is no selected <option>.');
95-
96-
// TODO(crbug.com/336844298): Add tests for mutation records during parsing
9795
}, 'The <selectedcontent> element should reflect the HTML contents of the selected <option>.');
9896
</script>
9997

0 commit comments

Comments
 (0)