Skip to content

Commit fdcd3e9

Browse files
committed
Merge branch 'dev' into bryan/main-reducer-testing
2 parents 7b65cab + c867130 commit fdcd3e9

File tree

10 files changed

+153
-90
lines changed

10 files changed

+153
-90
lines changed

package/timeJump.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1+
/* eslint-disable no-param-reassign */
12
// traverses given tree by accessing children through coords array
23
function traverseTree(tree, coords) {
34
let curr = tree;
4-
coords.forEach((coord) => {
5+
coords.forEach(coord => {
56
curr = curr.children[coord];
67
});
78
return curr;
@@ -21,8 +22,7 @@ module.exports = (origin, mode) => {
2122
});
2223
}
2324

24-
25-
return (target) => {
25+
return target => {
2626
// setting mode disables setState from posting messages to window
2727
mode.jumping = true;
2828
jump(target);

readme.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# React-Time-Travel
22

3+
![GitHub](https://img.shields.io/github/license/oslabs-beta/react-time-travel)
4+
![Travis (.com) branch](https://img.shields.io/travis/com/oslabs-beta/react-time-travel/dev?label=dev%20build)
5+
![Travis (.com) branch](https://img.shields.io/travis/com/oslabs-beta/react-time-travel/master?label=master%20build)
6+
![npm](https://img.shields.io/npm/v/react-time-travel?color=green)
7+
![David](https://img.shields.io/david/oslabs-beta/react-time-travel)
8+
![DevDependencies](https://img.shields.io/david/dev/oslabs-beta/react-time-travel.svg)
9+
![Snyk Vulnerabilities for GitHub Repo](https://img.shields.io/snyk/vulnerabilities/github/oslabs-beta/react-time-travel)
10+
311
<p align="center">
412
<img src="demo.gif" alt="Demo of React-Time-Travel">
513
</p>
@@ -10,7 +18,7 @@ Two parts are needed for this tool to function. The chrome extension must be ins
1018

1119
## Installing
1220

13-
1. Download the Chrome extension from Chrome Web Store.
21+
1. Download the [extension](https://chrome.google.com/webstore/detail/react-time-travel/cgibknllccemdnfhfpmjhffpjfeidjga) from Chrome Web Store.
1422

1523
2. Install the [npm package](https://www.npmjs.com/package/react-time-travel) in your code.
1624

src/app/__tests__/MainContainer.test.js

Lines changed: 19 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
/* eslint-disable react/jsx-filename-extension */
22

3-
import { mount, configure } from 'enzyme';
3+
import { shallow, configure } from 'enzyme';
44
import React from 'react';
5-
import { act } from 'react-dom/test-utils';
65
import Adapter from 'enzyme-adapter-react-16';
76
import MainContainer from '../containers/MainContainer';
87
import { useStoreContext } from '../store';
@@ -18,15 +17,8 @@ const chrome = require('sinon-chrome');
1817
configure({ adapter: new Adapter() });
1918

2019
const state = {
21-
tabs: {
22-
87: {
23-
snapshots: [{}, {}, {}, {}],
24-
sliderIndex: 0,
25-
viewIndex: -1,
26-
mode: {},
27-
},
28-
},
29-
currentTab: 87,
20+
tabs: {},
21+
currentTab: null,
3022
};
3123

3224
const dispatch = jest.fn();
@@ -35,12 +27,9 @@ useStoreContext.mockImplementation(() => [state, dispatch]);
3527

3628
let wrapper;
3729
global.chrome = chrome;
38-
let eventListener;
3930
const port = {
4031
onMessage: {
41-
addListener: fn => {
42-
eventListener = fn;
43-
},
32+
addListener: () => {},
4433
},
4534
onDisconnect: {
4635
addListener: () => {},
@@ -49,29 +38,32 @@ const port = {
4938
chrome.runtime.connect.returns(port);
5039

5140
beforeEach(() => {
52-
wrapper = mount(<MainContainer />);
41+
wrapper = shallow(<MainContainer />);
5342
useStoreContext.mockClear();
5443
dispatch.mockClear();
5544
});
5645

5746
describe('MainContainer rendering', () => {
58-
test.skip('With no connection, should not render any containers', () => {
59-
expect(wrapper.text()).toEqual('please install our npm package in your app');
47+
test('With no snapshots, should not render any containers', () => {
48+
expect(wrapper.text()).toEqual(
49+
'No React application found. Please install our npm package in your app.',
50+
);
6051
expect(wrapper.find(HeadContainer).length).toBe(0);
6152
expect(wrapper.find(ActionContainer).length).toBe(0);
6253
expect(wrapper.find(StateContainer).length).toBe(0);
6354
expect(wrapper.find(TravelContainer).length).toBe(0);
6455
expect(wrapper.find(ButtonsContainer).length).toBe(0);
6556
});
66-
test('With connection established, should render all containers', () => {
67-
// fake connect
68-
act(() => {
69-
eventListener({
70-
action: 'initialConnectSnapshots',
71-
payload: 'test',
72-
});
73-
});
74-
wrapper.update();
57+
test('With snapshots, should render all containers', () => {
58+
state.currentTab = 87;
59+
state.tabs[87] = {
60+
snapshots: [{}],
61+
viewIndex: -1,
62+
sliderIndex: 0,
63+
mode: {},
64+
};
65+
66+
wrapper = shallow(<MainContainer />);
7567
expect(wrapper.find(HeadContainer).length).toBe(1);
7668
expect(wrapper.find(ActionContainer).length).toBe(1);
7769
expect(wrapper.find(StateContainer).length).toBe(1);

src/app/components/SwitchApp.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ const SwitchAppDropdown = () => {
99
const tabsArray = [];
1010

1111
Object.keys(tabs).forEach(tab => {
12-
if (tab !== 'sourceTab') tabsArray.push({ value: tab, label: tabs[tab].title });
12+
tabsArray.push({ value: tab, label: tabs[tab].title });
1313
});
1414

1515
const currTab = {

src/app/containers/MainContainer.jsx

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useEffect, useState } from 'react';
1+
import React, { useEffect } from 'react';
22
import HeadContainer from './HeadContainer';
33
import ActionContainer from './ActionContainer';
44
import StateContainer from './StateContainer';
@@ -11,7 +11,6 @@ import {
1111
import { useStoreContext } from '../store';
1212

1313
function MainContainer() {
14-
const [npmExists, setnpm] = useState(false);
1514
const [store, dispatch] = useStoreContext();
1615
const { tabs, currentTab, port: currentPort } = store;
1716

@@ -24,22 +23,21 @@ function MainContainer() {
2423

2524
// listen for a message containing snapshots from the background script
2625
port.onMessage.addListener(message => {
27-
const { action, payload } = message;
26+
const { action, payload, sourceTab } = message;
2827
switch (action) {
2928
case 'deleteTab': {
3029
dispatch(deleteTab(payload));
3130
break;
3231
}
3332

3433
case 'sendSnapshots': {
35-
if (payload.sourceTab !== currentTab) dispatch(setTab(payload.sourceTab));
34+
dispatch(setTab(sourceTab));
3635
// set state with the information received from the background script
3736
dispatch(addNewSnapshots(payload));
3837
break;
3938
}
4039
case 'initialConnectSnapshots': {
4140
dispatch(initialConnect(payload));
42-
setnpm(true);
4341
break;
4442
}
4543
default:
@@ -54,7 +52,19 @@ function MainContainer() {
5452
dispatch(setPort(port));
5553
});
5654

57-
if (!npmExists) return <div style={{ color: 'black' }}>Please install our npm package in your app</div>;
55+
if (!tabs[currentTab]) {
56+
return (
57+
<div className="error-container">
58+
<a
59+
href="https://www.npmjs.com/package/react-time-travel"
60+
target="_blank"
61+
rel="noopener noreferrer"
62+
>
63+
No React application found. Please install our npm package in your app.
64+
</a>
65+
</div>
66+
);
67+
}
5868
const { viewIndex, sliderIndex, snapshots } = tabs[currentTab];
5969

6070
// if viewIndex is -1, then use the sliderIndex instead

src/app/reducers/mainReducer.js

Lines changed: 20 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -111,46 +111,40 @@ export default (state, action) => produce(state, draft => {
111111
const { payload } = action;
112112
Object.keys(payload).forEach(tab => {
113113
// check if tab exists in memory
114-
if (!tabs[tab]) {
115-
// add new tab
116-
tabs[tab] = {
117-
...payload[tab],
118-
sliderIndex: 0,
119-
viewIndex: -1,
120-
intervalId: null,
121-
playing: false,
122-
};
123-
}
114+
// add new tab
115+
tabs[tab] = {
116+
...payload[tab],
117+
sliderIndex: 0,
118+
viewIndex: -1,
119+
intervalId: null,
120+
playing: false,
121+
};
124122
});
125123

126124
// only set first tab if current tab is non existent
127125
const firstTab = parseInt(Object.keys(payload)[0], 10);
128-
draft.currentTab = currentTab === null ? firstTab : currentTab;
129-
126+
if (currentTab === undefined || currentTab === null) draft.currentTab = firstTab;
130127
break;
131128
}
132129
case types.NEW_SNAPSHOTS: {
133130
const { payload } = action;
134131

135132
Object.keys(tabs).forEach(tab => {
136-
if (tab !== 'sourceTab') {
137-
if (!payload[tab]) {
138-
delete tabs[tab];
139-
} else {
140-
const { snapshots: newSnaps } = payload[tab];
141-
tabs[tab] = {
142-
...tabs[tab],
143-
...payload[tab],
144-
sliderIndex: newSnaps.length - 1,
145-
};
146-
}
133+
if (!payload[tab]) {
134+
delete tabs[tab];
135+
} else {
136+
const { snapshots: newSnaps } = payload[tab];
137+
tabs[tab] = {
138+
...tabs[tab],
139+
...payload[tab],
140+
sliderIndex: newSnaps.length - 1,
141+
};
147142
}
148143
});
149144

150145
// only set first tab if current tab is non existent
151146
const firstTab = parseInt(Object.keys(payload)[0], 10);
152-
draft.currentTab = currentTab === null ? firstTab : currentTab;
153-
147+
if (currentTab === undefined || currentTab === null) draft.currentTab = firstTab;
154148
break;
155149
}
156150
case types.SET_TAB: {
@@ -162,7 +156,7 @@ export default (state, action) => produce(state, draft => {
162156
if (draft.currentTab === action.payload) {
163157
// if the deleted tab was set to currentTab, replace currentTab with
164158
// the first tabId within tabs obj
165-
const newCurrentTab = Object.keys(draft.tabs)[0];
159+
const newCurrentTab = parseInt(Object.keys(draft.tabs)[0], 10);
166160
draft.currentTab = newCurrentTab;
167161
}
168162
break;

src/app/styles/styles.scss

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,30 @@ body {
1818
overflow: hidden;
1919
}
2020

21+
.error-container {
22+
height: 100%;
23+
margin: 0 auto;
24+
background-color: $brand-color;
25+
overflow: hidden;
26+
27+
display: grid;
28+
justify-content: center;
29+
a {
30+
color: white;
31+
margin-top: 5%;
32+
height: 3%;
33+
}
34+
}
35+
2136
.body-container {
2237
height: 94%;
2338
display: grid;
2439
grid-template-columns: 1fr 2fr;
2540
grid-template-rows: 8fr 1fr;
2641
grid-template-areas:
27-
"actions states"
28-
"travel travel"
29-
"buttons buttons";
42+
'actions states'
43+
'travel travel'
44+
'buttons buttons';
3045
}
3146

3247
/* if extension width is less than 500px, stack the body containers */
@@ -35,10 +50,10 @@ body {
3550
grid-template-rows: 3fr 5fr 1fr;
3651
grid-template-columns: auto;
3752
grid-template-areas:
38-
"actions"
39-
"states"
40-
"travel"
41-
"buttons";
53+
'actions'
54+
'states'
55+
'travel'
56+
'buttons';
4257
}
4358
}
4459
.travel-container {

0 commit comments

Comments
 (0)