mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-08 17:06:15 -08:00
test(perf): count the long task that dispatches the J2 click
A long task's startTime precedes the click event's timestamp when the listener runs inside it, so the start-time filter dropped the task that performs the interaction. Long tasks now count when their range overlaps the window: on one main thread only the dispatching task can overlap the click. Layout shifts keep the start-time filter. J1 is unchanged (its window starts at -Infinity). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
994740ee94
commit
7de590c16d
3 files changed
+43
-3
No files matched your search
@@ -629,7 +629,12 @@ test('drops performance entries from before the click and keeps recent-input shi
|
||||
},
|
||||
]);
|
||||
longTask.emit([
|
||||
{ duration: 250, entryType: 'longtask', startTime: beforeClick },
|
||||
// A buffered J1 task that ended before the click.
|
||||
{
|
||||
duration: 250,
|
||||
entryType: 'longtask',
|
||||
startTime: beforeClick - 300,
|
||||
},
|
||||
{ duration: 90, entryType: 'longtask', startTime: now() },
|
||||
]);
|
||||
openSource(fixture);
|
||||
@@ -642,6 +647,30 @@ test('drops performance entries from before the click and keeps recent-input shi
|
||||
assert.deepEqual(state.longTaskDurationsMs, [90]);
|
||||
});
|
||||
|
||||
test('counts the long task that dispatches the click although it began before the event', async () => {
|
||||
const fixture = createOpenSourceFixture();
|
||||
const [, longTask] = fixture.observers as [FakeObserver, FakeObserver];
|
||||
const now = () => fixture.window.performance.now();
|
||||
fixture.card.addEventListener('click', () => openSource(fixture));
|
||||
fixture.card.click();
|
||||
const clickMs =
|
||||
(fixture.rawState().start?.epochMs ?? 0) -
|
||||
fixture.window.performance.timeOrigin;
|
||||
longTask.emit([
|
||||
// Began 20 ms before the click stamp and ran through it: the task
|
||||
// that dispatched the click and rendered the page.
|
||||
{ duration: 120, entryType: 'longtask', startTime: clickMs - 20 },
|
||||
// Ended before the click: earlier work, not part of the journey.
|
||||
{ duration: 60, entryType: 'longtask', startTime: clickMs - 100 },
|
||||
{ duration: 70, entryType: 'longtask', startTime: now() },
|
||||
]);
|
||||
await settle();
|
||||
const state = fixture.state();
|
||||
assert.equal(state.final, true);
|
||||
assert.equal(state.counters.longTasks, 2);
|
||||
assert.deepEqual(state.longTaskDurationsMs, [120, 70]);
|
||||
});
|
||||
|
||||
test('rejects a click start whose sentinel could not be sent', async () => {
|
||||
const fixture = createOpenSourceFixture({ bridge: false });
|
||||
fixture.card.addEventListener('click', () => openSource(fixture));
|
||||
|
||||
@@ -199,6 +199,17 @@ export function journeyRendererProbeScript(
|
||||
const entryEpochMs = performance.timeOrigin + entry.startTime;
|
||||
return entryEpochMs >= fromEpochMs && entryEpochMs <= untilEpochMs;
|
||||
};
|
||||
// A task overlaps the window when it ends after the start. The main
|
||||
// thread runs one task at a time, so the only task that overlaps the
|
||||
// click is the one that dispatches it, which began before the event's
|
||||
// timestamp and must still count.
|
||||
const overlapsWindow = (entry: PerformanceEntry, untilEpochMs: number) => {
|
||||
const entryEpochMs = performance.timeOrigin + entry.startTime;
|
||||
return (
|
||||
entryEpochMs + entry.duration >= fromEpochMs &&
|
||||
entryEpochMs <= untilEpochMs
|
||||
);
|
||||
};
|
||||
|
||||
const acceptLayoutShift = (
|
||||
entries: readonly PerformanceEntry[],
|
||||
@@ -227,7 +238,7 @@ export function journeyRendererProbeScript(
|
||||
untilEpochMs: number
|
||||
): void => {
|
||||
for (const entry of entries) {
|
||||
if (entry.duration <= 50 || !inWindow(entry, untilEpochMs)) {
|
||||
if (entry.duration <= 50 || !overlapsWindow(entry, untilEpochMs)) {
|
||||
continue;
|
||||
}
|
||||
state.counters.longTasks += 1;
|
||||
|
||||
@@ -316,7 +316,7 @@ strings and stream paths carry credentials and are never stored.
|
||||
| `renderer.ipcCallsToFirstPage` | Bridge `start` trace events between the start and end sentinels, counted by a second `journey-main-ipc-capture.ts` instance installed with `startSentinelId`. Calls before the start marker are tallied separately (`callsBeforeStart`); a start marker that is missing, repeated or received after the end sentinel fails the iteration. |
|
||||
| `renderer.domMutationsToFirstPage` | `MutationRecord`s from the click until the terminal batch. Records produced before the click (hover, settling) are taken from the observer at the start and counted under `evidence.settle` instead. |
|
||||
| `renderer.layoutShiftScore` | Sum of all `layout-shift` entries from the click until the post-paint cutoff, rounded to three decimals. Unlike J1 it includes entries with `hadRecentInput === true`: the journey is a response to the click and runs inside the 500 ms input window, so the CLS filter would always read 0. The split is under `evidence.layoutShift`. |
|
||||
| `renderer.longTasks` | `longtask` entries over 50 ms that started at or after the click (buffered entries from J1 are dropped) and before the cutoff. Evidence until it is shown to be stable on the CI runner, as for J1. |
|
||||
| `renderer.longTasks` | `longtask` entries over 50 ms whose time range overlaps the window from the click to the cutoff. The task that dispatches the click began before the event's timestamp and still counts; buffered J1 tasks that ended before the click are dropped. Evidence until it is shown to be stable on the CI runner, as for J1. |
|
||||
| `main.mockHttpRequestsToSettled` | Requests the proxy received from the click until, after the terminal batch, no new request had arrived for 1 s and none was in flight (a response slower than that, and what it triggers, stays inside the window). The window starts at the renderer's click stamp, the same boundary as every other J2 counter, not when Playwright began its actionability checks; the proxy stamps requests with the test process's wall clock, and both processes read the same host clock. Bounding by the terminal would compare the test process's clock with the renderer's, so the count up to the terminal epoch is evidence only (`evidence.httpRequestsToFirstPage`); `evidence.httpRequestsByRoute` names the requests. |
|
||||
|
||||
Two counters are listed under `unavailable`. `renderer.cdTicksToFirstPage`
|
||||
|
||||
Reference in new issue
Block a user