summaryrefslogtreecommitdiffstats
path: root/devtools/client/inspector/markup/test/browser_markup_shadowdom_navigation.js
blob: ece16815adc6e13940f911619fa35ec4a80a0031 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
/* Any copyright is dedicated to the Public Domain.
 http://creativecommons.org/publicdomain/zero/1.0/ */

"use strict";

// Test that the markup-view navigation works correctly with shadow dom slotted nodes.
// Each slotted nodes has two containers representing the same node front in the markup
// view, we need to make sure that navigating to the slotted version selects the slotted
// container, and navigating to the non-slotted element selects the non-slotted container.

const TEST_URL = `data:text/html;charset=utf-8,
  <test-component class="test-component">
    <div slot="slot1" class="slotted1"><div class="slot1-child">slot1-1</div></div>
    <div slot="slot1" class="slotted2">slot1-2</div>
  </test-component>

  <script>
    'use strict';
    customElements.define('test-component', class extends HTMLElement {
      constructor() {
        super();
        let shadowRoot = this.attachShadow({mode: 'open'});
        shadowRoot.innerHTML = '<slot class="slot1" name="slot1"></slot>';
      }
    });
  </script>`;

const TEST_DATA = [
  ["KEY_PageUp", "html"],
  ["KEY_ArrowDown", "head"],
  ["KEY_ArrowDown", "body"],
  ["KEY_ArrowDown", "test-component"],
  ["KEY_ArrowRight", "test-component"],
  ["KEY_ArrowDown", "shadow-root"],
  ["KEY_ArrowRight", "shadow-root"],
  ["KEY_ArrowDown", "slot1"],
  ["KEY_ArrowRight", "slot1"],
  ["KEY_ArrowDown", "div", "slotted1"],
  ["KEY_ArrowDown", "div", "slotted2"],
  ["KEY_ArrowDown", "slotted1"],
  ["KEY_ArrowRight", "slotted1"],
  ["KEY_ArrowDown", "slot1-child"],
  ["KEY_ArrowDown", "slotted2"],
];

add_task(async function () {
  const { inspector } = await openInspectorForURL(TEST_URL);

  info("Making sure the markup-view frame is focused");
  inspector.markup._frame.focus();

  info("Starting to iterate through the test data");
  for (const [key, expected, slottedClassName] of TEST_DATA) {
    info("Testing step: " + key + " to navigate to " + expected);
    EventUtils.synthesizeKey(key);

    info("Making sure markup-view children get updated");
    await waitForChildrenUpdated(inspector);

    info("Checking the right node is selected");
    checkSelectedNode(key, expected, slottedClassName, inspector);
  }

  // Same as in browser_markup_navigation.js, use a single catch-call event listener.
  await inspector.once("inspector-updated");
});

function checkSelectedNode(key, expected, slottedClassName, inspector) {
  const selectedContainer = inspector.markup.getSelectedContainer();
  const slotted = !!slottedClassName;

  is(
    selectedContainer.isSlotted(),
    slotted,
    `Selected container is ${slotted ? "slotted" : "not slotted"} as expected`
  );
  is(
    inspector.selection.isSlotted(),
    slotted,
    `Inspector selection is also ${slotted ? "slotted" : "not slotted"}`
  );
  ok(
    selectedContainer.elt.textContent.includes(expected),
    "Found expected content: " +
      expected +
      " in container after pressing " +
      key
  );

  if (slotted) {
    is(
      selectedContainer.node.className,
      slottedClassName,
      "Slotted has the expected classname " + slottedClassName
    );
  }
}