Skip to content
This repository was archived by the owner on Jul 30, 2020. It is now read-only.

fix(act): improve async act detection #50

Merged
merged 1 commit into from
Aug 27, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion cleanup-after-each.js
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
afterEach(require('./dist').cleanup);
afterEach(() => {
return require('./dist/cleanup-async')();
});
76 changes: 76 additions & 0 deletions src/__tests__/new-act.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
let asyncAct;

jest.mock('react-test-renderer', () => ({
act: cb => {
return cb();
},
}));

beforeEach(() => {
jest.resetModules();
asyncAct = require('../act-compat').asyncAct;
jest.spyOn(console, 'error').mockImplementation(() => {});
});

afterEach(() => {
console.error.mockRestore();
});

test('async act works when it does not exist (older versions of react)', async () => {
const callback = jest.fn();
await asyncAct(async () => {
await Promise.resolve();
await callback();
});
expect(console.error).toHaveBeenCalledTimes(0);
expect(callback).toHaveBeenCalledTimes(1);

callback.mockClear();
console.error.mockClear();

await asyncAct(async () => {
await Promise.resolve();
await callback();
});
expect(console.error).toHaveBeenCalledTimes(0);
expect(callback).toHaveBeenCalledTimes(1);
});

test('async act recovers from errors', async () => {
try {
await asyncAct(async () => {
await null;
throw new Error('test error');
});
} catch (err) {
console.error('call console.error');
}
expect(console.error).toHaveBeenCalledTimes(1);
expect(console.error.mock.calls).toMatchInlineSnapshot(`
Array [
Array [
"call console.error",
],
]
`);
});

test('async act recovers from sync errors', async () => {
try {
await asyncAct(() => {
throw new Error('test error');
});
} catch (err) {
console.error('call console.error');
}
expect(console.error).toHaveBeenCalledTimes(1);
expect(console.error.mock.calls).toMatchInlineSnapshot(`
Array [
Array [
"call console.error",
],
]
`);
});

/* eslint no-console:0 */
73 changes: 72 additions & 1 deletion src/__tests__/no-act.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,80 @@
import { act } from '../';
let act, asyncAct;

beforeEach(() => {
jest.resetModules();
act = require('..').act;
asyncAct = require('../act-compat').asyncAct;
jest.spyOn(console, 'error').mockImplementation(() => {});
});

afterEach(() => {
console.error.mockRestore();
});

jest.mock('react-test-renderer', () => ({}));

test('act works even when there is no act from test renderer', () => {
const callback = jest.fn();
act(callback);
expect(callback).toHaveBeenCalledTimes(1);
expect(console.error).toHaveBeenCalledTimes(0);
});

test('async act works when it does not exist (older versions of react)', async () => {
const callback = jest.fn();
await asyncAct(async () => {
await Promise.resolve();
await callback();
});
expect(console.error).toHaveBeenCalledTimes(0);
expect(callback).toHaveBeenCalledTimes(1);

callback.mockClear();
console.error.mockClear();

await asyncAct(async () => {
await Promise.resolve();
await callback();
});
expect(console.error).toHaveBeenCalledTimes(0);
expect(callback).toHaveBeenCalledTimes(1);
});

test('async act recovers from errors', async () => {
try {
await asyncAct(async () => {
await null;
throw new Error('test error');
});
} catch (err) {
console.error('call console.error');
}
expect(console.error).toHaveBeenCalledTimes(1);
expect(console.error.mock.calls).toMatchInlineSnapshot(`
Array [
Array [
"call console.error",
],
]
`);
});

test('async act recovers from sync errors', async () => {
try {
await asyncAct(() => {
throw new Error('test error');
});
} catch (err) {
console.error('call console.error');
}
expect(console.error).toHaveBeenCalledTimes(1);
expect(console.error.mock.calls).toMatchInlineSnapshot(`
Array [
Array [
"call console.error",
],
]
`);
});

/* eslint no-console:0 */
80 changes: 73 additions & 7 deletions src/__tests__/old-act.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,51 @@
import { asyncAct } from '../act-compat';
let asyncAct;

beforeEach(() => {
jest.resetModules();
asyncAct = require('../act-compat').asyncAct;
jest.spyOn(console, 'error').mockImplementation(() => {});
});

afterEach(() => {
console.error.mockRestore();
});

jest.mock('react-test-renderer', () => ({
act: cb => {
const promise = cb();
cb();
return {
then() {
console.error('blah, do not do this');
return promise;
console.error(
'Warning: Do not await the result of calling TestRenderer.act(...), it is not a Promise.',
);
},
};
},
}));

test('async act works even when the act is an old one', async () => {
jest.spyOn(console, 'error').mockImplementation(() => {});
const callback = jest.fn();
await asyncAct(async () => {
console.error('sigil');
await Promise.resolve();
await callback();
console.error('sigil');
});
expect(console.error.mock.calls).toMatchInlineSnapshot(`Array []`);
expect(console.error.mock.calls).toMatchInlineSnapshot(`
Array [
Array [
Array [
"sigil",
],
],
Array [
"It looks like you're using a version of react-test-renderer that supports the \\"act\\" function, but not an awaitable version of \\"act\\" which you will need. Please upgrade to at least [email protected] to remove this warning.",
],
Array [
"sigil",
],
]
`);
expect(callback).toHaveBeenCalledTimes(1);

// and it doesn't warn you twice
Expand All @@ -32,6 +58,46 @@ test('async act works even when the act is an old one', async () => {
});
expect(console.error).toHaveBeenCalledTimes(0);
expect(callback).toHaveBeenCalledTimes(1);
});

console.error.mockRestore();
test('async act recovers from async errors', async () => {
try {
await asyncAct(async () => {
await null;
throw new Error('test error');
});
} catch (err) {
console.error('call console.error');
}
expect(console.error).toHaveBeenCalledTimes(2);
expect(console.error.mock.calls).toMatchInlineSnapshot(`
Array [
Array [
"It looks like you're using a version of react-test-renderer that supports the \\"act\\" function, but not an awaitable version of \\"act\\" which you will need. Please upgrade to at least [email protected] to remove this warning.",
],
Array [
"call console.error",
],
]
`);
});

test('async act recovers from sync errors', async () => {
try {
await asyncAct(() => {
throw new Error('test error');
});
} catch (err) {
console.error('call console.error');
}
expect(console.error).toHaveBeenCalledTimes(1);
expect(console.error.mock.calls).toMatchInlineSnapshot(`
Array [
Array [
"call console.error",
],
]
`);
});

/* eslint no-console:0 */
Loading