| <!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> |