Skip to content

Commit af33719

Browse files
committed
Merge branch 'dev' into testing-cleanup
2 parents 3f80759 + 0d0e8fd commit af33719

File tree

18 files changed

+116
-94
lines changed

18 files changed

+116
-94
lines changed

demo-app-remix/server.js renamed to demo-app-remix/server.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ app.use(morgan("tiny"));
2828
app.all(
2929
"*",
3030
process.env.NODE_ENV === "development"
31-
? (req, res, next) => {
31+
? (req: any, res: any, next: any) => {
3232
purgeRequireCache();
3333

3434
return createRequestHandler({
@@ -41,7 +41,7 @@ app.all(
4141
mode: process.env.NODE_ENV,
4242
})
4343
);
44-
const port = process.env.PORT || 3003;
44+
const port: number | string = process.env.PORT || 3003;
4545

4646
app.listen(port, () => {
4747
console.log(`Express server listening on port ${port}`);

demo-app-remix/tsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"include": ["remix.env.d.ts", "**/*.ts", "**/*.tsx"],
2+
"include": ["remix.env.d.ts", "**/*.ts", "**/*.tsx", "server.ts"],
33
"compilerOptions": {
44
"lib": ["DOM", "DOM.Iterable", "ES2019"],
55
"isolatedModules": true,

src/README.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -47,17 +47,19 @@ Similar approach for Next.js and Remix demo apps
4747
## Linting
4848

4949
_Before_ beginning development, especially on teams, make sure to configure your linter and code formatting to conform to one unified setting (We recommend [the Airbnb style guide](https://github.com/airbnb/javascript)!) This will make reviewing PRs much more readable and less error-prone.  
50-
 
50+
 
51+
52+
# Possible Avenues for Future Iterators
5153

52-
# Possible Avenues for Future Iterators
5354
Here are some notes on the current state of Reactime and considerations for future development.
5455

5556
## Testing
5657

57-
For Reactime unit tests, pre-v.19 there were tests built out in two places. Backend tests were in backend >\_\_tests\_\_. Frontend tests were in src > app >\_\_tests\_\_. In v19, we specifically focused on rebuilding front tests to use React Testing Library (RTL) + Jest. Previously, front end testing existed but utilized Enzyme + Jest . Our decision to move to RTL stemmed on the fact that Enzyme did not support React V17 (third party Enzyme adaptor libraries were created to provide support to previous React versions, but were still very much out of date) and that Enzyme is no longer industry standard. We began the process of creating new frontend tests but they are not complete and this is a great place for future iterators to build out more. Since the new suite of RTL tests are not fully complete, we have kept the older Enzyme tests within the codebase to be referenced (src > app > __tests__enzyme). However, these will not be included in the tests run in the testing scripts.
58+
For Reactime unit tests, pre-v.19 there were tests built out in two places. Backend tests were in backend >\_\_tests\_\_. Frontend tests were in src > app >\_\_tests\_\_. In v19, we specifically focused on rebuilding front tests to use React Testing Library (RTL) + Jest. Previously, front end testing existed but utilized Enzyme + Jest . Our decision to move to RTL stemmed on the fact that Enzyme did not support React V17 (third party Enzyme adaptor libraries were created to provide support to previous React versions, but were still very much out of date) and that Enzyme is no longer industry standard. We began the process of creating new frontend tests but they are not complete and this is a great place for future iterators to build out more. Since the new suite of RTL tests are not fully complete, we have kept the older Enzyme tests within the codebase to be referenced (src > app > **tests**enzyme). However, these will not be included in the tests run in the testing scripts.
5859

5960
## Including Support for Hooks Beyond useState
60-
Reactime currently shows data stored via useState, but does not show data stored via other hooks such as useContext or useReducer. While showing this data would be simple, maintaining the time travel functionality of Reactime with these hooks would not. *Please see file demo-app/src/client/Components/ButtonsWithMoreHooks.jsx for more details.*
61+
62+
Reactime currently shows data stored via useState, but does not show data stored via other hooks such as useContext or useReducer. While showing this data would be simple, maintaining the time travel functionality of Reactime with these hooks would not. _Please see file demo-app/src/client/Components/ButtonsWithMoreHooks.jsx for more details._
6163

6264
To see how hook data is stored on the fiber tree:
6365

@@ -71,20 +73,19 @@ To see how hook data is stored on the fiber tree:
7173
Any changes to console.logs in Reactime can be seen by refreshing the browser the app is running in.
7274

7375
## Replace Functionality for Outdated Packages
74-
Packages emotion/core and material-ui/core haven't been updated to use React 18. This is the reason npm install --force is necessary when installing the dependencies of Reactime. Replacing the functionality these packages perform and removing them from Reactime would ensure compatibility moving forward.
7576

76-
React Developer Tools has deprecated \_\_REACT\_DEVTOOLS\_GLOBAL\_HOOK\_\_, which Reactime uses to extract a running application's fiber tree. At the time of the release of Reactime 19 (May 2023), this tool still works reliably to deliver said fiber tree. This will likely be the case until the React version (React version 18.2 at time of writing) undergoes updates that diverge beyond compatibility with \_\_REACT\_DEVTOOLS\_GLOBAL\_HOOK\_\_. At this time, Reactime will need to change how it extracts an application's fiber tree.
77+
Packages emotion/core and material-ui/core haven't been updated to use React 18. This is the reason npm install --force is necessary when installing the dependencies of Reactime. Replacing the functionality these packages perform and removing them from Reactime would ensure compatibility moving forward.
7778

78-
Changing how Reactime extracts the fiber tree before said React version update may yeild diminishing result, as whatever method will also need to be updated to match React's breaking updates.
79+
React Developer Tools has deprecated \_\_REACT_DEVTOOLS_GLOBAL_HOOK\_\_, which Reactime uses to extract a running application's fiber tree. At the time of the release of Reactime 19 (May 2023), this tool still works reliably to deliver said fiber tree. This will likely be the case until the React version (React version 18.2 at time of writing) undergoes updates that diverge beyond compatibility with \_\_REACT_DEVTOOLS_GLOBAL_HOOK\_\_. At this time, Reactime will need to change how it extracts an application's fiber tree.
7980

81+
Changing how Reactime extracts the fiber tree before said React version update may yeild diminishing result, as whatever method will also need to be updated to match React's breaking updates.
8082

8183
## Redux
8284

8385
Can Reactime be integrated with Redux compatibility so applications using Redux can track state in Reactime?
8486

8587
Yes, but it would be very time-consuming and not the most feasible option while Redux devtools exists already. With how Redux devtools is currently set up, a developer is unable to use Redux devtools as a third-party user and integrate its functionality into their own application, as Redux devtools is meant to be used directly on an application using Redux for state-tracking purposes. Since the devtools do not appear to have a public API for integrated use in an application or it simply does not exist, Redux devtools would need to be rebuilt from the ground up and then integrated into Reactime, or built into Reactime directly still from scratch.
8688

87-
8889
# File Structure
8990

9091
In the _src_ folder, there are three directories we care about: _app_, _backend_, and _extension_.
@@ -100,7 +101,7 @@ src/
100101
│   ├── containers/ # More React components
101102
│   ├── reducers/ # Redux mechanism for updating state
102103
│   ├── styles/ #
103-
│   ├── FrontendTypes.ts # Library of typescript interfaces
104+
│   ├── FrontendTypes.ts # Library of typescript interfaces
104105
│   ├── index.tsx # Starting point for root App component
105106
│   ├── module.d.ts #
106107
│   └── store.tsx #
@@ -127,7 +128,7 @@ src/
127128
│   ├── index.d.ts # Definitely Type file for Index
128129
│   ├── module.d.ts #
129130
│   ├── package.json #
130-
│   ├── puppeteerServer.js #
131+
│   ├── puppeteerServer.ts #
131132
132133
├── extension/ # Chrome Extension code
133134
│   ├── build/ # Destination for bundles and manifest.json (Chrome config file)
@@ -156,7 +157,6 @@ All the diagrams of data flows are available on [MIRO](https://miro.com/app/boar
156157
- Like regular web apps, Chrome Extensions are event-based. The background script is where one typically monitors for browser triggers (e.g. events like closing a tab, for example). The content script is what allows us to read or write to our target web application, usually as a result of [messages passed](https://developer.chrome.com/extensions/messaging) from the background script.
157158
- These two files help us handle requests both from the web browser and from the Reactime extension itself
158159

159-
160160
## Data Flow Architecture
161161

162162
The general flow of data is described in the following steps:
@@ -170,7 +170,6 @@ The general flow of data is described in the following steps:
170170
3. Likewise, when Reactime emits an action due to user interaction -- a "jump" request for example -- a message will be passed from Reactime via the background script to the content script. Then, the content script will pass a message to the target application containing a payload that represents the state the user wants the DOM to reflect or "jump" to.
171171
- One important thing to note here is that this jump action must be dispatched in the target application (i.e. _backend_ land), because only there do we have direct access to the DOM.
172172

173-
174173
# Reacti.me Website:
175174

176175
See [Reacti.me README](https://github.com/reactimetravel/reactime-website/blob/main/README.md) for instruction of how to update the website
@@ -239,6 +238,7 @@ Some relevant sections are reproduced below:
239238
- In other words, a background script works as a sort of middleman, directly maintaining connection with its parent extension, and acting as a proxy enabling communication between it and the content script.
240239

241240
# Past Medium Articles for Reference
241+
242242
- [Reactime 19: What time is it? It’s still Reactime!](https://medium.com/@minzo.kim/what-time-is-it-its-still-reactime-d496adfa908c)
243243
- [Reactime 18.0. Better than ever](https://medium.com/@zdf2424/reactime-18-0-better-than-ever-148b81606257)
244244
- [Reactime v17.0.0: Now with support for the Context API, and a modern UI](https://medium.com/@reactime/reactime-v17-0-0-now-with-support-for-the-context-api-and-a-modern-ui-f0edf9e54dae)

src/app/__tests__/ActionContainer.test.tsx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { render, screen, fireEvent } from '@testing-library/react';
55
import '@testing-library/jest-dom/extend-expect';
66
import ActionContainer from '../containers/ActionContainer';
77
import { useStoreContext } from '../store';
8+
import TravelContainer from '../containers/TravelContainer';
89

910
const state = {
1011
tabs: {
@@ -148,3 +149,17 @@ describe('unit testing for ActionContainer', () => {
148149
expect(dispatch).toHaveBeenCalledTimes(1);
149150
});
150151
});
152+
153+
describe('integration testing for ActionContainer', () => {
154+
beforeEach(() => {
155+
mockeduseStoreContext.mockClear();
156+
dispatch.mockClear();
157+
render(<ActionContainer actionView={true} />);
158+
render(<TravelContainer snapshotsLength={0} />);
159+
});
160+
161+
test('Slider resets on clear button', () => {
162+
fireEvent.click(screen.getAllByRole('button')[0]);
163+
expect(screen.getByRole('slider')).toHaveStyle('left: 0');
164+
});
165+
});

src/app/__tests__/ButtonContainer.test.tsx

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,8 @@ describe('Unit testing for ButtonContainer', () => {
2424
sliderIndex: 0,
2525
viewIndex: -1,
2626
mode: {
27-
paused: false,
27+
paused: true,
2828
locked: false,
29-
persist: false,
3029
},
3130
},
3231
},
@@ -46,7 +45,7 @@ describe('Unit testing for ButtonContainer', () => {
4645
dispatch.mockClear();
4746
mockedUsedStoreContext.mockClear();
4847
currentTab.mode = {
49-
paused: false,
48+
paused: true,
5049
persist: false,
5150
};
5251
});
@@ -55,18 +54,18 @@ describe('Unit testing for ButtonContainer', () => {
5554
test('it should have 4 buttons', () => {
5655
render(<ButtonsContainer />);
5756
expect(screen.getAllByRole('button')).toHaveLength(4);
58-
expect(screen.getAllByRole('button')[0]).toHaveTextContent('Unlocked');
57+
expect(screen.getAllByRole('button')[0]).toHaveTextContent('Locked');
5958
expect(screen.getAllByRole('button')[1]).toHaveTextContent('Download');
6059
expect(screen.getAllByRole('button')[2]).toHaveTextContent('Upload');
6160
expect(screen.getAllByRole('button')[3]).toHaveTextContent('Tutorial');
6261
});
6362
});
6463

65-
describe('When view is locked', () => {
66-
test('Button should show as locked', () => {
64+
describe('When view is unlock', () => {
65+
test('Button should show as unlocked', () => {
6766
state.tabs['87'].mode.paused = true;
6867
render(<ButtonsContainer />);
69-
expect(screen.getAllByRole('button')[0]).toHaveTextContent('Locked');
68+
expect(screen.getAllByRole('button')[0]).toHaveTextContent('Unlocked');
7069
});
7170
});
7271

src/app/__tests__/Loader.test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import Loader from '../components/Loader';
66
describe('unit testing for Loader.tsx', () => {
77
test('renders a loading icon', () => {
88
const { container } = render(<Loader loading={true} result={false} />);
9-
expect(container.firstChild).toHaveClass('css-xp4o0b');
9+
expect(container.firstChild).toHaveClass('css-1tm071a');
1010
});
1111

1212
test('renders a fail icon', () => {

src/app/__tests__/MainSlider.test.tsx

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -40,21 +40,11 @@ describe('Unit testing for MainSlider.jsx', () => {
4040
snapshotsLength: 3,
4141
};
4242

43-
const state = {
44-
tabs: {
45-
100: {
46-
sliderIndex: 1,
47-
},
48-
},
49-
currentTab: 100,
50-
};
51-
52-
// currently not working :( likely needs to correctly handle understanding what tab it should currently be at
5343
test('Component should have min, max, value with correct values to indicate slider position when there are multiple snapshots', () => {
5444
render(<MainSlider {...props} />);
5545
expect(screen.getByRole('slider')).toHaveAttribute('aria-valuemax', '2');
5646
expect(screen.getByRole('slider')).toHaveAttribute('aria-valuemin', '0');
57-
// expect(screen.getByRole('slider')).toHaveAttribute('aria-valuenow','0')
47+
expect(screen.getByRole('slider')).toHaveAttribute('aria-valuenow','0')
5848
});
5949
});
6050
});

src/app/__tests__/Tutorial.test.tsx

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,12 @@ const props = {
1616
let currentStepIndex = 5;
1717

1818
describe('Before Tutorial is entered', () => {
19-
test('How to use button exists', () => {
19+
test('Tutorial button exists', () => {
2020
render(<Tutorial {...props} />);
2121
expect(screen.getByText('Tutorial')).toBeInTheDocument();
2222
});
2323

24-
test('User clicking "How to use" while on map tab button starts map tutorial ', () => {
24+
test('User clicking tutorial button while on map tab starts map tutorial ', () => {
2525
props.currentTabInApp = 'map';
2626
render(<Tutorial {...props} />);
2727
fireEvent.click(screen.getByRole('button'));
@@ -30,17 +30,31 @@ describe('Before Tutorial is entered', () => {
3030
).toBeInTheDocument();
3131
});
3232

33-
test('User clicking "How to use" while on performance tab button starts performance tutorial ', () => {
33+
test('User clicking tutorial button while on performance tab starts performance tutorial ', () => {
3434
props.currentTabInApp = 'performance';
3535
render(<Tutorial {...props} />);
3636
fireEvent.click(screen.getByRole('button'));
3737
expect(screen.getByText('Performance Tab')).toBeInTheDocument();
3838
});
3939

40-
test('User clicking "How to use" while on performance comparison tab, no tutorial available ', () => {
41-
props.currentTabInApp = 'performance-comparison';
42-
currentStepIndex = 1;
40+
test('User clicking tutorial button while on history tab starts history tutorial ', () => {
41+
props.currentTabInApp = 'history';
4342
render(<Tutorial {...props} />);
4443
fireEvent.click(screen.getByRole('button'));
44+
expect(screen.getByText('History Tab')).toBeInTheDocument();
45+
});
46+
47+
test('User clicking tutorial button while on web metrics tab starts web metrics tutorial ', () => {
48+
props.currentTabInApp = 'webmetrics';
49+
render(<Tutorial {...props} />);
50+
fireEvent.click(screen.getByRole('button'));
51+
expect(screen.getByText('Webmetrics Tab')).toBeInTheDocument();
52+
});
53+
54+
test('User clicking tutorial button while on tree tab starts tree tutorial ', () => {
55+
props.currentTabInApp = 'tree';
56+
render(<Tutorial {...props} />);
57+
fireEvent.click(screen.getByRole('button'));
58+
expect(screen.getByText('Tree Tab')).toBeInTheDocument();
4559
});
4660
});

src/app/__tests__/action.test.tsx

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import React from 'react';
2-
import { render, screen } from '@testing-library/react';
2+
import { render, screen, fireEvent } from '@testing-library/react';
3+
import user from '@testing-library/user-event';
34
import '@testing-library/jest-dom/extend-expect'; // needed this to extend the jest-dom assertions (ex toHaveTextContent)
45
import Action from '../components/Action';
6+
import { changeView, changeSlider } from '../actions/actions';
57

68
// @ts-ignore
79
Action.cleanTime = jest.fn().mockReturnValue();
@@ -57,5 +59,42 @@ describe('unit testing for Action.tsx', () => {
5759
render(<Action {...props} />);
5860
expect(screen.getAllByRole('button')[0]).toHaveTextContent('NO TIME');
5961
});
62+
63+
test('When actualDuration exceeds 60, time should be formatted correctly', () => {
64+
props.componentData.actualDuration = 75;
65+
render(<Action {...props} />);
66+
expect(screen.getAllByRole('button')[0]).toHaveTextContent('+01:15.00');
67+
});
68+
69+
test('Using the ArrowUp key on Action snapshot should trigger handleOnKeyDown', () => {
70+
render(<Action {...props} />);
71+
fireEvent.keyDown(screen.getByRole('presentation'), {key: 'ArrowUp', code: 'ArrowUp', charCode: 38});
72+
expect(props.handleOnkeyDown).toHaveBeenCalled();
73+
});
74+
75+
test('Using the ArrowDown key on Action snapshot should trigger handleOnKeyDown', () => {
76+
render(<Action {...props} />);
77+
fireEvent.keyDown(screen.getByRole('presentation'), {key: 'ArrowDown', code: 'ArrowDown', charCode: 40});
78+
expect(props.handleOnkeyDown).toHaveBeenCalled();
79+
});
80+
81+
test('Using the Enter key on Action snapshot should trigger handleOnKeyDown', () => {
82+
render(<Action {...props} />);
83+
fireEvent.keyDown(screen.getByRole('presentation'), {key: 'Enter', code: 'Enter', charCode: 13});
84+
expect(props.handleOnkeyDown).toHaveBeenCalled();
85+
});
86+
87+
test('Clicking the snapshot should trigger onClick', () => {
88+
render(<Action {...props} />);
89+
fireEvent.click(screen.getByRole('presentation'));
90+
expect(props.dispatch).toHaveBeenCalledWith(changeView(2));;
91+
});
92+
93+
test('Clicking Jump button should trigger changeSlider and changeView', () => {
94+
render(<Action {...props} />);
95+
fireEvent.click(screen.getAllByRole('button')[1]);
96+
expect(props.dispatch).toHaveBeenCalledWith(changeSlider(2));
97+
expect(props.dispatch).toHaveBeenCalledWith(changeView(2));
98+
});
6099
});
61100
});

src/app/__tests__enzyme/ignore/ButtonsContainer.test.tsx

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ const state = {
1818
mode: {
1919
paused: false,
2020
locked: false,
21-
persist: false,
2221
},
2322
},
2423
},
@@ -42,7 +41,6 @@ describe('testing the bottom buttons', () => {
4241
useStoreContext.mockClear();
4342
currentTab.mode = {
4443
paused: false,
45-
persist: false,
4644
};
4745
});
4846

@@ -66,24 +64,4 @@ describe('testing the bottom buttons', () => {
6664
});
6765
});
6866

69-
describe.skip('persist button testing', () => {
70-
beforeEach(() => {
71-
wrapper.find('.persist-button').simulate('click');
72-
});
73-
74-
test('persist button dispatches upon click', () => {
75-
expect(dispatch.mock.calls.length).toBe(1);
76-
});
77-
78-
test('persist button dispatches toggleMode action', () => {
79-
expect(dispatch.mock.calls[0][0]).toEqual(toggleMode('persist'));
80-
});
81-
82-
test('persist button displays state', () => {
83-
expect(wrapper.find('.persist-button').text()).toBe('<FontAwesomeIcon />Persist');
84-
state.tabs[state.currentTab].mode.persist = true;
85-
wrapper = shallow(<ButtonsContainer />);
86-
expect(wrapper.find('.persist-button').text()).toBe('<FontAwesomeIcon />Unpersist');
87-
});
88-
});
8967
});

0 commit comments

Comments
 (0)