pseudo-elements-after-part.html (7279B)
1 <!DOCTYPE html> 2 <title>Pseudo-elements allowed after ::part()</title> 3 <link rel="help" href="https://drafts.csswg.org/css-shadow-parts/"> 4 <meta name="flags" content="ahem"> 5 <link rel="stylesheet" href="/fonts/ahem.css"> 6 <script src="/resources/testharness.js"></script> 7 <script src="/resources/testharnessreport.js"></script> 8 <script src="../support/parsing-testcommon.js"></script> 9 10 <body> 11 <span style="font-family: Ahem">X</span> 12 13 <script> 14 "use strict"; 15 16 test_invalid_selector("::part(mypart)::part(anotherpart)"); 17 test_invalid_selector("::part(mypart)::notarealpseudoelement"); 18 19 test_valid_selector("::part(mypart)::after"); 20 test_valid_selector("::part(mypart)::backdrop"); 21 test_valid_selector("::part(mypart)::before"); 22 test_valid_selector("::part(mypart)::cue"); 23 test_valid_selector("::part(mypart)::details-content"); 24 test_valid_selector("::part(mypart)::file-selector-button"); 25 test_valid_selector("::part(mypart)::first-letter"); 26 test_valid_selector("::part(mypart)::first-line"); 27 test_valid_selector("::part(mypart)::grammar-error"); 28 test_valid_selector("::part(mypart)::highlight(myhighlight)"); 29 test_valid_selector("::part(mypart)::marker"); 30 test_valid_selector("::part(mypart)::placeholder"); 31 test_valid_selector("::part(mypart)::search-text"); 32 test_valid_selector("::part(mypart)::selection"); 33 test_valid_selector("::part(mypart)::spelling-error"); 34 test_valid_selector("::part(mypart)::target-text"); 35 test_valid_selector("::part(mypart)::view-transition"); 36 test_valid_selector("::part(mypart)::view-transition-group(*)"); 37 test_valid_selector("::part(mypart)::view-transition-image-pair(*)"); 38 test_valid_selector("::part(mypart)::view-transition-new(*)"); 39 test_valid_selector("::part(mypart)::view-transition-old(*)"); 40 41 // to be used inside of a promise_test() function. 42 async function run_part_test(t, style_rules, part_html, assertion) { 43 let container = document.createElement("div"); 44 let shadow = container.attachShadow({mode: "open"}); 45 shadow.innerHTML = ` 46 ${part_html} 47 <slot></slot> 48 `; 49 document.body.append(container); 50 let style = document.createElement("style"); 51 style.innerText = style_rules; 52 document.head.append(style); 53 t.add_cleanup(() => { 54 container.remove(); 55 style.remove(); 56 }); 57 await assertion(container, shadow.firstElementChild); 58 } 59 60 function test_with_part(style_rules, part_html, assertion) { 61 promise_test(async (t) => { 62 await run_part_test(t, style_rules, part_html, assertion); 63 }, `::part styles with ${style_rules} and ${part_html}`); 64 } 65 66 // Generate a random-looking color using the string input as a "seed" 67 // (so different tests use different colors). 68 function generate_color(str) { 69 let sum = Array.from(str).reduce((sum, char) => sum + char.charCodeAt(0), 0); 70 return `rgb(${sum % 255}, ${(sum * 2 + 17) % 255}, ${(sum * 3 + 139) % 255})`; 71 } 72 73 function test_pseudo_computed_style(pseudo_element, tag, attributes) { 74 promise_test(async (t) => { 75 let our_color = generate_color(pseudo_element); 76 await run_part_test(t, 77 `::part(mypart)${pseudo_element} { 78 background: ${our_color}; 79 }`, 80 `<${tag} ${attributes} part='mypart'></${tag}>`, 81 async (container, part) => { 82 assert_equals(getComputedStyle(part, pseudo_element).backgroundColor, our_color); 83 }); 84 85 }, `computed style for ::part()${pseudo_element}`); 86 } 87 88 test_pseudo_computed_style("::after", "div", ""); 89 test_pseudo_computed_style("::backdrop", "div", "popover='auto'"); 90 test_pseudo_computed_style("::before", "div", ""); 91 // NOTE: not testing :cue at all. 92 test_pseudo_computed_style("::details-content", "details", ""); 93 test_pseudo_computed_style("::file-selector-button", "input", "type='file'"); 94 test_pseudo_computed_style("::first-letter", "div", ""); 95 test_pseudo_computed_style("::first-line", "div", ""); 96 test_pseudo_computed_style("::grammar-error", "div", ""); 97 test_pseudo_computed_style("::highlight(myhighlight)", "div", ""); 98 test_pseudo_computed_style("::placeholder", "input", "type='text' placeholder='enter text'"); 99 test_pseudo_computed_style("::search-text", "div", ""); 100 test_pseudo_computed_style("::selection", "div", ""); 101 test_pseudo_computed_style("::spelling-error", "div", ""); 102 test_pseudo_computed_style("::target-text", "div", ""); 103 // NOTE: Not yet testing computed style for view transition 104 // pseudo-elements since they currently only apply to the root element 105 // (but are intended to apply to others later). 106 107 test_with_part(`::part(mypart)::after { 108 display: block; 109 content: ""; 110 height: 77px; 111 }`, 112 `<div part='mypart'></div>`, 113 async (container, part) => { 114 assert_equals(container.getBoundingClientRect().height, 77); 115 }); 116 117 test_with_part(`::part(mypart)::before { 118 display: block; 119 content: ""; 120 height: 46px; 121 }`, 122 `<div part='mypart'></div>`, 123 async (container, part) => { 124 assert_equals(container.getBoundingClientRect().height, 46); 125 }); 126 127 test_with_part(`::part(mypart)::details-content { 128 height: 371px; 129 }`, 130 `<details part='mypart'><summary style="height:47px">summary</summary>details</details>`, 131 async (container, part) => { 132 assert_equals(container.getBoundingClientRect().height, 371 + 47); 133 }); 134 135 test_with_part(`::part(mypart)::file-selector-button { 136 height: 94px; 137 padding: 0; 138 margin: 0; 139 border: none; 140 appearance: none; 141 }`, 142 `<input type=file part=mypart>`, 143 async (container, part) => { 144 assert_equals(container.getBoundingClientRect().height, 94); 145 }); 146 147 test_with_part(`::part(mypart) { 148 font: 20px/1 Ahem; 149 } 150 ::part(mypart)::first-letter { 151 font-size: 86px; 152 }`, 153 `<div part=mypart>X<br>X</div>`, 154 async (container, part) => { 155 await document.fonts.ready; 156 assert_equals(container.getBoundingClientRect().height, 86 + 20); 157 }); 158 159 test_with_part(`::part(mypart) { 160 font: 20px/1 Ahem; 161 } 162 ::part(mypart)::first-line { 163 font-size: 86px; 164 }`, 165 `<div part=mypart>X<br>X</div>`, 166 async (container, part) => { 167 await document.fonts.ready; 168 assert_equals(container.getBoundingClientRect().height, 86 + 20); 169 }); 170 171 test_with_part(`::part(mypart)::marker { 172 font: 63px/1.0 Ahem; 173 content: "X"; 174 }`, 175 `<li style="list-style-position: inside" part="mypart"></li>`, 176 async (container, part) => { 177 await document.fonts.ready; 178 assert_equals(container.getBoundingClientRect().height, 63); 179 }); 180 181 </script>