| <!DOCTYPE html> | |
| <html> | |
| <head> | |
| <script src="../../http/tests/inspector/resources/protocol-test.js"></script> | |
| <script> | |
| function test() | |
| { | |
| let suite = ProtocolTest.createAsyncSuite("CSS.Keyframes.TreeScope"); | |
| async function keyframesFor(expression) | |
| { | |
| let {result} = await InspectorProtocol.awaitCommand({ | |
| method: "Runtime.evaluate", | |
| params: {expression, objectGroup: "test"}, | |
| }); | |
| let {nodeId} = await InspectorProtocol.awaitCommand({ | |
| method: "DOM.requestNode", | |
| params: {objectId: result.objectId}, | |
| }); | |
| return InspectorProtocol.awaitCommand({ | |
| method: "CSS.getMatchedStylesForNode", | |
| params: {nodeId, includePseudo: true, includeKeyframes: true}, | |
| }); | |
| } | |
| function expectOpacity(rules, expected, message) | |
| { | |
| ProtocolTest.expectEqual(rules.length, 1, "Only the resolved keyframe rule should be returned."); | |
| let opacity = rules[0]?.style.cssProperties.find((property) => property.name === "opacity")?.value; | |
| ProtocolTest.expectEqual(opacity, expected, message); | |
| } | |
| suite.addTestCase({ | |
| name: "CSS.Keyframes.TreeScope", | |
| async test() { | |
| await InspectorProtocol.awaitCommand({method: "DOM.getDocument", params: {}}); | |
| expectOpacity((await keyframesFor("document.getElementById('document-target')")).keyframes, "0.2", "The document target should use document keyframes."); | |
| expectOpacity((await keyframesFor("document.getElementById('first-host').shadowRoot.getElementById('target')")).keyframes, "0.8", "The shadow target should use its last matching scoped rule."); | |
| expectOpacity((await keyframesFor("document.getElementById('second-host').shadowRoot.getElementById('target')")).keyframes, "0.9", "A second shadow tree should use its own keyframes."); | |
| expectOpacity((await keyframesFor("document.getElementById('slotted-target')")).keyframes, "0.8", "A slotted animation name should resolve in the declaring shadow scope."); | |
| expectOpacity((await keyframesFor("document.getElementById('first-host').shadowRoot.getElementById('part-target')")).keyframes, "0.2", "A part animation name should resolve in the declaring document scope."); | |
| let styles = await keyframesFor("document.getElementById('first-host').shadowRoot.getElementById('pseudo-target')"); | |
| expectOpacity(styles.pseudoElements.find((pseudo) => pseudo.pseudoId === "before").keyframes, "0.8", "A shadow pseudo element should use its scoped keyframes."); | |
| }, | |
| }); | |
| suite.runTestCasesAndFinish(); | |
| } | |
| </script> | |
| <style> | |
| @keyframes shared { from { opacity: 0.2; } } | |
| #document-target { animation: shared 1s; } | |
| #first-host::part(target) { animation: shared 1s; } | |
| </style> | |
| </head> | |
| <body onload="runTest()"> | |
| <div id="document-target"></div> | |
| <div id="first-host"><span id="slotted-target" slot="target"></span></div> | |
| <div id="second-host"></div> | |
| <script> | |
| let firstRoot = document.getElementById("first-host").attachShadow({mode: "open"}); | |
| firstRoot.innerHTML = `<style> | |
| @keyframes shared { from { opacity: 0.7; } } | |
| @keyframes shared { from { opacity: 0.8; } } | |
| #target, ::slotted(span), #pseudo-target::before { animation: shared 1s; } | |
| #pseudo-target::before { content: ""; } | |
| </style> | |
| <div id="target"></div><div id="pseudo-target"></div> | |
| <div id="part-target" part="target"></div><slot name="target"></slot>`; | |
| let secondRoot = document.getElementById("second-host").attachShadow({mode: "open"}); | |
| secondRoot.innerHTML = `<style> | |
| @keyframes shared { from { opacity: 0.9; } } | |
| #target { animation: shared 1s; } | |
| </style><div id="target"></div>`; | |
| </script> | |
| </body> | |
| </html> |