Skip to content

Commit

Permalink
[BFCache] Basic event tests + helpers
Browse files Browse the repository at this point in the history
Change-Id: I034f9f5376dc3f9f32ca0b936dbd06e458c9160b
  • Loading branch information
hiroshige-g authored and chromium-wpt-export-bot committed May 10, 2021
1 parent 1c4e5c8 commit a9ac8e5
Show file tree
Hide file tree
Showing 6 changed files with 171 additions and 0 deletions.
27 changes: 27 additions & 0 deletions common/PrefixedLocalStorage.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,33 @@ PrefixedLocalStorage.prototype.setItem = function (baseKey, value) {
localStorage.setItem(this.prefixedKey(baseKey), value);
};

PrefixedLocalStorage.prototype.removeItem = function (baseKey) {
localStorage.removeItem(this.prefixedKey(baseKey));
};

PrefixedLocalStorage.prototype.getItem = function (baseKey) {
return localStorage.getItem(this.prefixedKey(baseKey));
};

PrefixedLocalStorage.prototype.pushItem = function (baseKey, value) {
let index = this.getItem(baseKey);
if (!index) { index = 0; } else { index = parseInt(index); }
this.setItem(baseKey + '.' + index, JSON.stringify(value));
this.setItem(baseKey, (index + 1));
};

PrefixedLocalStorage.prototype.getPushedItems = function (baseKey, startIndex) {
let index = this.getItem(baseKey);
if (!index) { index = 0; }
if (!startIndex) { startIndex = 0; }
const array = [];
for (let i = startIndex; i < index; ++i) {
const value = JSON.parse(this.getItem(baseKey + '.' + i));
array.push(value);
}
return array;
};

/**
* Listen for `storage` events pertaining to a particular key,
* prefixed with this object's prefix. Ignore when value is being set to null
Expand Down
12 changes: 12 additions & 0 deletions html/browsers/browsing-the-web/back-forward-cache/events.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!doctype html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/PrefixedLocalStorage.js"></script>
<title>Events fired during BFCached back navigation (cross-site)</title>
<script>
const prefixedLocalStorage = new PrefixedLocalStorageTest();
fetch_tests_from_prefixed_local_storage(prefixedLocalStorage);
window.open(prefixedLocalStorage.url('resources/events.html'),
'_blank',
'noopener');
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<script>
// TODO: assert that the previous page is in BFCache.
window.onload = () => setTimeout(() => history.back(), 100);
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<!doctype html>
<script src="/resources/testharness.js"></script>
<script src="/common/PrefixedLocalStorage.js"></script>
<script src="helper.sub.js"></script>
<script>

startRecordingEvents(['visibilitychange', 'pagehide', 'pageshow', 'load']);

const t = async_test('Events');
runTest(
() => location.href = backUrl,
t.step_func_done((isBFCached, observedEvents) => {
assert_implements_optional(isBFCached, 'Should be BFCached');
assert_array_equals(observedEvents, [
'window.load',
'window.pageshow',
'window.pagehide.persisted',
'document.visibilitychange.hidden',
'window.visibilitychange.hidden',
'document.visibilitychange.visible',
'window.visibilitychange.visible',
'window.pageshow.persisted']);
})
);
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// This Document is opened using `window.open()` with 'noopener' option by
// the main testharness Window and
// writes the result back to the main Window via `localStorage`.
// This is because the current test runners expect the top-level testharness
// Document is never unloaded in the middle of a test.

window.prefixedLocalStorage = new PrefixedLocalStorageResource({
close_on_cleanup: true
});

function startRecordingEvents(eventNames) {
window.testObservedEvents = [];
for (const eventName of eventNames) {
window.addEventListener(eventName, event => {
let result = eventName;
if (event.persisted) {
result += '.persisted';
}
if (eventName === 'visibilitychange') {
result += '.' + document.visibilityState;
}
prefixedLocalStorage.pushItem('observedEvents', 'window.' + result);
});
document.addEventListener(eventName, () => {
let result = eventName;
if (eventName === 'visibilitychange') {
result += '.' + document.visibilityState;
}
prefixedLocalStorage.pushItem('observedEvents', 'document.' + result);
});
}
}

function runTest(onStart, onBackNavigated) {
window.addEventListener('load', () => {
if (prefixedLocalStorage.getItem('state') === null) {
prefixedLocalStorage.setItem('state', 'started');

// Navigate after this document is fully loaded.
// Calling
// location.href = 'resources/back.html';
// synchronously here seems to cause `history.back()` on `back.html` to go
// back to the previous page of this page, not this page, on Firefox.
setTimeout(() => {
window.addEventListener('pageshow', (() => {
onBackNavigated(
true,
prefixedLocalStorage.getPushedItems('observedEvents'));
}));
onStart();
}, 100);
} else {
onBackNavigated(
false,
prefixedLocalStorage.getPushedItems('observedEvents'));
}
});
}

const originParam = new URL(location.href).searchParams.get('origin');

const origin =
originParam === 'same-origin' ? 'http://{{host}}:{{ports[http][0]}}' :
originParam === 'same-site' ? 'http://{{host}}:{{ports[http][1]}}' :
'http://{{hosts[alt][www]}}:{{ports[http][0]}}'; // cross-site

const backUrl =
origin +
'/html/browsers/browsing-the-web/back-forward-cache/resources/back.html';
34 changes: 34 additions & 0 deletions resources/testharness.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@

WindowTestEnvironment.prototype._dispatch = function(selector, callback_args, message_arg) {
this.dispatched_messages.push(message_arg);
if (window.prefixedLocalStorage) {
window.prefixedLocalStorage.setItem('dispatched_messages.' + Math.random(), JSON.stringify(message_arg));
}
this._forEach_windows(
function(w, same_origin) {
if (same_origin) {
Expand Down Expand Up @@ -3168,6 +3171,19 @@
);
};

/*
* Constructs a RemoteContext that tracks tests from prefixed local storage.
*/
Tests.prototype.create_remote_prefixed_local_storage = function(prefixedLocalStorage) {
const channel = new MessageChannel();
let index = 0;
prefixedLocalStorage.onSet('dispatched_messages', e => {
channel.port1.postMessage(JSON.parse(e.newValue));
});
channel.port2.onmessage = e => {}; // FOXME
return new RemoteContext(null, channel.port2);
};

Tests.prototype.fetch_tests_from_worker = function(worker) {
if (this.phase >= this.phases.COMPLETE) {
return;
Expand Down Expand Up @@ -3196,6 +3212,24 @@
}
expose(fetch_tests_from_window, 'fetch_tests_from_window');


Tests.prototype.fetch_tests_from_prefixed_local_storage = function(prefixedLocalStorage) {
if (this.phase >= this.phases.COMPLETE) {
return;
}

var remoteContext = this.create_remote_prefixed_local_storage(prefixedLocalStorage);
this.pending_remotes.push(remoteContext);
return remoteContext.done.then(() => {
prefixedLocalStorage.cleanup();
});
};

function fetch_tests_from_prefixed_local_storage(prefixedLocalStorage) {
return tests.fetch_tests_from_prefixed_local_storage(prefixedLocalStorage);
}
expose(fetch_tests_from_prefixed_local_storage, 'fetch_tests_from_prefixed_local_storage');

function timeout() {
if (tests.timeout_length === null) {
tests.timeout();
Expand Down

0 comments on commit a9ac8e5

Please sign in to comment.