Bug 1263304 - Add wpt tests for async waitUntil(). r=bkelly

This commit is contained in:
Catalin Badea 2016-11-21 02:14:53 +00:00
parent 794fc5461a
commit c313b322bb
2 changed files with 169 additions and 37 deletions

View File

@ -4,27 +4,79 @@
<script src="/resources/testharnessreport.js"></script>
<script src="resources/test-helpers.sub.js"></script>
<script>
promise_test(function(t) {
var script = 'resources/extendable-event-async-waituntil.js';
var scope = 'resources/async-waituntil';
var worker;
return service_worker_unregister_and_register(t, script, scope)
.then(function(registration) {
worker = registration.installing;
return wait_for_state(t, worker, 'activated');
})
.then(function() {
var channel = new MessageChannel();
var saw_message = new Promise(function(resolve) {
channel.port1.onmessage = function(e) { resolve(e.data); }
});
worker.postMessage({port: channel.port2}, [channel.port2]);
return saw_message;
})
.then(function(message) {
assert_equals(message, 'PASS');
return service_worker_unregister_and_done(t, scope);
})
}, 'Calling waitUntil asynchronously throws an exception');
function sync_message(worker, message, transfer) {
let wait = new Promise((res, rej) => {
navigator.serviceWorker.addEventListener('message', function(e) {
if (e.data === 'ACK') {
res();
} else {
rej();
}
});
});
worker.postMessage(message, transfer);
return wait;
}
function runTest(test, step, testBody) {
var scope = './resources/' + step;
var script = 'resources/extendable-event-async-waituntil.js?' + scope;
service_worker_unregister_and_register(test, script, scope)
.then(function(registration) {
let worker = registration.installing;
var channel = new MessageChannel();
var saw_message = new Promise(function(resolve) {
channel.port1.onmessage = function(e) { resolve(e.data); }
});
wait_for_state(test, worker, 'activated')
.then(function() {
return sync_message(worker, { step: 'init', port: channel.port2 },
[channel.port2]);
})
.then(function() { return testBody(worker); })
.then(function() { return saw_message; })
.then(function(output) {
assert_equals(output.result, output.expected);
})
.then(function() { return sync_message(worker, { step: 'done' }); })
.then(() => { service_worker_unregister_and_done(test, scope); })
.catch(unreached_rejection(test));
});
}
function msg_event_test(scope, test) {
var testBody = function(worker) {
return sync_message(worker, { step: scope });
};
runTest(test, scope, testBody);
}
async_test(msg_event_test.bind(this, 'no-current-extension-different-task'),
'Test calling waitUntil in a different task without an existing extension throws');
async_test(msg_event_test.bind(this, 'no-current-extension-different-microtask'),
'Test calling waitUntil in a different microtask without an existing extension throws');
async_test(msg_event_test.bind(this, 'current-extension-different-task'),
'Test calling waitUntil in a different task with an existing extension succeeds');
async_test(msg_event_test.bind(this, 'current-extension-expired-same-microtask-turn'),
'Test calling waitUntil with an existing extension promise handler succeeds');
// The promise handler will queue a new microtask after the check for new
// extensions was performed.
async_test(msg_event_test.bind(this, 'current-extension-expired-same-microtask-turn-extra'),
'Test calling waitUntil at the end of the microtask turn throws');
async_test(msg_event_test.bind(this, 'current-extension-expired-different-task'),
'Test calling waitUntil after the current extension expired in a different task fails');
async_test(function(t) {
var testBody = function(worker) {
return with_iframe('./resources/pending-respondwith-async-waituntil/dummy.html');
}
runTest(t, 'pending-respondwith-async-waituntil', testBody);
}, 'Test calling waitUntil asynchronously with pending respondWith promise.');
</script>

View File

@ -1,20 +1,100 @@
var result = 'FAIL: did not throw.';
// controlled by 'init'/'done' messages.
var resolveLockPromise;
var port;
self.addEventListener('message', function(event) {
event.data.port.postMessage(result);
});
var waitPromise;
var resolveTestPromise;
self.addEventListener('install', function(event) {
self.installEvent = event;
});
self.addEventListener('activate', function(event) {
try {
self.installEvent.waitUntil(new Promise(function(){}));
} catch (error) {
if (error.name == 'InvalidStateError')
result = 'PASS';
else
result = 'FAIL: unexpected exception: ' + error;
switch (event.data.step) {
case 'init':
event.waitUntil(new Promise((res) => { resolveLockPromise = res; }));
port = event.data.port;
break;
case 'done':
resolveLockPromise();
break;
case 'no-current-extension-different-task':
async_task_waituntil(event).then(reportResultExpecting('InvalidStateError'));
break;
case 'no-current-extension-different-microtask':
async_microtask_waituntil(event).then(reportResultExpecting('InvalidStateError'));
break;
case 'current-extension-different-task':
event.waitUntil(new Promise((res) => { resolveTestPromise = res; }));
async_task_waituntil(event).then(reportResultExpecting('OK')).then(resolveTestPromise);
break;
case 'current-extension-expired-same-microtask-turn':
waitPromise = Promise.resolve();
event.waitUntil(waitPromise);
waitPromise.then(() => { return sync_waituntil(event); })
.then(reportResultExpecting('OK'))
break;
case 'current-extension-expired-same-microtask-turn-extra':
// The promise handler queues a new microtask *after* the check for new
// extensions was performed.
waitPromise = Promise.resolve();
event.waitUntil(waitPromise);
waitPromise.then(() => { return async_microtask_waituntil(event); })
.then(reportResultExpecting('InvalidStateError'))
break;
case 'current-extension-expired-different-task':
event.waitUntil(Promise.resolve());
async_task_waituntil(event).then(reportResultExpecting('InvalidStateError'));
break;
}
event.source.postMessage('ACK');
});
self.addEventListener('fetch', function(event) {
var resolveFetch;
let response = new Promise((res) => { resolveFetch = res; });
event.respondWith(response);
async_task_waituntil(event)
.then(reportResultExpecting('OK'))
.then(() => { resolveFetch(new Response('OK')); });
});
function reportResultExpecting(expectedResult) {
return function (result) {
port.postMessage({result : result, expected: expectedResult});
return result;
};
}
function sync_waituntil(event) {
return new Promise((res, rej) => {
try {
event.waitUntil(Promise.resolve());
res('OK');
} catch (error) {
res(error.name);
}
});
}
function async_microtask_waituntil(event) {
return new Promise((res, rej) => {
Promise.resolve().then(() => {
try {
event.waitUntil(Promise.resolve());
res('OK');
} catch (error) {
res(error.name);
}
});
});
}
function async_task_waituntil(event) {
return new Promise((res, rej) => {
setTimeout(() => {
try {
event.waitUntil(Promise.resolve());
res('OK');
} catch (error) {
res(error.name);
}
}, 0);
});
}