mirror of
https://github.com/Foundry376/Mailspring.git
synced 2024-09-20 23:36:21 +08:00
fix(spec): re-enable NylasEnv specs and fix duplicate rejection log
Summary: This re-enables NylasEnv spec and fixes a particularly tricky test involving the Node event loop. See the comments I left on process.unhandledRejection and the new spec Test Plan: Manually run test in isolation and whole suite. All green! Reviewers: juan, mark, halla, spang Reviewed By: spang Differential Revision: https://phab.nylas.com/D3942
This commit is contained in:
parent
a42d67a77a
commit
75f38ec7cd
|
@ -1,6 +1,6 @@
|
|||
import { remote } from 'electron';
|
||||
|
||||
xdescribe("the `NylasEnv` global", function nylasEnvSpec() {
|
||||
describe("the `NylasEnv` global", function nylasEnvSpec() {
|
||||
describe('window sizing methods', () => {
|
||||
describe('::getPosition and ::setPosition', () =>
|
||||
it('sets the position of the window, and can retrieve the position just set', () => {
|
||||
|
@ -142,26 +142,39 @@ xdescribe("the `NylasEnv` global", function nylasEnvSpec() {
|
|||
expect(extra.column).toBe(3)
|
||||
});
|
||||
|
||||
it("Catches unhandled rejections", () => {
|
||||
it("Catches unhandled rejections", async () => {
|
||||
spyOn(NylasEnv, "reportError");
|
||||
const err = new Error("TEST");
|
||||
runs(() => {
|
||||
const p = new Promise((resolve, reject) => {
|
||||
setTimeout(() => {
|
||||
reject(err);
|
||||
}, 10)
|
||||
})
|
||||
p.then(() => {
|
||||
throw new Error("Shouldn't resolve")
|
||||
})
|
||||
advanceClock(10);
|
||||
|
||||
const p = new Promise((resolve, reject) => {
|
||||
reject(err);
|
||||
})
|
||||
waitsFor(() => NylasEnv.reportError.callCount > 0);
|
||||
runs(() => {
|
||||
expect(NylasEnv.reportError.callCount).toBe(1);
|
||||
expect(NylasEnv.reportError.calls[0].args[0]).toBe(err);
|
||||
expect(NylasEnv.reportError.calls[0].args[1].promise).toBeDefined();
|
||||
p.then(() => {
|
||||
throw new Error("Shouldn't resolve")
|
||||
})
|
||||
|
||||
/**
|
||||
* This test was started from within the `setTimeout` block of the
|
||||
* Node event loop. The unhandled rejection will not get caught
|
||||
* until the "pending callbacks" block (which happens next). Since
|
||||
* that happens immediately next it's important that we don't use:
|
||||
*
|
||||
* await new Promise(setImmediate)
|
||||
*
|
||||
* Because of setImmediate's position in the Node event loop
|
||||
* relative to this test and process.on('unhandledRejection'), using
|
||||
* setImmediate would require us to await for it twice.
|
||||
*
|
||||
* We can use the original, no-stubbed-out `setTimeout` to put our
|
||||
* test in the correct spot in the Node event loop relative to
|
||||
* unhandledRejection.
|
||||
*/
|
||||
await new Promise((resolve) => {
|
||||
window.originalSetTimeout(resolve, 0)
|
||||
})
|
||||
|
||||
expect(NylasEnv.reportError.callCount).toBe(1);
|
||||
expect(NylasEnv.reportError.calls[0].args[0]).toBe(err);
|
||||
});
|
||||
|
||||
describe("reportError", () => {
|
||||
|
|
|
@ -232,18 +232,23 @@ class NylasEnvConstructor
|
|||
originalError.stack = convertStackTrace(originalError.stack, sourceMapCache)
|
||||
@reportError(originalError, {url, line, column})
|
||||
|
||||
Promise.onPossiblyUnhandledRejection (error, promise) =>
|
||||
error.stack = convertStackTrace(error.stack, sourceMapCache)
|
||||
|
||||
# API Errors are logged to Sentry only under certain circumstances,
|
||||
# and are logged directly from the NylasAPI class.
|
||||
if error instanceof APIError
|
||||
return if error.statusCode isnt 400
|
||||
|
||||
@reportError(error)
|
||||
|
||||
process.on('uncaughtException', (e) => @reportError(e))
|
||||
process.on('unhandledRejection', (e) => @reportError(e))
|
||||
|
||||
# We use the native Node 'unhandledRejection' instead of Bluebird's
|
||||
# `Promise.onPossiblyUnhandledRejection`. Testing indicates that
|
||||
# the Node process method is a strict superset of Bluebird's handler.
|
||||
# With the introduction of transpiled async/await, it is now possible
|
||||
# to get a native, non-Bluebird Promise. In that case, Bluebird's
|
||||
# `onPossiblyUnhandledRejection` gets bypassed and we miss some
|
||||
# errors. The Node process handler catches all Bluebird promises plus
|
||||
# those created with a native Promise.
|
||||
process.on('unhandledRejection', (error) =>
|
||||
if @inDevMode()
|
||||
error.stack = convertStackTrace(error.stack, sourceMapCache)
|
||||
@reportError(error)
|
||||
else
|
||||
@reportError(error)
|
||||
)
|
||||
|
||||
if @inSpecMode() or @inDevMode()
|
||||
Promise.longStackTraces()
|
||||
|
|
Loading…
Reference in a new issue