resource-timing-fetch-variants.https.html (4422B)
1 <!DOCTYPE HTML> 2 <html> 3 <head> 4 <title>Test various interactions between fetch, service-workers and resource timing</title> 5 <meta charset="utf-8" /> 6 <script src="/resources/testharness.js"></script> 7 <script src="/resources/testharnessreport.js"></script> 8 <script src="resources/test-helpers.sub.js"></script> 9 <link rel="help" href="https://w3c.github.io/resource-timing/" > 10 <!-- 11 This test checks that the different properties in a PerformanceResourceTimingEntry 12 measure what they are supposed to measure according to spec. 13 14 It is achieved by generating programmatic delays and redirects inside a service worker, 15 and checking how the different metrics respond to the delays and redirects. 16 17 The deltas are not measured precisely, but rather relatively to the delay. 18 The delay needs to be long enough so that it's clear that what's measured is the test's 19 programmatic delay and not arbitrary system delays. 20 --> 21 </head> 22 23 <body> 24 <script> 25 26 const delay = 200; 27 const absolutePath = `${base_path()}/simple.txt` 28 function toSequence({before, after, entry}) { 29 /* 30 The order of keys is the same as in this chart: 31 https://w3c.github.io/resource-timing/#attribute-descriptions 32 */ 33 const keys = [ 34 'startTime', 35 'redirectStart', 36 'redirectEnd', 37 'workerStart', 38 'fetchStart', 39 'connectStart', 40 'requestStart', 41 'responseStart', 42 'responseEnd' 43 ]; 44 45 let cursor = before; 46 const step = value => { 47 // A zero/null value, reflect that in the sequence 48 if (!value) 49 return value; 50 51 // Value is the same as before 52 if (value === cursor) 53 return "same"; 54 55 // Oops, value is in the wrong place 56 if (value < cursor) 57 return "back"; 58 59 // Delta is greater than programmatic delay, this is where the delay is measured. 60 if ((value - cursor) >= delay) 61 return "delay"; 62 63 // Some small delta, probably measuring an actual networking stack delay 64 return "tick"; 65 } 66 67 const res = keys.map(key => { 68 const value = step(entry[key]); 69 if (entry[key]) 70 cursor = entry[key]; 71 return [key, value]; 72 }); 73 74 return Object.fromEntries([...res, ['after', step(after)]]); 75 } 76 async function testVariant(t, variant) { 77 const worker_url = 'resources/fetch-variants-worker.js'; 78 const url = encodeURIComponent(`simple.txt?delay=${delay}&variant=${variant}`); 79 const scope = `resources/iframe-with-fetch-variants.html?url=${url}`; 80 const registration = await service_worker_unregister_and_register(t, worker_url, scope); 81 t.add_cleanup(() => registration.unregister()); 82 await wait_for_state(t, registration.installing, 'activated'); 83 const frame = await with_iframe(scope); 84 t.add_cleanup(() => frame.remove()); 85 const result = await new Promise(resolve => window.addEventListener('message', message => { 86 resolve(message.data); 87 })) 88 89 return toSequence(result); 90 } 91 92 promise_test(async t => { 93 const result = await testVariant(t, 'redirect'); 94 assert_equals(result.redirectStart, 0); 95 }, 'Redirects done from within a service-worker should not be exposed to client ResourceTiming'); 96 97 promise_test(async t => { 98 const result = await testVariant(t, 'forward'); 99 assert_equals(result.connectStart, 'same'); 100 }, 'Connection info from within a service-worker should not be exposed to client ResourceTiming'); 101 102 promise_test(async t => { 103 const result = await testVariant(t, 'forward'); 104 assert_not_equals(result.requestStart, 'back'); 105 }, 'requestStart should never be before fetchStart'); 106 107 promise_test(async t => { 108 const result = await testVariant(t, 'delay-after-fetch'); 109 const whereIsDelayMeasured = Object.entries(result).find(r => r[1] === 'delay')[0]; 110 assert_equals(whereIsDelayMeasured, 'responseStart'); 111 }, 'Delay from within service-worker (after internal fetching) should be accessible through `responseStart`'); 112 113 promise_test(async t => { 114 const result = await testVariant(t, 'delay-before-fetch'); 115 const whereIsDelayMeasured = Object.entries(result).find(r => r[1] === 'delay')[0]; 116 assert_equals(whereIsDelayMeasured, 'responseStart'); 117 }, 'Delay from within service-worker (before internal fetching) should be measured before responseStart in the client ResourceTiming entry'); 118 </script> 119 120 </body> 121 </html>