Bug 1509598 [wpt PR 14215] - Move EventTiming tests to WPT, a=testonly

Automatic update from web-platform-tests
Move EventTiming tests to WPT

This CL moves the tests in http/tests/event-timing to external/wpt/event-timing.
The slow image is change from php based to python based. The click is now
handled by test driver. and setTimeout is replaced with step_timeout.

Bug: 841224
Change-Id: I035c087550a2d9a67cda1aed88553c16967d04b6
Reviewed-on: https://chromium-review.googlesource.com/c/1349451
Commit-Queue: Nicolás Peña Moreno <npm@chromium.org>
Reviewed-by: Timothy Dresser <tdresser@chromium.org>
Cr-Commit-Position: refs/heads/master@{#610669}

--

wpt-commits: 42061028f3951380908b400fb1b23a2d6e16bb22
wpt-pr: 14215
This commit is contained in:
Nicolás Peña 2018-11-30 18:01:37 +00:00 коммит произвёл James Graham
Родитель 52d9898011
Коммит fdf9e231c9
13 изменённых файлов: 743 добавлений и 0 удалений

Просмотреть файл

@ -0,0 +1,75 @@
<!DOCTYPE html>
<html>
<meta charset=utf-8 />
<title>Event Timing: buffer long-latency events before onload</title>
<button id='button' onclick='clickDelay()'>Generate a 'click' event</button>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src=/resources/testdriver.js></script>
<script src=/resources/testdriver-vendor.js></script>
<script src=./resources/event-timing-support.js></script>
<img src=./resources/slow-image.py>
<script>
let clickTimeMin;
let processingStartMin;
let firstClickStart = 0;
let firstClickEnd = 0;
function clickDelay() {
const onclickStart = performance.now();
if (firstClickStart == 0)
firstClickStart = onclickStart;
while(performance.now() < onclickStart + 10) {}
if (firstClickEnd == 0)
firstClickEnd = performance.now();
}
function validateEntries() {
const entries = performance.getEntriesByName('click', 'event');
const onloadTime = performance.timing.loadEventStart - performance.timeOrigin;
const entriesBeforeOnload = entries.filter(
e => e.startTime < onloadTime);
assert_equals(entriesBeforeOnload.length, 1,
"Long latency events before onload should be buffered.");
const entry = entriesBeforeOnload[0];
verifyClickEvent(entry, true);
assert_greater_than(entry.processingStart, processingStartMin,
"The entry should be processed later than processingStartMin.");
assert_greater_than(entry.startTime, clickTimeMin,
"The entry's start time should be later than clickTimeMin.");
assert_greater_than_equal(firstClickStart, entry.processingStart,
"The processingStart must be before the onclick starts.")
assert_greater_than_equal(entry.processingEnd, firstClickEnd,
"The processingEnd must be after onclick finishes.");
const entriesAfterOnload = entries.filter(
e => e.startTime > onloadTime);
assert_equals(entriesAfterOnload.length, 0,
"Events after onload shouldn't be buffered.");
}
/* Timeline:
Begin Busy Loop
Click 1 arrives
End Busy Loop
(Dispatch and Process Click 1 - buffered)
Onload Event Fires
Begin Busy Loop
Click 2 arrives
End Busy Loop
(Dispatch and Process Click 2 - not buffered)
*/
async_test(function(t) {
clickTimeMin = performance.now();
clickAndBlockMain('button');
processingStartMin = performance.now();
on_event(window, 'load', e => {
clickAndBlockMain('button').then(wait).then(
t.step_func_done(validateEntries));
});
}, "Event Timing: click, onload.");
</script>
</html>

Просмотреть файл

@ -0,0 +1,90 @@
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Event Timing: entries should be observable by its own frame.</title>
</head>
<body>
<button id='button' onclick='1'>Generate a 'click' event</button>
</body>
<div>
<iframe src=./resources/event-timing-crossiframe-childframe.html></iframe>
</div>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src=/resources/testdriver.js></script>
<script src=/resources/testdriver-vendor.js></script>
<script src=./resources/event-timing-support.js></script>
<img src=./resources/slow-image.py>
<script>
let clickTimeMin;
let processingStartMin;
function validateEntries() {
const entries = performance.getEntriesByName('click', 'event');
const onloadTime = performance.timing.loadEventStart - performance.timeOrigin;
assert_equals(entries.length, 1,
"Observer of main frames should only capture main-frame event-timing entries."
);
const entry = entries[0];
verifyClickEvent(entry, true);
assert_greater_than(entry.processingStart, processingStartMin,
"The entry's processing start should be later than processingStartMin.");
assert_greater_than(onloadTime, entry.processingStart,
"onload should occur later than the entry's procesisng start.");
assert_greater_than(entry.startTime, clickTimeMin,
"The entry's start time should be later than clickTimeMin.");
assert_greater_than(onloadTime, entry.startTime,
"onload should occur later than the entry's start time.");
}
function validateChildFrameEntries(childFrameData) {
assert_equals(childFrameData.bufferedEntries.length, 1,
"Event Timing of child frames should only capture child-frame event-timing entries."
);
const entry = entries[0];
verifyClickEvent(entry);
assert_greater_than(entry.processingStart, childFrameData.processingStartMin,
"The entry's processing start should be later than the child frame's processingStartMin.");
assert_greater_than(childFrameData.onloadTime, entry.processingStart,
"Child frame's onload should occur later than the entry's processing \
start.");
assert_greater_than(entry.startTime, childFrameData.clickTimeMin,
"The entry's start time should be later than the child frame's \
clickTimeMin.");
assert_greater_than(childFrameData.onloadTime, entry.startTime,
"Child frame's onload should be later than the entry's start time.");
assert_array_equals(childFrameData.observedEntries,
childFrameData.bufferedEntries,
"The child frame's observed entries should be buffered as well.");
}
async_test(function(t) {
clickTimeMin = performance.now();
clickAndBlockMain('button');
processingStartMin = performance.now();
const childFrameEntriesPromise = new Promise((resolve, reject) => {
window.addEventListener("message", (event) => {
resolve(event.data);
}, false);
});
on_event(window, 'load', e => {
childFrameEntriesPromise.then((entries) => {
t.step(() => {
validateChildFrameEntries(entries);
validateEntries();
});
t.done();
});
});
}, "Event Timing: entries should only be observable by its own frame.");
</script>
</html>

Просмотреть файл

@ -0,0 +1,79 @@
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Event Timing: entries should be observable by its own frame.
</title>
<script src=./resources/event-timing-support.js></script>
</head>
<body>
<h2>Description:</h2>
<p>
<div>
The goal of this manual test is to verify that observers that have
registered "event" entry type can observe the long-latency input events,
and verify the same behavior within iframe and in cross-frame scenario.
</div>
</p>
<h2>Manual test steps:</h2>
<p>
<div>
Step 1: Click the "make busy" button to make main-thread busy for 2 seconds.</span>
</div>
<div>
Step 2: do several clicks on "click while busy" while busy to generate long-latency inputs.
</div>
<div>
Step 3: observe in the "timeline" section that the long-latency clicks are captured by the observer.
</div>
<div>
Step 4: do step 1 to step 3 for the iframe. Observe that the observers only observe input events within its frame.
</div>
</p>
<div>
<h2>Actions:</h2>
<button id='busy_button' onclick='onMakeBusy()'>make busy</button>
<button id='click_input_button' onclick='1'> click while busy </button>
</div>
<h2>iframe:</h2>
<div>
<iframe name='childframe' width="100%" height="30%" src=./resources/event-timing-observer-manual-childframe.html></iframe>
</div>
<h2>Timeline:</h2>
<p id='timeline'></p>
</body>
<script>
function log(message) {
const timestamp = performance.now();
const elem = document.createElement('div');
elem.innerHTML = `${timestamp.toFixed(1)}: ${message}`;
const timeline = document.getElementById('timeline');
timeline.appendChild(elem);
}
function onMakeBusy() {
log("busy start");
step_timeout(()=>{
mainThreadBusy(2000);
log("busy end");
}, 0);
}
document.body.onload = () => {
new PerformanceObserver((entryList) => {
entryList.getEntries().forEach(e => {
log(`entry observed: ${JSON.stringify(e)}`);
});
}).observe({ entryTypes: ['event'] });
log("observer registered");
};
window.onmessage = (msg) => {
log("received msg: " + msg.data);
if (msg.data === 'CHILD_FRAME_IS_READY') {
// TODO(crbug/831729): automate clicks on iframe when testdriver support
// clicking in iframe.
}
};
</script>
</html>

Просмотреть файл

@ -0,0 +1,91 @@
<!DOCTYPE html>
<html>
<meta charset=utf-8 />
<title>Event Timing: Performance observers can observe long-latency events
</title>
<button id='button' onclick='1'>Generate a 'click' event</button>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src=/resources/testdriver.js></script>
<script src=/resources/testdriver-vendor.js></script>
<script src=./resources/event-timing-support.js></script>
<img src=./resources/slow-image.py>
<script>
let timeAfterFirstClick;
let observedEntries = [];
function verifyBuffer(bufferedEntries) {
const loadStart =
performance.timing.loadEventStart - performance.timeOrigin;
assert_equals(bufferedEntries.length, 1,
"Only events before onload should be buffered.");
const entry = bufferedEntries[0];
assert_greater_than(loadStart, entry.startTime,
"onload should be later than entry's start time.");
assert_greater_than(entry.processingStart, timeAfterFirstClick,
"The entry's processing start should be later than timeAfterFirstClick.");
verifyClickEvent(entry, true);
}
function verifyObserverEntries(observedEntries) {
const entriesAfterFirstClick = observedEntries.filter(
e => e.startTime > timeAfterFirstClick);
assert_equals(entriesAfterFirstClick.length, 1,
'There should be one event after timeAfterFirstClick.');
const entry1 = entriesAfterFirstClick[0];
verifyClickEvent(entry1);
assert_greater_than(entry1.processingStart, timeAfterFirstClick,
"entry1's processing start should be later than timeAfterFirstClick.");
assert_greater_than(entry1.startTime, timeAfterFirstClick,
"entry1's start time should be later than timeAfterFirstClick.");
const entriesBeforeFirstClick =
observedEntries.filter(e => e.startTime < timeAfterFirstClick);
assert_equals(entriesBeforeFirstClick.length, 1,
'There should be one event before timeAfterFirstClick.'
);
const entry2 = entriesBeforeFirstClick[0];
verifyClickEvent(entry2);
assert_greater_than(entry2.processingStart, timeAfterFirstClick,
"entry2's processing start should be later than timeAfterFirstClick.");
assert_greater_than(timeAfterFirstClick, entry2.startTime,
"timeAfterFirstClick should be later than entry2's start time.");
}
/* Timeline:
Observer starts
Begin Busy Loop
Click 1 arrives
End Busy Loop
(Dispatch and Process Click 1 (buffered, observed))
Onload Event Fires
Begin Busy Loop
Click 2 arrives
End Busy Loop
(Dispatch and Process Click 2 (buffered, observed))
observer callback start
*/
async_test(function(t) {
const observerPromise = new Promise((resolve, reject) => {
new PerformanceObserver(function(entryList) {
observedEntries = observedEntries.concat(entryList.getEntries());
if (observedEntries.length < 2) return;
resolve(observedEntries);
}).observe({ entryTypes: ['event'] });
});
clickAndBlockMain('button');
timeAfterFirstClick = performance.now();
on_event(window, 'load', function(e) {
// After onload start and before registering observer.
const bufferPromise = clickAndBlockMain('button').then(wait);
Promise.all([observerPromise, bufferPromise]).then((results) => {
t.step(verifyObserverEntries.bind(null, results[0]));
t.step(verifyBuffer.bind(null, performance.getEntriesByName('click', 'event')));
t.done();
});
});
}, "Event Timing: click, observer, onload, click.");
</script>
</html>

Просмотреть файл

@ -0,0 +1,52 @@
<!DOCTYPE html>
<html>
<meta charset=utf-8 />
<title>Event Timing: buffer long-latency events before onload</title>
<button id='button' onclick='1'>Generate a 'click' event</button>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src=/resources/testdriver.js></script>
<script src=/resources/testdriver-vendor.js></script>
<script src=./resources/event-timing-support.js></script>
<script>
/* Timeline:
Onload
PerformanceObserver is registered
Click 1
Click 2
PerformanceObserver should observe only one firstInput entry.
(Dispatch and Process Click 2 - not buffered)
*/
async_test(function(t) {
let numFirstInputObserved = 0;
let numEventsObserved = 0;
new PerformanceObserver(t.step_func((entryList, obs) => {
const observedEntries = entryList.getEntries();
numEventsObserved += observedEntries.filter(entry =>
entry.entryType == 'event').length;
numFirstInputObserved += observedEntries.filter(entry =>
entry.entryType == 'firstInput').length;
if (numEventsObserved >= 2) {
assert_equals(performance.getEntriesByType('event').length, 0,
"There should be no buffered event entries.");
assert_equals(performance.getEntriesByType('firstInput').length, 0,
"There should be no buffered firstInput entries.");
// There should be 2 event entries and one firstInput entry.
assert_equals(numEventsObserved, 2,
"There should be 2 observed event entries.");
assert_equals(numFirstInputObserved, 1,
"There should be only 1 observed firstInput entry.");
t.done();
}
})).observe({ entryTypes: ['event', 'firstInput'] });
on_event(window, 'load', () => {
clickAndBlockMain('button').then(wait).then(() => {
clickAndBlockMain('button').then(wait);
});
});
},
"Event Timing: check firstInput after onload, observer, click, click."
);
</script>
</html>

Просмотреть файл

@ -0,0 +1,75 @@
<!DOCTYPE html>
<html>
<meta charset=utf-8 />
<title>Event Timing: long-latency events after onload and before observer
registration are lost
</title>
<button id='button' onclick='1'>Generate a 'click' event</button>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src=/resources/testdriver.js></script>
<script src=/resources/testdriver-vendor.js></script>
<script src=./resources/event-timing-support.js></script>
<script>
let callbackTime;
let observerStart;
let processingStartMin;
function verifyBufferAndObserverEntries(observedEntries) {
// Verify buffer entries
const bufferedEntries = performance.getEntriesByName('click', 'event');
const bufferedEntriesBeforeObserver = bufferedEntries.filter(e => e.startTime <
observerStart);
assert_equals(bufferedEntries.length, 0,
"Long latency events after onload should not be buffered."
);
// Verify observer entries
assert_equals(observedEntries.length, 1, "Long latency task after observer start should be observed.");
const entry = observedEntries[0];
verifyClickEvent(entry);
assert_greater_than(entry.processingStart, processingStartMin,
"The entry's processing start should be later than processingStartMin.");
assert_greater_than(callbackTime, entry.processingStart,
"The callback time should be later than the entry's processing start.");
assert_greater_than(entry.startTime, observerStart,
"The entry's start time should be later than observer start.");
assert_greater_than(callbackTime, entry.startTime,
"The callback time should be later than entry's start time.");
}
function startObserver(t) {
new PerformanceObserver(t.step_func_done((entryList, obs) => {
callbackTime = performance.now();
const observedEntries = entryList.getEntries();
verifyBufferAndObserverEntries(observedEntries);
})).observe({ entryTypes: ['event'] });
observerStart = performance.now();
}
/* Timeline:
Onload Event fires
Begin Busy Loop
Click 1 arrives
End Busy Loop
(Dispatch and Process Click 1 (not buffered, not observed))
Observer start
Begin Busy Loop
Click 2 arrives
End Busy Loop
(Dispatch and Process Click 2 (not buffered, observed))
*/
async_test(function(t) {
on_event(window, 'load', () => {
clickAndBlockMain('button').then(() => {
startObserver(t);
clickAndBlockMain('button').then(wait);
processingStartMin = performance.now();
});
});
},
"Event Timing: onload, click, observer, click."
);
</script>
</html>

Просмотреть файл

@ -0,0 +1,47 @@
<!DOCTYPE html>
<html>
<meta charset=utf-8 />
<title>Event Timing: only observe the first input</title>
<button id='button' onclick='1'>Generate a 'click' event</button>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src=/resources/testdriver.js></script>
<script src=/resources/testdriver-vendor.js></script>
<script src=./resources/event-timing-support.js></script>
<script>
/* Test:
PerformanceObserver for firstInput is registered
Click 1
Click 2
Wait
Expected result:
PerformanceObserver should observe one and only one entry.
*/
async_test(function(t) {
let hasObservedFirstInput = false;
new PerformanceObserver(t.step_func((entryList) => {
assert_false(hasObservedFirstInput);
hasObservedFirstInput = true;
const observedEntries = entryList.getEntries();
assert_equals(observedEntries.length, 1);
assert_equals(observedEntries[0].entryType, 'firstInput');
assert_equals(observedEntries[0].name, 'click');
})).observe({ entryTypes: ['firstInput'] });
on_event(window, 'load', () => {
clickAndBlockMain('button').then(wait).then(() => {
clickAndBlockMain('button').then(wait);
// After some wait, the PerformanceObserver should have processed both clicks.
// One and only one firstInput entry should have been dispatched, so
// |hasObservedFirstInput| should be true.
t.step_timeout( () => {
assert_true(hasObservedFirstInput);
t.done();
}, 100);
});
});
},
"Event Timing: check firstInput for a PerformanceObserver observing only firstInput."
);
</script>
</html>

Просмотреть файл

@ -0,0 +1,37 @@
<!DOCTYPE html>
<html>
<meta charset=utf-8>
<title>Event Timing: make sure event-timing entries are retrievable by existing perf APIs.</title>
<button id='button' onclick='1'>Generate a 'click' event</button>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src=/resources/testdriver.js></script>
<script src=/resources/testdriver-vendor.js></script>
<script src=./resources/event-timing-support.js></script>
<img src=./resources/slow-image.py>
<script>
function validateEntries() {
const entriesByName = performance.getEntriesByName('click', 'event');
const entriesByType = performance.getEntriesByType('event');
const allEntries = performance.getEntries();
assert_equals(entriesByName.length, 1, 'event-timing entry should be retrievable by getEntriesByName');
const e = entriesByName[0];
assert_true(entriesByType.includes(e), 'event-timing entry should be retrievable by getEntries');
assert_true(allEntries.includes(e), 'event-timing entry should be retrievable by getEntriesByType');
}
/* Timeline:
Begin Busy Loop
Click 1 arrives
End Busy Loop
(Dispatch and Process Click 1 - buffered)
Onload Event Fires
Validate entries
*/
async_test(function(t) {
clickAndBlockMain('button').then(wait).then(t.step_func_done(validateEntries));
}, "Event Timing: make sure event-timing entries are retrievable by existing perf APIs.");
</script>
</html>

Просмотреть файл

@ -0,0 +1,60 @@
<!DOCTYPE html>
<html>
<meta charset=utf-8 />
<title>Event Timing only times certain types of trusted event.
</title>
<button id='button' onfocus='mainThreadBusy(100)'>Generate a 'click' event</button>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src=/resources/testdriver.js></script>
<script src=/resources/testdriver-vendor.js></script>
<script src=./resources/event-timing-support.js></script>
<script>
let trustedClickStart = 0;
function untrustedClickAndBlockMain(id) {
return new Promise((resolve, reject) => {
const target = document.getElementById(id);
target.dispatchEvent(new MouseEvent('click'));
// Block mainthread in the callback, as dispatchEvent() is an sync call.
resolve();
});
}
function trustedFocusAndBlockMain(id) {
return new Promise((resolve, reject) => {
const target = document.getElementById(id);
trustedFocusStart = performance.now();
target.focus();
// Block mainthread in the callback, as focus() is an sync call.
resolve();
});
}
async_test(function(t) {
new PerformanceObserver(entryList => {
const observerCallbackTime = performance.now();
const entries = entryList.getEntries();
t.step(()=>{
assert_equals(entries.length, 1,
"Observe more than one entries: " +
JSON.stringify(entries) + ".");
assert_equals(entries[0].name, 'click',
"The observed entry should be a click");
assert_greater_than(observerCallbackTime, entries[0].startTime,
"assert(untrustedClickStart > entries[0].startTime) failed");
assert_greater_than(entries[0].startTime, trustedClickStart,
"assert(entries[0].startTime > trustedClickStart) failed");
});
t.done();
}).observe({ entryTypes: ['event'] });
// untrusted event of a type event timing cares about
untrustedClickAndBlockMain('button').then(wait);
// trusted event of a type event timing doesn't cares about
trustedFocusAndBlockMain('button').then(wait);
// trusted event of a type event timing cares about
trustedClickStart = performance.now();
clickAndBlockMain('button').then(wait);
}, "Event Timing only times certain types of trusted event.");
</script>
</html>

Просмотреть файл

@ -0,0 +1,29 @@
<!DOCType html>
<html>
<script src=event-timing-support.js></script>
<button id='button_child_frame' onclick='2'>Generate a 'click' event</button>
<img src=slow-image.py>
<script>
const clickTimeMin = performance.now();
clickAndBlockMain('button_child_frame');
const processingStartMin = performance.now();
const observerPromise = new Promise((resolve, reject) => {
new PerformanceObserver((entryList) => {
resolve(entryList.getEntries());
}).observe({ entryTypes: ['event'] });
});
window.addEventListener('load', e => {
observerPromise.then((observedEntries) => {
const bufferedEntries = performance.getEntriesByType('event');
const onloadTime = performance.timing.loadEventStart - performance.timeOrigin;
top.postMessage({
"bufferedEntries" : bufferedEntries,
"observedEntries": observedEntries,
"clickTimeMin": clickTimeMin,
"processingStartMin" : processingStartMin,
"onloadTime" : onloadTime,
}, '*');
});
});
</script>
</html>

Просмотреть файл

@ -0,0 +1,43 @@
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
</head>
<script src=./event-timing-support.js></script>
<script>
function log(message) {
const timestamp = performance.now();
const elem = document.createElement('div');
elem.innerHTML = `${timestamp.toFixed(1)}: ${message}`;
const timeline = document.getElementById('timeline');
timeline.appendChild(elem);
}
function run() {
new PerformanceObserver((entryList) => {
entryList.getEntries().forEach(e => {
log(`entry observed: ${JSON.stringify(e)}`);
});
}).observe({ entryTypes: ['event'] });
log("observer registered");
top.postMessage('CHILD_FRAME_IS_READY', "*");
}
function onMakeBusy() {
log("busy start");
step_timeout(()=>{
mainThreadBusy(2000);
log("busy end");
}, 0);
}
</script>
<body onload='run()'>
<h3>Actions:</h3>
<p>
<button id='busy_button' onclick='onMakeBusy()'>Make busy</button>
<button id='click_input_button' onclick='1'> click while busy </button>
</p>
<h3>Timeline:</h3>
<p id='timeline'></p>
</body>
</html>

Просмотреть файл

@ -0,0 +1,58 @@
function clickOnElement(id, resolve) {
const element = document.getElementById(id);
const clickHandler = () => {
element.removeEventListener("click", clickHandler);
resolve();
};
element.addEventListener("click", clickHandler);
test_driver.click(element);
}
function mainThreadBusy(duration) {
const now = performance.now();
while (performance.now() < now + duration);
}
// This method should receive an entry of type 'event'. |is_first| is true only
// when the event also happens to correspond to the first event. In this case,
// the timings of the 'firstInput' entry should be equal to those of this entry.
function verifyClickEvent(entry, is_first=false) {
assert_true(entry.cancelable);
assert_equals(entry.name, 'click');
assert_equals(entry.entryType, 'event');
assert_greater_than(entry.duration, 50,
"The entry's duration should be greater than 50ms.");
assert_greater_than(entry.processingStart, entry.startTime,
"The entry's processingStart should be greater than startTime.");
assert_greater_than_equal(entry.processingEnd, entry.processingStart,
"The entry's processingEnd must be at least as large as processingStart.");
assert_greater_than_equal(entry.duration, entry.processingEnd - entry.startTime,
"The entry's duration must be at least as large as processingEnd - startTime.");
if (is_first) {
let firstInputs = performance.getEntriesByType('firstInput');
assert_equals(firstInputs.length, 1, 'There should be a single firstInput entry');
let firstInput = firstInputs[0];
assert_equals(firstInput.name, entry.name);
assert_equals(firstInput.entryType, 'firstInput');
assert_equals(firstInput.startTime, entry.startTime);
assert_equals(firstInput.duration, entry.duration);
assert_equals(firstInput.processingStart, entry.processingStart);
assert_equals(firstInput.processingEnd, entry.processingEnd);
assert_equals(firstInput.cancelable, entry.cancelable);
}
}
function wait() {
return new Promise((resolve, reject) => {
step_timeout(() => {
resolve();
}, 0);
});
}
function clickAndBlockMain(id) {
return new Promise((resolve, reject) => {
clickOnElement(id, resolve);
mainThreadBusy(300);
});
}

Просмотреть файл

@ -0,0 +1,7 @@
import time
def main(request, response):
# Sleep for 500ms to delay onload.
time.sleep(0.5)
response.headers.set("Cache-Control", "no-cache, must-revalidate");
response.headers.set("Location", "data:image/gif;base64,R0lGODlhAQABAJAAAMjIyAAAACwAAAAAAQABAAACAgQBADs%3D");