Skip to content

Commit 969ff3f

Browse files
adding tests to linkFiber
1 parent 6ceda66 commit 969ff3f

File tree

7 files changed

+196
-271
lines changed

7 files changed

+196
-271
lines changed
Lines changed: 59 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1,105 +1,76 @@
1-
/* eslint-disable jest/no-disabled-tests */
2-
/* eslint-disable react/state-in-constructor */
3-
/* eslint-disable lines-between-class-members */
4-
/* eslint-disable @typescript-eslint/no-unused-vars */
5-
/* eslint-disable @typescript-eslint/no-var-requires */
6-
/* eslint-disable import/order */
7-
/* eslint-disable import/no-extraneous-dependencies */
8-
/* eslint-disable react/jsx-filename-extension */
9-
import { string } from 'prop-types';
10-
import React, { useState } from 'react';
11-
import { render } from 'react-dom';
12-
import linkFiberStart from '../routers/linkFiber';
1+
import linkFiberInitialization from '../routers/linkFiber';
2+
import { Snapshot, Status, FiberRoot } from '../types/backendTypes';
3+
import Tree from '../models/tree';
4+
import { DevTools } from '../types/linkFiberTypes';
5+
import updateAndSendSnapShotTree from '../routers/snapShot';
6+
import throttle from '../controllers/throttle';
7+
8+
describe('linkFiber', () => {
9+
let snapShot: Snapshot;
10+
let mode: Status;
11+
let linkFiber;
12+
const mockPostMessage = jest.fn();
1313

14-
const puppeteer = require('puppeteer');
15-
const SERVER = require('../puppeteerServer');
16-
17-
// Apple uses port 5000 for Air Play.
18-
const APP = 'http://localhost:5001';
19-
20-
let linkFiber;
21-
let mode;
22-
let snapShot;
23-
24-
let browser;
25-
let page;
14+
beforeEach(() => {
15+
// Create snapshot and mode objects
16+
snapShot = {
17+
tree: new Tree('root', 'root'),
18+
};
19+
mode = {
20+
jumping: false,
21+
paused: false,
22+
navigating: undefined,
23+
};
2624

27-
interface fooState {
28-
foo: string;
29-
setFoo?: (string) => void;
30-
}
31-
function App(): JSX.Element {
32-
const [fooState, setFooState] = useState({
33-
foo: 'bar',
25+
linkFiber = linkFiberInitialization(snapShot, mode);
26+
// Set up mock postMessage function
27+
window.postMessage = mockPostMessage;
28+
29+
// Set up mock React DevTools global hook
30+
(window as any).__REACT_DEVTOOLS_GLOBAL_HOOK__ = {
31+
renderers: new Map<1, { version: string }>(),
32+
inject: jest.fn(),
33+
supportsFiber: true,
34+
onCommitFiberRoot: jest.fn(),
35+
onCommitFiberUnmount: jest.fn(),
36+
rendererInterfaces: {},
37+
};
3438
});
35-
return <div>{fooState}</div>;
36-
}
37-
38-
describe('unit test for linkFiber', () => {
39-
beforeAll(async () => {
40-
await SERVER;
41-
const args = puppeteer
42-
.defaultArgs()
43-
.filter((arg) => String(arg).toLowerCase() !== '--disable-extensions');
44-
browser = await puppeteer.launch({
45-
args: args.concat([
46-
'--no-sandbox',
47-
'--disable-setuid-sandbox',
48-
'---extensions-on-chrome-urls',
49-
'--whitelisted-extension-id=fmkadmapgofadopljbjfkapdkoienihi',
50-
'--whitelisted-extension-id=hilpbahfbckghckaiafiiinjkeagmfhn',
51-
'--load-extension=/mnt/d/Libraries/Documents/codeRepos/reactime/src/extension/build',
52-
]),
53-
devtools: true,
54-
ignoreDefaultArgs: true,
55-
});
56-
57-
const c = await puppeteer.connect({
58-
browserWSEndpoint: browser.wsEndpoint(),
59-
ignoreHTTPSErrors: false,
60-
});
6139

62-
page = await browser.newPage();
40+
afterEach(() => {
41+
jest.clearAllMocks();
42+
delete window.__REACT_DEVTOOLS_GLOBAL_HOOK__;
6343
});
6444

65-
afterAll(async () => {
66-
await SERVER.close();
67-
68-
await browser.close();
45+
it('link fiber should return a function', () => {
46+
expect(typeof linkFiber).toBe('function');
6947
});
7048

71-
beforeEach(() => {
72-
snapShot = { tree: null };
73-
mode = {
74-
jumping: false,
75-
paused: false,
76-
};
77-
linkFiber = linkFiberStart(snapShot, mode);
49+
it('returned function should not throw an error', () => {
50+
expect(() => linkFiber()).not.toThrowError();
51+
});
7852

79-
page.waitForFunction(
80-
async (lf) => {
81-
const container = document.createElement('div');
82-
render(<App />, container);
83-
lf(container);
53+
it('should send message to front end that React DevTools is installed', () => {
54+
linkFiber();
55+
expect(mockPostMessage).toHaveBeenCalled();
56+
expect(mockPostMessage).toHaveBeenCalledWith(
57+
{
58+
action: 'devToolsInstalled',
59+
payload: 'devToolsInstalled',
8460
},
85-
{},
86-
linkFiber,
61+
'*',
8762
);
8863
});
8964

90-
test('type of tree should be an object', () => {
91-
expect(typeof snapShot.tree).toBe('object');
65+
it('should not do anything if React Devtools is not installed', () => {
66+
delete window.__REACT_DEVTOOLS_GLOBAL_HOOK__;
67+
expect(() => linkFiber()).not.toThrowError();
68+
expect(mockPostMessage).not.toHaveBeenCalled();
9269
});
9370

94-
test.skip('linkFiber should mutate the snapshot tree property', () => {
95-
expect(snapShot.tree.state).toBe('root');
96-
expect(snapShot.tree.children).toHaveLength(1);
97-
expect(snapShot.tree.children[0].component.state.foo).toBe('bar');
98-
});
71+
xit('should not do anything if the target application is not a React App', () => {});
9972

100-
test.skip('linkFiber should modify the setState of the stateful component', () => {
101-
expect(snapShot.tree.children[0].component.setState.linkFiberChanged).toBe(true);
102-
});
103-
});
73+
xit('should send a message to the front end if the target application is a React App', () => {});
10474

105-
SERVER.close();
75+
xit('should initiate an event listener for visibility change', () => {});
76+
});

src/backend/__tests__/masterTree.test.tsx

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import componentActionsRecord from '../models/masterState';
44
import createTree from '../controllers/createTree/createTree';
55
import Tree from '../models/tree';
66
import React, { useState } from 'react';
7+
import { serializeState, scrubUnserializableMembers } from '../models/tree';
78
import {
89
allowedComponentTypes,
910
nextJSDefaultComponent,
@@ -62,7 +63,7 @@ describe('master tree tests', () => {
6263
componentActionsRecord.clear();
6364
});
6465
describe('create tree tests', () => {
65-
xit('should return a Tree if we pass in a empty fiber node', () => {
66+
it('should return a Tree if we pass in a empty fiber node', () => {
6667
const tree = createTree(mockFiberNode);
6768
const children = tree.children;
6869

@@ -73,7 +74,7 @@ describe('master tree tests', () => {
7374
expect(children[0].state).toEqual('stateless');
7475
});
7576

76-
xit('should filter out NextJS default components with no children or siblings', () => {
77+
it('should filter out NextJS default components with no children or siblings', () => {
7778
for (let name of nextJSDefaultComponent) {
7879
mockFiberNode.elementType.name = name;
7980
const tree = createTree(mockFiberNode);
@@ -99,14 +100,14 @@ describe('master tree tests', () => {
99100
}
100101
});
101102

102-
xit('should filter out remix default components with no children or siblings', () => {
103+
it('should filter out remix default components with no children or siblings', () => {
103104
for (let name of remixDefaultComponents) {
104105
mockFiberNode.elementType.name = name;
105106
const tree = createTree(mockFiberNode);
106107
}
107108
});
108109

109-
xit('should only traverse allowed components', () => {
110+
it('should only traverse allowed components', () => {
110111
for (let tag of allowedComponentTypes) {
111112
mockFiberNode.elementType.tag = tag;
112113
const tree = createTree(mockFiberNode);
@@ -120,11 +121,38 @@ describe('master tree tests', () => {
120121
});
121122
});
122123

123-
xdescribe('add sibling', () => {});
124+
describe('add sibling', () => {});
124125

125-
xdescribe('add children', () => {});
126+
describe('add children', () => {});
126127

127-
xdescribe('createComponentActionsRecord', () => {
128+
describe('serializing state', () => {
129+
const dummyState = {
130+
counter: 1,
131+
playerOne: 'X',
132+
board: [
133+
['', 'O', 'X'],
134+
['', 'O', 'X'],
135+
['O', 'X', ''],
136+
],
137+
};
138+
139+
const circularState: { [key: string]: any } = {};
140+
circularState.circ = circularState;
141+
142+
const serializedState = serializeState(dummyState);
143+
const serializedCircularState = serializeState(circularState);
144+
145+
it('should create a deep copy of state', () => {
146+
expect(dummyState).toEqual(serializedState);
147+
expect(dummyState).not.toBe(serializedState);
148+
});
149+
150+
it('should detect circular state', () => {
151+
expect(serializedCircularState).toEqual('circularState');
152+
});
153+
});
154+
155+
describe('createComponentActionsRecord', () => {
128156
it('should save a new component action record if the Fiber node is a stateful class component', () => {
129157
mockFiberNode.tag = 1; // ClassComponent
130158
mockFiberNode.stateNode = {

src/backend/controllers/throttle.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,3 +78,4 @@ export default function throttle(
7878
}
7979
};
8080
}
81+

src/backend/controllers/timeJump.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ async function updateReactFiberTree(
6767
const { index, state, hooksIndex, hooksState } = targetSnapshot.componentData;
6868
// ------------------------STATEFUL CLASS COMPONENT-------------------------
6969
// Check if it is a stateful class component
70-
// Index can be zero => falsy value => DO NOT REMOVE UNDEFINED
70+
// Index can be zero => falsy value => DO NOT REMOVE NULL
7171
if (index !== null) {
7272
// Obtain the BOUND update method at the given index
7373
const classComponent = componentActionsRecord.getComponentByIndex(index);
@@ -85,7 +85,7 @@ async function updateReactFiberTree(
8585
// Check if it is a stateful functional component
8686
// if yes, grab all relevant components for this snapshot by its index
8787
// call dispatch on each component passing in the corresponding currState value
88-
//index can be zero => falsy value => DO NOT REMOVE UNDEFINED
88+
//index can be zero => falsy value => DO NOT REMOVE NULL
8989
if (hooksIndex !== null) {
9090
// Obtain the array of BOUND update methods at the given indexes.
9191
// NOTE: each useState will be a separate update method. So if a component have 3 useState, we will obtain an array of 3 update methods.

src/backend/linkFiberOLD.ts

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
// import React, { useState } from 'react';
2+
// import { render } from 'react-dom';
3+
// import linkFiberInitialization from '../routers/linkFiber';
4+
5+
// const puppeteer = require('puppeteer');
6+
// const SERVER = require('../puppeteerServer');
7+
8+
// // Apple uses port 5000 for Air Play.
9+
// const APP = 'http://localhost:5001';
10+
11+
// let linkFiber;
12+
// let mode;
13+
// let snapShot;
14+
15+
// let browser;
16+
// let page;
17+
18+
// interface fooState {
19+
// foo: string;
20+
// setFoo?: (string) => void;
21+
// }
22+
// function App(): JSX.Element {
23+
// const [fooState, setFooState] = useState({
24+
// foo: 'bar',
25+
// });
26+
// return <div>{fooState}</div>;
27+
// }
28+
29+
// describe('unit test for linkFiber', () => {
30+
// beforeAll(async () => {
31+
// await SERVER;
32+
// const args = puppeteer
33+
// .defaultArgs()
34+
// .filter((arg) => String(arg).toLowerCase() !== '--disable-extensions');
35+
// browser = await puppeteer.launch({
36+
// args: args.concat([
37+
// '--no-sandbox',
38+
// '--disable-setuid-sandbox',
39+
// '---extensions-on-chrome-urls',
40+
// '--whitelisted-extension-id=fmkadmapgofadopljbjfkapdkoienihi',
41+
// '--whitelisted-extension-id=hilpbahfbckghckaiafiiinjkeagmfhn',
42+
// '--load-extension=/mnt/d/Libraries/Documents/codeRepos/reactime/src/extension/build',
43+
// ]),
44+
// devtools: true,
45+
// ignoreDefaultArgs: true,
46+
// });
47+
48+
// const c = await puppeteer.connect({
49+
// browserWSEndpoint: browser.wsEndpoint(),
50+
// ignoreHTTPSErrors: false,
51+
// });
52+
53+
// page = await browser.newPage();
54+
// });
55+
56+
// afterAll(async () => {
57+
// await SERVER.close();
58+
59+
// await browser.close();
60+
// });
61+
62+
// beforeEach(() => {
63+
// snapShot = { tree: null };
64+
// mode = {
65+
// jumping: false,
66+
// paused: false,
67+
// };
68+
// linkFiber = linkFiberInitialization(snapShot, mode);
69+
70+
// page.waitForFunction(
71+
// async (lf) => {
72+
// const container = document.createElement('div');
73+
// render(<App />, container);
74+
// lf(container);
75+
// },
76+
// {},
77+
// linkFiber,
78+
// );
79+
// });
80+
81+
// it('type of tree should be an object', () => {
82+
// expect(typeof snapShot.tree).toBe('object');
83+
// });
84+
85+
// it('linkFiber should mutate the snapshot tree property', () => {
86+
// expect(snapShot.tree.state).toBe('root');
87+
// expect(snapShot.tree.children).toHaveLength(1);
88+
// expect(snapShot.tree.children[0].component.state.foo).toBe('bar');
89+
// });
90+
91+
// it('linkFiber should modify the setState of the stateful component', () => {
92+
// expect(snapShot.tree.children[0].component.setState.linkFiberChanged).toBe(true);
93+
// });
94+
// });
95+
96+
// SERVER.close();

0 commit comments

Comments
 (0)