| <html> |
| <head> |
| <script src="../../http/tests/inspector/resources/protocol-test.js"></script> |
| <style> |
| .case1 { |
| color: red; |
| @media (min-width: 0px) { |
| color: yellow; |
| } |
| color: green; |
| } |
| |
| .case2 { |
| color: red; |
| @media (min-width: 0px) { |
| color: yellow; |
| } |
| &:not(.x) { |
| color: orange; |
| } |
| color: green; |
| } |
| |
| .case3 { |
| color: red; |
| @media (min-width: 0px) { |
| color: yellow; |
| @supports (display: grid) { |
| color: orange; |
| } |
| color: violet; |
| } |
| color: green; |
| } |
| </style> |
| <script> |
| function test() { |
| let suite = ProtocolTest.createAsyncSuite("CSS.setStyleText.Interleaved"); |
| |
| const colorReplacements = { |
| "red": "magenta", |
| "yellow": "cyan", |
| "orange": "tomato", |
| "green": "pink", |
| "violet": "navy", |
| }; |
| |
| async function getAuthorRulesForSelector(selector) { |
| let { root } = await InspectorProtocol.awaitCommand({ method: "DOM.getDocument" }); |
| let { nodeId } = await InspectorProtocol.awaitCommand({ |
| method: "DOM.querySelector", |
| params: { nodeId: root.nodeId, selector }, |
| }); |
| let { matchedCSSRules } = await InspectorProtocol.awaitCommand({ |
| method: "CSS.getMatchedStylesForNode", |
| params: { nodeId }, |
| }); |
| return matchedCSSRules |
| .map(({ rule }) => rule) |
| .filter((rule) => rule.origin === "author"); |
| } |
| |
| function collectColorProperties(rules) { |
| let results = []; |
| for (let rule of rules) { |
| let style = rule.style; |
| for (let prop of style.cssProperties) { |
| if (prop.name === "color" && prop.status !== "disabled") |
| results.push({ value: prop.value, styleId: style.styleId }); |
| } |
| } |
| return results; |
| } |
| |
| |
| async function testCase(caseName, selector, expectedColors) { |
| suite.addTestCase({ |
| name: `CSS.setStyleText.Interleaved.${caseName}`, |
| description: `Test editing each color property in ${selector} preserves other properties.`, |
| test: async () => { |
| for (let targetColor of expectedColors) { |
| let rules = await getAuthorRulesForSelector(selector); |
| let colorProps = collectColorProperties(rules); |
| |
| let target = colorProps.find((p) => p.value === targetColor); |
| if (!target) { |
| ProtocolTest.fail(`Could not find color property with value "${targetColor}".`); |
| continue; |
| } |
| |
| let newValue = colorReplacements[targetColor]; |
| ProtocolTest.log(`Editing "${targetColor}" to "${newValue}"...`); |
| await InspectorProtocol.awaitCommand({ |
| method: "CSS.setStyleText", |
| params: { |
| styleId: target.styleId, |
| text: `color: ${newValue};`, |
| }, |
| }); |
| } |
| |
| const filteredValueReplacer = (key, value) => { |
| if (["ruleId", "styleId", "range", "sourceLine", "sourceURL"].includes(key)) |
| return "<filtered>"; |
| return value; |
| }; |
| |
| ProtocolTest.log(""); |
| ProtocolTest.log("Author CSS rules after all edits:"); |
| ProtocolTest.json(await getAuthorRulesForSelector(selector), filteredValueReplacer); |
| }, |
| }); |
| } |
| |
| testCase("BasicInterleaving", ".case1", ["red", "yellow", "green"]); |
| testCase("ImplicitAndExplicitInterleaving", ".case2", ["red", "yellow", "orange", "green"]); |
| testCase("NestedInterleaving", ".case3", ["red", "yellow", "orange", "violet", "green"]); |
| |
| suite.runTestCasesAndFinish(); |
| } |
| </script> |
| </head> |
| <body onload="runTest()"> |
| <p>Tests that CSS.setStyleText correctly edits individual properties in interleaved nested declarations without affecting other properties.</p> |
| <div class="case1"></div> |
| <div class="case2"></div> |
| <div class="case3"></div> |
| </body> |
| </html> |