@samitouri / QOS-React / commits / 9fb794b6ed

Added multi-test setup logic

Brian Vaughn committed Apr 11, 2019 at 09:07 UTC 9fb794b6ed614b800e1ddd2601e72a7b95fc660c
11 files changed +142 -92
.eslintrc
+4
@@ -8,5 +8,9 @@
8 },
9 "settings": {
10 "version": "detect"
11 + },
12 + "globals": {
13 + "__DEV__": "readonly",
14 + "jasmine": "readonly"
15 }
16 }
flow.js
+9
@@ -9,3 +9,12 @@ declare module 'events' {
9
10 declare export default typeof EventEmitter;
11 }
12 +
13 +declare var __DEV__: boolean;
14 +
15 +declare var jasmine: {|
16 + getEnv: () => {|
17 + afterEach: (callback: Function) => void,
18 + beforeEach: (callback: Function) => void,
19 + |},
20 +|};
package.json
+6
@@ -16,6 +16,12 @@
16 "moduleNameMapper": {
17 "^src/(.*)$": "<rootDir>/src/$1"
18 },
19 + "setupFiles": [
20 + "<rootDir>/src/__tests__/setupEnv"
21 + ],
22 + "setupFilesAfterEnv": [
23 + "<rootDir>/src/__tests__/setupTests"
24 + ],
25 "snapshotSerializers": [
26 "<rootDir>/src/__tests__/storeSerializer"
27 ],
src/__tests__/__snapshots__/sanity-test.js.snap deleted
-11
@@ -1,11 +0,0 @@
1 -// Jest Snapshot v1, https://goo.gl/fbAQLP
2 -
3 -exports[`sanity should pass 1`] = `
4 -▾ <Grandparent>
5 - ▾ <Parent>
6 - <Child key="one">
7 - <Child key="two">
8 - ▾ <Parent>
9 - <Child key="one">
10 - <Child key="two">
11 -`;
src/__tests__/__snapshots__/store-test.js.snap new
+20
@@ -0,0 +1,20 @@
1 +// Jest Snapshot v1, https://goo.gl/fbAQLP
2 +
3 +exports[`Store should initialize a multiple root tree 1`] = `
4 +▾ <Parent>
5 + <Child key="one">
6 + <Child key="two">
7 +▾ <Parent>
8 + <Child key="one">
9 + <Child key="two">
10 +`;
11 +
12 +exports[`Store should initialize a simple tree 1`] = `
13 +▾ <Grandparent>
14 + ▾ <Parent>
15 + <Child key="one">
16 + <Child key="two">
17 + ▾ <Parent>
18 + <Child key="one">
19 + <Child key="two">
20 +`;
src/__tests__/sanity-test.js deleted
-41
@@ -1,41 +0,0 @@
1 -// @flow
2 -
3 -import { setup } from './utils';
4 -
5 -describe('sanity', () => {
6 - let React;
7 - let ReactDOM;
8 - let store;
9 -
10 - beforeEach(() => {
11 - store = setup();
12 -
13 - React = require('react');
14 - ReactDOM = require('react-dom');
15 - });
16 -
17 - it('should pass', () => {
18 - function Grandparent() {
19 - return (
20 - <React.Fragment>
21 - <Parent />
22 - <Parent />
23 - </React.Fragment>
24 - );
25 - }
26 -
27 - function Parent() {
28 - return [<Child key="one" />, <Child key="two" />];
29 - }
30 -
31 - function Child() {
32 - return <div>Hi!</div>;
33 - }
34 -
35 - ReactDOM.render(<Grandparent />, document.createElement('div'));
36 -
37 - jest.runAllTimers(); // Flush Bridge operations
38 -
39 - expect(store).toMatchSnapshot();
40 - });
41 -});
src/__tests__/setupEnv.js new
+7
@@ -0,0 +1,7 @@
1 +// @flow
2 +
3 +global.localStorage = {
4 + getItem: jest.fn(),
5 + setItem: jest.fn(),
6 + clear: jest.fn(),
7 +};
src/__tests__/setupTests.js new
+50
@@ -0,0 +1,50 @@
1 +// @flow
2 +
3 +import Agent from 'src/backend/agent';
4 +import { initBackend } from 'src/backend';
5 +import Bridge from 'src/bridge';
6 +import Store from 'src/devtools/store';
7 +import { installHook } from 'src/hook';
8 +
9 +let agent;
10 +let bridge;
11 +let bridgeListeners;
12 +
13 +// Mimic the global we set with Webpack's DefinePlugin
14 +global.__DEV__ = process.env.NODE_ENV !== 'production';
15 +
16 +const env = jasmine.getEnv();
17 +env.beforeEach(() => {
18 + // It's important to reset modules between test runs;
19 + // Without this, ReactDOM won't re-inject itself into the new hook.
20 + jest.resetModules();
21 +
22 + // Fake timers let us flush Bridge operations between setup and assertions.
23 + jest.useFakeTimers();
24 +
25 + installHook(global);
26 +
27 + bridgeListeners = [];
28 +
29 + bridge = new Bridge(
30 + {
31 + listen(callback) {
32 + bridgeListeners.push(callback);
33 + },
34 + send(event: string, payload: any, transferable?: Array<any>) {
35 + bridgeListeners.forEach(callback => callback({ event, payload }));
36 + },
37 + },
38 + { batchDuration: 0 }
39 + );
40 +
41 + agent = new Agent();
42 + agent.addBridge(bridge);
43 +
44 + initBackend(global.__REACT_DEVTOOLS_GLOBAL_HOOK__, agent, global);
45 +
46 + global.store = new Store(bridge);
47 +});
48 +env.afterEach(() => {
49 + delete global.__REACT_DEVTOOLS_GLOBAL_HOOK__;
50 +});
src/__tests__/store-test.js new
+43
@@ -0,0 +1,43 @@
1 +// @flow
2 +
3 +describe('Store', () => {
4 + let React;
5 + let ReactDOM;
6 + let store;
7 +
8 + beforeEach(() => {
9 + store = global.store;
10 +
11 + React = require('react');
12 + ReactDOM = require('react-dom');
13 + });
14 +
15 + it('should initialize a simple tree', () => {
16 + const Grandparent = () => (
17 + <React.Fragment>
18 + <Parent />
19 + <Parent />
20 + </React.Fragment>
21 + );
22 + const Parent = () => [<Child key="one" />, <Child key="two" />];
23 + const Child = () => <div>Hi!</div>;
24 +
25 + ReactDOM.render(<Grandparent />, document.createElement('div'));
26 +
27 + jest.runAllTimers(); // Flush Bridge operations
28 +
29 + expect(store).toMatchSnapshot();
30 + });
31 +
32 + it('should initialize a multiple root tree', () => {
33 + const Parent = () => [<Child key="one" />, <Child key="two" />];
34 + const Child = () => <div>Hi!</div>;
35 +
36 + ReactDOM.render(<Parent />, document.createElement('div'));
37 + ReactDOM.render(<Parent />, document.createElement('div'));
38 +
39 + jest.runAllTimers(); // Flush Bridge operations
40 +
41 + expect(store).toMatchSnapshot();
42 + });
43 +});
src/__tests__/utils.js deleted
-40
@@ -1,40 +0,0 @@
1 -// @flow
2 -
3 -import Agent from 'src/backend/agent';
4 -import { initBackend } from 'src/backend';
5 -import Bridge from 'src/bridge';
6 -import Store from 'src/devtools/store';
7 -import { installHook } from 'src/hook';
8 -
9 -export function setup(): Store {
10 - installHook(global);
11 -
12 - jest.useFakeTimers();
13 -
14 - // TODO Replace this with a polyfill?
15 - global.localStorage = {
16 - getItem: jest.fn(),
17 - setItem: jest.fn(),
18 - clear: jest.fn(),
19 - };
20 -
21 - const listeners = [];
22 - const bridge = new Bridge(
23 - {
24 - listen(callback) {
25 - listeners.push(callback);
26 - },
27 - send(event: string, payload: any, transferable?: Array<any>) {
28 - listeners.forEach(callback => callback({ event, payload }));
29 - },
30 - },
31 - { batchDuration: 0 }
32 - );
33 -
34 - const agent = new Agent();
35 - agent.addBridge(bridge);
36 -
37 - initBackend(global.__REACT_DEVTOOLS_GLOBAL_HOOK__, agent, global);
38 -
39 - return new Store(bridge);
40 -}
src/hook.js
+3
@@ -189,6 +189,9 @@ export function installHook(target: any): DevToolsHook | null {
189 target,
190 '__REACT_DEVTOOLS_GLOBAL_HOOK__',
191 ({
192 + // This property needs to be configurable for the test environment,
193 + // else we won't be able to delete and recreate it beween tests.
194 + configurable: __DEV__,
195 enumerable: false,
196 get() {
197 return hook;