Source code

Revision control

Copy as Markdown

Other Tools

<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<meta name="timeout" content="long">
<script src="/resources/testharness.js"></script>
<title>Exceptional cases</title>
</head>
<body>
<script>
function makeTest(...bodies) {
const closeScript = '<' + '/script>';
let src = `
<!DOCTYPE HTML>
<html>
<head>
<title>Document title</title>
<script src="/resources/testharness.js?${Math.random()}">${closeScript}
</head>
<body>
<div id="log"></div>`;
bodies.forEach((body) => {
src += '<script>(' + body + ')();' + closeScript;
});
const iframe = document.createElement('iframe');
document.body.appendChild(iframe);
iframe.contentDocument.write(src);
return new Promise((resolve) => {
window.addEventListener('message', function onMessage(e) {
if (e.source !== iframe.contentWindow) {
return;
}
if (!e.data || e.data.type !=='complete') {
return;
}
window.removeEventListener('message', onMessage);
resolve(e.data);
});
iframe.contentDocument.close();
}).then(({ tests, status }) => {
const summary = {
harness: getEnumProp(status, status.status),
tests: {}
};
tests.forEach((test) => {
summary.tests[test.name] = getEnumProp(test, test.status);
});
return summary;
});
}
function getEnumProp(object, value) {
for (let property in object) {
if (!/^[A-Z]+$/.test(property)) {
continue;
}
if (object[property] === value) {
return property;
}
}
}
promise_test(() => {
return makeTest(
() => { done(); }
).then(({harness, tests}) => {
assert_equals(harness, 'ERROR');
assert_array_equals(Object.keys(tests), []);
});
}, 'completion signaled before testing begins');
promise_test(() => {
return makeTest(
() => { assert_true(true); done(); }
).then(({harness, tests}) => {
assert_equals(harness, 'ERROR');
assert_array_equals(Object.keys(tests), []);
});
}, 'passing assertion before testing begins');
promise_test(() => {
return makeTest(
() => { assert_false(true); }
).then(({harness, tests}) => {
assert_equals(harness, 'ERROR');
assert_array_equals(Object.keys(tests), []);
});
}, 'failing assertion before testing begins');
promise_test(() => {
return makeTest(
() => { throw new Error('this error is expected'); }
).then(({harness, tests}) => {
assert_equals(harness, 'ERROR');
assert_array_equals(Object.keys(tests), []);
});
}, 'uncaught exception before testing begins');
promise_test(() => {
return makeTest(
() => {
setup({ allow_uncaught_exception: true });
throw new Error('this error is expected');
},
() => {
test(function() {}, 'a');
test(function() {}, 'b');
}
).then(({harness, tests}) => {
assert_equals(harness, 'OK');
assert_equals(tests.a, 'PASS');
assert_equals(tests.b, 'PASS');
});
}, 'uncaught exception with subsequent subtest');
promise_test(() => {
return makeTest(
() => {
async_test((t) => {
setTimeout(() => {
setTimeout(() => t.done(), 0);
async_test((t) => { setTimeout(t.done.bind(t), 0); }, 'after');
throw new Error('this error is expected');
}, 0);
}, 'during');
}
).then(({harness, tests}) => {
assert_equals(harness, 'ERROR');
assert_equals(tests.during, 'PASS');
assert_equals(tests.after, 'PASS');
});
}, 'uncaught exception during async_test');
promise_test(() => {
return makeTest(
() => {
promise_test(() => {
return new Promise((resolve) => {
setTimeout(() => {
resolve();
promise_test(() => Promise.resolve(), 'after');
throw new Error('this error is expected');
}, 0);
});
}, 'during');
}
).then(({harness, tests}) => {
assert_equals(harness, 'ERROR');
assert_equals(tests.during, 'PASS');
assert_equals(tests.after, 'PASS');
});
}, 'uncaught exception during promise_test');
promise_test(() => {
return makeTest(
() => { test(() => {}, 'before'); },
() => { throw new Error('this error is expected'); },
() => { test(() => {}, 'after'); }
).then(({harness, tests}) => {
assert_equals(harness, 'ERROR');
assert_equals(tests.before, 'PASS');
assert_equals(tests.after, 'PASS');
});
}, 'uncaught exception between tests');
promise_test(() => {
return makeTest(
() => { promise_test(() => Promise.resolve(), 'before'); },
() => { throw new Error('this error is expected'); },
() => { promise_test(() => Promise.resolve(), 'after'); }
).then(({harness, tests}) => {
assert_equals(harness, 'ERROR');
assert_equals(tests.before, 'PASS');
assert_equals(tests.after, 'PASS');
});
}, 'uncaught exception between promise_tests');
// This feature of testharness.js is only observable in browsers which
// implement the `unhandledrejection` event.
if ('onunhandledrejection' in window) {
promise_test(() => {
return makeTest(
() => { Promise.reject(new Error('this error is expected')); }
).then(({harness, tests}) => {
assert_equals(harness, 'ERROR');
assert_array_equals(Object.keys(tests), []);
});
}, 'unhandled rejection before testing begins');
promise_test(() => {
return makeTest(
() => {
async_test((t) => {
Promise.reject(new Error('this error is expected'));
window.addEventListener('unhandledrejection', () => {
setTimeout(() => t.done(), 0);
async_test((t) => { setTimeout(t.done.bind(t), 0); }, 'after');
t.done();
});
}, 'during');
}
).then(({harness, tests}) => {
assert_equals(harness, 'ERROR');
assert_equals(tests.during, 'PASS');
assert_equals(tests.after, 'PASS');
});
}, 'unhandled rejection during async_test');
promise_test(() => {
return makeTest(
() => {
promise_test(() => {
return new Promise((resolve) => {
Promise.reject(new Error('this error is expected'));
window.addEventListener('unhandledrejection', () => {
resolve();
promise_test(() => Promise.resolve(), 'after');
throw new Error('this error is expected');
}, 0);
});
}, 'during');
}
).then(({harness, tests}) => {
assert_equals(harness, 'ERROR');
assert_equals(tests.during, 'PASS');
assert_equals(tests.after, 'PASS');
});
}, 'unhandled rejection during promise_test');
promise_test(() => {
return makeTest(
() => {
setup({ explicit_done: true });
test(() => {}, 'before');
Promise.reject(new Error('this error is expected'));
window.addEventListener('unhandledrejection', () => {
test(() => {}, 'after');
done();
});
}
).then(({harness, tests}) => {
assert_equals(harness, 'ERROR');
assert_equals(tests.before, 'PASS');
assert_true('after' in tests);
});
}, 'unhandled rejection between tests');
promise_test(() => {
return makeTest(
() => {
setup({ explicit_done: true });
async_test((t) => { setTimeout(t.done.bind(t), 0); }, 'before');
Promise.reject(new Error('this error is expected'));
window.addEventListener('unhandledrejection', () => {
async_test((t) => { setTimeout(t.done.bind(t), 0); }, 'after');
done();
});
}
).then(({harness, tests}) => {
assert_equals(harness, 'ERROR');
assert_equals(tests.before, 'PASS');
assert_equals(tests.after, 'PASS');
});
}, 'unhandled rejection between async_tests');
promise_test(() => {
return makeTest(
() => {
setup({ explicit_done: true });
promise_test(() => Promise.resolve(), 'before');
Promise.reject(new Error('this error is expected'));
window.addEventListener('unhandledrejection', () => {
promise_test(() => Promise.resolve(), 'after');
done();
});
}
).then(({harness, tests}) => {
assert_equals(harness, 'ERROR');
assert_equals(tests.before, 'PASS');
assert_true('after' in tests);
});
}, 'unhandled rejection between promise_tests');
promise_test(() => {
return makeTest(
() => {
test((t) => {
t.add_cleanup(() => { throw new Error('this error is expected'); });
}, 'during');
test((t) => {}, 'after');
}
).then(({harness, tests}) => {
assert_equals(harness, 'ERROR');
assert_equals(tests.during, 'PASS');
assert_equals(tests.after, 'NOTRUN');
});
}, 'exception in `add_cleanup` of a test');
}
promise_test(() => {
return makeTest(
() => {
setup({explicit_done: true});
window.addEventListener('DOMContentLoaded', () => {
async_test((t) => {
t.add_cleanup(() => {
setTimeout(() => {
async_test((t) => t.done(), 'after');
done();
}, 0);
throw new Error('this error is expected');
});
setTimeout(t.done.bind(t), 0);
}, 'during');
});
}
).then(({harness, tests}) => {
assert_equals(harness, 'ERROR');
assert_equals(tests.during, 'PASS');
assert_equals(tests.after, 'NOTRUN');
});
}, 'exception in `add_cleanup` of an async_test');
promise_test(() => {
return makeTest(
() => {
promise_test((t) => {
t.add_cleanup(() => { throw new Error('this error is expected'); });
return Promise.resolve();
}, 'test');
}
).then(({harness, tests}) => {
assert_equals(harness, 'ERROR');
assert_equals(tests.test, 'PASS');
});
}, 'exception in `add_cleanup` of a promise_test');
promise_test(() => {
return makeTest(
() => {
promise_test((t) => {
t.step(() => {
throw new Error('this error is expected');
});
}, 'test');
async_test((t) => t.done(), 'after');
}
).then(({harness, tests}) => {
assert_equals(harness, 'OK');
assert_equals(tests.test, 'FAIL');
assert_equals(tests.after, 'PASS');
});
}, 'exception in `step` of an async_test');
promise_test(() => {
return makeTest(
() => {
promise_test((t) => {
t.step(() => {
throw new Error('this error is expected');
});
return new Promise(() => {});
}, 'test');
// This following test should be run to completion despite the fact
// that the promise returned by the previous test never resolves.
promise_test((t) => Promise.resolve(), 'after');
}
).then(({harness, tests}) => {
assert_equals(harness, 'OK');
assert_equals(tests.test, 'FAIL');
assert_equals(tests.after, 'PASS');
});
}, 'exception in `step` of a promise_test');
</script>
</body>
</html>