blob: 6ca9247619526689db286e6eef740f521ce70ad0 [file] [log] [blame]
<!DOCTYPE html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
<script src="resources/test-helpers.sub.js"></script>
<script>
// This is tentative because currently this feature only has an explainer and
// no formal spec.
// https://github.com/wanderview/fetchevent-worker-timing/blob/master/explainer.md
async function wait_for_performance_entries(url, performance, entry_type) {
const entries = await performance.getEntriesByName(url);
if (entries.length > 0) {
return entries;
}
return new Promise((resolve) => {
new PerformanceObserver((list, observer) => {
const entries = list.getEntriesByName(url);
if (entries.length > 0) {
observer.disconnect();
resolve(entries);
}
}).observe({ entryTypes: [entry_type] });
});
}
function load_image(target_document, url) {
return new Promise((resolve, reject) => {
const image = target_document.createElement('img');
image.onload = () => { resolve(image); }
image.onerror = () => { reject(`Failed to load: ${url}`); };
image.src = url;
});
}
promise_test(async (t) => {
const registration = await service_worker_unregister_and_register(
t, 'resources/fetch-event-worker-timing.js', 'resources/');
promise_test(async (t) => registration.unregister(),
'Unregister service worker');
await wait_for_state(t, registration.installing, 'activated');
}, 'Set up an active service worker');
promise_test(async (t) => {
const frame = await with_iframe('resources/empty.html?fallback');
t.add_cleanup(() => frame.remove());
const performance = frame.contentWindow.performance;
const entries = await wait_for_performance_entries(
frame.src, performance, 'navigation');
assert_equals(entries.length, 1, 'PerformanceNavigationTiming is observed');
const worker_timings = await entries[0].workerTiming;
const expected_worker_timings = [
{
name: "network-fallback mark 1",
entryType: "mark",
detail: { foo: 'foo' }
},
{
name: "network-fallback mark 2",
entryType: "mark",
detail: { bar: 'bar' }
},
{
name: "network-fallback measure",
entryType: "measure",
detail: { baz: 'baz' }
}
];
assert_equals(worker_timings.length, expected_worker_timings.length,
'workerTiming is completed when PerformanceResourceTiming is observed');
for (let i = 0; i < workerTimings.length; i++) {
assert_equals(worker_timings[i].name,
expected_worker_timings[i].name, 'entry name');
assert_equals(worker_timings[i].entryType,
expected_worker_timings[i].entryType, 'entry type');
assert_object_equals(worker_timings[i].detail,
expected_worker_timings[i].detail, 'entry detail');
}
}, 'workerTiming for navigation in a frame with network fallback');
promise_test(async (t) => {
const frame= await with_iframe('resources/empty.html?fetch-event');
t.add_cleanup(() => frame.remove());
const performance = frame.contentWindow.performance;
const entries = await wait_for_performance_entries(
frame.src, performance, 'navigation');
assert_equals(entries.length, 1, 'PerformanceNavigationTiming is observed');
const worker_timings = await entries[0].workerTiming;
const expected_worker_timings = [
{
name: "fetch-event mark 1",
entryType: "mark",
detail: { foo: 'foo' }
},
{
name: "fetch-event mark 2",
entryType: "mark",
detail: { bar: 'bar' }
},
{
name: "fetch-event measure",
entryType: "measure",
detail: { baz: 'baz' }
}
];
assert_equals(worker_timings.length, expected_worker_timings.length,
'workerTiming is completed when PerformanceResourceTiming is observed');
for (let i = 0; i < workerTimings.length; i++) {
assert_equals(worker_timings[i].name,
expected_worker_timings[i].name, 'entry name');
assert_equals(worker_timings[i].entryType,
expected_worker_timings[i].entryType, 'entry type');
assert_object_equals(worker_timings[i].detail,
expected_worker_timings[i].detail, 'entry detail');
}
}, 'workerTiming for navigation in a frame for a response from a fetch ' +
'handler');
promise_test(async (t) => {
const frame = await with_iframe('resources/empty.html');
t.add_cleanup(() => frame.remove());
const performance = frame.contentWindow.performance;
const image_path = base_path() + 'resources/square.png?fallback';
const image_url = get_host_info()['HTTPS_ORIGIN'] + image_path;
let entries = await performance.getEntriesByName(image_url);
assert_equals(entries.length, 0, 'No PerformanceResourceTiming');
const image = await load_image(frame.contentDocument,
'square.png?fetch-event');
entries = await wait_for_performance_entries(
image.src, performance, 'resource');
assert_equals(entries.length, 1, 'PerformanceResourceTiming is observed');
const worker_timings = await entries[0].workerTiming;
const expected_worker_timings = [
{
name: "network-fallback mark 1",
entryType: "mark",
detail: { foo: 'foo' }
},
{
name: "network-fallback mark 2",
entryType: "mark",
detail: { bar: 'bar' }
},
{
name: "network-fallback measure",
entryType: "measure",
detail: { baz: 'baz' }
}
];
assert_equals(worker_timings.length, expected_worker_timings.length,
'workerTiming is completed when PerformanceResourceTiming is observed');
for (let i = 0; i < workerTimings.length; i++) {
assert_equals(worker_timings[i].name,
expected_worker_timings[i].name, 'entry name');
assert_equals(worker_timings[i].entryType,
expected_worker_timings[i].entryType, 'entry type');
assert_object_equals(worker_timings[i].detail,
expected_worker_timings[i].detail, 'entry detail');
}
}, 'workerTiming for subresources in a frame with network fallback');
promise_test(async (t) => {
const frame = await with_iframe('resources/empty.html');
t.add_cleanup(() => frame.remove());
const performance = frame.contentWindow.performance;
const image_path = base_path() + 'resources/square.png?fetch-event';
const image_url = get_host_info()['HTTPS_ORIGIN'] + image_path;
let entries = await performance.getEntriesByName(image_url);
assert_equals(entries.length, 0, 'No PerformanceResourceTiming');
const image = await load_image(frame.contentDocument,
'square.png?fetch-event');
entries = await wait_for_performance_entries(
image.src, performance, 'resource');
assert_equals(entries.length, 1, 'PerformanceResourceTiming is observed');
const worker_timings = await entries[0].workerTiming;
const expected_worker_timings = [
{
name: "fetch-event mark 1",
entryType: "mark",
detail: { foo: 'foo' }
},
{
name: "fetch-event mark 2",
entryType: "mark",
detail: { bar: 'bar' }
},
{
name: "fetch-event measure",
entryType: "measure",
detail: { baz: 'baz' }
}
];
assert_equals(worker_timings.length, expected_worker_timings.length,
'workerTiming is completed when PerformanceResourceTiming is observed');
for (let i = 0; i < workerTimings.length; i++) {
assert_equals(worker_timings[i].name,
expected_worker_timings[i].name, 'entry name');
assert_equals(worker_timings[i].entryType,
expected_worker_timings[i].entryType, 'entry type');
assert_object_equals(worker_timings[i].detail,
expected_worker_timings[i].detail, 'entry detail');
}
}, 'workerTiming for subresources in a frame for a response from a fetch' +
'handler');
</script>