Fix test flakiness by using jest timers
Summary: Some tests were occasionally flaky, by emulating delays, time variation should no longer influence tests. Reviewed By: passy Differential Revision: D28572946 fbshipit-source-id: f4134a6509a0ec0be2e8f36e5623c4882b5531b8
This commit is contained in:
committed by
Facebook GitHub Bot
parent
8d508c8634
commit
d9c986fcf8
@@ -7,6 +7,8 @@
|
|||||||
* @format
|
* @format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
jest.useFakeTimers();
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import produce from 'immer';
|
import produce from 'immer';
|
||||||
import {FlipperPlugin} from '../plugin';
|
import {FlipperPlugin} from '../plugin';
|
||||||
@@ -24,7 +26,6 @@ import {
|
|||||||
import {selectPlugin} from '../reducers/connections';
|
import {selectPlugin} from '../reducers/connections';
|
||||||
import {updateSettings} from '../reducers/settings';
|
import {updateSettings} from '../reducers/settings';
|
||||||
import {switchPlugin} from '../reducers/pluginManager';
|
import {switchPlugin} from '../reducers/pluginManager';
|
||||||
import {sleep} from 'flipper-plugin/src/utils/sleep';
|
|
||||||
|
|
||||||
interface PersistedState {
|
interface PersistedState {
|
||||||
count: 1;
|
count: 1;
|
||||||
@@ -521,7 +522,7 @@ test('PluginContainer + Sandy plugin supports deeplink', async () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
await sleep(10);
|
jest.runAllTimers();
|
||||||
expect(linksSeen).toEqual(['universe!']);
|
expect(linksSeen).toEqual(['universe!']);
|
||||||
expect(renderer.baseElement).toMatchInlineSnapshot(`
|
expect(renderer.baseElement).toMatchInlineSnapshot(`
|
||||||
<body>
|
<body>
|
||||||
@@ -552,7 +553,7 @@ test('PluginContainer + Sandy plugin supports deeplink', async () => {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
await sleep(10);
|
jest.runAllTimers();
|
||||||
expect(linksSeen).toEqual(['universe!']);
|
expect(linksSeen).toEqual(['universe!']);
|
||||||
|
|
||||||
// ...nor does a random other store update that does trigger a plugin container render
|
// ...nor does a random other store update that does trigger a plugin container render
|
||||||
@@ -575,7 +576,7 @@ test('PluginContainer + Sandy plugin supports deeplink', async () => {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
await sleep(10);
|
jest.runAllTimers();
|
||||||
expect(linksSeen).toEqual(['universe!', 'london!']);
|
expect(linksSeen).toEqual(['universe!', 'london!']);
|
||||||
|
|
||||||
// and same link does trigger if something else was selected in the mean time
|
// and same link does trigger if something else was selected in the mean time
|
||||||
@@ -597,7 +598,7 @@ test('PluginContainer + Sandy plugin supports deeplink', async () => {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
await sleep(10);
|
jest.runAllTimers();
|
||||||
expect(linksSeen).toEqual(['universe!', 'london!', 'london!']);
|
expect(linksSeen).toEqual(['universe!', 'london!', 'london!']);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -798,7 +799,7 @@ test('PluginContainer + Sandy device plugin supports deeplink', async () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
await sleep(10);
|
jest.runAllTimers();
|
||||||
expect(linksSeen).toEqual([theUniverse]);
|
expect(linksSeen).toEqual([theUniverse]);
|
||||||
expect(renderer.baseElement).toMatchInlineSnapshot(`
|
expect(renderer.baseElement).toMatchInlineSnapshot(`
|
||||||
<body>
|
<body>
|
||||||
@@ -829,7 +830,7 @@ test('PluginContainer + Sandy device plugin supports deeplink', async () => {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
await sleep(10);
|
jest.runAllTimers();
|
||||||
expect(linksSeen).toEqual([theUniverse]);
|
expect(linksSeen).toEqual([theUniverse]);
|
||||||
|
|
||||||
// ...nor does a random other store update that does trigger a plugin container render
|
// ...nor does a random other store update that does trigger a plugin container render
|
||||||
@@ -852,7 +853,7 @@ test('PluginContainer + Sandy device plugin supports deeplink', async () => {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
await sleep(10);
|
jest.runAllTimers();
|
||||||
expect(linksSeen).toEqual([theUniverse, 'london!']);
|
expect(linksSeen).toEqual([theUniverse, 'london!']);
|
||||||
|
|
||||||
// and same link does trigger if something else was selected in the mean time
|
// and same link does trigger if something else was selected in the mean time
|
||||||
@@ -874,7 +875,7 @@ test('PluginContainer + Sandy device plugin supports deeplink', async () => {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
await sleep(10);
|
jest.runAllTimers();
|
||||||
expect(linksSeen).toEqual([theUniverse, 'london!', 'london!']);
|
expect(linksSeen).toEqual([theUniverse, 'london!', 'london!']);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -976,7 +977,7 @@ test('Sandy plugins support isPluginSupported + selectPlugin', async () => {
|
|||||||
pluginInstance.selectPlugin(definition.id, 'data');
|
pluginInstance.selectPlugin(definition.id, 'data');
|
||||||
expect(store.getState().connections.selectedPlugin).toBe(definition.id);
|
expect(store.getState().connections.selectedPlugin).toBe(definition.id);
|
||||||
expect(pluginInstance.activatedStub).toBeCalledTimes(2);
|
expect(pluginInstance.activatedStub).toBeCalledTimes(2);
|
||||||
await sleep(10);
|
jest.runAllTimers();
|
||||||
expect(renderer.baseElement.querySelector('h1')).toMatchInlineSnapshot(`
|
expect(renderer.baseElement.querySelector('h1')).toMatchInlineSnapshot(`
|
||||||
<h1>
|
<h1>
|
||||||
Plugin1
|
Plugin1
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ import {createStore, Store} from 'redux';
|
|||||||
import produce from 'immer';
|
import produce from 'immer';
|
||||||
import {sleep} from '../promiseTimeout';
|
import {sleep} from '../promiseTimeout';
|
||||||
|
|
||||||
|
jest.useFakeTimers();
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
counter: {count: 0},
|
counter: {count: 0},
|
||||||
somethingUnrelated: false,
|
somethingUnrelated: false,
|
||||||
@@ -73,13 +75,13 @@ describe('sideeffect', () => {
|
|||||||
expect(events.length).toBe(0);
|
expect(events.length).toBe(0);
|
||||||
|
|
||||||
// arrive as a single effect
|
// arrive as a single effect
|
||||||
await sleep(10);
|
jest.advanceTimersByTime(10);
|
||||||
expect(events).toEqual(['counter: 2']);
|
expect(events).toEqual(['counter: 2']);
|
||||||
|
|
||||||
// no more events arrive after unsubscribe
|
// no more events arrive after unsubscribe
|
||||||
unsubscribe();
|
unsubscribe();
|
||||||
store.dispatch({type: 'inc'});
|
store.dispatch({type: 'inc'});
|
||||||
await sleep(10);
|
jest.advanceTimersByTime(10);
|
||||||
expect(events).toEqual(['counter: 2']);
|
expect(events).toEqual(['counter: 2']);
|
||||||
expect(warn).not.toBeCalled();
|
expect(warn).not.toBeCalled();
|
||||||
expect(error).not.toBeCalled();
|
expect(error).not.toBeCalled();
|
||||||
@@ -99,13 +101,13 @@ describe('sideeffect', () => {
|
|||||||
expect(events.length).toBe(0);
|
expect(events.length).toBe(0);
|
||||||
|
|
||||||
// unrelated event doesn't trigger
|
// unrelated event doesn't trigger
|
||||||
await sleep(10);
|
jest.advanceTimersByTime(10);
|
||||||
expect(events.length).toBe(0);
|
expect(events.length).toBe(0);
|
||||||
|
|
||||||
// counter increment does
|
// counter increment does
|
||||||
store.dispatch({type: 'inc'});
|
store.dispatch({type: 'inc'});
|
||||||
|
|
||||||
await sleep(10);
|
jest.advanceTimersByTime(10);
|
||||||
expect(events).toEqual(['counter: 1']);
|
expect(events).toEqual(['counter: 1']);
|
||||||
expect(warn).not.toBeCalled();
|
expect(warn).not.toBeCalled();
|
||||||
expect(error).not.toBeCalled();
|
expect(error).not.toBeCalled();
|
||||||
@@ -125,13 +127,13 @@ describe('sideeffect', () => {
|
|||||||
expect(events.length).toBe(0);
|
expect(events.length).toBe(0);
|
||||||
|
|
||||||
// unrelated event doesn't trigger
|
// unrelated event doesn't trigger
|
||||||
await sleep(10);
|
jest.advanceTimersByTime(10);
|
||||||
expect(events.length).toBe(0);
|
expect(events.length).toBe(0);
|
||||||
|
|
||||||
// counter increment does
|
// counter increment does
|
||||||
store.dispatch({type: 'inc'});
|
store.dispatch({type: 'inc'});
|
||||||
|
|
||||||
await sleep(10);
|
jest.advanceTimersByTime(10);
|
||||||
expect(events).toEqual(['counter: 1']);
|
expect(events).toEqual(['counter: 1']);
|
||||||
expect(warn).not.toBeCalled();
|
expect(warn).not.toBeCalled();
|
||||||
expect(error).not.toBeCalled();
|
expect(error).not.toBeCalled();
|
||||||
@@ -151,7 +153,7 @@ describe('sideeffect', () => {
|
|||||||
store.dispatch({type: 'inc'});
|
store.dispatch({type: 'inc'});
|
||||||
}).not.toThrow();
|
}).not.toThrow();
|
||||||
|
|
||||||
await sleep(10);
|
jest.advanceTimersByTime(10);
|
||||||
expect(error.mock.calls).toMatchInlineSnapshot(`
|
expect(error.mock.calls).toMatchInlineSnapshot(`
|
||||||
Array [
|
Array [
|
||||||
Array [
|
Array [
|
||||||
@@ -178,7 +180,7 @@ describe('sideeffect', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
store.dispatch({type: 'inc'});
|
store.dispatch({type: 'inc'});
|
||||||
await sleep(200);
|
jest.advanceTimersByTime(200);
|
||||||
expect(done).toBe(true);
|
expect(done).toBe(true);
|
||||||
expect(warn.mock.calls[0][0]).toContain("Side effect 'test' took");
|
expect(warn.mock.calls[0][0]).toContain("Side effect 'test' took");
|
||||||
});
|
});
|
||||||
@@ -195,30 +197,40 @@ describe('sideeffect', () => {
|
|||||||
|
|
||||||
// Fires immediately
|
// Fires immediately
|
||||||
store.dispatch({type: 'inc'});
|
store.dispatch({type: 'inc'});
|
||||||
await sleep(100);
|
jest.advanceTimersByTime(100);
|
||||||
expect(events).toEqual(['counter: 1']);
|
expect(events).toEqual(['counter: 1']);
|
||||||
|
|
||||||
// no new tick in the next 100 ms
|
// no new tick in the next 100 ms
|
||||||
await sleep(300);
|
jest.advanceTimersByTime(300);
|
||||||
store.dispatch({type: 'inc'});
|
store.dispatch({type: 'inc'});
|
||||||
|
|
||||||
await sleep(300);
|
jest.advanceTimersByTime(300);
|
||||||
store.dispatch({type: 'inc'});
|
store.dispatch({type: 'inc'});
|
||||||
|
|
||||||
expect(events).toEqual(['counter: 1']);
|
expect(events).toEqual(['counter: 1']);
|
||||||
await sleep(1000);
|
jest.advanceTimersByTime(1000);
|
||||||
expect(events).toEqual(['counter: 1', 'counter: 3']);
|
expect(events).toEqual(['counter: 1', 'counter: 3']);
|
||||||
|
|
||||||
// long time now effect, it will fire right away again
|
// long time no effect, it will fire right away again
|
||||||
await sleep(2000);
|
// N.b. we need call sleep here to create a timeout, as time wouldn't progress otherwise
|
||||||
|
const p = sleep(2000);
|
||||||
|
jest.advanceTimersByTime(2000);
|
||||||
|
await p;
|
||||||
|
|
||||||
// ..but firing an event that doesn't match the selector doesn't reset the timer
|
// ..but firing an event that doesn't match the selector doesn't reset the timer
|
||||||
store.dispatch({type: 'unrelated'});
|
store.dispatch({type: 'unrelated'});
|
||||||
await sleep(100);
|
expect(events).toEqual(['counter: 1', 'counter: 3']);
|
||||||
|
|
||||||
|
jest.advanceTimersByTime(100);
|
||||||
|
|
||||||
store.dispatch({type: 'inc'});
|
store.dispatch({type: 'inc'});
|
||||||
store.dispatch({type: 'inc'});
|
store.dispatch({type: 'inc'});
|
||||||
await sleep(100);
|
jest.advanceTimersByTime(100);
|
||||||
|
|
||||||
|
const p2 = sleep(2000);
|
||||||
|
jest.advanceTimersByTime(2000);
|
||||||
|
await p2;
|
||||||
|
|
||||||
expect(events).toEqual(['counter: 1', 'counter: 3', 'counter: 5']);
|
expect(events).toEqual(['counter: 1', 'counter: 3', 'counter: 5']);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -239,7 +251,7 @@ describe('sideeffect', () => {
|
|||||||
store.dispatch({type: 'inc'});
|
store.dispatch({type: 'inc'});
|
||||||
store.dispatch({type: 'inc'});
|
store.dispatch({type: 'inc'});
|
||||||
// arrive as a single effect
|
// arrive as a single effect
|
||||||
await sleep(10);
|
jest.advanceTimersByTime(10);
|
||||||
expect(events).toEqual(['counter: 2', 'counter: 4']);
|
expect(events).toEqual(['counter: 2', 'counter: 4']);
|
||||||
unsubscribe?.();
|
unsubscribe?.();
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user