Skip to content

Commit bcabdb7

Browse files
committed
Merge branch 'dev' into reactime19.0-Jackie
2 parents 972801e + 374736e commit bcabdb7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1163
-299
lines changed

.babelrc

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
{
2-
"presets": [
3-
"airbnb"
4-
],
2+
"presets": ["airbnb", "@babel/preset-typescript"],
53
"plugins": ["@emotion"]
64
}

.eslintrc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@
33
"airbnb",
44
"plugin:jest/recommended",
55
"plugin:@typescript-eslint/eslint-recommended",
6-
"plugin:@typescript-eslint/recommended"
6+
"plugin:@typescript-eslint/recommended",
7+
"plugin:testing-library/react", // added in for RTL tests
8+
"plugin:jest-dom/recommended" // added in for RTL tests
79
],
810
"root": true,
9-
"plugins": ["jest", "react", "react-hooks", "@typescript-eslint"],
11+
"plugins": ["jest", "react", "react-hooks", "@typescript-eslint", "testing-library", "jest-dom"],
1012
"rules": {
1113
"arrow-parens": [2, "as-needed"],
1214
"import/no-unresolved": "off",

demo-app/src/client/Components/Buttons.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React from 'react';
22
import Increment from './Increment';
33

4-
function Buttons():JSX.Element {
4+
function Buttons(): JSX.Element {
55
const buttons = [];
66
for (let i = 0; i < 4; i++) {
77
buttons.push(<Increment key={i} />);
@@ -20,4 +20,3 @@ function Buttons():JSX.Element {
2020
}
2121

2222
export default Buttons;
23-

jest.config.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
const { TextEncoder } = require('util');
2+
module.exports = {
3+
globals: {
4+
TextEncoder: TextEncoder,
5+
},
6+
transform: {
7+
'^.+\\.(js|ts|tsx)$': 'ts-jest',
8+
},
9+
testPathIgnorePatterns: ['www', './src/backend/__tests__/ignore', './src/app/__tests__enzyme/ignore'],
10+
coveragePathIgnorePatterns: ['/src/backend/__tests__/ignore/', '/src/app/__tests__enzyme/ignore'],
11+
transformIgnorePatterns: ['/node_modules/(?!d3|d3-array|internmap|delaunator|robust-predicates)'],
12+
testRegex: '(/__tests__/.*|\\.(test|spec))\\.(ts|tsx|js)$',
13+
moduleFileExtensions: ['ts', 'tsx', 'js'],
14+
setupFilesAfterEnv: ['@testing-library/jest-dom/extend-expect'],
15+
testEnvironment: 'jsdom',
16+
moduleNameMapper: {
17+
'\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
18+
'<rootDir>/__mocks__/fileMock.js',
19+
'\\.(scss|sass|css)$': 'identity-obj-proxy',
20+
},
21+
};

package.json

Lines changed: 9 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,14 @@
11
{
22
"name": "reactime",
33
"description": "build web extension bundle.js",
4-
"jest": {
5-
"transform": {
6-
"^.+\\.(js|ts|tsx)$": "ts-jest"
7-
},
8-
"testPathIgnorePatterns": [
9-
"www",
10-
"./src/backend/__tests__/ignore"
11-
],
12-
"coveragePathIgnorePatterns": [
13-
"/src/backend/__tests__/ignore/"
14-
],
15-
"transformIgnorePatterns": [
16-
"/node_modules/(?!d3|d3-array|internmap|delaunator|robust-predicates)"
17-
],
18-
"testRegex": "(/__tests__/.*|\\.(test|spec))\\.(ts|tsx|js)$",
19-
"moduleFileExtensions": [
20-
"ts",
21-
"tsx",
22-
"js"
23-
]
24-
},
254
"scripts": {
265
"build": "NODE_OPTIONS=--openssl-legacy-provider webpack --mode production",
276
"dev": "NODE_OPTIONS=--openssl-legacy-provider webpack --mode development --watch",
287
"buildlegacy": "webpack --mode production",
298
"devlegacy": "webpack --mode development --watch",
309
"test": "jest --verbose --coverage",
3110
"test-backend": "jest --verbose --coverage src/backend",
11+
"test-frontend": "jest --verbose --coverage src/app",
3212
"test-on": "./node_modules/.bin/jest $1",
3313
"docker-test-lint": "eslint --ext .js --ext .jsx src",
3414
"docs": "typedoc --json docs --inputFiles src/app --inputFiles src/backend --readme docs/readme.md",
@@ -110,9 +90,12 @@
11090
"@babel/plugin-proposal-decorators": "^7.10.5",
11191
"@babel/preset-env": "^7.12.7",
11292
"@babel/preset-react": "^7.12.7",
93+
"@babel/preset-typescript": "^7.21.5",
11394
"@emotion/babel-plugin": "^11.7.2",
95+
"@inrupt/jest-jsdom-polyfills": "^1.6.2",
11496
"@testing-library/jest-dom": "^4.2.4",
11597
"@testing-library/react": "^13.4.0",
98+
"@testing-library/user-event": "^14.4.3",
11699
"@types/chai": "^4.2.14",
117100
"@types/chrome": "^0.0.119",
118101
"@types/d3": "^7.4.0",
@@ -134,15 +117,19 @@
134117
"eslint-config-airbnb": "^18.2.0",
135118
"eslint-plugin-import": "^2.22.0",
136119
"eslint-plugin-jest": "^22.21.0",
120+
"eslint-plugin-jest-dom": "^4.0.3",
137121
"eslint-plugin-jsx-a11y": "^6.3.1",
138122
"eslint-plugin-react": "^7.20.3",
139123
"eslint-plugin-react-hooks": "^1.7.0",
124+
"eslint-plugin-testing-library": "^5.10.3",
140125
"express": "^4.17.1",
141126
"jest": "^29.5.0",
142127
"jest-cli": "^26.1.0",
143128
"jest-diff": "^26.1.0",
129+
"jest-environment-jsdom": "^29.5.0",
144130
"jest-runner-eslint": "^2.0.0",
145131
"jscharting-react": "^1.2.1",
132+
"jsdom": "^21.1.2",
146133
"prettier": "2.8.4",
147134
"puppeteer": "^14.3.0",
148135
"react-devtools-core": "^4.27.3",
@@ -195,12 +182,12 @@
195182
"d3-scale-chromatic": "^3.0.0",
196183
"d3-shape": "^2.0.0",
197184
"d3-zoom": "^3.0.0",
185+
"identity-obj-proxy": "^3.0.0",
198186
"immer": "^9.0.12",
199187
"intro.js": "^5.0.0",
200188
"intro.js-react": "^0.6.0",
201189
"jest-runner": "^26.1.0",
202190
"jscharting": "^3.0.2",
203-
"jsdom": "^21.1.1",
204191
"jsondiffpatch": "^0.3.11",
205192
"lodash": "^4.17.21",
206193
"prop-types": "^15.7.2",

src/app/__tests__/ActionContainer.test.tsx

Lines changed: 34 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,10 @@
11
/* eslint-disable @typescript-eslint/no-explicit-any */
22
/* eslint-disable react/jsx-filename-extension */
3-
4-
import { shallow, configure } from 'enzyme';
53
import React from 'react';
6-
import Adapter from 'enzyme-adapter-react-16';
4+
import { render, screen, fireEvent } from '@testing-library/react';
5+
import '@testing-library/jest-dom/extend-expect';
76
import ActionContainer from '../containers/ActionContainer';
87
import { useStoreContext } from '../store';
9-
import { emptySnapshots } from '../actions/actions';
10-
import Action from '../components/Action';
11-
import RouteDescription from '../components/RouteDescription';
12-
13-
configure({ adapter: new (Adapter as any)() });
148

159
const state = {
1610
tabs: {
@@ -112,33 +106,45 @@ const state = {
112106
};
113107

114108
const dispatch = jest.fn();
115-
109+
jest.spyOn(React, 'useEffect').mockImplementation(() => jest.fn());
116110
jest.mock('../store');
117-
useStoreContext.mockImplementation(() => [state, dispatch]);
118111

119-
let wrapper;
112+
const mockeduseStoreContext = jest.mocked(useStoreContext);
113+
mockeduseStoreContext.mockImplementation(() => [state, dispatch]);
120114

121-
// actionView={true} must be passed in to <ActionContainer /> in beforeEach() to deal with new
122-
// conditional rendering in ActionContainer that shows/hides time-travel functionality
115+
const MockRouteDescription = jest.fn();
116+
jest.mock('../components/RouteDescription', () => () => {
117+
MockRouteDescription();
118+
return <div>MockRouteDescription</div>;
119+
});
123120

124-
beforeEach(() => {
125-
wrapper = shallow(<ActionContainer actionView={true} />);
126-
// wrapper2 = shallow(<RouteDescription />);
127-
useStoreContext.mockClear();
128-
dispatch.mockClear();
121+
const MockSwitchApp = jest.fn();
122+
jest.mock('../components/SwitchApp', () => () => {
123+
MockSwitchApp();
124+
return <div>MockSwitchApp</div>;
129125
});
130126

131-
describe('testing the emptySnapshot button', () => {
132-
test('emptySnapshot button should dispatch action upon click', () => {
133-
wrapper.find('.empty-button').simulate('click');
134-
expect(dispatch.mock.calls.length).toBe(1);
127+
describe('unit testing for ActionContainer', () => {
128+
beforeEach(() => {
129+
mockeduseStoreContext.mockClear();
130+
dispatch.mockClear();
131+
render(<ActionContainer actionView={true} />);
135132
});
136-
test('emptying snapshots should send emptySnapshot action to dispatch', () => {
137-
wrapper.find('.empty-button').simulate('click');
138-
expect(dispatch.mock.calls[0][0]).toEqual(emptySnapshots());
133+
134+
test('Expect top arrow to be rendered', () => {
135+
expect(screen.getByRole('complementary')).toBeInTheDocument();
139136
});
140-
});
141137

142-
test('number of RouteDescription components should reflect number of unique routes', () => {
143-
expect(wrapper.find(RouteDescription).length).toBe(2);
138+
test('Expect RouteDescription to be rendered', () => {
139+
expect(screen.getAllByText('MockRouteDescription')).toHaveLength(2);
140+
});
141+
142+
test('Expect SwitchApp to be rendered', () => {
143+
expect(screen.getByText('MockSwitchApp')).toBeInTheDocument();
144+
});
145+
146+
test('Click works on clear button', async () => {
147+
fireEvent.click(screen.getAllByRole('button')[0]);
148+
await expect(dispatch).toHaveBeenCalledTimes(1);
149+
});
144150
});
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import React from 'react';
2+
import { render, screen, fireEvent } from '@testing-library/react';
3+
import '@testing-library/jest-dom/extend-expect'; // needed this to extend the jest-dom assertions (ex toHaveTextContent)
4+
import { TextEncoder } from 'util';
5+
global.TextEncoder = TextEncoder;
6+
import ButtonsContainer from '../containers/ButtonsContainer';
7+
import { useStoreContext } from '../store';
8+
9+
// const { Steps } = require('intro.js-react');
10+
jest.mock('../store');
11+
const mockedUsedStoreContext = jest.mocked(useStoreContext);
12+
// useStoreContext as jest.Mock<useStoreContext>.mockImplementaton(() => [state, dispatch])
13+
14+
global.URL.createObjectURL = jest.fn(() => 'https://pdf.com');
15+
global.URL.revokeObjectURL = jest.fn();
16+
17+
describe('Unit testing for ButtonContainer', () => {
18+
beforeEach;
19+
20+
const state = {
21+
tabs: {
22+
87: {
23+
snapshots: [1, 2, 3, 4],
24+
sliderIndex: 0,
25+
viewIndex: -1,
26+
mode: {
27+
paused: false,
28+
locked: false,
29+
persist: false,
30+
},
31+
},
32+
},
33+
currentTab: 87,
34+
};
35+
36+
const currentTab = state.tabs[state.currentTab];
37+
const dispatch = jest.fn();
38+
const exportHandler = jest.fn().mockImplementation(() => 'clicked');
39+
const importHandler = jest.fn();
40+
const fileDownload = jest.fn();
41+
42+
mockedUsedStoreContext.mockImplementation(() => [state, dispatch]);
43+
// useStoreContext.mockImplementation(() => [state, dispatch]);
44+
45+
beforeEach(() => {
46+
dispatch.mockClear();
47+
mockedUsedStoreContext.mockClear();
48+
currentTab.mode = {
49+
paused: false,
50+
persist: false,
51+
};
52+
});
53+
54+
describe('When button container is loaded', () => {
55+
test('should have 4 buttons ', () => {
56+
render(<ButtonsContainer />);
57+
expect(screen.getAllByRole('button')).toHaveLength(4);
58+
expect(screen.getAllByRole('button')[0]).toHaveTextContent('Lock');
59+
expect(screen.getAllByRole('button')[1]).toHaveTextContent('Download');
60+
expect(screen.getAllByRole('button')[2]).toHaveTextContent('Upload');
61+
expect(screen.getAllByRole('button')[3]).toHaveTextContent('How to use');
62+
});
63+
});
64+
65+
describe('When view is unlock', () => {
66+
test('Button should show as unlocked', () => {
67+
state.tabs['87'].mode.paused = true;
68+
render(<ButtonsContainer />);
69+
expect(screen.getAllByRole('button')[0]).toHaveTextContent('Unlock');
70+
});
71+
});
72+
73+
describe('Upload/Download', () => {
74+
test('Clicking upload and download buttons', async () => {
75+
render(<ButtonsContainer />);
76+
fireEvent.click(screen.getAllByRole('button')[1]);
77+
fireEvent.click(screen.getAllByRole('button')[2]);
78+
expect(screen.getAllByRole('button')[1]).toBeInTheDocument();
79+
expect(screen.getAllByRole('button')[2]).toBeInTheDocument();
80+
});
81+
});
82+
});
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import React from 'react';
2+
import { render, screen } from '@testing-library/react';
3+
import '@testing-library/jest-dom/extend-expect'; // needed this to extend the jest-dom assertions (ex toHaveTextContent)
4+
import ErrorContainer from '../containers/ErrorContainer';
5+
import { useStoreContext } from '../store';
6+
7+
const state = {
8+
currentTab: null,
9+
currentTitle: 'No Target',
10+
tabs: {},
11+
};
12+
13+
const MockErrorMsg = jest.fn();
14+
jest.mock('../components/ErrorMsg', () => () => {
15+
MockErrorMsg();
16+
return <div>MockErrorMsg</div>;
17+
});
18+
19+
jest.mock('../store');
20+
const mockeduseStoreContext = jest.mocked(useStoreContext);
21+
22+
const dispatch = jest.fn();
23+
mockeduseStoreContext.mockImplementation(() => [state, dispatch]);
24+
25+
describe('unit testing for ErrorContainer.tsx', () => {
26+
test('logo image renders as expected', () => {
27+
render(<ErrorContainer />);
28+
expect(screen.getByAltText('Reactime Logo')).toBeInTheDocument();
29+
});
30+
31+
test('ErrorMsg component renders as expected', () => {
32+
render(<ErrorContainer />);
33+
expect(screen.getByText('MockErrorMsg')).toBeInTheDocument();
34+
});
35+
36+
test('Reactime website shows as expected', () => {
37+
render(<ErrorContainer />);
38+
expect(
39+
screen.getByText('Please visit the Reactime website for more info.'),
40+
).toBeInTheDocument();
41+
});
42+
43+
describe('Loading Checks show up as expected', () => {
44+
test('Content script launching check shows', () => {
45+
render(<ErrorContainer />);
46+
expect(
47+
screen.getByText(`Checking if content script has been launched on current tab`),
48+
).toBeInTheDocument();
49+
});
50+
test('React Dev Tool Install check shows', () => {
51+
render(<ErrorContainer />);
52+
expect(
53+
screen.getByText(`Checking if React Dev Tools has been installed`),
54+
).toBeInTheDocument();
55+
});
56+
test('Compatible app check shows', () => {
57+
render(<ErrorContainer />);
58+
expect(screen.getByText(`Checking if target is a compatible React app`)).toBeInTheDocument();
59+
});
60+
});
61+
62+
describe('Launching header shows correct tab info', () => {
63+
test('When currentTitle has no target', () => {
64+
render(<ErrorContainer />);
65+
expect(screen.getByText(`Launching Reactime on tab: No Target`)).toBeInTheDocument();
66+
expect(screen.queryByText(`Launching Reactime on tab: Test Page`)).not.toBeInTheDocument();
67+
});
68+
69+
test('When currentTitle has a target title', () => {
70+
state.currentTitle = 'Test Page';
71+
render(<ErrorContainer />);
72+
expect(screen.getByText(`Launching Reactime on tab: Test Page`)).toBeInTheDocument();
73+
expect(screen.queryByText(`Launching Reactime on tab: No Target`)).not.toBeInTheDocument();
74+
});
75+
});
76+
});

0 commit comments

Comments
 (0)