diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
commit | 6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /devtools/client/inspector/grids/test | |
parent | Initial commit. (diff) | |
download | thunderbird-upstream.tar.xz thunderbird-upstream.zip |
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'devtools/client/inspector/grids/test')
40 files changed, 3131 insertions, 0 deletions
diff --git a/devtools/client/inspector/grids/test/browser.ini b/devtools/client/inspector/grids/test/browser.ini new file mode 100644 index 0000000000..bb0f9f9136 --- /dev/null +++ b/devtools/client/inspector/grids/test/browser.ini @@ -0,0 +1,49 @@ +[DEFAULT] +tags = devtools +subsuite = devtools +support-files = + doc_iframe_reloaded.html + doc_subgrid.html + head.js + !/devtools/client/inspector/test/head.js + !/devtools/client/inspector/test/shared-head.js + !/devtools/client/shared/test/shared-head.js + !/devtools/client/shared/test/telemetry-test-helpers.js + !/devtools/client/shared/test/highlighter-test-actor.js + +[browser_grids_accordion-state.js] +[browser_grids_color-in-rules-grid-toggle.js] +[browser_grids_display-setting-extend-grid-lines.js] +[browser_grids_display-setting-show-grid-line-numbers.js] +[browser_grids_display-setting-show-grid-areas.js] +[browser_grids_grid-list-color-picker-on-ESC.js] +[browser_grids_grid-list-color-picker-on-RETURN.js] +[browser_grids_grid-list-element-rep.js] +[browser_grids_grid-list-no-grids.js] +[browser_grids_grid-list-on-iframe-reloaded.js] +skip-if = (verify && (os == 'win' || os == 'linux')) +[browser_grids_grid-list-on-mutation-element-added.js] +skip-if = true #Bug 1557326 +[browser_grids_grid-list-on-mutation-element-removed.js] +[browser_grids_grid-list-on-target-added-removed.js] +[browser_grids_grid-list-subgrids-z-order.js] +[browser_grids_grid-list-subgrids_01.js] +[browser_grids_grid-list-subgrids_02.js] +[browser_grids_grid-list-toggle-grids_01.js] +[browser_grids_grid-list-toggle-grids_02.js] +[browser_grids_grid-list-toggle-multiple-grids.js] +[browser_grids_grid-outline-cannot-show-outline.js] +[browser_grids_grid-outline-highlight-area.js] +[browser_grids_grid-outline-highlight-cell.js] +[browser_grids_grid-outline-multiple-grids.js] +[browser_grids_grid-outline-selected-grid.js] +[browser_grids_grid-outline-updates-on-grid-change.js] +skip-if = (os == "linux") || (os == 'mac') || (os == 'win' && (debug || asan)) #Bug 1557181 +[browser_grids_grid-outline-writing-mode.js] +skip-if = (verify && (os == 'win')) +[browser_grids_highlighter-setting-rules-grid-toggle.js] +[browser_grids_highlighter-toggle-telemetry.js] +[browser_grids_number-of-css-grids-telemetry.js] +[browser_grids_persist-color-palette.js] +[browser_grids_restored-after-reload.js] +[browser_grids_restored-multiple-grids-after-reload.js] diff --git a/devtools/client/inspector/grids/test/browser_grids_accordion-state.js b/devtools/client/inspector/grids/test/browser_grids_accordion-state.js new file mode 100644 index 0000000000..c02fc85dfa --- /dev/null +++ b/devtools/client/inspector/grids/test/browser_grids_accordion-state.js @@ -0,0 +1,108 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Tests that the grid's accordion state is persistent through hide/show in the layout +// view. + +const TEST_URI = ` + <style type='text/css'> + #grid { + display: grid; + } + </style> + <div id="grid"> + <div id="cell1">cell1</div> + <div id="cell2">cell2</div> + </div> +`; + +const GRID_OPENED_PREF = "devtools.layout.grid.opened"; +const GRID_PANE_SELECTOR = "#layout-grid-section"; +const ACCORDION_HEADER_SELECTOR = ".accordion-header"; +const ACCORDION_CONTENT_SELECTOR = ".accordion-content"; + +add_task(async function () { + await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI)); + const { inspector, gridInspector, toolbox } = await openLayoutView(); + const { document: doc } = gridInspector; + + await testAccordionStateAfterClickingHeader(doc); + await testAccordionStateAfterSwitchingSidebars(inspector, doc); + await testAccordionStateAfterReopeningLayoutView(toolbox); + + Services.prefs.clearUserPref(GRID_OPENED_PREF); +}); + +async function testAccordionStateAfterClickingHeader(doc) { + const item = await waitFor(() => doc.querySelector(GRID_PANE_SELECTOR)); + const header = item.querySelector(ACCORDION_HEADER_SELECTOR); + const content = item.querySelector(ACCORDION_CONTENT_SELECTOR); + + info("Checking initial state of the grid panel."); + ok( + !content.hidden && content.childElementCount > 0, + "The grid panel content is visible." + ); + ok( + Services.prefs.getBoolPref(GRID_OPENED_PREF), + `${GRID_OPENED_PREF} is pref on by default.` + ); + + info("Clicking the grid header to hide the grid panel."); + header.click(); + + info("Checking the new state of the grid panel."); + ok(content.hidden, "The grid panel content is hidden."); + ok( + !Services.prefs.getBoolPref(GRID_OPENED_PREF), + `${GRID_OPENED_PREF} is pref off.` + ); +} + +async function testAccordionStateAfterSwitchingSidebars(inspector, doc) { + info( + "Checking the grid accordion state is persistent after switching sidebars." + ); + + info("Selecting the computed view."); + inspector.sidebar.select("computedview"); + + info("Selecting the layout view."); + inspector.sidebar.select("layoutview"); + + const item = await waitFor(() => doc.querySelector(GRID_PANE_SELECTOR)); + const content = item.querySelector(ACCORDION_CONTENT_SELECTOR); + + info("Checking the state of the grid panel."); + ok(content.hidden, "The grid panel content is hidden."); + ok( + !Services.prefs.getBoolPref(GRID_OPENED_PREF), + `${GRID_OPENED_PREF} is pref off.` + ); +} + +async function testAccordionStateAfterReopeningLayoutView(toolbox) { + info( + "Checking the grid accordion state is persistent after closing and re-opening the " + + "layout view." + ); + + info("Closing the toolbox."); + await toolbox.destroy(); + + info("Re-opening the layout view."); + const { gridInspector } = await openLayoutView(); + const { document: doc } = gridInspector; + + const item = await waitFor(() => doc.querySelector(GRID_PANE_SELECTOR)); + const content = item.querySelector(ACCORDION_CONTENT_SELECTOR); + + info("Checking the state of the grid panel."); + ok(content.hidden, "The grid panel content is hidden."); + ok( + !Services.prefs.getBoolPref(GRID_OPENED_PREF), + `${GRID_OPENED_PREF} is pref off.` + ); +} diff --git a/devtools/client/inspector/grids/test/browser_grids_color-in-rules-grid-toggle.js b/devtools/client/inspector/grids/test/browser_grids_color-in-rules-grid-toggle.js new file mode 100644 index 0000000000..a12f4f2435 --- /dev/null +++ b/devtools/client/inspector/grids/test/browser_grids_color-in-rules-grid-toggle.js @@ -0,0 +1,93 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Test toggling the grid highlighter in the rule view with changes to the grid color +// from the layout view. + +const TEST_URI = ` + <style type='text/css'> + #grid { + display: grid; + } + </style> + <div id="grid"> + <div id="cell1">cell1</div> + <div id="cell2">cell2</div> + </div> +`; + +add_task(async function () { + await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI)); + const { inspector, gridInspector, layoutView } = await openLayoutView(); + const { document: doc } = gridInspector; + const { store } = inspector; + const cPicker = layoutView.swatchColorPickerTooltip; + const spectrum = cPicker.spectrum; + const swatch = doc.querySelector( + "#layout-grid-container .layout-color-swatch" + ); + + info("Scrolling into view of the #grid color swatch."); + swatch.scrollIntoView(); + + info("Opening the color picker by clicking on the #grid color swatch."); + const onColorPickerReady = cPicker.once("ready"); + swatch.click(); + await onColorPickerReady; + + await simulateColorPickerChange(cPicker, [0, 255, 0, 0.5]); + + is( + swatch.style.backgroundColor, + "rgba(0, 255, 0, 0.5)", + "The color swatch's background was updated." + ); + + info("Pressing RETURN to commit the color change."); + const onGridColorUpdate = waitUntilState( + store, + state => state.grids[0].color === "#00FF0080" + ); + const onColorPickerHidden = cPicker.tooltip.once("hidden"); + focusAndSendKey(spectrum.element.ownerDocument.defaultView, "RETURN"); + await onColorPickerHidden; + await onGridColorUpdate; + + is( + swatch.style.backgroundColor, + "rgba(0, 255, 0, 0.5)", + "The color swatch's background was kept after RETURN." + ); + + info("Selecting the rule view."); + const ruleView = selectRuleView(inspector); + const highlighters = ruleView.highlighters; + + await selectNode("#grid", inspector); + + const container = getRuleViewProperty(ruleView, "#grid", "display").valueSpan; + const gridToggle = container.querySelector(".js-toggle-grid-highlighter"); + + info("Toggling ON the CSS grid highlighter from the rule-view."); + const onHighlighterShown = highlighters.once( + "grid-highlighter-shown", + (nodeFront, options) => { + info("Checking the grid highlighter display settings."); + const { + color, + showGridAreasOverlay, + showGridLineNumbers, + showInfiniteLines, + } = options; + + is(color, "#00FF0080", "CSS grid highlighter color is correct."); + ok(!showGridAreasOverlay, "Show grid areas overlay option is off."); + ok(!showGridLineNumbers, "Show grid line numbers option is off."); + ok(!showInfiniteLines, "Show infinite lines option is off."); + } + ); + gridToggle.click(); + await onHighlighterShown; +}); diff --git a/devtools/client/inspector/grids/test/browser_grids_display-setting-extend-grid-lines.js b/devtools/client/inspector/grids/test/browser_grids_display-setting-extend-grid-lines.js new file mode 100644 index 0000000000..89f2bb36dd --- /dev/null +++ b/devtools/client/inspector/grids/test/browser_grids_display-setting-extend-grid-lines.js @@ -0,0 +1,59 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Tests that the 'Extend grid lines infinitely' grid highlighter setting will update +// the redux store and pref setting. + +const TEST_URI = ` + <style type='text/css'> + #grid { + display: grid; + } + </style> + <div id="grid"> + <div id="cell1">cell1</div> + <div id="cell2">cell2</div> + </div> +`; + +const SHOW_INFINITE_LINES_PREF = "devtools.gridinspector.showInfiniteLines"; + +add_task(async function () { + await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI)); + const { inspector, gridInspector } = await openLayoutView(); + const { document: doc } = gridInspector; + const { store } = inspector; + + await selectNode("#grid", inspector); + const checkbox = doc.getElementById("grid-setting-extend-grid-lines"); + + ok( + !Services.prefs.getBoolPref(SHOW_INFINITE_LINES_PREF), + "'Extend grid lines infinitely' is pref off by default." + ); + + info("Toggling ON the 'Extend grid lines infinitely' setting."); + let onCheckboxChange = waitUntilState( + store, + state => state.highlighterSettings.showInfiniteLines + ); + checkbox.click(); + await onCheckboxChange; + + info("Toggling OFF the 'Extend grid lines infinitely' setting."); + onCheckboxChange = waitUntilState( + store, + state => !state.highlighterSettings.showInfiniteLines + ); + checkbox.click(); + await onCheckboxChange; + + ok( + !Services.prefs.getBoolPref(SHOW_INFINITE_LINES_PREF), + "'Extend grid lines infinitely' is pref off." + ); + + Services.prefs.clearUserPref(SHOW_INFINITE_LINES_PREF); +}); diff --git a/devtools/client/inspector/grids/test/browser_grids_display-setting-show-grid-areas.js b/devtools/client/inspector/grids/test/browser_grids_display-setting-show-grid-areas.js new file mode 100644 index 0000000000..afc091b7ab --- /dev/null +++ b/devtools/client/inspector/grids/test/browser_grids_display-setting-show-grid-areas.js @@ -0,0 +1,59 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Tests that the 'Display grid areas' grid highlighter setting will update +// the redux store and pref setting. + +const TEST_URI = ` + <style type='text/css'> + #grid { + display: grid; + } + </style> + <div id="grid"> + <div id="cell1">cell1</div> + <div id="cell2">cell2</div> + </div> +`; + +const SHOW_GRID_AREAS_PREF = "devtools.gridinspector.showGridAreas"; + +add_task(async function () { + await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI)); + const { inspector, gridInspector } = await openLayoutView(); + const { document: doc } = gridInspector; + const { store } = inspector; + + await selectNode("#grid", inspector); + const checkbox = doc.getElementById("grid-setting-show-grid-areas"); + + ok( + !Services.prefs.getBoolPref(SHOW_GRID_AREAS_PREF), + "'Display grid areas' is pref off by default." + ); + + info("Toggling ON the 'Display grid areas' setting."); + let onCheckboxChange = waitUntilState( + store, + state => state.highlighterSettings.showGridAreasOverlay + ); + checkbox.click(); + await onCheckboxChange; + + info("Toggling OFF the 'Display grid areas' setting."); + onCheckboxChange = waitUntilState( + store, + state => !state.highlighterSettings.showGridAreasOverlay + ); + checkbox.click(); + await onCheckboxChange; + + ok( + !Services.prefs.getBoolPref(SHOW_GRID_AREAS_PREF), + "'Display grid areas' is pref off." + ); + + Services.prefs.clearUserPref(SHOW_GRID_AREAS_PREF); +}); diff --git a/devtools/client/inspector/grids/test/browser_grids_display-setting-show-grid-line-numbers.js b/devtools/client/inspector/grids/test/browser_grids_display-setting-show-grid-line-numbers.js new file mode 100644 index 0000000000..3dee2533cd --- /dev/null +++ b/devtools/client/inspector/grids/test/browser_grids_display-setting-show-grid-line-numbers.js @@ -0,0 +1,65 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Tests that the 'Display numbers on lines' grid highlighter setting will update +// the redux store and pref setting. + +const TEST_URI = ` + <style type='text/css'> + #grid { + display: grid; + } + </style> + <div id="grid"> + <div id="cell1">cell1</div> + <div id="cell2">cell2</div> + </div> +`; + +const SHOW_GRID_LINE_NUMBERS = "devtools.gridinspector.showGridLineNumbers"; + +add_task(async function () { + await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI)); + const { inspector, gridInspector } = await openLayoutView(); + const { document: doc } = gridInspector; + const { store } = inspector; + + await selectNode("#grid", inspector); + const checkbox = doc.getElementById("grid-setting-show-grid-line-numbers"); + + info("Checking the initial state of the CSS grid highlighter setting."); + ok( + !Services.prefs.getBoolPref(SHOW_GRID_LINE_NUMBERS), + "'Display numbers on lines' is pref off by default." + ); + + info("Toggling ON the 'Display numbers on lines' setting."); + let onCheckboxChange = waitUntilState( + store, + state => state.highlighterSettings.showGridLineNumbers + ); + checkbox.click(); + await onCheckboxChange; + + ok( + Services.prefs.getBoolPref(SHOW_GRID_LINE_NUMBERS), + "'Display numbers on lines' is pref on." + ); + + info("Toggling OFF the 'Display numbers on lines' setting."); + onCheckboxChange = waitUntilState( + store, + state => !state.highlighterSettings.showGridLineNumbers + ); + checkbox.click(); + await onCheckboxChange; + + ok( + !Services.prefs.getBoolPref(SHOW_GRID_LINE_NUMBERS), + "'Display numbers on lines' is pref off." + ); + + Services.prefs.clearUserPref(SHOW_GRID_LINE_NUMBERS); +}); diff --git a/devtools/client/inspector/grids/test/browser_grids_grid-list-color-picker-on-ESC.js b/devtools/client/inspector/grids/test/browser_grids_grid-list-color-picker-on-ESC.js new file mode 100644 index 0000000000..661c65c6e0 --- /dev/null +++ b/devtools/client/inspector/grids/test/browser_grids_grid-list-color-picker-on-ESC.js @@ -0,0 +1,75 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Tests that the grid item's color change in the colorpicker is reverted when ESCAPE is +// pressed. + +const TEST_URI = ` + <style type='text/css'> + #grid { + display: grid; + } + </style> + <div id="grid"> + <div id="cell1">cell1</div> + <div id="cell2">cell2</div> + </div> +`; + +add_task(async function () { + await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI)); + const { inspector, gridInspector, layoutView } = await openLayoutView(); + const { document: doc } = gridInspector; + const { store } = inspector; + const cPicker = layoutView.swatchColorPickerTooltip; + const spectrum = cPicker.spectrum; + const swatch = doc.querySelector( + "#layout-grid-container .layout-color-swatch" + ); + + info("Checking the initial state of the Grid Inspector."); + is( + swatch.style.backgroundColor, + "rgb(148, 0, 255)", + "The color swatch's background is correct." + ); + is( + store.getState().grids[0].color, + "#9400FF", + "The grid color state is correct." + ); + + info("Scrolling into view of the #grid color swatch."); + swatch.scrollIntoView(); + + info("Opening the color picker by clicking on the #grid color swatch."); + const onColorPickerReady = cPicker.once("ready"); + swatch.click(); + await onColorPickerReady; + + await simulateColorPickerChange(cPicker, [0, 255, 0, 0.5]); + + is( + swatch.style.backgroundColor, + "rgba(0, 255, 0, 0.5)", + "The color swatch's background was updated." + ); + + info("Pressing ESCAPE to close the tooltip."); + const onGridColorUpdate = waitUntilState( + store, + state => state.grids[0].color === "#9400FF" + ); + const onColorPickerHidden = cPicker.tooltip.once("hidden"); + focusAndSendKey(spectrum.element.ownerDocument.defaultView, "ESCAPE"); + await onColorPickerHidden; + await onGridColorUpdate; + + is( + swatch.style.backgroundColor, + "rgb(148, 0, 255)", + "The color swatch's background was reverted after ESCAPE." + ); +}); diff --git a/devtools/client/inspector/grids/test/browser_grids_grid-list-color-picker-on-RETURN.js b/devtools/client/inspector/grids/test/browser_grids_grid-list-color-picker-on-RETURN.js new file mode 100644 index 0000000000..599730fb4a --- /dev/null +++ b/devtools/client/inspector/grids/test/browser_grids_grid-list-color-picker-on-RETURN.js @@ -0,0 +1,75 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Tests that the grid item's color change in the colorpicker is committed when RETURN is +// pressed. + +const TEST_URI = ` + <style type='text/css'> + #grid { + display: grid; + } + </style> + <div id="grid"> + <div id="cell1">cell1</div> + <div id="cell2">cell2</div> + </div> +`; + +add_task(async function () { + await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI)); + const { inspector, gridInspector, layoutView } = await openLayoutView(); + const { document: doc } = gridInspector; + const { store } = inspector; + const cPicker = layoutView.swatchColorPickerTooltip; + const spectrum = cPicker.spectrum; + const swatch = doc.querySelector( + "#layout-grid-container .layout-color-swatch" + ); + + info("Checking the initial state of the Grid Inspector."); + is( + swatch.style.backgroundColor, + "rgb(148, 0, 255)", + "The color swatch's background is correct." + ); + is( + store.getState().grids[0].color, + "#9400FF", + "The grid color state is correct." + ); + + info("Scrolling into view of the #grid color swatch."); + swatch.scrollIntoView(); + + info("Opening the color picker by clicking on the #grid color swatch."); + const onColorPickerReady = cPicker.once("ready"); + swatch.click(); + await onColorPickerReady; + + await simulateColorPickerChange(cPicker, [0, 255, 0, 0.5]); + + is( + swatch.style.backgroundColor, + "rgba(0, 255, 0, 0.5)", + "The color swatch's background was updated." + ); + + info("Pressing RETURN to commit the color change."); + const onGridColorUpdate = waitUntilState( + store, + state => state.grids[0].color === "#00FF0080" + ); + const onColorPickerHidden = cPicker.tooltip.once("hidden"); + focusAndSendKey(spectrum.element.ownerDocument.defaultView, "RETURN"); + await onColorPickerHidden; + await onGridColorUpdate; + + is( + swatch.style.backgroundColor, + "rgba(0, 255, 0, 0.5)", + "The color swatch's background was kept after RETURN." + ); +}); diff --git a/devtools/client/inspector/grids/test/browser_grids_grid-list-element-rep.js b/devtools/client/inspector/grids/test/browser_grids_grid-list-element-rep.js new file mode 100644 index 0000000000..a1fba8d5e4 --- /dev/null +++ b/devtools/client/inspector/grids/test/browser_grids_grid-list-element-rep.js @@ -0,0 +1,68 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Tests that the grid item's element rep will display the box model higlighter on hover +// and select the node on click. + +const TEST_URI = ` + <style type='text/css'> + #grid { + display: grid; + } + </style> + <div id="grid"> + <div id="cell1">cell1</div> + <div id="cell2">cell2</div> + </div> +`; + +add_task(async function () { + await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI)); + const { inspector, gridInspector } = await openLayoutView(); + const { document: doc } = gridInspector; + const { store } = inspector; + const { waitForHighlighterTypeShown } = getHighlighterTestHelpers(inspector); + + const gridList = doc.querySelector("#grid-list"); + const elementRep = gridList.children[0].querySelector(".open-inspector"); + info("Scrolling into the view the #grid element node rep."); + elementRep.scrollIntoView(); + + info("Listen to node-highlight event and mouse over the widget"); + const onHighlight = waitForHighlighterTypeShown( + inspector.highlighters.TYPES.BOXMODEL + ); + EventUtils.synthesizeMouse( + elementRep, + 10, + 5, + { type: "mouseover" }, + doc.defaultView + ); + const { nodeFront } = await onHighlight; + + ok(nodeFront, "nodeFront was returned from highlighting the node."); + is(nodeFront.tagName, "DIV", "The highlighted node has the correct tagName."); + is( + nodeFront.attributes[0].name, + "id", + "The highlighted node has the correct attributes." + ); + is( + nodeFront.attributes[0].value, + "grid", + "The highlighted node has the correct id." + ); + + const onSelection = inspector.selection.once("new-node-front"); + EventUtils.sendMouseEvent({ type: "click" }, elementRep, doc.defaultView); + await onSelection; + + is( + inspector.selection.nodeFront, + store.getState().grids[0].nodeFront, + "The selected node is the one stored on the grid item's state." + ); +}); diff --git a/devtools/client/inspector/grids/test/browser_grids_grid-list-no-grids.js b/devtools/client/inspector/grids/test/browser_grids_grid-list-no-grids.js new file mode 100644 index 0000000000..ce9cbc7866 --- /dev/null +++ b/devtools/client/inspector/grids/test/browser_grids_grid-list-no-grids.js @@ -0,0 +1,37 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Tests that no grid list items and a "no grids available" message is displayed when +// there are no grid containers on the page. + +const TEST_URI = ` + <style type='text/css'> + </style> + <div id="grid"> + <div id="cell1">cell1</div> + <div id="cell2">cell2</div> + </div> +`; + +add_task(async function () { + await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI)); + const { inspector, gridInspector } = await openLayoutView(); + const { document: doc } = gridInspector; + const { highlighters } = inspector; + + await selectNode("#grid", inspector); + const noGridList = doc.querySelector( + "#layout-grid-section .devtools-sidepanel-no-result" + ); + const gridList = doc.getElementById("grid-list"); + + info("Checking the initial state of the Grid Inspector."); + ok(noGridList, "The message no grid containers is displayed."); + ok(!gridList, "No grid containers are listed."); + ok( + !highlighters.gridHighlighters.size, + "No CSS grid highlighter exists in the highlighters overlay." + ); +}); diff --git a/devtools/client/inspector/grids/test/browser_grids_grid-list-on-iframe-reloaded.js b/devtools/client/inspector/grids/test/browser_grids_grid-list-on-iframe-reloaded.js new file mode 100644 index 0000000000..b5871414f8 --- /dev/null +++ b/devtools/client/inspector/grids/test/browser_grids_grid-list-on-iframe-reloaded.js @@ -0,0 +1,57 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Tests that the list of grids does refresh when an iframe containing a grid is removed +// and re-created. +// See bug 1378306 where this happened with jsfiddle. + +const TEST_URI = URL_ROOT + "doc_iframe_reloaded.html"; + +add_task(async function () { + await addTab(TEST_URI); + const { gridInspector, inspector } = await openLayoutView(); + const { document: doc } = gridInspector; + const { highlighters, store } = inspector; + const gridList = doc.getElementById("grid-list"); + const checkbox = gridList.children[0].querySelector("input"); + + info("Clicking on the first checkbox to highlight the grid"); + const onHighlighterShown = highlighters.once("grid-highlighter-shown"); + const onCheckboxChange = waitUntilState( + store, + state => state.grids.length == 1 && state.grids[0].highlighted + ); + checkbox.click(); + await onHighlighterShown; + await onCheckboxChange; + + ok(checkbox.checked, "The checkbox is checked"); + is(gridList.childNodes.length, 1, "There's one grid in the list"); + is(highlighters.gridHighlighters.size, 1, "There's a highlighter shown"); + is( + highlighters.state.grids.size, + 1, + "There's a saved grid state to be restored." + ); + + info("Reload the iframe in content and expect the grid list to update"); + const oldGrid = store.getState().grids[0]; + const onNewListUnchecked = waitUntilState( + store, + state => + state.grids.length == 1 && + state.grids[0].actorID !== oldGrid.actorID && + !state.grids[0].highlighted + ); + const onHighlighterHidden = highlighters.once("grid-highlighter-hidden"); + SpecialPowers.spawn(gBrowser.selectedBrowser, [], () => + content.wrappedJSObject.reloadIFrame() + ); + await onNewListUnchecked; + await onHighlighterHidden; + + is(gridList.childNodes.length, 1, "There's still one grid in the list"); + ok(!highlighters.state.grids.size, "No grids to be restored on page reload."); +}); diff --git a/devtools/client/inspector/grids/test/browser_grids_grid-list-on-mutation-element-added.js b/devtools/client/inspector/grids/test/browser_grids_grid-list-on-mutation-element-added.js new file mode 100644 index 0000000000..e197f03b02 --- /dev/null +++ b/devtools/client/inspector/grids/test/browser_grids_grid-list-on-mutation-element-added.js @@ -0,0 +1,100 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Tests that the grid list updates when a new grid container is added to the page. + +const TEST_URI = ` + <style type='text/css'> + .grid { + display: grid; + } + </style> + <div id="grid1" class="grid"> + <div class="cell1">cell1</div> + <div class="cell2">cell2</div> + </div> + <div id="grid2"> + <div class="cell1">cell1</div> + <div class="cell2">cell2</div> + </div> +`; + +add_task(async function () { + await pushPref("devtools.gridinspector.maxHighlighters", 1); + await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI)); + const { inspector, gridInspector } = await openLayoutView(); + const { document: doc } = gridInspector; + const { highlighters, store } = inspector; + + await selectNode("#grid", inspector); + const gridList = doc.getElementById("grid-list"); + const checkbox1 = gridList.children[0].querySelector("input"); + + info("Checking the initial state of the Grid Inspector."); + is(gridList.childNodes.length, 1, "One grid container is listed."); + ok( + !highlighters.gridHighlighters.size, + "No CSS grid highlighter exists in the highlighters overlay." + ); + + info("Toggling ON the CSS grid highlighter from the layout panel."); + let onHighlighterShown = highlighters.once("grid-highlighter-shown"); + checkbox1.click(); + await onHighlighterShown; + + info("Checking the CSS grid highlighter is created."); + is(highlighters.gridHighlighters.size, 1, "CSS grid highlighter is shown."); + + info("Adding the #grid2 container in the content page."); + const onGridListUpdate = waitUntilState( + store, + state => + state.grids.length == 2 && + state.grids[0].highlighted && + !state.grids[1].highlighted + ); + SpecialPowers.spawn(gBrowser.selectedBrowser, [], () => + content.document.getElementById("grid2").classList.add("grid") + ); + await onGridListUpdate; + + info("Checking the new Grid Inspector state."); + is(gridList.childNodes.length, 2, "Two grid containers are listed."); + is(highlighters.gridHighlighters.size, 1, "CSS grid highlighter is shown."); + + const checkbox2 = gridList.children[1].querySelector("input"); + + info("Toggling ON the CSS grid highlighter for #grid2."); + onHighlighterShown = highlighters.once("grid-highlighter-shown"); + let onCheckboxChange = waitUntilState( + store, + state => + state.grids.length == 2 && + !state.grids[0].highlighted && + state.grids[1].highlighted + ); + checkbox2.click(); + await onHighlighterShown; + await onCheckboxChange; + + info("Checking the CSS grid highlighter is still shown."); + is(highlighters.gridHighlighters.size, 1, "CSS grid highlighter is shown."); + + info("Toggling OFF the CSS grid highlighter from the layout panel."); + const onHighlighterHidden = highlighters.once("grid-highlighter-hidden"); + onCheckboxChange = waitUntilState( + store, + state => + state.grids.length == 2 && + !state.grids[0].highlighted && + !state.grids[1].highlighted + ); + checkbox2.click(); + await onHighlighterHidden; + await onCheckboxChange; + + info("Checking the CSS grid highlighter is not shown."); + ok(!highlighters.gridHighlighters.size, "No CSS grid highlighter is shown."); +}); diff --git a/devtools/client/inspector/grids/test/browser_grids_grid-list-on-mutation-element-removed.js b/devtools/client/inspector/grids/test/browser_grids_grid-list-on-mutation-element-removed.js new file mode 100644 index 0000000000..7a60759071 --- /dev/null +++ b/devtools/client/inspector/grids/test/browser_grids_grid-list-on-mutation-element-removed.js @@ -0,0 +1,63 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Tests that the grid item is removed from the grid list when the grid container is +// removed from the page. + +const TEST_URI = ` + <style type='text/css'> + #grid { + display: grid; + } + </style> + <div id="grid"> + <div id="cell1">cell1</div> + <div id="cell2">cell2</div> + </div> +`; + +add_task(async function () { + await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI)); + const { inspector, gridInspector } = await openLayoutView(); + const { document: doc } = gridInspector; + const { highlighters, store } = inspector; + + await selectNode("#grid", inspector); + const gridList = doc.getElementById("grid-list"); + const checkbox = gridList.children[0].querySelector("input"); + + info("Checking the initial state of the Grid Inspector."); + is(gridList.childNodes.length, 1, "One grid container is listed."); + ok(!highlighters.gridHighlighters.size, "No CSS grid highlighter is shown."); + + info("Toggling ON the CSS grid highlighter from the layout panel."); + const onHighlighterShown = highlighters.once("grid-highlighter-shown"); + let onCheckboxChange = waitUntilState( + store, + state => state.grids.length == 1 && state.grids[0].highlighted + ); + checkbox.click(); + await onHighlighterShown; + await onCheckboxChange; + + info("Checking the CSS grid highlighter is created."); + is(highlighters.gridHighlighters.size, 1, "CSS grid highlighter is shown."); + + info("Removing the #grid container in the content page."); + const onHighlighterHidden = highlighters.once("grid-highlighter-hidden"); + onCheckboxChange = waitUntilState(store, state => !state.grids.length); + SpecialPowers.spawn(gBrowser.selectedBrowser, [], () => + content.document.getElementById("grid").remove() + ); + await onHighlighterHidden; + await onCheckboxChange; + + info("Checking the CSS grid highlighter is not shown."); + ok(!highlighters.gridHighlighters.size, "No CSS grid highlighter is shown."); + const noGridList = doc.querySelector( + "#layout-grid-section .devtools-sidepanel-no-result" + ); + ok(noGridList, "The message no grid containers is displayed."); +}); diff --git a/devtools/client/inspector/grids/test/browser_grids_grid-list-on-target-added-removed.js b/devtools/client/inspector/grids/test/browser_grids_grid-list-on-target-added-removed.js new file mode 100644 index 0000000000..051fc14e53 --- /dev/null +++ b/devtools/client/inspector/grids/test/browser_grids_grid-list-on-target-added-removed.js @@ -0,0 +1,203 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Tests that the list of grids does refresh when targets are added or removed (e.g. when +// there's a navigation and iframe are added or removed) + +add_task(async function () { + await addTab(getDocumentBuilderUrl("example.com", "top-level-com-grid")); + const { gridInspector } = await openLayoutView(); + const { document: doc } = gridInspector; + + const checkGridList = (expected, assertionMessage) => + checkGridListItems(doc, expected, assertionMessage); + + checkGridList( + ["div#top-level-com-grid"], + "One grid item is displayed at first" + ); + + info( + "Check that adding same-origin iframe with a grid will update the grid list" + ); + const sameOriginIframeBrowsingContext = await SpecialPowers.spawn( + gBrowser.selectedBrowser, + [getDocumentBuilderUrl("example.com", "iframe-com-grid")], + src => { + const iframe = content.document.createElement("iframe"); + iframe.id = "same-origin"; + iframe.src = src; + content.document.body.append(iframe); + return iframe.browsingContext; + } + ); + + await waitFor(() => getGridListItems(doc).length == 2); + checkGridList( + ["div#top-level-com-grid", "div#iframe-com-grid"], + "The same-origin iframe grid is displayed" + ); + + info("Check that adding remote iframe with a grid will update the grid list"); + const remoteIframeBrowsingContext = await SpecialPowers.spawn( + gBrowser.selectedBrowser, + [getDocumentBuilderUrl("example.org", "iframe-org-grid")], + src => { + const iframe = content.document.createElement("iframe"); + iframe.id = "remote"; + iframe.src = src; + content.document.body.append(iframe); + return iframe.browsingContext; + } + ); + + await waitFor(() => getGridListItems(doc).length == 3); + checkGridList( + ["div#top-level-com-grid", "div#iframe-com-grid", "div#iframe-org-grid"], + "The remote iframe grid is displayed" + ); + + info("Check that adding new grids in iframes does update the grid list"); + SpecialPowers.spawn(sameOriginIframeBrowsingContext, [], () => { + const section = content.document.createElement("section"); + section.id = "com-added-grid-container"; + section.style = "display: grid;"; + content.document.body.append(section); + }); + + await waitFor(() => getGridListItems(doc).length == 4); + checkGridList( + [ + "div#top-level-com-grid", + "div#iframe-com-grid", + "section#com-added-grid-container", + "div#iframe-org-grid", + ], + "The new grid in the same origin iframe is displayed" + ); + + SpecialPowers.spawn(remoteIframeBrowsingContext, [], () => { + const section = content.document.createElement("section"); + section.id = "org-added-grid-container"; + section.style = "display: grid;"; + content.document.body.append(section); + }); + + await waitFor(() => getGridListItems(doc).length == 5); + checkGridList( + [ + "div#top-level-com-grid", + "div#iframe-com-grid", + "section#com-added-grid-container", + "div#iframe-org-grid", + "section#org-added-grid-container", + ], + "The new grid in the same origin iframe is displayed" + ); + + info("Check that removing iframes will update the grid list"); + SpecialPowers.spawn(gBrowser.selectedBrowser, [], () => { + content.document.querySelector("iframe#same-origin").remove(); + }); + + await waitFor(() => getGridListItems(doc).length == 3); + checkGridList( + [ + "div#top-level-com-grid", + "div#iframe-org-grid", + "section#org-added-grid-container", + ], + "The same-origin iframe grids were removed from the list" + ); + + SpecialPowers.spawn(gBrowser.selectedBrowser, [], () => { + content.document.querySelector("iframe#remote").remove(); + }); + + await waitFor(() => getGridListItems(doc).length == 1); + checkGridList( + ["div#top-level-com-grid"], + "The remote iframe grids were removed as well" + ); + + info("Navigate to a new origin"); + await navigateTo(getDocumentBuilderUrl("example.org", "top-level-org-grid")); + await waitFor(() => { + const listItems = getGridListItems(doc); + return ( + listItems.length == 1 && + listItems[0].textContent.includes("#top-level-org-grid") + ); + }); + checkGridList( + ["div#top-level-org-grid"], + "The grid from the new origin document is displayed" + ); + + info("Check that adding remote iframe will still update the grid list"); + SpecialPowers.spawn( + gBrowser.selectedBrowser, + [getDocumentBuilderUrl("example.com", "iframe-com-grid-remote")], + src => { + const iframe = content.document.createElement("iframe"); + iframe.id = "remote"; + iframe.src = src; + content.document.body.append(iframe); + } + ); + + await waitFor(() => getGridListItems(doc).length == 2); + checkGridList( + ["div#top-level-org-grid", "div#iframe-com-grid-remote"], + "The grid from the new origin document is displayed" + ); + + info( + "Check that adding same-origin iframe with a grid will update the grid list" + ); + SpecialPowers.spawn( + gBrowser.selectedBrowser, + [getDocumentBuilderUrl("example.org", "iframe-org-grid-same-origin")], + src => { + const iframe = content.document.createElement("iframe"); + iframe.id = "same-origin"; + iframe.src = src; + content.document.body.append(iframe); + } + ); + await waitFor(() => getGridListItems(doc).length == 3); + checkGridList( + [ + "div#top-level-org-grid", + "div#iframe-com-grid-remote", + "div#iframe-org-grid-same-origin", + ], + "The grid from the new same-origin iframe is displayed" + ); +}); + +function getDocumentBuilderUrl(origin, gridContainerId) { + return `https://${origin}/document-builder.sjs?html=${encodeURIComponent( + `<style> + #${gridContainerId} { + display: grid; + } + </style> + <div id="${gridContainerId}"></div>` + )}`; +} + +function getGridListItems(doc) { + return Array.from(doc.querySelectorAll("#grid-list .objectBox-node")); +} + +function checkGridListItems(doc, expectedItems, assertionText) { + const gridItems = getGridListItems(doc).map(el => el.textContent); + is( + JSON.stringify(gridItems.sort()), + JSON.stringify(expectedItems.sort()), + assertionText + ); +} diff --git a/devtools/client/inspector/grids/test/browser_grids_grid-list-subgrids-z-order.js b/devtools/client/inspector/grids/test/browser_grids_grid-list-subgrids-z-order.js new file mode 100644 index 0000000000..da1b11f4c8 --- /dev/null +++ b/devtools/client/inspector/grids/test/browser_grids_grid-list-subgrids-z-order.js @@ -0,0 +1,83 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Test the z order of grids. + +const TEST_URI = URL_ROOT + "doc_subgrid.html"; + +add_task(async () => { + await addTab(TEST_URI); + const { gridInspector, inspector } = await openLayoutView(); + const { document: doc } = gridInspector; + const { highlighters, store } = inspector; + + await selectNode("#grid", inspector); + await waitUntilState(store, state => state.grids.length === 5); + + const parentEl = doc.getElementById("grid-list"); + // Input for .container + const parentInput = parentEl.children[0].querySelector("input"); + const subgridEl = parentEl.children[1]; + // Input for <main> + const subgridInput = subgridEl.children[1].querySelector("input"); + const grandSubgridEl = subgridEl.children[2]; + // Input for .aside1 + const grandSubgridInput = grandSubgridEl.children[0].querySelector("input"); + + info( + "Toggling ON the CSS grid highlighters for .container, <main> and .aside1" + ); + const grandSubgridFront = await toggle(grandSubgridInput, highlighters); + const subgridFront = await toggle(subgridInput, highlighters); + let parentFront = await toggle(parentInput, highlighters); + await waitUntilState( + store, + state => state.grids.filter(g => g.highlighted).length === 3 + ); + + info("Check z-index of grid highlighting"); + is(getZIndex(store, parentFront), 0, "z-index of parent grid is 0"); + is(getZIndex(store, subgridFront), 1, "z-index of subgrid is 1"); + is(getZIndex(store, grandSubgridFront), 2, "z-index of subgrid is 2"); + + info("Toggling OFF the CSS grid highlighters for .container"); + await toggle(parentInput, highlighters); + await waitUntilState( + store, + state => state.grids.filter(g => g.highlighted).length === 2 + ); + + info("Check z-index keeps even if the parent grid is hidden"); + is(getZIndex(store, subgridFront), 1, "z-index of subgrid is 1"); + is(getZIndex(store, grandSubgridFront), 2, "z-index of subgrid is 2"); + + info("Toggling ON again the CSS grid highlighters for .container"); + parentFront = await toggle(parentInput, highlighters); + await waitUntilState( + store, + state => state.grids.filter(g => g.highlighted).length === 3 + ); + + info("Check z-index of all of grids highlighting keeps"); + is(getZIndex(store, parentFront), 0, "z-index of parent grid is 0"); + is(getZIndex(store, subgridFront), 1, "z-index of subgrid is 1"); + is(getZIndex(store, grandSubgridFront), 2, "z-index of subgrid is 2"); +}); + +function getZIndex(store, nodeFront) { + const grids = store.getState().grids; + const gridData = grids.find(g => g.nodeFront === nodeFront); + return gridData.zIndex; +} + +async function toggle(input, highlighters) { + const eventName = input.checked + ? "grid-highlighter-hidden" + : "grid-highlighter-shown"; + const onHighlighterEvent = highlighters.once(eventName); + input.click(); + const nodeFront = await onHighlighterEvent; + return nodeFront; +} diff --git a/devtools/client/inspector/grids/test/browser_grids_grid-list-subgrids_01.js b/devtools/client/inspector/grids/test/browser_grids_grid-list-subgrids_01.js new file mode 100644 index 0000000000..bcb0faeef8 --- /dev/null +++ b/devtools/client/inspector/grids/test/browser_grids_grid-list-subgrids_01.js @@ -0,0 +1,138 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Tests that the list of grids show the subgrids in the correct nested list and toggling +// the CSS grid highlighter for a subgrid. + +const TEST_URI = URL_ROOT + "doc_subgrid.html"; + +add_task(async function () { + await addTab(TEST_URI); + const { gridInspector, inspector } = await openLayoutView(); + const { document: doc } = gridInspector; + const { highlighters, store } = inspector; + + await selectNode(".container", inspector); + const gridListEl = doc.getElementById("grid-list"); + const containerSubgridListEl = gridListEl.children[1]; + const mainSubgridListEl = containerSubgridListEl.querySelector("ul"); + + info("Checking the initial state of the Grid Inspector."); + is( + getGridItemElements(gridListEl).length, + 1, + "One grid container is listed." + ); + is( + getGridItemElements(containerSubgridListEl).length, + 2, + "Got the correct number of subgrids in div.container" + ); + is( + getGridItemElements(mainSubgridListEl).length, + 2, + "Got the correct number of subgrids in main.subgrid" + ); + ok( + !highlighters.gridHighlighters.size && + !highlighters.parentGridHighlighters.size, + "No CSS grid highlighter is shown." + ); + + info("Toggling ON the CSS grid highlighter for header."); + let onHighlighterShown = highlighters.once("grid-highlighter-shown"); + let onCheckboxChange = waitUntilState( + store, + state => state.grids[1].highlighted + ); + let checkbox = containerSubgridListEl.children[0].querySelector("input"); + checkbox.click(); + await onHighlighterShown; + await onCheckboxChange; + + info( + "Checking the CSS grid highlighter and parent grid highlighter are created." + ); + is(highlighters.gridHighlighters.size, 1, "CSS grid highlighter is shown."); + is( + highlighters.parentGridHighlighters.size, + 1, + "CSS grid highlighter for parent grid container is shown." + ); + + info("Toggling ON the CSS grid highlighter for main."); + onHighlighterShown = highlighters.once("grid-highlighter-shown"); + onCheckboxChange = waitUntilState( + store, + state => state.grids[1].highlighted && state.grids[2].highlighted + ); + checkbox = containerSubgridListEl.children[1].querySelector("input"); + checkbox.click(); + await onHighlighterShown; + await onCheckboxChange; + + info("Checking the number of CSS grid highlighters present."); + is( + highlighters.gridHighlighters.size, + 2, + "Got the correct number of CSS grid highlighter shown." + ); + is( + highlighters.parentGridHighlighters.size, + 1, + "Only 1 parent grid highlighter should be shown for the same subgrid parent." + ); + + info("Toggling OFF the CSS grid highlighter for main."); + let onHighlighterHidden = highlighters.once("grid-highlighter-hidden"); + onCheckboxChange = waitUntilState( + store, + state => state.grids[1].highlighted && !state.grids[2].highlighted + ); + checkbox.click(); + await onHighlighterHidden; + await onCheckboxChange; + + info("Checking the number of CSS grid highlighters present."); + is( + highlighters.gridHighlighters.size, + 1, + "Got the correct number of CSS grid highlighter shown." + ); + is( + highlighters.parentGridHighlighters.size, + 1, + "Got the correct number of CSS grid parent highlighter shown." + ); + + info("Toggling OFF the CSS grid highlighter for header."); + onHighlighterHidden = highlighters.once("grid-highlighter-hidden"); + onCheckboxChange = waitUntilState( + store, + state => !state.grids[1].highlighted + ); + checkbox = containerSubgridListEl.children[0].querySelector("input"); + checkbox.click(); + await onHighlighterHidden; + await onCheckboxChange; + + info("Checking the CSS grid highlighter is not shown."); + ok( + !highlighters.gridHighlighters.size && + !highlighters.parentGridHighlighters.size, + "No CSS grid highlighter is shown." + ); +}); + +/** + * Returns the grid item elements <li> from the grid list element <ul>. + * + * @param {Element} gridListEl + * The grid list element <ul>. + * @return {Array<Element>} containing the grid item elements <li>. + */ +function getGridItemElements(gridListEl) { + return [...gridListEl.children].filter(node => node.nodeName === "li"); +} diff --git a/devtools/client/inspector/grids/test/browser_grids_grid-list-subgrids_02.js b/devtools/client/inspector/grids/test/browser_grids_grid-list-subgrids_02.js new file mode 100644 index 0000000000..83f07e339a --- /dev/null +++ b/devtools/client/inspector/grids/test/browser_grids_grid-list-subgrids_02.js @@ -0,0 +1,72 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Test the state of grid highlighters after toggling the checkbox of subgrids. + +const TEST_URI = URL_ROOT + "doc_subgrid.html"; + +add_task(async () => { + await addTab(TEST_URI); + const { gridInspector, inspector } = await openLayoutView(); + const { document: doc } = gridInspector; + const { highlighters, store } = inspector; + + await selectNode(".container", inspector); + const parentEl = doc.getElementById("grid-list"); + // Input for .container + const parentInput = parentEl.children[0].querySelector("input"); + const subgridEl = parentEl.children[1]; + // Input for <main> + const subgridInput = subgridEl.children[1].querySelector("input"); + const grandSubgridEl = subgridEl.children[2]; + // Input for .aside1 + const grandSubgridInput = grandSubgridEl.children[0].querySelector("input"); + + info( + "Toggling ON the CSS grid highlighters for .container, <main> and .aside1" + ); + await toggleHighlighter(parentInput, highlighters); + await toggleHighlighter(subgridInput, highlighters); + await toggleHighlighter(grandSubgridInput, highlighters); + await waitUntilState( + store, + state => state.grids.filter(g => g.highlighted).length === 3 + ); + + info("Check the state of highlighters"); + is( + highlighters.gridHighlighters.size, + 3, + "All highlighters are use as normal highlighter" + ); + + info("Toggling OFF the CSS grid highlighter for <main>"); + await toggleHighlighter(subgridInput, highlighters); + await waitUntilState( + store, + state => state.grids.filter(g => g.highlighted).length === 2 + ); + + info("Check the state of highlighters after hiding subgrid for <main>"); + is( + highlighters.gridHighlighters.size, + 2, + "2 highlighters are use as normal highlighter" + ); + is( + highlighters.parentGridHighlighters.size, + 1, + "The highlighter for <main> is used as parent highlighter" + ); +}); + +async function toggleHighlighter(input, highlighters) { + const eventName = input.checked + ? "grid-highlighter-hidden" + : "grid-highlighter-shown"; + const onHighlighterEvent = highlighters.once(eventName); + input.click(); + await onHighlighterEvent; +} diff --git a/devtools/client/inspector/grids/test/browser_grids_grid-list-toggle-grids_01.js b/devtools/client/inspector/grids/test/browser_grids_grid-list-toggle-grids_01.js new file mode 100644 index 0000000000..f66e70042c --- /dev/null +++ b/devtools/client/inspector/grids/test/browser_grids_grid-list-toggle-grids_01.js @@ -0,0 +1,63 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Tests toggling ON/OFF the grid highlighter from the grid ispector panel. + +const TEST_URI = ` + <style type='text/css'> + #grid { + display: grid; + } + </style> + <div id="grid"> + <div id="cell1">cell1</div> + <div id="cell2">cell2</div> + </div> +`; + +add_task(async function () { + await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI)); + const { gridInspector, inspector } = await openLayoutView(); + const { document: doc } = gridInspector; + const { highlighters, store } = inspector; + + await selectNode("#grid", inspector); + const gridList = doc.getElementById("grid-list"); + const checkbox = gridList.children[0].querySelector("input"); + + info("Checking the initial state of the Grid Inspector."); + is(gridList.childNodes.length, 1, "One grid container is listed."); + ok( + !checkbox.checked, + `Grid item ${checkbox.value} is unchecked in the grid list.` + ); + ok(!highlighters.gridHighlighters.size, "No CSS grid highlighter is shown."); + + info("Toggling ON the CSS grid highlighter from the layout panel."); + const onHighlighterShown = highlighters.once("grid-highlighter-shown"); + let onCheckboxChange = waitUntilState( + store, + state => state.grids.length == 1 && state.grids[0].highlighted + ); + checkbox.click(); + await onHighlighterShown; + await onCheckboxChange; + + info("Checking the CSS grid highlighter is created."); + is(highlighters.gridHighlighters.size, 1, "CSS grid highlighter is shown."); + + info("Toggling OFF the CSS grid highlighter from the layout panel."); + const onHighlighterHidden = highlighters.once("grid-highlighter-hidden"); + onCheckboxChange = waitUntilState( + store, + state => state.grids.length == 1 && !state.grids[0].highlighted + ); + checkbox.click(); + await onHighlighterHidden; + await onCheckboxChange; + + info("Checking the CSS grid highlighter is not shown."); + ok(!highlighters.gridHighlighters.size, "No CSS grid highlighter is shown."); +}); diff --git a/devtools/client/inspector/grids/test/browser_grids_grid-list-toggle-grids_02.js b/devtools/client/inspector/grids/test/browser_grids_grid-list-toggle-grids_02.js new file mode 100644 index 0000000000..82f3d9bef4 --- /dev/null +++ b/devtools/client/inspector/grids/test/browser_grids_grid-list-toggle-grids_02.js @@ -0,0 +1,96 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Test toggling the grid highlighter in the grid inspector panel with multiple grids in +// the page. + +const TEST_URI = ` + <style type='text/css'> + .grid { + display: grid; + } + </style> + <div id="grid1" class="grid"> + <div class="cell1">cell1</div> + <div class="cell2">cell2</div> + </div> + <div id="grid2" class="grid"> + <div class="cell1">cell1</div> + <div class="cell2">cell2</div> + </div> +`; + +add_task(async function () { + await pushPref("devtools.gridinspector.maxHighlighters", 1); + await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI)); + const { inspector, gridInspector } = await openLayoutView(); + const { document: doc } = gridInspector; + const { highlighters, store } = inspector; + + await selectNode("#grid1", inspector); + const gridList = doc.getElementById("grid-list"); + const checkbox1 = gridList.children[0].querySelector("input"); + const checkbox2 = gridList.children[1].querySelector("input"); + + info("Checking the initial state of the Grid Inspector."); + is(gridList.childNodes.length, 2, "2 grid containers are listed."); + ok( + !checkbox1.checked, + `Grid item ${checkbox1.value} is unchecked in the grid list.` + ); + ok( + !checkbox2.checked, + `Grid item ${checkbox2.value} is unchecked in the grid list.` + ); + ok(!highlighters.gridHighlighters.size, "No CSS grid highlighter is shown."); + + info("Toggling ON the CSS grid highlighter for #grid1."); + let onHighlighterShown = highlighters.once("grid-highlighter-shown"); + let onCheckboxChange = waitUntilState( + store, + state => + state.grids.length == 2 && + state.grids[0].highlighted && + !state.grids[1].highlighted + ); + checkbox1.click(); + await onHighlighterShown; + await onCheckboxChange; + + info("Checking the CSS grid highlighter is created."); + is(highlighters.gridHighlighters.size, 1, "CSS grid highlighter is shown."); + + info("Toggling ON the CSS grid highlighter for #grid2."); + onHighlighterShown = highlighters.once("grid-highlighter-shown"); + onCheckboxChange = waitUntilState( + store, + state => + state.grids.length == 2 && + !state.grids[0].highlighted && + state.grids[1].highlighted + ); + checkbox2.click(); + await onHighlighterShown; + await onCheckboxChange; + + info("Checking the CSS grid highlighter is still shown."); + is(highlighters.gridHighlighters.size, 1, "CSS grid highlighter is shown."); + + info("Toggling OFF the CSS grid highlighter from the layout panel."); + const onHighlighterHidden = highlighters.once("grid-highlighter-hidden"); + onCheckboxChange = waitUntilState( + store, + state => + state.grids.length == 2 && + !state.grids[0].highlighted && + !state.grids[1].highlighted + ); + checkbox2.click(); + await onHighlighterHidden; + await onCheckboxChange; + + info("Checking the CSS grid highlighter is not shown."); + ok(!highlighters.gridHighlighters.size, "No CSS grid highlighter is shown."); +}); diff --git a/devtools/client/inspector/grids/test/browser_grids_grid-list-toggle-multiple-grids.js b/devtools/client/inspector/grids/test/browser_grids_grid-list-toggle-multiple-grids.js new file mode 100644 index 0000000000..857ff75912 --- /dev/null +++ b/devtools/client/inspector/grids/test/browser_grids_grid-list-toggle-multiple-grids.js @@ -0,0 +1,243 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Test toggling multiple grid highlighters in the grid inspector panel. + +const TEST_URI = ` + <style type='text/css'> + .grid { + display: grid; + } + </style> + <div id="grid1" class="grid"> + <div class="cell1">cell1</div> + <div class="cell2">cell2</div> + </div> + <div id="grid2" class="grid"> + <div class="cell1">cell1</div> + <div class="cell2">cell2</div> + </div> + <div id="grid3" class="grid"> + <div class="cell1">cell1</div> + <div class="cell2">cell2</div> + </div> + <div id="grid4" class="grid"> + <div class="cell1">cell1</div> + <div class="cell2">cell2</div> + </div> +`; + +add_task(async function () { + await pushPref("devtools.gridinspector.maxHighlighters", 3); + await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI)); + const { inspector, gridInspector } = await openLayoutView(); + const { document: doc } = gridInspector; + const { highlighters, store } = inspector; + + await selectNode("#grid1", inspector); + const gridList = doc.getElementById("grid-list"); + const checkbox1 = gridList.children[0].querySelector("input"); + const checkbox2 = gridList.children[1].querySelector("input"); + const checkbox3 = gridList.children[2].querySelector("input"); + const checkbox4 = gridList.children[3].querySelector("input"); + + info("Checking the initial state of the Grid Inspector."); + is(gridList.childNodes.length, 4, "4 grid containers are listed."); + ok( + !checkbox1.checked, + `Grid item ${checkbox1.value} is unchecked in the grid list.` + ); + ok( + !checkbox2.checked, + `Grid item ${checkbox2.value} is unchecked in the grid list.` + ); + ok( + !checkbox3.checked, + `Grid item ${checkbox3.value} is unchecked in the grid list.` + ); + ok( + !checkbox4.checked, + `Grid item ${checkbox4.value} is unchecked in the grid list.` + ); + ok(!highlighters.gridHighlighters.size, "No CSS grid highlighter is shown."); + + info("Toggling ON the CSS grid highlighter for #grid1."); + let onHighlighterShown = highlighters.once("grid-highlighter-shown"); + let onCheckboxChange = waitUntilState( + store, + state => + state.grids.length == 4 && + state.grids[0].highlighted && + !state.grids[0].disabled && + !state.grids[1].highlighted && + !state.grids[1].disabled && + !state.grids[2].highlighted && + !state.grids[2].disabled && + !state.grids[3].highlighted && + !state.grids[3].disabled + ); + checkbox1.click(); + await onHighlighterShown; + await onCheckboxChange; + + info( + "Check that the CSS grid highlighter is created and the saved grid state." + ); + is( + highlighters.gridHighlighters.size, + 1, + "Got expected number of grid highlighters shown." + ); + is( + highlighters.state.grids.size, + 1, + "Got expected number of grids in the saved state" + ); + + info("Toggling ON the CSS grid highlighter for #grid2."); + onHighlighterShown = highlighters.once("grid-highlighter-shown"); + onCheckboxChange = waitUntilState( + store, + state => + state.grids.length == 4 && + state.grids[0].highlighted && + !state.grids[0].disabled && + state.grids[1].highlighted && + !state.grids[1].disabled && + !state.grids[2].highlighted && + !state.grids[2].disabled && + !state.grids[3].highlighted && + !state.grids[3].disabled + ); + checkbox2.click(); + await onHighlighterShown; + await onCheckboxChange; + + is( + highlighters.gridHighlighters.size, + 2, + "Got expected number of grid highlighters shown." + ); + is( + highlighters.state.grids.size, + 2, + "Got expected number of grids in the saved state" + ); + + info("Toggling ON the CSS grid highlighter for #grid3."); + onHighlighterShown = highlighters.once("grid-highlighter-shown"); + onCheckboxChange = waitUntilState( + store, + state => + state.grids.length == 4 && + state.grids[0].highlighted && + !state.grids[0].disabled && + state.grids[1].highlighted && + !state.grids[1].disabled && + state.grids[2].highlighted && + !state.grids[2].disabled && + !state.grids[3].highlighted && + state.grids[3].disabled + ); + checkbox3.click(); + await onHighlighterShown; + await onCheckboxChange; + + is( + highlighters.gridHighlighters.size, + 3, + "Got expected number of grid highlighters shown." + ); + is( + highlighters.state.grids.size, + 3, + "Got expected number of grids in the saved state" + ); + + info("Toggling OFF the CSS grid highlighter for #grid3."); + let onHighlighterHidden = highlighters.once("grid-highlighter-hidden"); + onCheckboxChange = waitUntilState( + store, + state => + state.grids.length == 4 && + state.grids[0].highlighted && + !state.grids[0].disabled && + state.grids[1].highlighted && + !state.grids[1].disabled && + !state.grids[2].highlighted && + !state.grids[2].disabled && + !state.grids[3].highlighted && + !state.grids[3].disabled + ); + checkbox3.click(); + await onHighlighterHidden; + await onCheckboxChange; + + is( + highlighters.gridHighlighters.size, + 2, + "Got expected number of grid highlighters shown." + ); + is( + highlighters.state.grids.size, + 2, + "Got expected number of grids in the saved state" + ); + + info("Toggling OFF the CSS grid highlighter for #grid2."); + onHighlighterHidden = highlighters.once("grid-highlighter-hidden"); + onCheckboxChange = waitUntilState( + store, + state => + state.grids.length == 4 && + state.grids[0].highlighted && + !state.grids[0].disabled && + !state.grids[1].highlighted && + !state.grids[1].disabled && + !state.grids[2].highlighted && + !state.grids[2].disabled && + !state.grids[3].highlighted && + !state.grids[3].disabled + ); + checkbox2.click(); + await onHighlighterHidden; + await onCheckboxChange; + + is( + highlighters.gridHighlighters.size, + 1, + "Got expected number of grid highlighters shown." + ); + is( + highlighters.state.grids.size, + 1, + "Got expected number of grids in the saved state" + ); + + info("Toggling OFF the CSS grid highlighter for #grid1."); + onHighlighterHidden = highlighters.once("grid-highlighter-hidden"); + onCheckboxChange = waitUntilState( + store, + state => + state.grids.length == 4 && + !state.grids[0].highlighted && + !state.grids[0].disabled && + !state.grids[1].highlighted && + !state.grids[1].disabled && + !state.grids[2].highlighted && + !state.grids[2].disabled && + !state.grids[3].highlighted && + !state.grids[3].disabled + ); + checkbox1.click(); + await onHighlighterHidden; + await onCheckboxChange; + + info( + "Check that the CSS grid highlighter is not shown and the saved grid state." + ); + ok(!highlighters.gridHighlighters.size, "No CSS grid highlighter is shown."); + ok(!highlighters.state.grids.size, "No grids in the saved state"); +}); diff --git a/devtools/client/inspector/grids/test/browser_grids_grid-outline-cannot-show-outline.js b/devtools/client/inspector/grids/test/browser_grids_grid-outline-cannot-show-outline.js new file mode 100644 index 0000000000..a2f293c44d --- /dev/null +++ b/devtools/client/inspector/grids/test/browser_grids_grid-outline-cannot-show-outline.js @@ -0,0 +1,57 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Tests that grid outline does not show when cells are too small to be drawn and that +// "Cannot show outline for this grid." message is displayed. + +const TEST_URI = ` + <style type='text/css'> + #grid { + display: grid; + grid-template-columns: repeat(51, 20px); + grid-template-rows: repeat(51, 20px); + } + </style> + <div id="grid"> + <div id="cellA">cell A</div> + <div id="cellB">cell B</div> + </div> +`; + +add_task(async function () { + await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI)); + + const { inspector, gridInspector } = await openLayoutView(); + const { document: doc } = gridInspector; + const { highlighters, store } = inspector; + + await selectNode("#grid", inspector); + const outline = doc.getElementById("grid-outline-container"); + const gridList = doc.getElementById("grid-list"); + const checkbox = gridList.children[0].querySelector("input"); + + info("Toggling ON the CSS grid highlighter from the layout panel."); + const onHighlighterShown = highlighters.once("grid-highlighter-shown"); + const onGridOutlineRendered = waitForDOM(doc, ".grid-outline-text", 1); + const onCheckboxChange = waitUntilState( + store, + state => state.grids.length == 1 && state.grids[0].highlighted + ); + checkbox.click(); + await onHighlighterShown; + await onCheckboxChange; + const elements = await onGridOutlineRendered; + + const cannotShowGridOutline = elements[0]; + + info( + "Checking the grid outline is not rendered and an appropriate message is shown." + ); + ok(!outline, "Outline component is not shown."); + ok( + cannotShowGridOutline, + "The message 'Cannot show outline for this grid' is displayed." + ); +}); diff --git a/devtools/client/inspector/grids/test/browser_grids_grid-outline-highlight-area.js b/devtools/client/inspector/grids/test/browser_grids_grid-outline-highlight-area.js new file mode 100644 index 0000000000..7a93e561cc --- /dev/null +++ b/devtools/client/inspector/grids/test/browser_grids_grid-outline-highlight-area.js @@ -0,0 +1,77 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Tests that the grid area and cell are highlighted when hovering over a grid area in the +// grid outline. + +const TEST_URI = ` + <style type='text/css'> + #grid { + display: grid; + grid-template-areas: + "header" + "footer"; + } + .top { + grid-area: header; + } + .bottom { + grid-area: footer; + } + </style> + <div id="grid"> + <div id="cella" className="top">Cell A</div> + <div id="cellb" className="bottom">Cell B</div> + </div> +`; + +add_task(async function () { + await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI)); + + const { inspector, gridInspector } = await openLayoutView(); + const { document: doc } = gridInspector; + const { store } = inspector; + const HIGHLIGHTER_TYPE = inspector.highlighters.TYPES.GRID; + const { waitForHighlighterTypeShown } = getHighlighterTestHelpers(inspector); + + const gridList = doc.getElementById("grid-list"); + const checkbox = gridList.children[0].querySelector("input"); + + info("Toggling ON the CSS grid highlighter from the layout panel."); + const onHighlighterShown = waitForHighlighterTypeShown(HIGHLIGHTER_TYPE); + const onGridOutlineRendered = waitForDOM(doc, "#grid-cell-group rect", 2); + const onCheckboxChange = waitUntilState( + store, + state => state.grids.length == 1 && state.grids[0].highlighted + ); + checkbox.click(); + + info("Wait for checkbox to change"); + await onCheckboxChange; + + info("Wait for highlighter to be shown"); + await onHighlighterShown; + + info("Wait for outline to be rendered"); + await onGridOutlineRendered; + + info("Hovering over grid cell A in the grid outline."); + const onCellAHighlight = waitForHighlighterTypeShown(HIGHLIGHTER_TYPE); + + synthesizeMouseOverOnGridCell(doc, 0); + + const { options } = await onCellAHighlight; + + info( + "Checking the grid highlighter options for the show grid area and cell parameters." + ); + const { showGridCell, showGridArea } = options; + const { gridFragmentIndex, rowNumber, columnNumber } = showGridCell; + + is(gridFragmentIndex, "0", "Should be the first grid fragment index."); + is(rowNumber, "1", "Should be the first grid row."); + is(columnNumber, "1", "Should be the first grid column."); + is(showGridArea, "header", "Grid area name should be 'header'."); +}); diff --git a/devtools/client/inspector/grids/test/browser_grids_grid-outline-highlight-cell.js b/devtools/client/inspector/grids/test/browser_grids_grid-outline-highlight-cell.js new file mode 100644 index 0000000000..0f5f329f9b --- /dev/null +++ b/devtools/client/inspector/grids/test/browser_grids_grid-outline-highlight-cell.js @@ -0,0 +1,65 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Tests that the grid cell is highlighted when hovering over the grid outline of a +// grid cell. + +const TEST_URI = ` + <style type='text/css'> + #grid { + display: grid; + } + </style> + <div id="grid"> + <div id="cella">Cell A</div> + <div id="cellb">Cell B</div> + </div> +`; + +add_task(async function () { + await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI)); + + const { inspector, gridInspector } = await openLayoutView(); + const { document: doc } = gridInspector; + const { store } = inspector; + const HIGHLIGHTER_TYPE = inspector.highlighters.TYPES.GRID; + const { waitForHighlighterTypeShown } = getHighlighterTestHelpers(inspector); + + const gridList = doc.getElementById("grid-list"); + const checkbox = gridList.children[0].querySelector("input"); + + info("Toggling ON the CSS grid highlighter from the layout panel."); + const onHighlighterShown = waitForHighlighterTypeShown(HIGHLIGHTER_TYPE); + const onGridOutlineRendered = waitForDOM(doc, "#grid-cell-group rect", 2); + const onCheckboxChange = waitUntilState( + store, + state => state.grids.length == 1 && state.grids[0].highlighted + ); + checkbox.click(); + + info("Wait for checkbox to change"); + await onCheckboxChange; + + info("Wait for highlighter to be shown"); + await onHighlighterShown; + + info("Wait for outline to be rendered"); + await onGridOutlineRendered; + + info("Hovering over grid cell A in the grid outline."); + const onCellAHighlight = waitForHighlighterTypeShown(HIGHLIGHTER_TYPE); + + synthesizeMouseOverOnGridCell(doc, 0); + + const { options } = await onCellAHighlight; + + info("Checking show grid cell options are correct."); + const { showGridCell } = options; + const { gridFragmentIndex, rowNumber, columnNumber } = showGridCell; + + is(gridFragmentIndex, "0", "Should be the first grid fragment index."); + is(rowNumber, "1", "Should be the first grid row."); + is(columnNumber, "1", "Should be the first grid column."); +}); diff --git a/devtools/client/inspector/grids/test/browser_grids_grid-outline-multiple-grids.js b/devtools/client/inspector/grids/test/browser_grids_grid-outline-multiple-grids.js new file mode 100644 index 0000000000..a65cfd7528 --- /dev/null +++ b/devtools/client/inspector/grids/test/browser_grids_grid-outline-multiple-grids.js @@ -0,0 +1,76 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Tests that the grid outline is not shown when more than one grid is highlighted. + +const TEST_URI = ` + <style type='text/css'> + .grid { + display: grid; + } + </style> + <div id="grid1" class="grid"> + <div class="cell1">cell1</div> + <div class="cell2">cell2</div> + </div> + <div id="grid2" class="grid"> + <div class="cell1">cell1</div> + <div class="cell2">cell2</div> + </div> +`; + +add_task(async function () { + await pushPref("devtools.gridinspector.maxHighlighters", 2); + await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI)); + const { inspector, gridInspector } = await openLayoutView(); + const { document: doc } = gridInspector; + const { highlighters, store } = inspector; + + await selectNode("#grid1", inspector); + const gridList = doc.getElementById("grid-list"); + const checkbox1 = gridList.children[0].querySelector("input"); + const checkbox2 = gridList.children[1].querySelector("input"); + + info("Toggling ON the CSS grid highlighter for #grid1."); + let onHighlighterShown = highlighters.once("grid-highlighter-shown"); + const onGridOutlineRendered = waitForDOM(doc, "#grid-cell-group rect", 2); + let onCheckboxChange = waitUntilState( + store, + state => + state.grids.length === 2 && + state.grids[0].highlighted && + !state.grids[1].highlighted + ); + checkbox1.click(); + await onHighlighterShown; + await onCheckboxChange; + const elements = await onGridOutlineRendered; + + info("Checking the grid outline for #grid1 is shown."); + ok( + doc.getElementById("grid-outline-container"), + "Grid outline container is rendered." + ); + is(elements.length, 2, "Grid outline is shown."); + + info("Toggling ON the CSS grid highlighter for #grid2."); + onHighlighterShown = highlighters.once("grid-highlighter-shown"); + onCheckboxChange = waitUntilState( + store, + state => + state.grids.length === 2 && + state.grids[0].highlighted && + state.grids[1].highlighted + ); + checkbox2.click(); + await onHighlighterShown; + await onCheckboxChange; + + info("Checking the grid outline is not shown."); + ok( + !doc.getElementById("grid-outline-container"), + "Grid outline is not rendered." + ); +}); diff --git a/devtools/client/inspector/grids/test/browser_grids_grid-outline-selected-grid.js b/devtools/client/inspector/grids/test/browser_grids_grid-outline-selected-grid.js new file mode 100644 index 0000000000..ada2a635e4 --- /dev/null +++ b/devtools/client/inspector/grids/test/browser_grids_grid-outline-selected-grid.js @@ -0,0 +1,51 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Tests that the grid outline is shown when a grid container is selected. + +const TEST_URI = ` + <style type='text/css'> + #grid { + display: grid; + } + </style> + <div id="grid"> + <div id="cella">Cell A</div> + <div id="cellb">Cell B</div> + <div id="cellc">Cell C</div> + </div> +`; + +add_task(async function () { + await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI)); + + const { inspector, gridInspector } = await openLayoutView(); + const { document: doc } = gridInspector; + const { highlighters, store } = inspector; + + const gridList = doc.getElementById("grid-list"); + const checkbox = gridList.children[0].querySelector("input"); + + info("Checking the initial state of the Grid Inspector."); + ok( + !doc.getElementById("grid-outline-container"), + "There should be no grid outline shown." + ); + + info("Toggling ON the CSS grid highlighter from the layout panel."); + const onHighlighterShown = highlighters.once("grid-highlighter-shown"); + const onCheckboxChange = waitUntilState( + store, + state => state.grids.length == 1 && state.grids[0].highlighted + ); + const onGridOutlineRendered = waitForDOM(doc, "#grid-cell-group rect", 3); + checkbox.click(); + await onHighlighterShown; + await onCheckboxChange; + const elements = await onGridOutlineRendered; + + info("Checking the grid outline is shown."); + is(elements.length, 3, "Grid outline is shown."); +}); diff --git a/devtools/client/inspector/grids/test/browser_grids_grid-outline-updates-on-grid-change.js b/devtools/client/inspector/grids/test/browser_grids_grid-outline-updates-on-grid-change.js new file mode 100644 index 0000000000..778217cc40 --- /dev/null +++ b/devtools/client/inspector/grids/test/browser_grids_grid-outline-updates-on-grid-change.js @@ -0,0 +1,64 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Tests that the grid outline does reflect the grid in the page even after the grid has +// changed. + +const TEST_URI = ` + <style> + .container { + display: grid; + grid-template-columns: repeat(2, 20vw); + grid-auto-rows: 20px; + } + </style> + <div class="container"> + <div>item 1</div> + <div>item 2</div> + </div> +`; + +add_task(async function () { + await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI)); + + const { inspector, gridInspector } = await openLayoutView(); + const { document: doc } = gridInspector; + const { highlighters, store } = inspector; + + info("Clicking on the first checkbox to highlight the grid"); + const checkbox = doc.querySelector("#grid-list input"); + + const onHighlighterShown = highlighters.once("grid-highlighter-shown"); + const onCheckboxChange = waitUntilState( + store, + state => state.grids.length == 1 && state.grids[0].highlighted + ); + const onGridOutlineRendered = waitForDOM(doc, ".grid-outline-cell", 2); + + checkbox.click(); + + await onHighlighterShown; + await onCheckboxChange; + let elements = await onGridOutlineRendered; + + info("Checking the grid outline is shown."); + is(elements.length, 2, "Grid outline is shown."); + + info("Changing the grid in the page"); + const onReflow = inspector.once("reflow-in-selected-target"); + const onGridOutlineChanged = waitForDOM(doc, ".grid-outline-cell", 4); + + await SpecialPowers.spawn(gBrowser.selectedBrowser, [], () => { + const div = content.document.createElement("div"); + div.textContent = "item 3"; + content.document.querySelector(".container").appendChild(div); + }); + + await onReflow; + elements = await onGridOutlineChanged; + + info("Checking the grid outline is correct."); + is(elements.length, 4, "Grid outline was changed."); +}); diff --git a/devtools/client/inspector/grids/test/browser_grids_grid-outline-writing-mode.js b/devtools/client/inspector/grids/test/browser_grids_grid-outline-writing-mode.js new file mode 100644 index 0000000000..c27a8b481f --- /dev/null +++ b/devtools/client/inspector/grids/test/browser_grids_grid-outline-writing-mode.js @@ -0,0 +1,156 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Tests that the grid outline adjusts to match the container's writing mode. + +const TEST_URI = ` + <style type='text/css'> + .grid { + display: grid; + width: 400px; + height: 300px; + } + .rtl { + direction: rtl; + } + .v-rl { + writing-mode: vertical-rl; + } + .v-lr { + writing-mode: vertical-lr; + } + .s-rl { + writing-mode: sideways-rl; + } + .s-lr { + writing-mode: sideways-lr; + } + </style> + <div class="grid"> + <div id="cella">Cell A</div> + <div id="cellb">Cell B</div> + <div id="cellc">Cell C</div> + </div> + <div class="grid rtl"> + <div id="cella">Cell A</div> + <div id="cellb">Cell B</div> + <div id="cellc">Cell C</div> + </div> + <div class="grid v-rl"> + <div id="cella">Cell A</div> + <div id="cellb">Cell B</div> + <div id="cellc">Cell C</div> + </div> + <div class="grid v-lr"> + <div id="cella">Cell A</div> + <div id="cellb">Cell B</div> + <div id="cellc">Cell C</div> + </div> + <div class="grid s-rl"> + <div id="cella">Cell A</div> + <div id="cellb">Cell B</div> + <div id="cellc">Cell C</div> + </div> + <div class="grid s-lr"> + <div id="cella">Cell A</div> + <div id="cellb">Cell B</div> + <div id="cellc">Cell C</div> + </div> +`; + +add_task(async function () { + await pushPref("devtools.gridinspector.maxHighlighters", 1); + await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI)); + + const { inspector, gridInspector } = await openLayoutView(); + const { document: doc } = gridInspector; + const { highlighters, store } = inspector; + + info("Checking the initial state of the Grid Inspector."); + ok( + !doc.getElementById("grid-outline-container"), + "There should be no grid outline shown." + ); + + let elements; + + elements = await enableGrid(doc, highlighters, store, 0); + is( + elements[0].style.transform, + "matrix(1, 0, 0, 1, 0, 0)", + "Transform matches for horizontal-tb and ltr." + ); + await disableGrid(doc, highlighters, store, 0); + + elements = await enableGrid(doc, highlighters, store, 1); + is( + elements[0].style.transform, + "matrix(-1, 0, 0, 1, 200, 0)", + "Transform matches for horizontal-tb and rtl" + ); + await disableGrid(doc, highlighters, store, 1); + + elements = await enableGrid(doc, highlighters, store, 2); + is( + elements[0].style.transform, + "matrix(6.12323e-17, 1, -1, 6.12323e-17, 200, 0)", + "Transform matches for vertical-rl and ltr" + ); + await disableGrid(doc, highlighters, store, 2); + + elements = await enableGrid(doc, highlighters, store, 3); + is( + elements[0].style.transform, + "matrix(-6.12323e-17, 1, 1, 6.12323e-17, 0, 0)", + "Transform matches for vertical-lr and ltr" + ); + await disableGrid(doc, highlighters, store, 3); + + elements = await enableGrid(doc, highlighters, store, 4); + is( + elements[0].style.transform, + "matrix(6.12323e-17, 1, -1, 6.12323e-17, 200, 0)", + "Transform matches for sideways-rl and ltr" + ); + await disableGrid(doc, highlighters, store, 4); + + elements = await enableGrid(doc, highlighters, store, 5); + is( + elements[0].style.transform, + "matrix(6.12323e-17, -1, 1, 6.12323e-17, -9.18485e-15, 150)", + "Transform matches for sideways-lr and ltr" + ); + await disableGrid(doc, highlighters, store, 5); +}); + +async function enableGrid(doc, highlighters, store, index) { + info(`Enabling the CSS grid highlighter for grid ${index}.`); + const onHighlighterShown = highlighters.once("grid-highlighter-shown"); + const onCheckboxChange = waitUntilState( + store, + state => state.grids.length == 6 && state.grids[index].highlighted + ); + const onGridOutlineRendered = waitForDOM(doc, "#grid-cell-group"); + const gridList = doc.getElementById("grid-list"); + gridList.children[index].querySelector("input").click(); + await onHighlighterShown; + await onCheckboxChange; + return onGridOutlineRendered; +} + +async function disableGrid(doc, highlighters, store, index) { + info(`Disabling the CSS grid highlighter for grid ${index}.`); + const onHighlighterShown = highlighters.once("grid-highlighter-hidden"); + const onCheckboxChange = waitUntilState( + store, + state => state.grids.length == 6 && !state.grids[index].highlighted + ); + const onGridOutlineRemoved = waitForDOM(doc, "#grid-cell-group", 0); + const gridList = doc.getElementById("grid-list"); + gridList.children[index].querySelector("input").click(); + await onHighlighterShown; + await onCheckboxChange; + return onGridOutlineRemoved; +} diff --git a/devtools/client/inspector/grids/test/browser_grids_highlighter-setting-rules-grid-toggle.js b/devtools/client/inspector/grids/test/browser_grids_highlighter-setting-rules-grid-toggle.js new file mode 100644 index 0000000000..c2c22b8b87 --- /dev/null +++ b/devtools/client/inspector/grids/test/browser_grids_highlighter-setting-rules-grid-toggle.js @@ -0,0 +1,75 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Test toggling the grid highlighter in the rule view with changes in the grid +// display setting from the layout view. + +const TEST_URI = ` + <style type='text/css'> + #grid { + display: grid; + } + </style> + <div id="grid"> + <div id="cell1">cell1</div> + <div id="cell2">cell2</div> + </div> +`; + +const SHOW_INFINITE_LINES_PREF = "devtools.gridinspector.showInfiniteLines"; + +add_task(async function () { + await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI)); + const { inspector, gridInspector } = await openLayoutView(); + const { document: doc } = gridInspector; + const { store } = inspector; + + const checkbox = doc.getElementById("grid-setting-extend-grid-lines"); + + ok( + !Services.prefs.getBoolPref(SHOW_INFINITE_LINES_PREF), + "'Extend grid lines infinitely' is pref off by default." + ); + + info("Toggling ON the 'Extend grid lines infinitely' setting."); + const onCheckboxChange = waitUntilState( + store, + state => state.highlighterSettings.showInfiniteLines + ); + checkbox.click(); + await onCheckboxChange; + + info("Selecting the rule view."); + const ruleView = selectRuleView(inspector); + const highlighters = ruleView.highlighters; + + await selectNode("#grid", inspector); + + const container = getRuleViewProperty(ruleView, "#grid", "display").valueSpan; + const gridToggle = container.querySelector(".js-toggle-grid-highlighter"); + + info("Toggling ON the CSS grid highlighter from the rule-view."); + const onHighlighterShown = highlighters.once( + "grid-highlighter-shown", + (nodeFront, options) => { + info("Checking the grid highlighter display settings."); + const { + color, + showGridAreasOverlay, + showGridLineNumbers, + showInfiniteLines, + } = options; + + is(color, "#9400FF", "CSS grid highlighter color is correct."); + ok(!showGridAreasOverlay, "Show grid areas overlay option is off."); + ok(!showGridLineNumbers, "Show grid line numbers option is off."); + ok(showInfiniteLines, "Show infinite lines option is on."); + } + ); + gridToggle.click(); + await onHighlighterShown; + + Services.prefs.clearUserPref(SHOW_INFINITE_LINES_PREF); +}); diff --git a/devtools/client/inspector/grids/test/browser_grids_highlighter-toggle-telemetry.js b/devtools/client/inspector/grids/test/browser_grids_highlighter-toggle-telemetry.js new file mode 100644 index 0000000000..329acf3713 --- /dev/null +++ b/devtools/client/inspector/grids/test/browser_grids_highlighter-toggle-telemetry.js @@ -0,0 +1,63 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Test that the telemetry count is correct when the grid highlighter is activated from +// the layout view. + +const TEST_URI = ` + <style type='text/css'> + #grid { + display: grid; + } + </style> + <div id="grid"> + <div id="cell1">cell1</div> + <div id="cell2">cell2</div> + </div> +`; + +add_task(async function () { + await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI)); + startTelemetry(); + const { gridInspector, inspector } = await openLayoutView(); + const { document: doc } = gridInspector; + const { highlighters, store } = inspector; + + await selectNode("#grid", inspector); + const gridList = doc.getElementById("grid-list"); + const checkbox = gridList.children[0].querySelector("input"); + + info("Toggling ON the CSS grid highlighter from the layout panel."); + const onHighlighterShown = highlighters.once("grid-highlighter-shown"); + let onCheckboxChange = waitUntilState( + store, + state => state.grids.length == 1 && state.grids[0].highlighted + ); + checkbox.click(); + await onHighlighterShown; + await onCheckboxChange; + + info("Toggling OFF the CSS grid highlighter from the layout panel."); + const onHighlighterHidden = highlighters.once("grid-highlighter-hidden"); + onCheckboxChange = waitUntilState( + store, + state => state.grids.length == 1 && !state.grids[0].highlighted + ); + checkbox.click(); + await onHighlighterHidden; + await onCheckboxChange; + + checkResults(); +}); + +function checkResults() { + checkTelemetry("devtools.grid.gridinspector.opened", "", 1, "scalar"); + checkTelemetry( + "DEVTOOLS_GRID_HIGHLIGHTER_TIME_ACTIVE_SECONDS", + "", + null, + "hasentries" + ); +} diff --git a/devtools/client/inspector/grids/test/browser_grids_number-of-css-grids-telemetry.js b/devtools/client/inspector/grids/test/browser_grids_number-of-css-grids-telemetry.js new file mode 100644 index 0000000000..6ec6b32a63 --- /dev/null +++ b/devtools/client/inspector/grids/test/browser_grids_number-of-css-grids-telemetry.js @@ -0,0 +1,56 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Tests that the telemetry count for the number of CSS Grid Elements on a page navigation +// is correct when the toolbox is opened. + +const TEST_URI1 = ` + <div></div> +`; + +const TEST_URI2 = ` + <style type='text/css'> + #grid { + display: grid; + } + </style> + <div id="grid"> + <div id="cell1">cell1</div> + <div id="cell2">cell2</div> + </div> +`; + +add_task(async function () { + await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI1)); + + startTelemetry(); + + const { inspector } = await openLayoutView(); + const { store } = inspector; + + info("Navigate to TEST_URI2"); + + const onGridListUpdate = waitUntilState( + store, + state => state.grids.length == 1 + ); + await navigateTo( + "data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI2) + ); + await onGridListUpdate; + + checkResults(); +}); + +function checkResults() { + // Check for: + // - 1 CSS Grid Element + checkTelemetry( + "DEVTOOLS_NUMBER_OF_CSS_GRIDS_IN_A_PAGE", + "", + { 0: 0, 1: 1, 2: 0 }, + "array" + ); +} diff --git a/devtools/client/inspector/grids/test/browser_grids_persist-color-palette.js b/devtools/client/inspector/grids/test/browser_grids_persist-color-palette.js new file mode 100644 index 0000000000..0a4e10dfa0 --- /dev/null +++ b/devtools/client/inspector/grids/test/browser_grids_persist-color-palette.js @@ -0,0 +1,58 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Tests that the when a custom color has been previously set, we initialize +// the grid with that color. + +const TEST_URI = ` + <style type='text/css'> + #grid { + display: grid; + } + </style> + <div id="grid"> + <div class="cell1">cell1</div> + <div class="cell2">cell2</div> + </div> +`; + +add_task(async function () { + await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI)); + const { inspector, gridInspector, layoutView, toolbox } = + await openLayoutView(); + const { document: doc } = gridInspector; + const { store } = inspector; + const cPicker = layoutView.swatchColorPickerTooltip; + const swatch = doc.querySelector( + "#layout-grid-container .layout-color-swatch" + ); + + info("Scrolling into view of the #grid color swatch."); + swatch.scrollIntoView(); + + info("Opening the color picker by clicking on the #grid color swatch."); + const onColorPickerReady = cPicker.once("ready"); + swatch.click(); + await onColorPickerReady; + + await simulateColorPickerChange(cPicker, [51, 48, 0, 1]); + + info("Closing the toolbox."); + await toolbox.destroy(); + info("Open the toolbox again."); + await openLayoutView(); + + info("Check that the previously set custom color is used."); + is( + swatch.style.backgroundColor, + "rgb(51, 48, 0)", + "The color swatch's background is correct." + ); + is( + store.getState().grids[0].color, + "#333000", + "The grid color state is correct." + ); +}); diff --git a/devtools/client/inspector/grids/test/browser_grids_restored-after-reload.js b/devtools/client/inspector/grids/test/browser_grids_restored-after-reload.js new file mode 100644 index 0000000000..412bf98af9 --- /dev/null +++ b/devtools/client/inspector/grids/test/browser_grids_restored-after-reload.js @@ -0,0 +1,115 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Tests that the grid highlighter is re-displayed after reloading a page and the grid +// item is highlighted. + +const TEST_URI = ` + <style type='text/css'> + #grid { + display: grid; + } + </style> + <div id="grid"> + <div id="cell1">cell1</div> + <div id="cell2">cell2</div> + </div> +`; + +const OTHER_URI = ` + <style type='text/css'> + #grid { + display: grid; + } + </style> + <div id="grid"> + <div id="cell1">cell1</div> + <div id="cell2">cell2</div> + <div id="cell3">cell3</div> + </div> +`; + +add_task(async function () { + await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI)); + const { gridInspector, inspector } = await openLayoutView(); + const { document: doc } = gridInspector; + const { highlighters, store } = inspector; + const HIGHLIGHTER_TYPE = inspector.highlighters.TYPES.GRID; + const { waitForHighlighterTypeRestored, waitForHighlighterTypeDiscarded } = + getHighlighterTestHelpers(inspector); + + await selectNode("#grid", inspector); + const gridList = doc.getElementById("grid-list"); + const checkbox = gridList.children[0].querySelector("input"); + + info("Toggling ON the CSS grid highlighter from the layout panel."); + const onHighlighterShown = highlighters.once("grid-highlighter-shown"); + const onCheckboxChange = waitUntilState( + store, + state => state.grids.length == 1 && state.grids[0].highlighted + ); + checkbox.click(); + await onHighlighterShown; + await onCheckboxChange; + + info( + "Check that the CSS grid highlighter is created and the saved grid state." + ); + is(highlighters.gridHighlighters.size, 1, "CSS grid highlighter is shown."); + is( + highlighters.state.grids.size, + 1, + "There's a saved grid state to be restored." + ); + + info( + "Reload the page, expect the highlighter to be displayed once again and " + + "grid is checked" + ); + const onRestored = waitForHighlighterTypeRestored(HIGHLIGHTER_TYPE); + let onGridListRestored = waitUntilState( + store, + state => state.grids.length == 1 && state.grids[0].highlighted + ); + + const onReloaded = inspector.once("reloaded"); + await reloadBrowser(); + info("Wait for inspector to be reloaded after page reload"); + await onReloaded; + + await onRestored; + await onGridListRestored; + + info( + "Check that the grid highlighter can be displayed after reloading the page" + ); + is(highlighters.gridHighlighters.size, 1, "CSS grid highlighter is shown."); + is( + highlighters.state.grids.size, + 1, + "The saved grid state has the correct number of saved states." + ); + + info( + "Navigate to another URL, and check that the highlighter is hidden and " + + "grid is unchecked" + ); + const otherUri = + "data:text/html;charset=utf-8," + encodeURIComponent(OTHER_URI); + const onDiscarded = waitForHighlighterTypeDiscarded(HIGHLIGHTER_TYPE); + onGridListRestored = waitUntilState( + store, + state => state.grids.length == 1 && !state.grids[0].highlighted + ); + await navigateTo(otherUri); + await onDiscarded; + await onGridListRestored; + + info( + "Check that the grid highlighter is hidden after navigating to a different page" + ); + ok(!highlighters.gridHighlighters.size, "CSS grid highlighter is hidden."); + ok(!highlighters.state.grids.size, "No grids to be restored on page reload."); +}); diff --git a/devtools/client/inspector/grids/test/browser_grids_restored-multiple-grids-after-reload.js b/devtools/client/inspector/grids/test/browser_grids_restored-multiple-grids-after-reload.js new file mode 100644 index 0000000000..81ac7619ff --- /dev/null +++ b/devtools/client/inspector/grids/test/browser_grids_restored-multiple-grids-after-reload.js @@ -0,0 +1,156 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Tests that the grid highlighters are re-displayed after reloading a page and multiple +// grids are highlighted. + +const TEST_URI = ` + <style type='text/css'> + .grid { + display: grid; + } + </style> + <div id="grid1" class="grid"> + <div class="cell1">cell1</div> + <div class="cell2">cell2</div> + </div> + <div id="grid2" class="grid"> + <div class="cell1">cell1</div> + <div class="cell2">cell2</div> + </div> + <div id="grid3" class="grid"> + <div class="cell1">cell1</div> + <div class="cell2">cell2</div> + </div> + <div id="grid4" class="grid"> + <div class="cell1">cell1</div> + <div class="cell2">cell2</div> + </div> +`; + +add_task(async function () { + await pushPref("devtools.gridinspector.maxHighlighters", 3); + await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI)); + const { gridInspector, inspector } = await openLayoutView(); + const { document: doc } = gridInspector; + const { highlighters, store } = inspector; + + await selectNode("#grid1", inspector); + const gridList = doc.getElementById("grid-list"); + const checkbox1 = gridList.children[0].querySelector("input"); + const checkbox2 = gridList.children[1].querySelector("input"); + const checkbox3 = gridList.children[2].querySelector("input"); + + info("Toggling ON the CSS grid highlighter for #grid1."); + let onHighlighterShown = highlighters.once("grid-highlighter-shown"); + let onCheckboxChange = waitUntilState( + store, + state => + state.grids.length == 4 && + state.grids[0].highlighted && + !state.grids[0].disabled && + !state.grids[1].highlighted && + !state.grids[1].disabled && + !state.grids[2].highlighted && + !state.grids[2].disabled && + !state.grids[3].highlighted && + !state.grids[3].disabled + ); + checkbox1.click(); + await onHighlighterShown; + await onCheckboxChange; + + info("Toggling ON the CSS grid highlighter for #grid2."); + onHighlighterShown = highlighters.once("grid-highlighter-shown"); + onCheckboxChange = waitUntilState( + store, + state => + state.grids.length == 4 && + state.grids[0].highlighted && + !state.grids[0].disabled && + state.grids[1].highlighted && + !state.grids[1].disabled && + !state.grids[2].highlighted && + !state.grids[2].disabled && + !state.grids[3].highlighted && + !state.grids[3].disabled + ); + checkbox2.click(); + await onHighlighterShown; + await onCheckboxChange; + + info("Toggling ON the CSS grid highlighter for #grid3."); + onHighlighterShown = highlighters.once("grid-highlighter-shown"); + onCheckboxChange = waitUntilState( + store, + state => + state.grids.length == 4 && + state.grids[0].highlighted && + !state.grids[0].disabled && + state.grids[1].highlighted && + !state.grids[1].disabled && + state.grids[2].highlighted && + !state.grids[2].disabled && + !state.grids[3].highlighted && + state.grids[3].disabled + ); + checkbox3.click(); + await onHighlighterShown; + await onCheckboxChange; + + info( + "Check that the CSS grid highlighters are created and the saved grid state." + ); + is( + highlighters.gridHighlighters.size, + 3, + "Got expected number of grid highlighters shown." + ); + is( + highlighters.state.grids.size, + 3, + "Got expected number of grids in the saved state" + ); + + info( + "Reload the page, expect the highlighters to be displayed once again and " + + "grids are checked" + ); + const onStateRestored = waitForNEvents( + highlighters, + "highlighter-restored", + 3 + ); + const onGridListRestored = waitUntilState( + store, + state => + state.grids.length == 4 && + state.grids[0].highlighted && + !state.grids[0].disabled && + state.grids[1].highlighted && + !state.grids[1].disabled && + state.grids[2].highlighted && + !state.grids[2].disabled && + !state.grids[3].highlighted && + state.grids[3].disabled + ); + await reloadBrowser(); + await onStateRestored; + await onGridListRestored; + + info( + "Check that the grid highlighters can be displayed after reloading the page" + ); + is( + highlighters.gridHighlighters.size, + 3, + "Got expected number of grid highlighters shown." + ); + is( + highlighters.state.grids.size, + 3, + "Got expected number of grids in the saved state" + ); +}); diff --git a/devtools/client/inspector/grids/test/doc_iframe_reloaded.html b/devtools/client/inspector/grids/test/doc_iframe_reloaded.html new file mode 100644 index 0000000000..a452dd4d8c --- /dev/null +++ b/devtools/client/inspector/grids/test/doc_iframe_reloaded.html @@ -0,0 +1,9 @@ +<!DOCTYPE html> +<iframe srcdoc="<style>.grid{display:grid;}</style><div class='grid'><span>a</span><span>b</span></div>"></iframe> +<script> +"use strict"; +function reloadIFrame() { // eslint-disable-line no-unused-vars + const iFrame = document.querySelector("iframe"); + iFrame.setAttribute("srcdoc", iFrame.getAttribute("srcdoc")); +} +</script> diff --git a/devtools/client/inspector/grids/test/doc_subgrid.html b/devtools/client/inspector/grids/test/doc_subgrid.html new file mode 100644 index 0000000000..fef13bcc5c --- /dev/null +++ b/devtools/client/inspector/grids/test/doc_subgrid.html @@ -0,0 +1,56 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8" /> + <style> + .container { + display: grid; + grid-gap: 5px; + grid-template: auto / 1fr 3fr 1fr; + background: lightyellow; + } + + .subgrid { + display: grid; + grid: subgrid / subgrid; + } + + header, aside, section, footer { + background: lightblue; + font-family: sans-serif; + font-size: 3em; + } + + header, footer { + grid-column: span 3; + } + + main { + grid-column: span 3; + } + + .aside1 { + grid-column: 1; + } + + .aside2 { + grid-column: 3; + } + + section { + grid-column: 2; + } + </style> +</head> +<body> + <div class="container"> + <header class="subgrid">Header</header> + <main class="subgrid"> + <aside class="aside1 subgrid">aside</aside> + <section>section</section> + <aside class="aside2 subgrid">aside2</aside> + </main> + <footer>footer</footer> + </div> +</body> +</html> diff --git a/devtools/client/inspector/grids/test/head.js b/devtools/client/inspector/grids/test/head.js new file mode 100644 index 0000000000..5b54004abc --- /dev/null +++ b/devtools/client/inspector/grids/test/head.js @@ -0,0 +1,40 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint no-unused-vars: [2, {"vars": "local"}] */ + +"use strict"; + +// Import the inspector's head.js first (which itself imports shared-head.js). +Services.scriptloader.loadSubScript( + "chrome://mochitests/content/browser/devtools/client/inspector/test/head.js", + this +); + +const asyncStorage = require("resource://devtools/shared/async-storage.js"); + +Services.prefs.setIntPref("devtools.toolbox.footer.height", 350); +registerCleanupFunction(async function () { + Services.prefs.clearUserPref("devtools.toolbox.footer.height"); + await asyncStorage.removeItem("gridInspectorHostColors"); +}); + +/** + * Simulate a mouseover event on a grid cell currently rendered in the grid + * inspector. + * + * @param {Document} doc + * The owner document for the grid inspector. + * @param {Number} gridCellIndex + * The index (0-based) of the grid cell that should be hovered. + */ +function synthesizeMouseOverOnGridCell(doc, gridCellIndex = 0) { + // Make sure to retrieve the current live grid item before attempting to + // interact with it using mouse APIs. + const gridCell = doc.querySelectorAll("#grid-cell-group rect")[gridCellIndex]; + + EventUtils.synthesizeMouseAtCenter( + gridCell, + { type: "mouseover" }, + doc.defaultView + ); +} diff --git a/devtools/client/inspector/grids/test/xpcshell/.eslintrc.js b/devtools/client/inspector/grids/test/xpcshell/.eslintrc.js new file mode 100644 index 0000000000..86bd54c245 --- /dev/null +++ b/devtools/client/inspector/grids/test/xpcshell/.eslintrc.js @@ -0,0 +1,6 @@ +"use strict"; + +module.exports = { + // Extend from the common devtools xpcshell eslintrc config. + extends: "../../../../../.eslintrc.xpcshell.js", +}; diff --git a/devtools/client/inspector/grids/test/xpcshell/head.js b/devtools/client/inspector/grids/test/xpcshell/head.js new file mode 100644 index 0000000000..733c0400da --- /dev/null +++ b/devtools/client/inspector/grids/test/xpcshell/head.js @@ -0,0 +1,10 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/* eslint no-unused-vars: [2, {"vars": "local"}] */ + +const { require } = ChromeUtils.importESModule( + "resource://devtools/shared/loader/Loader.sys.mjs" +); diff --git a/devtools/client/inspector/grids/test/xpcshell/test_compare_fragments_geometry.js b/devtools/client/inspector/grids/test/xpcshell/test_compare_fragments_geometry.js new file mode 100644 index 0000000000..57f617a3ec --- /dev/null +++ b/devtools/client/inspector/grids/test/xpcshell/test_compare_fragments_geometry.js @@ -0,0 +1,129 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const { + compareFragmentsGeometry, +} = require("resource://devtools/client/inspector/grids/utils/utils.js"); + +const TESTS = [ + { + desc: "No fragments", + grids: [[], []], + expected: true, + }, + { + desc: "Different number of fragments", + grids: [ + [{}, {}, {}], + [{}, {}], + ], + expected: false, + }, + { + desc: "Different number of columns", + grids: [ + [{ cols: { lines: [{}, {}] }, rows: { lines: [] } }], + [{ cols: { lines: [{}] }, rows: { lines: [] } }], + ], + expected: false, + }, + { + desc: "Different number of rows", + grids: [ + [{ cols: { lines: [{}, {}] }, rows: { lines: [{}] } }], + [{ cols: { lines: [{}, {}] }, rows: { lines: [{}, {}] } }], + ], + expected: false, + }, + { + desc: "Different number of rows and columns", + grids: [ + [{ cols: { lines: [{}] }, rows: { lines: [{}] } }], + [{ cols: { lines: [{}, {}] }, rows: { lines: [{}, {}] } }], + ], + expected: false, + }, + { + desc: "Different column sizes", + grids: [ + [ + { + cols: { lines: [{ start: 0 }, { start: 500 }] }, + rows: { lines: [] }, + }, + ], + [ + { + cols: { lines: [{ start: 0 }, { start: 1000 }] }, + rows: { lines: [] }, + }, + ], + ], + expected: false, + }, + { + desc: "Different row sizes", + grids: [ + [ + { + cols: { lines: [{ start: 0 }, { start: 500 }] }, + rows: { lines: [{ start: -100 }] }, + }, + ], + [ + { + cols: { lines: [{ start: 0 }, { start: 500 }] }, + rows: { lines: [{ start: 0 }] }, + }, + ], + ], + expected: false, + }, + { + desc: "Different row and column sizes", + grids: [ + [ + { + cols: { lines: [{ start: 0 }, { start: 500 }] }, + rows: { lines: [{ start: -100 }] }, + }, + ], + [ + { + cols: { lines: [{ start: 0 }, { start: 505 }] }, + rows: { lines: [{ start: 0 }] }, + }, + ], + ], + expected: false, + }, + { + desc: "Complete structure, same fragments", + grids: [ + [ + { + cols: { lines: [{ start: 0 }, { start: 100.3 }, { start: 200.6 }] }, + rows: { lines: [{ start: 0 }, { start: 1000 }, { start: 2000 }] }, + }, + ], + [ + { + cols: { lines: [{ start: 0 }, { start: 100.3 }, { start: 200.6 }] }, + rows: { lines: [{ start: 0 }, { start: 1000 }, { start: 2000 }] }, + }, + ], + ], + expected: true, + }, +]; + +function run_test() { + for (const { desc, grids, expected } of TESTS) { + if (desc) { + info(desc); + } + equal(compareFragmentsGeometry(grids[0], grids[1]), expected); + } +} diff --git a/devtools/client/inspector/grids/test/xpcshell/xpcshell.ini b/devtools/client/inspector/grids/test/xpcshell/xpcshell.ini new file mode 100644 index 0000000000..c52a930c71 --- /dev/null +++ b/devtools/client/inspector/grids/test/xpcshell/xpcshell.ini @@ -0,0 +1,6 @@ +[DEFAULT] +tags = devtools +firefox-appdir = browser +head = head.js + +[test_compare_fragments_geometry.js] |