Skip to content

Commit

Permalink
Upgrade redux-devtools to latest version (#781)
Browse files Browse the repository at this point in the history
* Initial work of @redux-devtools/app upgrade

* Add missing PersistGate

* Fix lint errors

* Add patches/@redux-devtools+inspector-monitor-trace-tab+1.0.0.patch

* Add window dragable in header & custom buttons

* Custom Settings (Remove connection tab)

* Fix tabs style

* Update docs/redux-devtools-integration.md

* Update default instances state

* Update E2E tests

* Remove socketcluster-client alias

* Cleanup
  • Loading branch information
jhen0409 authored Jul 25, 2023
1 parent 39b0dd9 commit a1c272c
Show file tree
Hide file tree
Showing 22 changed files with 2,150 additions and 1,400 deletions.
56 changes: 30 additions & 26 deletions __e2e__/app.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -202,72 +202,76 @@ describe('Application launch', () => {
});

it('should have @@INIT action on Redux DevTools', async () => {
expect(
await mainWindow.textContent('//div[contains(@class, "actionListRows-")]')
).toMatch(/@@redux\/INIT/); // Last store is `RemoteDev store instance 1`
const el = await mainWindow.locator('div').filter({ hasText: '@@redux/INIT' }).first();
expect(await el.isVisible()).toBeTruthy(); // Last store is `RemoteDev store instance 1`
});

let currentInstance = 'Autoselect instances'; // Default instance
const wait = () => delay(750);
const selectInstance = async (instance) => {
await mainWindow.click(`//div[text()="${currentInstance}"]`);
let el = mainWindow.locator(`//div[text()="${currentInstance}"]`);
expect(await el.isVisible()).toBeTruthy();
await el.click({ force: true });
await wait();
currentInstance = instance;
await mainWindow.click(`//div[text()="${instance}"]`);
el = mainWindow.locator(`//div[text()="${instance}"]`);
expect(await el.isVisible()).toBeTruthy();
await el.click({ force: true });
await wait();
};
const commit = async () => {
await mainWindow.click('//div[text()="Commit"]');
await mainWindow.click('//button[text()="Commit"]', { force: true });
await wait();
};

const expectActions = {
'Redux store instance 1': {
expt: [
/@@INIT/,
/TEST_PASS_FOR_REDUX_STORE_1/,
/SHOW_FOR_REDUX_STORE_1/,
'@@INIT',
'TEST_PASS_FOR_REDUX_STORE_1',
'SHOW_FOR_REDUX_STORE_1',
],
notExpt: [/NOT_SHOW_FOR_REDUX_STORE_1/, /TEST_PASS_FOR_REDUX_STORE_2/],
notExpt: ['NOT_SHOW_FOR_REDUX_STORE_1', 'TEST_PASS_FOR_REDUX_STORE_2'],
},
'Redux store instance 2': {
expt: [/@@INIT/, /TEST_PASS_FOR_REDUX_STORE_2/],
expt: ['@@INIT', 'TEST_PASS_FOR_REDUX_STORE_2'],
notExpt: [
/TEST_PASS_FOR_REDUX_STORE_1/,
/NOT_SHOW_1_FOR_REDUX_STORE_2/,
/NOT_SHOW_2_FOR_REDUX_STORE_2/,
/NOT_SHOW_3_FOR_REDUX_STORE_2/,
'TEST_PASS_FOR_REDUX_STORE_1',
'NOT_SHOW_1_FOR_REDUX_STORE_2',
'NOT_SHOW_2_FOR_REDUX_STORE_2',
'NOT_SHOW_3_FOR_REDUX_STORE_2',
],
},
'MobX store instance 1': {
expt: [/@@INIT/, /testPassForMobXStore1/],
notExpt: [/TEST_PASS_FOR_REDUX_STORE_2/],
expt: ['@@INIT', 'testPassForMobXStore1'],
notExpt: ['TEST_PASS_FOR_REDUX_STORE_2'],
},
'MobX store instance 2': {
expt: [/@@INIT/, /testPassForMobXStore2/],
notExpt: [/testPassForMobXStore1/],
expt: ['@@INIT', 'testPassForMobXStore2'],
notExpt: ['testPassForMobXStore1'],
},
'RemoteDev store instance 1': {
expt: [/@@redux\/INIT/, /TEST_PASS_FOR_REMOTEDEV_STORE_1/],
notExpt: [/testPassForMobXStore2/],
expt: ['@@redux/INIT', 'TEST_PASS_FOR_REMOTEDEV_STORE_1'],
notExpt: ['testPassForMobXStore2'],
},
};

const runExpectActions = (name, val) => {
const runExpectActions = async (name) => {
const { expt, notExpt } = expectActions[name];

for (const action of expt) {
expect(val).toMatch(action);
const el = await mainWindow.locator('div').filter({ hasText: action }).first();
expect(await el.isVisible()).toBeTruthy();
}
for (const action of notExpt) {
expect(val).not.toMatch(action);
const el = await mainWindow.locator('div').filter({ hasText: action }).first();
expect(await el.isVisible()).toBeFalsy();
}
};

const checkInstance = async (name) => {
await selectInstance(name);
const val = await mainWindow.textContent('//div[contains(@class, "actionListRows-")]');
runExpectActions(name, val);
await runExpectActions(name);
await commit();
};

Expand Down
2 changes: 1 addition & 1 deletion app/containers/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import * as debuggerActions from '../actions/debugger';
import * as settingActions from '../actions/setting';
import ReduxDevTools from './ReduxDevTools';
import ReduxDevTools from './redux/DevTools';
import ReactInspector from './ReactInspector';
import FormInput from '../components/FormInput';
import Draggable from '../components/Draggable';
Expand Down
2 changes: 1 addition & 1 deletion app/containers/ReactInspector.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const styles = {
waiting: {
height: '100%',
display: 'flex',
webkitUserSelect: 'none',
WebkitUserSelect: 'none',
textAlign: 'center',
color: '#aaa',
justifyContent: 'center',
Expand Down
143 changes: 0 additions & 143 deletions app/containers/ReduxDevTools.js

This file was deleted.

41 changes: 41 additions & 0 deletions app/containers/redux/DevTools.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { Container, Notification } from '@redux-devtools/ui';
import { clearNotification } from '@redux-devtools/app/lib/esm/actions';
import Actions from '@redux-devtools/app/lib/esm/containers/Actions';
import Settings from './Settings';
import Header from './Header';

const App = () => {
const section = useSelector(state => state.section);
const theme = useSelector(state => state.theme);
const notification = useSelector(state => state.notification);

const dispatch = useDispatch();

let body;
switch (section) {
case 'Settings':
body = <Settings />;
break;
default:
body = <Actions />;
}

return (
<Container themeData={theme}>
<Header section={section} />
{body}
{notification && (
<Notification
type={notification.type}
onClose={() => dispatch(clearNotification())}
>
{notification.message}
</Notification>
)}
</Container>
);
};

export default App;
59 changes: 59 additions & 0 deletions app/containers/redux/Header.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import React, { useCallback } from 'react';
import PropTypes from 'prop-types';
import { useDispatch } from 'react-redux';
import { Tabs, Toolbar, Button, Divider } from '@redux-devtools/ui';
import { GoBook } from 'react-icons/go';
import styled from 'styled-components';
import { changeSection } from '@redux-devtools/app/lib/esm/actions';
import { shell } from 'electron';

const WindowDraggable = styled.div`
display: flex;
flex: 1;
height: 100%;
-webkit-app-region: drag;
-webkit-user-select: none;
`;

const tabs = [{ name: 'Actions' }, { name: 'Settings' }];

const Header = (props) => {
const { section } = props;

const dispatch = useDispatch();

const handleChangeSection = useCallback(
(sec) => dispatch(changeSection(sec)),
[dispatch, changeSection],
);

const openHelp = useCallback(() => shell.openExternal('https://goo.gl/SHU4yL'), []);

return (
<Toolbar compact noBorder borderPosition="bottom">
<Tabs
main
collapsible
tabs={tabs}
onClick={handleChangeSection}
selected={section || 'Actions'}
style={{ flex: 'unset' }}
/>
<WindowDraggable />
<Divider />
<Button
title="Documentation"
tooltipPosition="bottom"
onClick={openHelp}
>
<GoBook />
</Button>
</Toolbar>
);
};

Header.propTypes = {
section: PropTypes.string,
};

export default Header;
26 changes: 26 additions & 0 deletions app/containers/redux/Settings.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/* eslint-disable import/no-named-as-default */
import React, { Component } from 'react';
import Tabs from '@redux-devtools/ui/lib/esm/Tabs/Tabs';
import Themes from '@redux-devtools/app/lib/esm/components/Settings/Themes';

export default class Settings extends Component {
state = { selected: 'Themes' };

tabs = [
{ name: 'Themes', component: Themes },
];

handleSelect = (selected) => {
this.setState({ selected });
};

render() {
return (
<Tabs
tabs={this.tabs}
selected={this.state.selected}
onClick={this.handleSelect}
/>
);
}
}
Loading

0 comments on commit a1c272c

Please sign in to comment.