summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/largest-contentful-paint/resources/mouseover-utils.js
blob: 1836f2e4ad2ae3b169ffc59abc1b7955f91fb255 (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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
let counter = 0;
const loadImage = size => {
  return event => {
    let zoom;
    if (location.search.includes("replace")) {
      zoom = document.getElementById("image");
    } else {
      zoom = new Image();
    }
    zoom.src=`/images/green-${size}.png`;
    ++counter;
    zoom.elementTiming = "zoom" + counter;
    document.body.appendChild(zoom);
  }
};
const loadBackgroundImage = size => {
  return event => {
    const div = document.createElement("div");
    const [width, height] = size.split("x");
    ++counter;
    div.style = `background-image:
      url(/images/green-${size}.png?${counter}); width: ${width}px; height: ${height}px`;
    div.elementTiming = "zoom" + counter;
    document.body.appendChild(div);
  }
};

const registerMouseover = background => {
  const image = document.getElementById("image");
  const span = document.getElementById("span");
  const func = background ? loadBackgroundImage : loadImage;
  image.addEventListener("mouseover", func("100x50"));
  span.addEventListener("mouseover", func("256x256"));
}

const dispatch_mouseover = () => {
  span.dispatchEvent(new Event("mouseover"))
};

const wait_for_lcp_entries = async entries_expected => {
  await new Promise(resolve => {
    let entries_seen = 0;
    const PO = new PerformanceObserver(list => {
    const entries = list.getEntries();
      for (let entry of entries) {
        if (entry.url) {
          entries_seen++;
        }
      }
      if (entries_seen == entries_expected) {
        PO.disconnect();
        resolve()
      } else if (entries_seen > entries_expected) {
        PO.disconnect();
        reject();
      }
    });
    PO.observe({type: "largest-contentful-paint", buffered: true});
  });
};
const wait_for_element_timing_entry = async identifier => {
  await new Promise(resolve => {
    const PO = new PerformanceObserver(list => {
    const entries = list.getEntries();
      for (let entry of entries) {
        if (entry.identifier == identifier) {
          PO.disconnect();
          resolve()
        }
      }
    });
    PO.observe({type: "element", buffered: true});
  });
};
const wait_for_resource_timing_entry = async name => {
  await new Promise(resolve => {
    const PO = new PerformanceObserver(list => {
    const entries = list.getEntries();
      for (let entry of entries) {
        if (entry.name.includes(name)) {
          PO.disconnect();
          resolve()
        }
      }
    });
    PO.observe({type: "resource", buffered: true});
  });
};

const run_mouseover_test = background => {
  promise_test(async t => {
    // await the first LCP entry
    await wait_for_lcp_entries(1);
    // Hover over the image
    registerMouseover(background);
    if (test_driver) {
      await new test_driver.Actions().pointerMove(0, 0, {origin: image}).send();
    }
    if (!background) {
      await wait_for_element_timing_entry("zoom1");
    } else {
      await wait_for_resource_timing_entry("png?1");
      await new Promise(r => requestAnimationFrame(r));
    }
    // There's only a single LCP entry, because the zoom was skipped.
    await wait_for_lcp_entries(1);

    // Wait 600 ms as the heuristic is 500 ms.
    // This will no longer be necessary once the heuristic relies on Task
    // Attribution.
    await new Promise(r => step_timeout(r, 600));

    // Hover over the span.
    if (test_driver) {
      await new test_driver.Actions().pointerMove(0, 0, {origin: span}).send();
    }
    if (!background) {
      await wait_for_element_timing_entry("zoom2");
    } else {
      await wait_for_resource_timing_entry("png?2");
      await new Promise(r => requestAnimationFrame(r));
    }
    // There are 2 LCP entries, as the image loaded due to span hover is a
    // valid LCP candidate.
    await wait_for_lcp_entries(2);
  }, `LCP mouseover heuristics ignore ${background ?
        "background" : "element"}-based zoom widgets`);
}