Skip to content

Commit 0afa514

Browse files
committed
Merge branch 'dev' into feature-hooks
2 parents 1c0cabe + 3c596b8 commit 0afa514

File tree

12 files changed

+196
-56
lines changed

12 files changed

+196
-56
lines changed

demo-app/src/client/Router.tsx

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,27 +6,26 @@ import Nav from './Components/Nav';
66
import Board from './Components/Board';
77
import Home from './Components/Home';
88
import Buttons from './Components/Buttons';
9-
import ButtonsWithMoreHooks from './Components/ButtonsWithMoreHooks';
9+
// import ButtonsWithMoreHooks from './Components/ButtonsWithMoreHooks';
1010

1111
const domNode = document.getElementById('root');
1212
const root = createRoot(domNode);
1313

1414
root.render(
1515
<BrowserRouter key='BrowserRouter'>
16-
<Nav key='Nav'/>
16+
<Nav key='Nav' />
1717
<Routes key='Routes'>
18-
<Route path='/' element={<Home key='Home'/>} />
18+
<Route path='/' element={<Home key='Home' />} />
1919
<Route path='/tictactoe' element={<Board key='Board' />} />
2020
{/* Switch between the two "buttons" paths below via commenting/uncommenting to alternate between
2121
the public facing Buttons page and the fiber node hooks research page "ButtonsWithMoreHooks" */}
22-
<Route path='/buttons' element={<Buttons key='Buttons'/>} />
22+
<Route path='/buttons' element={<Buttons key='Buttons' />} />
2323
{/* <Route path='/buttons' element={<ButtonsWithMoreHooks key='ButtonsWithMoreHooks'/>} /> */}
2424
</Routes>
25-
</BrowserRouter>
25+
</BrowserRouter>,
2626

27-
/** Comment out everything above this and uncomment the line below to skip all of the
27+
/** Comment out everything above this and uncomment the line below as ButtonsWithMoreHooks import statement to skip all of the
2828
* router components and make fiber node hooks research easier */
2929

30-
// <ButtonsWithMoreHooks/>
31-
30+
// <ButtonsWithMoreHooks/>
3231
);

src/app/__tests__/ButtonContainer.test.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React from 'react';
22
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)
3+
import '@testing-library/jest-dom/extend-expect';
44
import { TextEncoder } from 'util';
55
global.TextEncoder = TextEncoder;
66
import ButtonsContainer from '../containers/ButtonsContainer';
@@ -55,18 +55,18 @@ describe('Unit testing for ButtonContainer', () => {
5555
test('should have 4 buttons ', () => {
5656
render(<ButtonsContainer />);
5757
expect(screen.getAllByRole('button')).toHaveLength(4);
58-
expect(screen.getAllByRole('button')[0]).toHaveTextContent('Lock');
58+
expect(screen.getAllByRole('button')[0]).toHaveTextContent('Unlocked');
5959
expect(screen.getAllByRole('button')[1]).toHaveTextContent('Download');
6060
expect(screen.getAllByRole('button')[2]).toHaveTextContent('Upload');
61-
expect(screen.getAllByRole('button')[3]).toHaveTextContent('How to use');
61+
expect(screen.getAllByRole('button')[3]).toHaveTextContent('Tutorial');
6262
});
6363
});
6464

6565
describe('When view is unlock', () => {
6666
test('Button should show as unlocked', () => {
6767
state.tabs['87'].mode.paused = true;
6868
render(<ButtonsContainer />);
69-
expect(screen.getAllByRole('button')[0]).toHaveTextContent('Unlock');
69+
expect(screen.getAllByRole('button')[0]).toHaveTextContent('Locked');
7070
});
7171
});
7272

src/app/__tests__/Tutorial.test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ let currentStepIndex = 5;
1818
describe('Before Tutorial is entered', () => {
1919
test('How to use button exists', () => {
2020
render(<Tutorial {...props} />);
21-
expect(screen.getByText('How to use')).toBeInTheDocument();
21+
expect(screen.getByText('Tutorial')).toBeInTheDocument();
2222
});
2323

2424
test('User clicking "How to use" while on map tab button starts map tutorial ', () => {

src/app/__tests__/WebMetrics.test.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,14 @@ import React from 'react';
22
import { render } from '@testing-library/react';
33
import '@testing-library/jest-dom/extend-expect';
44
import WebMetrics from '../components/WebMetrics';
5+
import { useStoreContext } from '../store';
56

67
jest.mock('react-apexcharts', () => ({ __esModule: true, default: () => <div /> }));
8+
const dispatch = jest.fn();
9+
// jest.spyOn(React, 'useEffect').mockImplementation(() => jest.fn());
10+
jest.mock('../store');
11+
const mockedStoreContext = jest.mocked(useStoreContext);
12+
mockedStoreContext.mockImplementation(() => [, dispatch]);
713

814
describe('WebMetrics graph testing', () => {
915
test('should have 1 div with class name "metric" ', () => {

src/app/components/Diff.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ function Diff(props: DiffProps): JSX.Element {
1515
const [mainState] = useStoreContext();
1616
const { currentTab, tabs } = mainState; // k/v pairs of mainstate store object being created
1717
const { snapshots, viewIndex, sliderIndex } = tabs[currentTab];
18-
let previous:unknown;
18+
let previous: unknown;
1919

2020
// previous follows viewIndex or sliderIndex
2121
if (viewIndex !== -1) {
@@ -66,7 +66,6 @@ function Diff(props: DiffProps): JSX.Element {
6666
const html: StatelessCleanning = formatters.html.format(delta, previousDisplay);
6767
if (show) formatters.html.showUnchanged();
6868
else formatters.html.hideUnchanged();
69-
7069
if (previous === undefined || delta === undefined) {
7170
return (
7271
<div className='no-data-message'>

src/app/components/FrontendTypes.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ export interface TreeProps {
3232
state?: string | object;
3333
stateSnaphot?: object;
3434
children?: any[];
35+
snapshots?:[];
36+
currLocation?:object;
37+
38+
3539
};
3640
}
3741

src/app/components/StateRoute/History.tsx

Lines changed: 62 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,6 @@ function History(props: Record<string, unknown>): JSX.Element {
135135
const treeRoot = d3.hierarchy(data);
136136
return d3.tree().size([innerWidth, innerHeight])(treeRoot);
137137
};
138-
// const hierarchy = d3.hierarchy(root);
139138
const d3root = tree(root);
140139

141140
const currNode = labelCurrentNode(d3root);
@@ -171,36 +170,81 @@ function History(props: Record<string, unknown>): JSX.Element {
171170
.enter()
172171
.append('g')
173172
.style('cursor', 'pointer')
173+
.attr('class', `snapshotNode`)
174174
.on('click', (event, d) => {
175175
dispatch(changeView(d.data.index));
176176
dispatch(changeSlider(d.data.index));
177-
})
178-
// added to display state change information to node tree
179-
.on('mouseover', (event, d) => {
180-
const [x, y] = d3.pointer(event);
177+
181178
// created popup div and appended it to display div(returned in this function)
182179
// D3 doesn't utilize z-index for priority,
183180
// rather decides on placement by order of rendering
184181
// needed to define the return div with a className to have a target to append to
185182
// with the correct level of priority
186-
const div = d3
187-
.select('.display')
188-
.append('div')
189-
.attr('class', 'tooltip')
190-
.style('left', `${event.clientX}px`)
191-
.style('top', `${event.clientY}px`);
192-
d3.selectAll('.tooltip').html(findDiff(d.data.index));
183+
function renderToolTip() {
184+
const [x, y] = d3.pointer(event);
185+
const div = d3
186+
.select('.display:first-child')
187+
.append('div')
188+
.attr('class', `tooltip`)
189+
.attr('id', `tt-${d.data.index}`)
190+
.style('left', `${event.clientX - 10}px`)
191+
.style('top', `${event.clientY - 10}px`)
192+
.style('max-height', `25%`)
193+
.style('overflow', `scroll`);
194+
d3.selectAll('.tooltip').html(findDiff(d.data.index));
195+
}
196+
197+
if (d3.selectAll('.tooltip')._groups['0'].length === 0) {
198+
renderToolTip();
199+
} else {
200+
if (d3.selectAll(`#tt-${d.data.index}`)._groups['0'].length === 0) {
201+
d3.selectAll('.tooltip').remove();
202+
renderToolTip();
203+
}
204+
}
193205
})
194-
.on('mouseout', (d) => {
195-
// when appending divs on mouseover the appended dives would not disappear
196-
// when using D3's 'transition' on mouseover/mouseout
197-
// solution: remove all tooltop divs on mouseout
198-
d3.selectAll('.tooltip').remove();
206+
.on('mouseenter', function (event, d) {
207+
const [x, y] = d3.pointer(event);
208+
if (d3.selectAll('.tooltip')._groups['0'].length === 0) {
209+
const div = d3
210+
.select('.display:first-child')
211+
.append('div')
212+
.attr('class', `tooltip`)
213+
.attr('id', `tt-${d.data.index}`)
214+
.style('left', `${event.clientX + 0}px`)
215+
.style('top', `${event.clientY + 0}px`)
216+
.style('max-height', `25%`)
217+
.style('overflow', `auto`)
218+
.on('mouseenter', function (event, d) {})
219+
.on('mouseleave', function (event, d) {
220+
d3.selectAll('.tooltip').remove().style('display', 'hidden');
221+
});
222+
223+
d3.selectAll('.tooltip').html(findDiff(d.data.index));
224+
}
225+
})
226+
.on('mouseleave', function (event, d) {
227+
if (event.relatedTarget.id !== `tt-${d.data.index}`) {
228+
d3.selectAll('.tooltip').transition().delay(100).remove();
229+
}
199230
})
200-
.attr('transform', (d) => `translate(${d.x},${d.y})`);
231+
232+
.attr('transform', function (d) {
233+
return `translate(${d.x},${d.y})`;
234+
});
235+
236+
const tooltip = d3
237+
.select('.tooltip')
238+
.on('mousemove', function (event, d) {
239+
d3.select('.tooltip').style('opacity', '1');
240+
})
241+
.on('mouseleave', function (event, d) {
242+
d3.selectAll('.tooltip').remove();
243+
});
201244

202245
node
203246
.append('circle')
247+
204248
.attr('fill', (d) => {
205249
if (d.data.index === currLocation.index) {
206250
return 'red';

src/app/components/StateRoute/StateRoute.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ const StateRoute = (props: StateRouteProps) => {
7777
// if true invoke render Tree with snapshot
7878
const renderTree = () => {
7979
if (hierarchy) {
80-
return <Tree snapshot={snapshot} />;
80+
return <Tree snapshot={snapshot} snapshots={snapshots} currLocation={currLocation} />;
8181
}
8282
return <div className='noState'>{NO_STATE_MSG}</div>;
8383
};

src/app/components/StateRoute/Tree.tsx

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import JSONTree from 'react-json-tree';
33

44
import { setCurrentTabInApp } from '../../actions/actions';
55
import { useStoreContext } from '../../store';
6-
import { TreeProps } from '../../components/FrontendTypes'
6+
import { TreeProps } from '../../components/FrontendTypes';
77

88
const colors = {
99
scheme: 'paraiso',
@@ -33,20 +33,19 @@ const getItemString = (type, data: { state?: object | string; name: string; chil
3333
return <span />;
3434
};
3535

36-
3736
const Tree = (props: TreeProps) => {
38-
const { snapshot } = props;
37+
const { snapshot, snapshots, currLocation } = props;
3938
const [store, dispatch] = useStoreContext();
4039

4140
useEffect(() => {
42-
dispatch(setCurrentTabInApp('history'));
41+
dispatch(setCurrentTabInApp('tree'));
4342
}, []);
4443

4544
return (
4645
<>
4746
{snapshot && (
4847
<JSONTree
49-
data={snapshot}
48+
data={snapshots[currLocation.index] || snapshot}
5049
theme={{ extend: colors, tree: () => ({ className: 'json-tree' }) }}
5150
shouldExpandNode={() => true}
5251
getItemString={getItemString}

src/app/components/Tutorial.tsx

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,97 @@ export default class Tutorial extends Component<TutorialProps, TutorialState> {
223223
},
224224
];
225225
break;
226+
case 'webmetrics':
227+
steps = [
228+
{
229+
title: 'Webmetrics Tab',
230+
element: '.web-metrics-container',
231+
intro: 'This section will show 4 webmetrics for your page when it loads.',
232+
position: 'top',
233+
},
234+
{
235+
title: 'LCP',
236+
element: document.querySelectorAll('.metric')[0],
237+
intro:
238+
'<strong>Largest Contentful Paint</strong><br/>The amount of time it takes for the largest image, video or text block within the viewport to be fully rendered and interactive.',
239+
position: 'top',
240+
},
241+
242+
{
243+
title: 'FID',
244+
element: document.querySelectorAll('.metric')[1],
245+
intro:
246+
'<strong>First Input Delay</strong><br/>A measurement of load responsiveness, the time from the first user interaction (for example, a click) to the browser responding to that interaction.',
247+
position: 'top',
248+
},
249+
250+
{
251+
title: 'FCP',
252+
element: document.querySelectorAll('.metric')[2],
253+
intro:
254+
'<strong>First Contentful Paint</strong><br/>The amount of time it takes to render the first DOM element of any variety',
255+
position: 'top',
256+
},
257+
258+
{
259+
title: 'TTFB',
260+
element: document.querySelectorAll('.metric')[3],
261+
intro:
262+
"<strong>Time To First Byte</strong><br/>The amount of time it takes for a user's browser to receive the first byte of page content from the server.",
263+
position: 'top',
264+
},
265+
];
266+
break;
267+
case 'history':
268+
steps = [
269+
{
270+
title: 'History Tab',
271+
element: '.display',
272+
intro:
273+
'The history tab shows all snapshots as a timeline and includes branches to represent divergent state history created from time traveling backwards and making new state changes.',
274+
position: 'top',
275+
},
276+
{
277+
title: 'Viewing History Snapshot',
278+
element: document.querySelectorAll('.snapshotNode')[0],
279+
intro:
280+
'Each node will represent a snapshot in the page. <ul><li>A single snapshot will show as a node while multiple snapshots will be represented as a timeline.</li><li>Highlighting over one will show any state changes compared to the previous snapshot. </li><li>Clicking a node will set the snapshot as the current one.</li></ul>',
281+
position: 'top',
282+
},
283+
{
284+
title: 'Navigating through Snapshots',
285+
element: '.routedescription',
286+
intro: 'All snapshots can also be seen and navigated here as well.',
287+
position: 'right',
288+
},
289+
290+
{
291+
title: 'Clicking on Jump Button',
292+
element: document.querySelectorAll('.individual-action')[0],
293+
intro:
294+
'The button on the right of each snapshot can be used to jump to a given point in state to view the state history at that point.',
295+
position: 'right',
296+
},
297+
{
298+
title: 'Renaming The Snapshot',
299+
element: document.querySelectorAll('.action-component-text')[0],
300+
intro:
301+
'A snapshot can be renamed to provided more clarity or distinguish specific snapshots.',
302+
position: 'left',
303+
},
304+
];
305+
break;
306+
case 'tree':
307+
steps = [
308+
{
309+
title: 'Tree Tab',
310+
element: '.display',
311+
intro:
312+
'The tree tab can be used to view a text display of the state snapshots in a JSON format.',
313+
position: 'top',
314+
},
315+
];
316+
break;
226317
default:
227318
steps = [
228319
{

0 commit comments

Comments
 (0)