mirror of
https://github.com/reduxjs/redux-devtools.git
synced 2025-02-16 19:40:58 +03:00
feature(redux-devtools-test-generator): convert to TypeScript (#634)
* stash * stash * compiles * Tests * finish * fix packages * somemore * update snapshot
This commit is contained in:
parent
d1c222d847
commit
d49535da03
|
@ -18,12 +18,14 @@
|
||||||
"babel-loader": "^8.1.0",
|
"babel-loader": "^8.1.0",
|
||||||
"clean-webpack-plugin": "^3.0.0",
|
"clean-webpack-plugin": "^3.0.0",
|
||||||
"cross-env": "^7.0.2",
|
"cross-env": "^7.0.2",
|
||||||
|
"css-loader": "^4.2.1",
|
||||||
"eslint": "^7.6.0",
|
"eslint": "^7.6.0",
|
||||||
"eslint-config-prettier": "^6.11.0",
|
"eslint-config-prettier": "^6.11.0",
|
||||||
"eslint-plugin-babel": "^5.3.1",
|
"eslint-plugin-babel": "^5.3.1",
|
||||||
"eslint-plugin-jest": "^23.20.0",
|
"eslint-plugin-jest": "^23.20.0",
|
||||||
"eslint-plugin-prettier": "^3.1.4",
|
"eslint-plugin-prettier": "^3.1.4",
|
||||||
"eslint-plugin-react": "^7.20.5",
|
"eslint-plugin-react": "^7.20.5",
|
||||||
|
"file-loader": "^6.0.0",
|
||||||
"fork-ts-checker-webpack-plugin": "^5.1.0",
|
"fork-ts-checker-webpack-plugin": "^5.1.0",
|
||||||
"html-webpack-plugin": "^4.3.0",
|
"html-webpack-plugin": "^4.3.0",
|
||||||
"jest": "^26.2.2",
|
"jest": "^26.2.2",
|
||||||
|
|
|
@ -36,6 +36,14 @@
|
||||||
"prepublishOnly": "npm run clean && npm run build"
|
"prepublishOnly": "npm run clean && npm run build"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@types/base16": "^1.0.2",
|
||||||
|
"@types/codemirror": "^0.0.97",
|
||||||
|
"@types/prop-types": "^15.7.3",
|
||||||
|
"@types/react-jsonschema-form": "^1.7.4",
|
||||||
|
"@types/react-select": "^3.0.19",
|
||||||
|
"@types/redux-devtools-themes": "^1.0.0",
|
||||||
|
"@types/simple-element-resize-detector": "^1.3.0",
|
||||||
|
"@types/styled-components": "^5.1.2",
|
||||||
"base16": "^1.0.0",
|
"base16": "^1.0.0",
|
||||||
"codemirror": "^5.56.0",
|
"codemirror": "^5.56.0",
|
||||||
"color": "^3.1.2",
|
"color": "^3.1.2",
|
||||||
|
@ -51,11 +59,8 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@storybook/addon-essentials": "^6.0.21",
|
"@storybook/addon-essentials": "^6.0.21",
|
||||||
"@storybook/react": "^6.0.21",
|
"@storybook/react": "^6.0.21",
|
||||||
"@types/codemirror": "^0.0.97",
|
|
||||||
"@types/enzyme": "^3.10.5",
|
"@types/enzyme": "^3.10.5",
|
||||||
"@types/enzyme-adapter-react-16": "^1.0.6",
|
"@types/enzyme-adapter-react-16": "^1.0.6",
|
||||||
"@types/react-jsonschema-form": "^1.7.4",
|
|
||||||
"@types/react-select": "^3.0.19",
|
|
||||||
"csstype": "^3.0.2",
|
"csstype": "^3.0.2",
|
||||||
"enzyme": "^3.11.0",
|
"enzyme": "^3.11.0",
|
||||||
"enzyme-adapter-react-16": "^1.15.3",
|
"enzyme-adapter-react-16": "^1.15.3",
|
||||||
|
|
|
@ -44,13 +44,13 @@ function isForm<P>(rest?: FormProps<P>): rest is FormProps<P> {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class Dialog<P> extends (PureComponent || Component)<
|
export default class Dialog<P> extends (PureComponent || Component)<
|
||||||
DialogProps | (DialogProps & FormProps<P>)
|
DialogProps | (Omit<DialogProps, 'onSubmit'> & FormProps<P>)
|
||||||
> {
|
> {
|
||||||
submitButton?: HTMLInputElement | null;
|
submitButton?: HTMLInputElement | null;
|
||||||
|
|
||||||
onSubmit = () => {
|
onSubmit = () => {
|
||||||
if (this.submitButton) this.submitButton.click();
|
if (this.submitButton) this.submitButton.click();
|
||||||
else this.props.onSubmit();
|
else (this.props.onSubmit as () => void)();
|
||||||
};
|
};
|
||||||
|
|
||||||
getFormButtonRef: React.RefCallback<HTMLInputElement> = (node) => {
|
getFormButtonRef: React.RefCallback<HTMLInputElement> = (node) => {
|
||||||
|
|
|
@ -23,7 +23,7 @@ export interface EditorProps {
|
||||||
theme?: Base16Theme;
|
theme?: Base16Theme;
|
||||||
foldGutter: boolean;
|
foldGutter: boolean;
|
||||||
autofocus: boolean;
|
autofocus: boolean;
|
||||||
onChange: (value: string, change: CodeMirror.EditorChangeLinkedList) => void;
|
onChange?: (value: string, change: CodeMirror.EditorChangeLinkedList) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -47,7 +47,7 @@ export default class Editor extends Component<EditorProps> {
|
||||||
|
|
||||||
if (this.props.onChange) {
|
if (this.props.onChange) {
|
||||||
this.cm.on('change', (doc, change) => {
|
this.cm.on('change', (doc, change) => {
|
||||||
this.props.onChange(doc.getValue(), change);
|
this.props.onChange!(doc.getValue(), change);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
declare module 'simple-element-resize-detector' {
|
|
||||||
export default function (
|
|
||||||
element: HTMLElement,
|
|
||||||
handler: () => void
|
|
||||||
): HTMLIFrameElement;
|
|
||||||
}
|
|
|
@ -25,14 +25,7 @@ describe('Editor', function () {
|
||||||
|
|
||||||
return range;
|
return range;
|
||||||
};
|
};
|
||||||
const wrapper = mount(
|
const wrapper = mount(<Editor value="var a = 1;" />);
|
||||||
<Editor
|
|
||||||
value="var a = 1;"
|
|
||||||
onChange={() => {
|
|
||||||
//noop
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
|
|
||||||
it('renders correctly', () => {
|
it('renders correctly', () => {
|
||||||
expect(mountToJson(wrapper)).toMatchSnapshot();
|
expect(mountToJson(wrapper)).toMatchSnapshot();
|
||||||
|
|
|
@ -7,7 +7,6 @@ exports[`Editor renders correctly 1`] = `
|
||||||
lineNumbers={true}
|
lineNumbers={true}
|
||||||
lineWrapping={false}
|
lineWrapping={false}
|
||||||
mode="javascript"
|
mode="javascript"
|
||||||
onChange={[Function]}
|
|
||||||
readOnly={false}
|
readOnly={false}
|
||||||
value="var a = 1;"
|
value="var a = 1;"
|
||||||
>
|
>
|
||||||
|
|
|
@ -2,10 +2,10 @@ import React from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { createDevTools } from 'redux-devtools';
|
import { createDevTools } from 'redux-devtools';
|
||||||
import DockMonitor from 'redux-devtools-dock-monitor';
|
import DockMonitor from 'redux-devtools-dock-monitor';
|
||||||
|
import { Location } from 'history';
|
||||||
import DevtoolsInspector from '../../../src/DevtoolsInspector';
|
import DevtoolsInspector from '../../../src/DevtoolsInspector';
|
||||||
import getOptions from './getOptions';
|
import getOptions from './getOptions';
|
||||||
import { base16Themes } from '../../../src/utils/createStylingFromTheme';
|
import { base16Themes } from '../../../src/utils/createStylingFromTheme';
|
||||||
import { Location } from 'history';
|
|
||||||
import { DemoAppState } from './reducers';
|
import { DemoAppState } from './reducers';
|
||||||
|
|
||||||
const CustomComponent = () => (
|
const CustomComponent = () => (
|
||||||
|
|
|
@ -194,7 +194,7 @@ const createRootReducer = (
|
||||||
): Reducer<DemoAppState, DemoAppAction> =>
|
): Reducer<DemoAppState, DemoAppAction> =>
|
||||||
combineReducers<DemoAppState, DemoAppAction>({
|
combineReducers<DemoAppState, DemoAppAction>({
|
||||||
router: connectRouter(history) as Reducer<RouterState, DemoAppAction>,
|
router: connectRouter(history) as Reducer<RouterState, DemoAppAction>,
|
||||||
timeoutUpdateEnabled: (state = false, action: DemoAppAction) =>
|
timeoutUpdateEnabled: (state = false, action) =>
|
||||||
action.type === 'TOGGLE_TIMEOUT_UPDATE'
|
action.type === 'TOGGLE_TIMEOUT_UPDATE'
|
||||||
? action.timeoutUpdateEnabled
|
? action.timeoutUpdateEnabled
|
||||||
: state,
|
: state,
|
||||||
|
@ -207,7 +207,7 @@ const createRootReducer = (
|
||||||
// noop
|
// noop
|
||||||
}
|
}
|
||||||
) => state,
|
) => state,
|
||||||
array: (state = [], action: DemoAppAction) =>
|
array: (state = [], action) =>
|
||||||
action.type === 'PUSH'
|
action.type === 'PUSH'
|
||||||
? [...state, Math.random()]
|
? [...state, Math.random()]
|
||||||
: action.type === 'POP'
|
: action.type === 'POP'
|
||||||
|
@ -215,13 +215,13 @@ const createRootReducer = (
|
||||||
: action.type === 'REPLACE'
|
: action.type === 'REPLACE'
|
||||||
? [Math.random(), ...state.slice(1)]
|
? [Math.random(), ...state.slice(1)]
|
||||||
: state,
|
: state,
|
||||||
hugeArrays: (state = [], action: DemoAppAction) =>
|
hugeArrays: (state = [], action) =>
|
||||||
action.type === 'PUSH_HUGE_ARRAY' ? [...state, ...HUGE_ARRAY] : state,
|
action.type === 'PUSH_HUGE_ARRAY' ? [...state, ...HUGE_ARRAY] : state,
|
||||||
hugeObjects: (state = [], action: DemoAppAction) =>
|
hugeObjects: (state = [], action) =>
|
||||||
action.type === 'ADD_HUGE_OBJECT' ? [...state, HUGE_OBJECT] : state,
|
action.type === 'ADD_HUGE_OBJECT' ? [...state, HUGE_OBJECT] : state,
|
||||||
iterators: (state = [], action: DemoAppAction) =>
|
iterators: (state = [], action) =>
|
||||||
action.type === 'ADD_ITERATOR' ? [...state, createIterator()] : state,
|
action.type === 'ADD_ITERATOR' ? [...state, createIterator()] : state,
|
||||||
nested: (state = NESTED, action: DemoAppAction) =>
|
nested: (state = NESTED, action) =>
|
||||||
action.type === 'CHANGE_NESTED'
|
action.type === 'CHANGE_NESTED'
|
||||||
? {
|
? {
|
||||||
...state,
|
...state,
|
||||||
|
@ -238,29 +238,26 @@ const createRootReducer = (
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
: state,
|
: state,
|
||||||
recursive: (state: { obj?: unknown }[] = [], action: DemoAppAction) =>
|
recursive: (state: { obj?: unknown }[] = [], action) =>
|
||||||
action.type === 'ADD_RECURSIVE' ? [...state, { ...RECURSIVE }] : state,
|
action.type === 'ADD_RECURSIVE' ? [...state, { ...RECURSIVE }] : state,
|
||||||
immutables: (
|
immutables: (state: Immutable.Map<string, unknown>[] = [], action) =>
|
||||||
state: Immutable.Map<string, unknown>[] = [],
|
|
||||||
action: DemoAppAction
|
|
||||||
) =>
|
|
||||||
action.type === 'ADD_IMMUTABLE_MAP' ? [...state, IMMUTABLE_MAP] : state,
|
action.type === 'ADD_IMMUTABLE_MAP' ? [...state, IMMUTABLE_MAP] : state,
|
||||||
maps: (state: Map<string, MapValue>[] = [], action: DemoAppAction) =>
|
maps: (state: Map<string, MapValue>[] = [], action) =>
|
||||||
action.type === 'ADD_NATIVE_MAP' ? [...state, NATIVE_MAP] : state,
|
action.type === 'ADD_NATIVE_MAP' ? [...state, NATIVE_MAP] : state,
|
||||||
immutableNested: (state = IMMUTABLE_NESTED, action: DemoAppAction) =>
|
immutableNested: (state = IMMUTABLE_NESTED, action) =>
|
||||||
action.type === 'CHANGE_IMMUTABLE_NESTED'
|
action.type === 'CHANGE_IMMUTABLE_NESTED'
|
||||||
? state.updateIn(
|
? state.updateIn(
|
||||||
['long', 'nested', 0, 'path', 'to', 'a'],
|
['long', 'nested', 0, 'path', 'to', 'a'],
|
||||||
(str: string) => str + '!'
|
(str: string) => str + '!'
|
||||||
)
|
)
|
||||||
: state,
|
: state,
|
||||||
addFunction: (state = null, action: DemoAppAction) =>
|
addFunction: (state = null, action) =>
|
||||||
action.type === 'ADD_FUNCTION' ? { f: FUNC } : state,
|
action.type === 'ADD_FUNCTION' ? { f: FUNC } : state,
|
||||||
addSymbol: (state = null, action: DemoAppAction) =>
|
addSymbol: (state = null, action) =>
|
||||||
action.type === 'ADD_SYMBOL'
|
action.type === 'ADD_SYMBOL'
|
||||||
? { s: window.Symbol('symbol'), error: new Error('TEST') }
|
? { s: window.Symbol('symbol'), error: new Error('TEST') }
|
||||||
: state,
|
: state,
|
||||||
shuffleArray: (state = DEFAULT_SHUFFLE_ARRAY, action: DemoAppAction) =>
|
shuffleArray: (state = DEFAULT_SHUFFLE_ARRAY, action) =>
|
||||||
action.type === 'SHUFFLE_ARRAY' ? shuffle(state) : state,
|
action.type === 'SHUFFLE_ARRAY' ? shuffle(state) : state,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -53,11 +53,9 @@
|
||||||
"redux-devtools-themes": "^1.0.0"
|
"redux-devtools-themes": "^1.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/runtime": "^7.11.2",
|
|
||||||
"@types/dateformat": "^3.0.1",
|
"@types/dateformat": "^3.0.1",
|
||||||
"@types/hex-rgba": "^1.0.0",
|
"@types/hex-rgba": "^1.0.0",
|
||||||
"@types/history": "^4.7.7",
|
"@types/history": "^4.7.7",
|
||||||
"@types/lodash.debounce": "^4.0.6",
|
|
||||||
"@types/lodash.shuffle": "^4.2.6",
|
"@types/lodash.shuffle": "^4.2.6",
|
||||||
"@types/react": "^16.9.46",
|
"@types/react": "^16.9.46",
|
||||||
"@types/react-dragula": "^1.1.0",
|
"@types/react-dragula": "^1.1.0",
|
||||||
|
@ -67,7 +65,6 @@
|
||||||
"connected-react-router": "^6.8.0",
|
"connected-react-router": "^6.8.0",
|
||||||
"history": "^4.10.1",
|
"history": "^4.10.1",
|
||||||
"immutable": "^4.0.0-rc.12",
|
"immutable": "^4.0.0-rc.12",
|
||||||
"lodash.isequalwith": "^4.4.0",
|
|
||||||
"lodash.shuffle": "^4.2.0",
|
"lodash.shuffle": "^4.2.0",
|
||||||
"react": "^16.13.1",
|
"react": "^16.13.1",
|
||||||
"react-bootstrap": "^1.3.0",
|
"react-bootstrap": "^1.3.0",
|
||||||
|
|
|
@ -1,2 +1,5 @@
|
||||||
import DevtoolsInspector from './DevtoolsInspector';
|
import DevtoolsInspector from './DevtoolsInspector';
|
||||||
export default DevtoolsInspector;
|
export default DevtoolsInspector;
|
||||||
|
export { Tab, TabComponentProps } from './ActionPreview';
|
||||||
|
export { DevtoolsInspectorState } from './redux';
|
||||||
|
export { base16Themes } from './utils/createStylingFromTheme';
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
{
|
{
|
||||||
"presets": ["@babel/preset-env", "@babel/preset-react"],
|
"presets": [
|
||||||
|
"@babel/preset-env",
|
||||||
|
"@babel/preset-react",
|
||||||
|
"@babel/preset-typescript"
|
||||||
|
],
|
||||||
"plugins": [
|
"plugins": [
|
||||||
"@babel/plugin-proposal-class-properties",
|
"@babel/plugin-proposal-class-properties",
|
||||||
"@babel/plugin-proposal-do-expressions"
|
"@babel/plugin-transform-runtime"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
1
packages/redux-devtools-test-generator/.eslintignore
Normal file
1
packages/redux-devtools-test-generator/.eslintignore
Normal file
|
@ -0,0 +1 @@
|
||||||
|
lib
|
37
packages/redux-devtools-test-generator/.eslintrc.js
Normal file
37
packages/redux-devtools-test-generator/.eslintrc.js
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
module.exports = {
|
||||||
|
extends: '../../.eslintrc',
|
||||||
|
overrides: [
|
||||||
|
{
|
||||||
|
files: ['*.ts', '*.tsx'],
|
||||||
|
extends: '../../eslintrc.ts.react.base.json',
|
||||||
|
parserOptions: {
|
||||||
|
tsconfigRootDir: __dirname,
|
||||||
|
project: ['./tsconfig.json'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: ['demo/**/*.ts', 'demo/**/*.tsx'],
|
||||||
|
extends: '../../eslintrc.ts.react.base.json',
|
||||||
|
parserOptions: {
|
||||||
|
tsconfigRootDir: __dirname,
|
||||||
|
project: ['./demo/tsconfig.json'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: ['demo/config/webpack.config.ts'],
|
||||||
|
extends: '../../eslintrc.ts.base.json',
|
||||||
|
parserOptions: {
|
||||||
|
tsconfigRootDir: __dirname,
|
||||||
|
project: ['./demo/config/tsconfig.json'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: ['test/*.ts', 'test/*.tsx'],
|
||||||
|
extends: '../../eslintrc.ts.react.jest.base.json',
|
||||||
|
parserOptions: {
|
||||||
|
tsconfigRootDir: __dirname,
|
||||||
|
project: ['./test/tsconfig.json'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
|
@ -29,7 +29,7 @@ const testComponent = (props) => (
|
||||||
);
|
);
|
||||||
|
|
||||||
export default createDevTools(
|
export default createDevTools(
|
||||||
<Inspector
|
<InspectorMonitor
|
||||||
tabs: defaultTabs => [...defaultTabs, { name: 'Test', component: testComponent }]
|
tabs: defaultTabs => [...defaultTabs, { name: 'Test', component: testComponent }]
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"extends": "../../../../tsconfig.base.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"resolveJsonModule": true
|
||||||
|
},
|
||||||
|
"include": ["webpack.config.ts"]
|
||||||
|
}
|
|
@ -1,14 +1,14 @@
|
||||||
const path = require('path');
|
import * as path from 'path';
|
||||||
const webpack = require('webpack');
|
import * as webpack from 'webpack';
|
||||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
import HtmlWebpackPlugin from 'html-webpack-plugin';
|
||||||
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
|
import { CleanWebpackPlugin } from 'clean-webpack-plugin';
|
||||||
|
import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin';
|
||||||
const pkg = require('./package.json');
|
import pkg from '../../package.json';
|
||||||
|
|
||||||
const isProduction = process.env.NODE_ENV === 'production';
|
const isProduction = process.env.NODE_ENV === 'production';
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
devtool: 'eval-source-map',
|
mode: process.env.NODE_ENV || 'development',
|
||||||
entry: isProduction
|
entry: isProduction
|
||||||
? ['./demo/src/js/index']
|
? ['./demo/src/js/index']
|
||||||
: [
|
: [
|
||||||
|
@ -20,39 +20,14 @@ module.exports = {
|
||||||
path: path.join(__dirname, 'demo/dist'),
|
path: path.join(__dirname, 'demo/dist'),
|
||||||
filename: 'js/bundle.js',
|
filename: 'js/bundle.js',
|
||||||
},
|
},
|
||||||
plugins: [
|
|
||||||
new CleanWebpackPlugin(),
|
|
||||||
new HtmlWebpackPlugin({
|
|
||||||
inject: true,
|
|
||||||
template: 'demo/src/index.html',
|
|
||||||
package: pkg,
|
|
||||||
}),
|
|
||||||
new webpack.DefinePlugin({
|
|
||||||
'process.env': {
|
|
||||||
NODE_ENV: JSON.stringify(process.env.NODE_ENV),
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
].concat(
|
|
||||||
isProduction
|
|
||||||
? [
|
|
||||||
new webpack.optimize.UglifyJsPlugin({
|
|
||||||
compress: { warnings: false },
|
|
||||||
output: { comments: false },
|
|
||||||
}),
|
|
||||||
]
|
|
||||||
: [new webpack.HotModuleReplacementPlugin()]
|
|
||||||
),
|
|
||||||
resolve: {
|
|
||||||
extensions: ['.js', '.jsx'],
|
|
||||||
},
|
|
||||||
module: {
|
module: {
|
||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
test: /\.jsx?$/,
|
test: /\.(js|ts)x?$/,
|
||||||
loader: 'babel-loader',
|
loader: 'babel-loader',
|
||||||
include: [
|
include: [
|
||||||
path.join(__dirname, 'src'),
|
path.join(__dirname, '../../src'),
|
||||||
path.join(__dirname, 'demo/src/js'),
|
path.join(__dirname, '../src/js'),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -66,6 +41,22 @@ module.exports = {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
resolve: {
|
||||||
|
extensions: ['.js', '.jsx', '.ts', '.tsx'],
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
new CleanWebpackPlugin(),
|
||||||
|
new HtmlWebpackPlugin({
|
||||||
|
inject: true,
|
||||||
|
template: 'demo/src/index.html',
|
||||||
|
package: pkg,
|
||||||
|
}),
|
||||||
|
new ForkTsCheckerWebpackPlugin({
|
||||||
|
typescript: {
|
||||||
|
configFile: 'demo/tsconfig.json',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
].concat(isProduction ? [] : [new webpack.HotModuleReplacementPlugin()]),
|
||||||
devServer: isProduction
|
devServer: isProduction
|
||||||
? null
|
? null
|
||||||
: {
|
: {
|
||||||
|
@ -78,4 +69,5 @@ module.exports = {
|
||||||
},
|
},
|
||||||
historyApiFallback: true,
|
historyApiFallback: true,
|
||||||
},
|
},
|
||||||
|
devtool: 'eval-source-map',
|
||||||
};
|
};
|
|
@ -1,11 +1,35 @@
|
||||||
import React from 'react';
|
import React, { CSSProperties } from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import pkg from '../../../package.json';
|
|
||||||
import { Button, Toolbar, Spacer } from 'devui';
|
import { Button, Toolbar, Spacer } from 'devui';
|
||||||
import getOptions from './getOptions';
|
|
||||||
import { push as pushRoute } from 'connected-react-router';
|
import { push as pushRoute } from 'connected-react-router';
|
||||||
|
import pkg from '../../../package.json';
|
||||||
|
import getOptions from './getOptions';
|
||||||
|
import { DemoAppState } from './reducers';
|
||||||
|
import {
|
||||||
|
AddFunctionAction,
|
||||||
|
AddHugeObjectAction,
|
||||||
|
AddImmutableMapAction,
|
||||||
|
AddIteratorAction,
|
||||||
|
AddRecursiveAction,
|
||||||
|
AddSymbolAction,
|
||||||
|
ChangeImmutableNestedAction,
|
||||||
|
ChangeNestedAction,
|
||||||
|
HugePayloadAction,
|
||||||
|
IncrementAction,
|
||||||
|
PopAction,
|
||||||
|
PushAction,
|
||||||
|
PushHugeArrayAction,
|
||||||
|
ReplaceAction,
|
||||||
|
ShuffleArrayAction,
|
||||||
|
TimeoutUpdateAction,
|
||||||
|
ToggleTimeoutUpdateAction,
|
||||||
|
} from './reducers';
|
||||||
|
|
||||||
const styles = {
|
const styles: {
|
||||||
|
wrapper: CSSProperties;
|
||||||
|
muted: CSSProperties;
|
||||||
|
link: CSSProperties;
|
||||||
|
} = {
|
||||||
wrapper: {
|
wrapper: {
|
||||||
height: '100vh',
|
height: '100vh',
|
||||||
width: '450px',
|
width: '450px',
|
||||||
|
@ -24,7 +48,30 @@ const styles = {
|
||||||
|
|
||||||
const ROOT = '/'; // process.env.NODE_ENV === 'production' ? '/' : '/';
|
const ROOT = '/'; // process.env.NODE_ENV === 'production' ? '/' : '/';
|
||||||
|
|
||||||
class DemoApp extends React.Component {
|
interface Props
|
||||||
|
extends Omit<DemoAppState, 'addFunction' | 'addSymbol' | 'shuffleArray'> {
|
||||||
|
toggleTimeoutUpdate: (timeoutUpdateEnabled: boolean) => void;
|
||||||
|
timeoutUpdate: () => void;
|
||||||
|
increment: () => void;
|
||||||
|
push: () => void;
|
||||||
|
pop: () => void;
|
||||||
|
replace: () => void;
|
||||||
|
changeNested: () => void;
|
||||||
|
pushHugeArray: () => void;
|
||||||
|
addIterator: () => void;
|
||||||
|
addHugeObject: () => void;
|
||||||
|
addRecursive: () => void;
|
||||||
|
addImmutableMap: () => void;
|
||||||
|
changeImmutableNested: () => void;
|
||||||
|
hugePayload: () => void;
|
||||||
|
addFunction: () => void;
|
||||||
|
addSymbol: () => void;
|
||||||
|
shuffleArray: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
class DemoApp extends React.Component<Props> {
|
||||||
|
timeout?: number;
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const options = getOptions(this.props.router.location);
|
const options = getOptions(this.props.router.location);
|
||||||
|
|
||||||
|
@ -48,7 +95,7 @@ class DemoApp extends React.Component {
|
||||||
<Toolbar>
|
<Toolbar>
|
||||||
<Spacer />
|
<Spacer />
|
||||||
<Button onClick={this.props.pushHugeArray}>Push Huge Array</Button>
|
<Button onClick={this.props.pushHugeArray}>Push Huge Array</Button>
|
||||||
<Button onClick={this.props.addHugeObect}>Add Huge Object</Button>
|
<Button onClick={this.props.addHugeObject}>Add Huge Object</Button>
|
||||||
<Button onClick={this.props.hugePayload}>Huge Payload</Button>
|
<Button onClick={this.props.hugePayload}>Huge Payload</Button>
|
||||||
<Spacer />
|
<Spacer />
|
||||||
</Toolbar>
|
</Toolbar>
|
||||||
|
@ -98,36 +145,40 @@ class DemoApp extends React.Component {
|
||||||
this.props.toggleTimeoutUpdate(enabled);
|
this.props.toggleTimeoutUpdate(enabled);
|
||||||
|
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
this.timeout = setInterval(this.props.timeoutUpdate, 1000);
|
this.timeout = window.setInterval(this.props.timeoutUpdate, 1000);
|
||||||
} else {
|
} else {
|
||||||
clearTimeout(this.timeout);
|
clearTimeout(this.timeout);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect((state) => state, {
|
export default connect((state: DemoAppState) => state, {
|
||||||
toggleTimeoutUpdate: (timeoutUpdateEnabled) => ({
|
toggleTimeoutUpdate: (
|
||||||
|
timeoutUpdateEnabled: boolean
|
||||||
|
): ToggleTimeoutUpdateAction => ({
|
||||||
type: 'TOGGLE_TIMEOUT_UPDATE',
|
type: 'TOGGLE_TIMEOUT_UPDATE',
|
||||||
timeoutUpdateEnabled,
|
timeoutUpdateEnabled,
|
||||||
}),
|
}),
|
||||||
timeoutUpdate: () => ({ type: 'TIMEOUT_UPDATE' }),
|
timeoutUpdate: (): TimeoutUpdateAction => ({ type: 'TIMEOUT_UPDATE' }),
|
||||||
increment: () => ({ type: 'INCREMENT' }),
|
increment: (): IncrementAction => ({ type: 'INCREMENT' }),
|
||||||
push: () => ({ type: 'PUSH' }),
|
push: (): PushAction => ({ type: 'PUSH' }),
|
||||||
pop: () => ({ type: 'POP' }),
|
pop: (): PopAction => ({ type: 'POP' }),
|
||||||
replace: () => ({ type: 'REPLACE' }),
|
replace: (): ReplaceAction => ({ type: 'REPLACE' }),
|
||||||
changeNested: () => ({ type: 'CHANGE_NESTED' }),
|
changeNested: (): ChangeNestedAction => ({ type: 'CHANGE_NESTED' }),
|
||||||
pushHugeArray: () => ({ type: 'PUSH_HUGE_ARRAY' }),
|
pushHugeArray: (): PushHugeArrayAction => ({ type: 'PUSH_HUGE_ARRAY' }),
|
||||||
addIterator: () => ({ type: 'ADD_ITERATOR' }),
|
addIterator: (): AddIteratorAction => ({ type: 'ADD_ITERATOR' }),
|
||||||
addHugeObect: () => ({ type: 'ADD_HUGE_OBJECT' }),
|
addHugeObject: (): AddHugeObjectAction => ({ type: 'ADD_HUGE_OBJECT' }),
|
||||||
addRecursive: () => ({ type: 'ADD_RECURSIVE' }),
|
addRecursive: (): AddRecursiveAction => ({ type: 'ADD_RECURSIVE' }),
|
||||||
addImmutableMap: () => ({ type: 'ADD_IMMUTABLE_MAP' }),
|
addImmutableMap: (): AddImmutableMapAction => ({ type: 'ADD_IMMUTABLE_MAP' }),
|
||||||
changeImmutableNested: () => ({ type: 'CHANGE_IMMUTABLE_NESTED' }),
|
changeImmutableNested: (): ChangeImmutableNestedAction => ({
|
||||||
hugePayload: () => ({
|
type: 'CHANGE_IMMUTABLE_NESTED',
|
||||||
|
}),
|
||||||
|
hugePayload: (): HugePayloadAction => ({
|
||||||
type: 'HUGE_PAYLOAD',
|
type: 'HUGE_PAYLOAD',
|
||||||
payload: Array.from({ length: 10000 }).map((_, i) => i),
|
payload: Array.from({ length: 10000 }).map((_, i) => i),
|
||||||
}),
|
}),
|
||||||
addFunction: () => ({ type: 'ADD_FUNCTION' }),
|
addFunction: (): AddFunctionAction => ({ type: 'ADD_FUNCTION' }),
|
||||||
addSymbol: () => ({ type: 'ADD_SYMBOL' }),
|
addSymbol: (): AddSymbolAction => ({ type: 'ADD_SYMBOL' }),
|
||||||
shuffleArray: () => ({ type: 'SHUFFLE_ARRAY' }),
|
shuffleArray: (): ShuffleArrayAction => ({ type: 'SHUFFLE_ARRAY' }),
|
||||||
pushRoute,
|
pushRoute,
|
||||||
})(DemoApp);
|
})(DemoApp);
|
|
@ -1,12 +1,18 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { createDevTools } from 'redux-devtools';
|
import { createDevTools } from 'redux-devtools';
|
||||||
import InspectorMonitor from 'redux-devtools-inspector-monitor';
|
import InspectorMonitor, {
|
||||||
|
base16Themes,
|
||||||
|
Tab,
|
||||||
|
} from 'redux-devtools-inspector-monitor';
|
||||||
import DockMonitor from 'redux-devtools-dock-monitor';
|
import DockMonitor from 'redux-devtools-dock-monitor';
|
||||||
|
import { Location } from 'history';
|
||||||
import getOptions from './getOptions';
|
import getOptions from './getOptions';
|
||||||
import TestGenerator from '../../../src';
|
import TestGenerator from '../../../src';
|
||||||
|
import { DemoAppState } from './reducers';
|
||||||
|
import { Action } from 'redux';
|
||||||
|
|
||||||
export const getDevTools = (location) =>
|
export const getDevTools = (location: { search: string }) =>
|
||||||
createDevTools(
|
createDevTools(
|
||||||
<DockMonitor
|
<DockMonitor
|
||||||
defaultIsVisible
|
defaultIsVisible
|
||||||
|
@ -15,27 +21,28 @@ export const getDevTools = (location) =>
|
||||||
changeMonitorKey="ctrl-m"
|
changeMonitorKey="ctrl-m"
|
||||||
>
|
>
|
||||||
<InspectorMonitor
|
<InspectorMonitor
|
||||||
theme={getOptions(location).theme}
|
theme={getOptions(location).theme as keyof typeof base16Themes}
|
||||||
shouldPersistState
|
|
||||||
invertTheme={!getOptions(location).dark}
|
invertTheme={!getOptions(location).dark}
|
||||||
supportImmutable={getOptions(location).supportImmutable}
|
supportImmutable={getOptions(location).supportImmutable}
|
||||||
tabs={(defaultTabs) => [
|
tabs={(defaultTabs) =>
|
||||||
|
[
|
||||||
{
|
{
|
||||||
name: 'Test',
|
name: 'Test',
|
||||||
component: TestGenerator,
|
component: TestGenerator,
|
||||||
},
|
},
|
||||||
...defaultTabs,
|
...defaultTabs,
|
||||||
]}
|
] as Tab<unknown, Action<unknown>>[]
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</DockMonitor>
|
</DockMonitor>
|
||||||
);
|
);
|
||||||
|
|
||||||
const UnconnectedDevTools = ({ location }) => {
|
const UnconnectedDevTools = ({ location }: { location: Location }) => {
|
||||||
const DevTools = getDevTools(location);
|
const DevTools = getDevTools(location);
|
||||||
return <DevTools />;
|
return <DevTools />;
|
||||||
};
|
};
|
||||||
|
|
||||||
const mapStateToProps = (state) => ({
|
const mapStateToProps = (state: DemoAppState) => ({
|
||||||
location: state.router.location,
|
location: state.router.location,
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
export default function getOptions(location) {
|
|
||||||
return {
|
|
||||||
useExtension: location.search.indexOf('ext') !== -1,
|
|
||||||
supportImmutable: location.search.indexOf('immutable') !== -1,
|
|
||||||
theme: do {
|
|
||||||
const match = location.search.match(/theme=([^&]+)/);
|
|
||||||
match ? match[1] : 'inspector';
|
|
||||||
},
|
|
||||||
dark: location.search.indexOf('dark') !== -1,
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
export interface Options {
|
||||||
|
useExtension: boolean;
|
||||||
|
supportImmutable: boolean;
|
||||||
|
theme: string;
|
||||||
|
dark: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function getOptions(location: { search: string }) {
|
||||||
|
return {
|
||||||
|
useExtension: location.search.indexOf('ext') !== -1,
|
||||||
|
supportImmutable: location.search.indexOf('immutable') !== -1,
|
||||||
|
theme: getTheme(),
|
||||||
|
dark: location.search.indexOf('dark') !== -1,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTheme() {
|
||||||
|
const match = /theme=([^&]+)/.exec(location.search);
|
||||||
|
return match ? match[1] : 'inspector';
|
||||||
|
}
|
|
@ -1,22 +1,27 @@
|
||||||
import '@babel/polyfill';
|
|
||||||
import 'devui/lib/presets';
|
import 'devui/lib/presets';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { render } from 'react-dom';
|
import { render } from 'react-dom';
|
||||||
import { Container } from 'devui';
|
import { Container } from 'devui';
|
||||||
import DemoApp from './DemoApp';
|
|
||||||
import { Provider } from 'react-redux';
|
import { Provider } from 'react-redux';
|
||||||
import createRootReducer from './reducers';
|
import {
|
||||||
import { createStore, applyMiddleware, compose } from 'redux';
|
createStore,
|
||||||
|
applyMiddleware,
|
||||||
|
compose,
|
||||||
|
StoreEnhancer,
|
||||||
|
StoreEnhancerStoreCreator,
|
||||||
|
} from 'redux';
|
||||||
import logger from 'redux-logger';
|
import logger from 'redux-logger';
|
||||||
import { Route } from 'react-router';
|
import { Route } from 'react-router';
|
||||||
import { createBrowserHistory } from 'history';
|
import { createBrowserHistory } from 'history';
|
||||||
import { ConnectedRouter, routerMiddleware } from 'connected-react-router';
|
import { ConnectedRouter, routerMiddleware } from 'connected-react-router';
|
||||||
import { persistState } from 'redux-devtools';
|
import { persistState } from 'redux-devtools';
|
||||||
|
import DemoApp from './DemoApp';
|
||||||
|
import createRootReducer from './reducers';
|
||||||
import getOptions from './getOptions';
|
import getOptions from './getOptions';
|
||||||
import { ConnectedDevTools, getDevTools } from './DevTools';
|
import { ConnectedDevTools, getDevTools } from './DevTools';
|
||||||
|
|
||||||
function getDebugSessionKey() {
|
function getDebugSessionKey() {
|
||||||
const matches = window.location.href.match(/[?&]debug_session=([^&#]+)\b/);
|
const matches = /[?&]debug_session=([^&#]+)\b/.exec(window.location.href);
|
||||||
return matches && matches.length > 0 ? matches[1] : null;
|
return matches && matches.length > 0 ? matches[1] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,21 +35,23 @@ const DevTools = getDevTools(window.location);
|
||||||
const history = createBrowserHistory();
|
const history = createBrowserHistory();
|
||||||
|
|
||||||
const useDevtoolsExtension =
|
const useDevtoolsExtension =
|
||||||
!!window.__REDUX_DEVTOOLS_EXTENSION__ &&
|
!!((window as unknown) as { __REDUX_DEVTOOLS_EXTENSION__: unknown }) &&
|
||||||
getOptions(window.location).useExtension;
|
getOptions(window.location).useExtension;
|
||||||
|
|
||||||
const enhancer = compose(
|
const enhancer = compose(
|
||||||
applyMiddleware(logger, routerMiddleware(history)),
|
applyMiddleware(logger, routerMiddleware(history)),
|
||||||
(...args) => {
|
(next: StoreEnhancerStoreCreator) => {
|
||||||
const instrument = useDevtoolsExtension
|
const instrument = useDevtoolsExtension
|
||||||
? window.__REDUX_DEVTOOLS_EXTENSION__()
|
? ((window as unknown) as {
|
||||||
|
__REDUX_DEVTOOLS_EXTENSION__(): StoreEnhancer;
|
||||||
|
}).__REDUX_DEVTOOLS_EXTENSION__()
|
||||||
: DevTools.instrument();
|
: DevTools.instrument();
|
||||||
return instrument(...args);
|
return instrument(next);
|
||||||
},
|
},
|
||||||
persistState(getDebugSessionKey())
|
persistState(getDebugSessionKey())
|
||||||
);
|
);
|
||||||
|
|
||||||
const store = createStore(createRootReducer(history), {}, enhancer);
|
const store = createStore(createRootReducer(history), enhancer);
|
||||||
|
|
||||||
render(
|
render(
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
|
@ -1,125 +0,0 @@
|
||||||
import Immutable from 'immutable';
|
|
||||||
import shuffle from 'lodash.shuffle';
|
|
||||||
import { combineReducers } from 'redux';
|
|
||||||
import { connectRouter } from 'connected-react-router';
|
|
||||||
|
|
||||||
const NESTED = {
|
|
||||||
long: {
|
|
||||||
nested: [
|
|
||||||
{
|
|
||||||
path: {
|
|
||||||
to: {
|
|
||||||
a: 'key',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const IMMUTABLE_NESTED = Immutable.fromJS(NESTED);
|
|
||||||
|
|
||||||
/* eslint-disable babel/new-cap */
|
|
||||||
|
|
||||||
const IMMUTABLE_MAP = Immutable.Map({
|
|
||||||
map: Immutable.Map({ a: 1, b: 2, c: 3 }),
|
|
||||||
list: Immutable.List(['a', 'b', 'c']),
|
|
||||||
set: Immutable.Set(['a', 'b', 'c']),
|
|
||||||
stack: Immutable.Stack(['a', 'b', 'c']),
|
|
||||||
seq: Immutable.Seq([1, 2, 3, 4, 5, 6, 7, 8]),
|
|
||||||
});
|
|
||||||
|
|
||||||
/* eslint-enable babel/new-cap */
|
|
||||||
|
|
||||||
const HUGE_ARRAY = Array.from({ length: 5000 }).map((_, key) => ({
|
|
||||||
str: 'key ' + key,
|
|
||||||
}));
|
|
||||||
|
|
||||||
const HUGE_OBJECT = Array.from({ length: 5000 }).reduce(
|
|
||||||
(o, _, key) => ((o['key ' + key] = 'item ' + key), o),
|
|
||||||
{}
|
|
||||||
);
|
|
||||||
|
|
||||||
const FUNC = function (a, b, c) {
|
|
||||||
return a + b + c;
|
|
||||||
};
|
|
||||||
|
|
||||||
const RECURSIVE = {};
|
|
||||||
RECURSIVE.obj = RECURSIVE;
|
|
||||||
|
|
||||||
function createIterator() {
|
|
||||||
const iterable = {};
|
|
||||||
iterable[window.Symbol.iterator] = function* iterator() {
|
|
||||||
for (var i = 0; i < 333; i++) {
|
|
||||||
yield 'item ' + i;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return iterable;
|
|
||||||
}
|
|
||||||
|
|
||||||
const DEFAULT_SHUFFLE_ARRAY = [0, 1, null, { id: 1 }, { id: 2 }, 'string'];
|
|
||||||
|
|
||||||
const createRootReducer = (history) =>
|
|
||||||
combineReducers({
|
|
||||||
router: connectRouter(history),
|
|
||||||
timeoutUpdateEnabled: (state = false, action) =>
|
|
||||||
action.type === 'TOGGLE_TIMEOUT_UPDATE'
|
|
||||||
? action.timeoutUpdateEnabled
|
|
||||||
: state,
|
|
||||||
store: (state = 0, action) =>
|
|
||||||
action.type === 'INCREMENT' ? state + 1 : state,
|
|
||||||
undefined: (state = { val: undefined }) => state,
|
|
||||||
null: (state = null) => state,
|
|
||||||
func: (state = () => {}) => state,
|
|
||||||
array: (state = [], action) =>
|
|
||||||
action.type === 'PUSH'
|
|
||||||
? [...state, Math.random()]
|
|
||||||
: action.type === 'POP'
|
|
||||||
? state.slice(0, state.length - 1)
|
|
||||||
: action.type === 'REPLACE'
|
|
||||||
? [Math.random(), ...state.slice(1)]
|
|
||||||
: state,
|
|
||||||
hugeArrays: (state = [], action) =>
|
|
||||||
action.type === 'PUSH_HUGE_ARRAY' ? [...state, ...HUGE_ARRAY] : state,
|
|
||||||
hugeObjects: (state = [], action) =>
|
|
||||||
action.type === 'ADD_HUGE_OBJECT' ? [...state, HUGE_OBJECT] : state,
|
|
||||||
iterators: (state = [], action) =>
|
|
||||||
action.type === 'ADD_ITERATOR' ? [...state, createIterator()] : state,
|
|
||||||
nested: (state = NESTED, action) =>
|
|
||||||
action.type === 'CHANGE_NESTED'
|
|
||||||
? {
|
|
||||||
...state,
|
|
||||||
long: {
|
|
||||||
nested: [
|
|
||||||
{
|
|
||||||
path: {
|
|
||||||
to: {
|
|
||||||
a: state.long.nested[0].path.to.a + '!',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
}
|
|
||||||
: state,
|
|
||||||
recursive: (state = [], action) =>
|
|
||||||
action.type === 'ADD_RECURSIVE' ? [...state, { ...RECURSIVE }] : state,
|
|
||||||
immutables: (state = [], action) =>
|
|
||||||
action.type === 'ADD_IMMUTABLE_MAP' ? [...state, IMMUTABLE_MAP] : state,
|
|
||||||
immutableNested: (state = IMMUTABLE_NESTED, action) =>
|
|
||||||
action.type === 'CHANGE_IMMUTABLE_NESTED'
|
|
||||||
? state.updateIn(
|
|
||||||
['long', 'nested', 0, 'path', 'to', 'a'],
|
|
||||||
(str) => str + '!'
|
|
||||||
)
|
|
||||||
: state,
|
|
||||||
addFunction: (state = null, action) =>
|
|
||||||
action.type === 'ADD_FUNCTION' ? { f: FUNC } : state,
|
|
||||||
addSymbol: (state = null, action) =>
|
|
||||||
action.type === 'ADD_SYMBOL' ? { s: window.Symbol('symbol') } : state,
|
|
||||||
shuffleArray: (state = DEFAULT_SHUFFLE_ARRAY, action) =>
|
|
||||||
action.type === 'SHUFFLE_ARRAY' ? shuffle(state) : state,
|
|
||||||
});
|
|
||||||
|
|
||||||
export default createRootReducer;
|
|
232
packages/redux-devtools-test-generator/demo/src/js/reducers.ts
Normal file
232
packages/redux-devtools-test-generator/demo/src/js/reducers.ts
Normal file
|
@ -0,0 +1,232 @@
|
||||||
|
import Immutable from 'immutable';
|
||||||
|
import shuffle from 'lodash.shuffle';
|
||||||
|
import { combineReducers, Reducer } from 'redux';
|
||||||
|
import {
|
||||||
|
connectRouter,
|
||||||
|
LocationChangeAction,
|
||||||
|
RouterState,
|
||||||
|
} from 'connected-react-router';
|
||||||
|
import { History } from 'history';
|
||||||
|
|
||||||
|
type Nested = { long: { nested: { path: { to: { a: string } } }[] } };
|
||||||
|
|
||||||
|
const NESTED = {
|
||||||
|
long: {
|
||||||
|
nested: [
|
||||||
|
{
|
||||||
|
path: {
|
||||||
|
to: {
|
||||||
|
a: 'key',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const IMMUTABLE_NESTED = Immutable.fromJS(NESTED);
|
||||||
|
|
||||||
|
const IMMUTABLE_MAP = Immutable.Map({
|
||||||
|
map: Immutable.Map({ a: 1, b: 2, c: 3 }),
|
||||||
|
list: Immutable.List(['a', 'b', 'c']),
|
||||||
|
set: Immutable.Set(['a', 'b', 'c']),
|
||||||
|
stack: Immutable.Stack(['a', 'b', 'c']),
|
||||||
|
seq: Immutable.Seq([1, 2, 3, 4, 5, 6, 7, 8]),
|
||||||
|
});
|
||||||
|
|
||||||
|
const HUGE_ARRAY = Array.from({ length: 5000 }).map((_, key) => ({
|
||||||
|
str: `key ${key}`,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const HUGE_OBJECT = Array.from({ length: 5000 }).reduce(
|
||||||
|
(o: { [key: string]: string }, _, key) => (
|
||||||
|
(o[`key ${key}`] = `item ${key}`), o
|
||||||
|
),
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
|
||||||
|
const FUNC = function (a: number, b: number, c: number) {
|
||||||
|
return a + b + c;
|
||||||
|
};
|
||||||
|
|
||||||
|
const RECURSIVE: { obj?: unknown } = {};
|
||||||
|
RECURSIVE.obj = RECURSIVE;
|
||||||
|
|
||||||
|
function createIterator() {
|
||||||
|
const iterable: { [Symbol.iterator](): IterableIterator<string> } = {
|
||||||
|
[Symbol.iterator]: function* iterator() {
|
||||||
|
for (let i = 0; i < 333; i++) {
|
||||||
|
yield `item ${i}`;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
return iterable;
|
||||||
|
}
|
||||||
|
|
||||||
|
const DEFAULT_SHUFFLE_ARRAY = [0, 1, null, { id: 1 }, { id: 2 }, 'string'];
|
||||||
|
|
||||||
|
export interface ToggleTimeoutUpdateAction {
|
||||||
|
type: 'TOGGLE_TIMEOUT_UPDATE';
|
||||||
|
timeoutUpdateEnabled: boolean;
|
||||||
|
}
|
||||||
|
export interface TimeoutUpdateAction {
|
||||||
|
type: 'TIMEOUT_UPDATE';
|
||||||
|
}
|
||||||
|
export interface IncrementAction {
|
||||||
|
type: 'INCREMENT';
|
||||||
|
}
|
||||||
|
export interface PushAction {
|
||||||
|
type: 'PUSH';
|
||||||
|
}
|
||||||
|
export interface PopAction {
|
||||||
|
type: 'POP';
|
||||||
|
}
|
||||||
|
export interface ReplaceAction {
|
||||||
|
type: 'REPLACE';
|
||||||
|
}
|
||||||
|
export interface ChangeNestedAction {
|
||||||
|
type: 'CHANGE_NESTED';
|
||||||
|
}
|
||||||
|
export interface PushHugeArrayAction {
|
||||||
|
type: 'PUSH_HUGE_ARRAY';
|
||||||
|
}
|
||||||
|
export interface AddIteratorAction {
|
||||||
|
type: 'ADD_ITERATOR';
|
||||||
|
}
|
||||||
|
export interface AddHugeObjectAction {
|
||||||
|
type: 'ADD_HUGE_OBJECT';
|
||||||
|
}
|
||||||
|
export interface AddRecursiveAction {
|
||||||
|
type: 'ADD_RECURSIVE';
|
||||||
|
}
|
||||||
|
export interface AddImmutableMapAction {
|
||||||
|
type: 'ADD_IMMUTABLE_MAP';
|
||||||
|
}
|
||||||
|
export interface ChangeImmutableNestedAction {
|
||||||
|
type: 'CHANGE_IMMUTABLE_NESTED';
|
||||||
|
}
|
||||||
|
export interface HugePayloadAction {
|
||||||
|
type: 'HUGE_PAYLOAD';
|
||||||
|
payload: number[];
|
||||||
|
}
|
||||||
|
export interface AddFunctionAction {
|
||||||
|
type: 'ADD_FUNCTION';
|
||||||
|
}
|
||||||
|
export interface AddSymbolAction {
|
||||||
|
type: 'ADD_SYMBOL';
|
||||||
|
}
|
||||||
|
export interface ShuffleArrayAction {
|
||||||
|
type: 'SHUFFLE_ARRAY';
|
||||||
|
}
|
||||||
|
type DemoAppAction =
|
||||||
|
| ToggleTimeoutUpdateAction
|
||||||
|
| TimeoutUpdateAction
|
||||||
|
| IncrementAction
|
||||||
|
| PushAction
|
||||||
|
| PopAction
|
||||||
|
| ReplaceAction
|
||||||
|
| ChangeNestedAction
|
||||||
|
| PushHugeArrayAction
|
||||||
|
| AddIteratorAction
|
||||||
|
| AddHugeObjectAction
|
||||||
|
| AddRecursiveAction
|
||||||
|
| AddImmutableMapAction
|
||||||
|
| ChangeImmutableNestedAction
|
||||||
|
| HugePayloadAction
|
||||||
|
| AddFunctionAction
|
||||||
|
| AddSymbolAction
|
||||||
|
| ShuffleArrayAction
|
||||||
|
| LocationChangeAction;
|
||||||
|
|
||||||
|
export interface DemoAppState {
|
||||||
|
router: RouterState;
|
||||||
|
timeoutUpdateEnabled: boolean;
|
||||||
|
store: number;
|
||||||
|
undefined: { val: undefined };
|
||||||
|
null: null;
|
||||||
|
func: () => void;
|
||||||
|
array: number[];
|
||||||
|
hugeArrays: { str: string }[];
|
||||||
|
hugeObjects: { [key: string]: string }[];
|
||||||
|
iterators: { [Symbol.iterator](): IterableIterator<string> }[];
|
||||||
|
nested: Nested;
|
||||||
|
recursive: { obj?: unknown }[];
|
||||||
|
immutables: Immutable.Map<string, unknown>[];
|
||||||
|
immutableNested: Immutable.Map<unknown, unknown>;
|
||||||
|
addFunction: { f: (a: number, b: number, c: number) => number } | null;
|
||||||
|
addSymbol: { s: symbol; error: Error } | null;
|
||||||
|
shuffleArray: unknown[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const createRootReducer = (
|
||||||
|
history: History
|
||||||
|
): Reducer<DemoAppState, DemoAppAction> =>
|
||||||
|
combineReducers<DemoAppState, DemoAppAction>({
|
||||||
|
router: connectRouter(history) as Reducer<RouterState, DemoAppAction>,
|
||||||
|
timeoutUpdateEnabled: (state = false, action) =>
|
||||||
|
action.type === 'TOGGLE_TIMEOUT_UPDATE'
|
||||||
|
? action.timeoutUpdateEnabled
|
||||||
|
: state,
|
||||||
|
store: (state = 0, action) =>
|
||||||
|
action.type === 'INCREMENT' ? state + 1 : state,
|
||||||
|
undefined: (state = { val: undefined }) => state,
|
||||||
|
null: (state = null) => state,
|
||||||
|
func: (
|
||||||
|
state = () => {
|
||||||
|
// noop
|
||||||
|
}
|
||||||
|
) => state,
|
||||||
|
array: (state = [], action) =>
|
||||||
|
action.type === 'PUSH'
|
||||||
|
? [...state, Math.random()]
|
||||||
|
: action.type === 'POP'
|
||||||
|
? state.slice(0, state.length - 1)
|
||||||
|
: action.type === 'REPLACE'
|
||||||
|
? [Math.random(), ...state.slice(1)]
|
||||||
|
: state,
|
||||||
|
hugeArrays: (state = [], action) =>
|
||||||
|
action.type === 'PUSH_HUGE_ARRAY' ? [...state, ...HUGE_ARRAY] : state,
|
||||||
|
hugeObjects: (state = [], action) =>
|
||||||
|
action.type === 'ADD_HUGE_OBJECT' ? [...state, HUGE_OBJECT] : state,
|
||||||
|
iterators: (state = [], action) =>
|
||||||
|
action.type === 'ADD_ITERATOR' ? [...state, createIterator()] : state,
|
||||||
|
nested: (state = NESTED, action) =>
|
||||||
|
action.type === 'CHANGE_NESTED'
|
||||||
|
? {
|
||||||
|
...state,
|
||||||
|
long: {
|
||||||
|
nested: [
|
||||||
|
{
|
||||||
|
path: {
|
||||||
|
to: {
|
||||||
|
a: state.long.nested[0].path.to.a + '!',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: state,
|
||||||
|
recursive: (state = [], action) =>
|
||||||
|
action.type === 'ADD_RECURSIVE' ? [...state, { ...RECURSIVE }] : state,
|
||||||
|
immutables: (state = [], action) =>
|
||||||
|
action.type === 'ADD_IMMUTABLE_MAP' ? [...state, IMMUTABLE_MAP] : state,
|
||||||
|
immutableNested: (state = IMMUTABLE_NESTED, action) =>
|
||||||
|
action.type === 'CHANGE_IMMUTABLE_NESTED'
|
||||||
|
? state.updateIn(
|
||||||
|
['long', 'nested', 0, 'path', 'to', 'a'],
|
||||||
|
(str: string) => str + '!'
|
||||||
|
)
|
||||||
|
: state,
|
||||||
|
addFunction: (state = null, action) =>
|
||||||
|
action.type === 'ADD_FUNCTION' ? { f: FUNC } : state,
|
||||||
|
addSymbol: (state = null, action) =>
|
||||||
|
action.type === 'ADD_SYMBOL'
|
||||||
|
? { s: window.Symbol('symbol'), error: new Error('TEST') }
|
||||||
|
: state,
|
||||||
|
shuffleArray: (state = DEFAULT_SHUFFLE_ARRAY, action) =>
|
||||||
|
action.type === 'SHUFFLE_ARRAY' ? shuffle(state) : state,
|
||||||
|
});
|
||||||
|
|
||||||
|
export default createRootReducer;
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"extends": "../../../tsconfig.react.base.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"resolveJsonModule": true
|
||||||
|
},
|
||||||
|
"include": ["../src", "src"]
|
||||||
|
}
|
4
packages/redux-devtools-test-generator/jest.config.js
Normal file
4
packages/redux-devtools-test-generator/jest.config.js
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
module.exports = {
|
||||||
|
preset: 'ts-jest',
|
||||||
|
setupFilesAfterEnv: ['<rootDir>/test/setup.ts'],
|
||||||
|
};
|
|
@ -2,22 +2,6 @@
|
||||||
"name": "redux-devtools-test-generator",
|
"name": "redux-devtools-test-generator",
|
||||||
"version": "0.6.2",
|
"version": "0.6.2",
|
||||||
"description": "Generate tests for redux devtools.",
|
"description": "Generate tests for redux devtools.",
|
||||||
"main": "lib/index.js",
|
|
||||||
"files": [
|
|
||||||
"lib"
|
|
||||||
],
|
|
||||||
"scripts": {
|
|
||||||
"start": "webpack-dev-server",
|
|
||||||
"clean": "rimraf lib",
|
|
||||||
"build": "babel src --out-dir lib",
|
|
||||||
"test": "jest --no-cache",
|
|
||||||
"prepare": "npm run clean && npm run build",
|
|
||||||
"prepublishOnly": "npm run test && npm run clean && npm run build"
|
|
||||||
},
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/reduxjs/redux-devtools.git"
|
|
||||||
},
|
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"redux",
|
"redux",
|
||||||
"devtools",
|
"devtools",
|
||||||
|
@ -28,35 +12,64 @@
|
||||||
"time travel",
|
"time travel",
|
||||||
"live edit"
|
"live edit"
|
||||||
],
|
],
|
||||||
"author": "Mihail Diordiev <zalmoxisus@gmail.com> (https://github.com/zalmoxisus)",
|
"homepage": "https://github.com/reduxjs/redux-devtools/tree/master/packages/redux-devtools-test-generator",
|
||||||
"license": "MIT",
|
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/reduxjs/redux-devtools/issues"
|
"url": "https://github.com/reduxjs/redux-devtools/issues"
|
||||||
},
|
},
|
||||||
"homepage": "https://github.com/reduxjs/redux-devtools",
|
"license": "MIT",
|
||||||
|
"author": "Mihail Diordiev <zalmoxisus@gmail.com> (https://github.com/zalmoxisus)",
|
||||||
|
"files": [
|
||||||
|
"lib",
|
||||||
|
"src"
|
||||||
|
],
|
||||||
|
"main": "lib/index.js",
|
||||||
|
"types": "lib/index.d.ts",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/reduxjs/redux-devtools.git"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"start": "webpack-dev-server --config demo/config/webpack.config.ts",
|
||||||
|
"build": "npm run build:types && npm run build:js",
|
||||||
|
"build:types": "tsc --emitDeclarationOnly",
|
||||||
|
"build:js": "babel src --out-dir lib --extensions \".ts,.tsx\" --source-maps inline",
|
||||||
|
"clean": "rimraf lib",
|
||||||
|
"test": "jest",
|
||||||
|
"lint": "eslint . --ext .ts,.tsx",
|
||||||
|
"lint:fix": "eslint . --ext .ts,.tsx --fix",
|
||||||
|
"type-check": "tsc --noEmit",
|
||||||
|
"type-check:watch": "npm run type-check -- --watch",
|
||||||
|
"preversion": "npm run type-check && npm run lint && npm run test",
|
||||||
|
"prepublishOnly": "npm run clean && npm run build"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@types/prop-types": "^15.7.3",
|
||||||
|
"devui": "^1.0.0-6",
|
||||||
|
"es6template": "^1.0.5",
|
||||||
|
"javascript-stringify": "^2.0.1",
|
||||||
|
"jsan": "^3.1.13",
|
||||||
|
"object-path": "^0.11.4",
|
||||||
|
"prop-types": "^15.7.2",
|
||||||
|
"react-icons": "^3.10.0",
|
||||||
|
"simple-diff": "^1.6.0"
|
||||||
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/cli": "^7.10.5",
|
"@types/history": "^4.7.7",
|
||||||
"@babel/core": "^7.11.1",
|
"@types/jsan": "^3.1.0",
|
||||||
"@babel/plugin-proposal-class-properties": "^7.10.4",
|
"@types/lodash.shuffle": "^4.2.6",
|
||||||
"@babel/plugin-proposal-do-expressions": "^7.10.4",
|
"@types/object-path": "^0.11.0",
|
||||||
"@babel/polyfill": "^7.10.4",
|
"@types/react": "^16.9.46",
|
||||||
"@babel/preset-env": "^7.11.0",
|
"@types/react-router": "^5.1.8",
|
||||||
"@babel/preset-react": "^7.10.4",
|
"@types/redux-logger": "^3.0.8",
|
||||||
"babel-loader": "^8.1.0",
|
|
||||||
"clean-webpack-plugin": "^3.0.0",
|
|
||||||
"connected-react-router": "^6.8.0",
|
"connected-react-router": "^6.8.0",
|
||||||
"css-loader": "^4.2.1",
|
|
||||||
"enzyme": "^3.11.0",
|
"enzyme": "^3.11.0",
|
||||||
"enzyme-adapter-react-16": "^1.15.3",
|
"enzyme-adapter-react-16": "^1.15.3",
|
||||||
"enzyme-to-json": "^3.5.0",
|
"enzyme-to-json": "^3.5.0",
|
||||||
"expect": "^26.2.0",
|
|
||||||
"file-loader": "^6.0.0",
|
|
||||||
"history": "^4.10.1",
|
"history": "^4.10.1",
|
||||||
"html-webpack-plugin": "^4.3.0",
|
|
||||||
"immutable": "^4.0.0-rc.12",
|
"immutable": "^4.0.0-rc.12",
|
||||||
"jest": "^26.2.2",
|
"jest": "^26.2.2",
|
||||||
"lodash.isequalwith": "^4.4.0",
|
|
||||||
"lodash.shuffle": "^4.2.0",
|
"lodash.shuffle": "^4.2.0",
|
||||||
|
"react": "^16.13.1",
|
||||||
"react-dom": "^16.13.1",
|
"react-dom": "^16.13.1",
|
||||||
"react-redux": "^7.2.1",
|
"react-redux": "^7.2.1",
|
||||||
"react-router": "^5.2.0",
|
"react-router": "^5.2.0",
|
||||||
|
@ -64,27 +77,11 @@
|
||||||
"redux-devtools": "^3.7.0",
|
"redux-devtools": "^3.7.0",
|
||||||
"redux-devtools-dock-monitor": "^1.2.0",
|
"redux-devtools-dock-monitor": "^1.2.0",
|
||||||
"redux-devtools-inspector-monitor": "^0.14.0",
|
"redux-devtools-inspector-monitor": "^0.14.0",
|
||||||
"redux-logger": "^3.0.6",
|
"redux-logger": "^3.0.6"
|
||||||
"rimraf": "^3.0.2",
|
|
||||||
"seamless-immutable": "^7.1.4",
|
|
||||||
"style-loader": "^1.2.1",
|
|
||||||
"webpack": "^4.44.1",
|
|
||||||
"webpack-dev-server": "^3.11.0"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"peerDependencies": {
|
||||||
"devui": "^1.0.0-6",
|
"@types/react": "^16.3.18",
|
||||||
"es6template": "^1.0.5",
|
"react": "^16.3.0",
|
||||||
"javascript-stringify": "^2.0.1",
|
"redux-devtools-inspector-monitor": "^0.14.0"
|
||||||
"jsan": "^3.1.13",
|
|
||||||
"object-path": "^0.11.4",
|
|
||||||
"prop-types": "^15.7.2",
|
|
||||||
"react": "^16.13.1",
|
|
||||||
"react-icons": "^3.10.0",
|
|
||||||
"simple-diff": "^1.6.0"
|
|
||||||
},
|
|
||||||
"jest": {
|
|
||||||
"setupFilesAfterEnv": [
|
|
||||||
"<rootDir>/test/setup.js"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,38 +1,54 @@
|
||||||
import React, { PureComponent, Component } from 'react';
|
import React, { PureComponent, Component, ReactNode } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { stringify } from 'javascript-stringify';
|
import { stringify } from 'javascript-stringify';
|
||||||
import objectPath from 'object-path';
|
import objectPath from 'object-path';
|
||||||
import jsan from 'jsan';
|
import jsan from 'jsan';
|
||||||
import diff from 'simple-diff';
|
import diff, { Event } from 'simple-diff';
|
||||||
import es6template from 'es6template';
|
import es6template from 'es6template';
|
||||||
import { Editor } from 'devui';
|
import { Editor } from 'devui';
|
||||||
|
import { TabComponentProps } from 'redux-devtools-inspector-monitor';
|
||||||
|
import { Action } from 'redux';
|
||||||
|
import { AssertionLocals, DispatcherLocals, WrapLocals } from './types';
|
||||||
|
|
||||||
export const fromPath = (path) =>
|
export const fromPath = (path: (string | number)[]) =>
|
||||||
path.map((a) => (typeof a === 'string' ? `.${a}` : `[${a}]`)).join('');
|
path.map((a) => (typeof a === 'string' ? `.${a}` : `[${a}]`)).join('');
|
||||||
|
|
||||||
function getState(s, defaultValue) {
|
function getState<S>(
|
||||||
|
s: { state: S; error?: string } | undefined,
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
|
defaultValue?: {}
|
||||||
|
) {
|
||||||
if (!s) return defaultValue;
|
if (!s) return defaultValue;
|
||||||
return JSON.parse(jsan.stringify(s.state));
|
return JSON.parse(jsan.stringify(s.state));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function compare(s1, s2, cb, defaultValue) {
|
export function compare<S>(
|
||||||
const paths = []; // Already processed
|
s1: { state: S; error?: string } | undefined,
|
||||||
function generate({ type, newPath, newValue, newIndex }) {
|
s2: { state: S; error?: string },
|
||||||
let curState;
|
cb: (value: { path: string; curState: number | string | undefined }) => void,
|
||||||
let path = fromPath(newPath);
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
|
defaultValue?: {}
|
||||||
|
) {
|
||||||
|
const paths: string[] = []; // Already processed
|
||||||
|
function generate(
|
||||||
|
event: Event | { type: 'move-item'; newPath: (string | number)[] }
|
||||||
|
) {
|
||||||
|
let curState: number | string | undefined;
|
||||||
|
let path = fromPath(event.newPath);
|
||||||
|
|
||||||
if (type === 'remove-item' || type === 'move-item') {
|
if (event.type === 'remove-item' || event.type === 'move-item') {
|
||||||
if (paths.length && paths.indexOf(path) !== -1) return;
|
if (paths.length && paths.indexOf(path) !== -1) return;
|
||||||
paths.push(path);
|
paths.push(path);
|
||||||
const v = objectPath.get(s2.state, newPath);
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
|
const v = objectPath.get((s2.state as unknown) as object, event.newPath);
|
||||||
curState = v.length;
|
curState = v.length;
|
||||||
path += '.length';
|
path += '.length';
|
||||||
} else if (type === 'add-item') {
|
} else if (event.type === 'add-item') {
|
||||||
generate({ type: 'move-item', newPath });
|
generate({ type: 'move-item', newPath: event.newPath });
|
||||||
path += `[${newIndex}]`;
|
path += `[${event.newIndex}]`;
|
||||||
curState = stringify(newValue);
|
curState = stringify(event.newValue);
|
||||||
} else {
|
} else {
|
||||||
curState = stringify(newValue);
|
curState = stringify(event.newValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
// console.log(`expect(store${path}).toEqual(${curState});`);
|
// console.log(`expect(store${path}).toEqual(${curState});`);
|
||||||
|
@ -45,17 +61,34 @@ export function compare(s1, s2, cb, defaultValue) {
|
||||||
).forEach(generate);
|
).forEach(generate);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class TestGenerator extends (PureComponent || Component) {
|
interface Props<S, A extends Action<unknown>>
|
||||||
getMethod(action) {
|
extends Omit<TabComponentProps<S, A>, 'monitorState' | 'updateMonitorState'> {
|
||||||
let type = action.type;
|
name?: string;
|
||||||
|
isVanilla?: boolean;
|
||||||
|
wrap?: string | ((locals: WrapLocals) => string);
|
||||||
|
dispatcher?: string | ((locals: DispatcherLocals) => string);
|
||||||
|
assertion?: string | ((locals: AssertionLocals) => string);
|
||||||
|
useCodemirror: boolean;
|
||||||
|
indentation?: number;
|
||||||
|
header?: ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class TestGenerator<
|
||||||
|
S,
|
||||||
|
A extends Action<unknown>
|
||||||
|
> extends (PureComponent || Component)<Props<S, A>> {
|
||||||
|
getMethod(action: A) {
|
||||||
|
let type: string = action.type as string;
|
||||||
if (type[0] === '┗') type = type.substr(1).trim();
|
if (type[0] === '┗') type = type.substr(1).trim();
|
||||||
let args = action.arguments;
|
const args = ((action as unknown) as { arguments: unknown[] }).arguments
|
||||||
if (args) args = args.map((arg) => stringify(arg)).join(',');
|
? ((action as unknown) as { arguments: unknown[] }).arguments
|
||||||
else args = '';
|
.map((arg) => stringify(arg))
|
||||||
|
.join(',')
|
||||||
|
: '';
|
||||||
return `${type}(${args})`;
|
return `${type}(${args})`;
|
||||||
}
|
}
|
||||||
|
|
||||||
getAction(action) {
|
getAction(action: A) {
|
||||||
if (action.type === '@@INIT') return '{}';
|
if (action.type === '@@INIT') return '{}';
|
||||||
return stringify(action);
|
return stringify(action);
|
||||||
}
|
}
|
||||||
|
@ -76,7 +109,7 @@ export default class TestGenerator extends (PureComponent || Component) {
|
||||||
if (typeof assertion === 'string')
|
if (typeof assertion === 'string')
|
||||||
assertion = es6template.compile(assertion);
|
assertion = es6template.compile(assertion);
|
||||||
if (typeof wrap === 'string') {
|
if (typeof wrap === 'string') {
|
||||||
const ident = wrap.match(/\n.+\$\{assertions}/);
|
const ident = /\n.+\$\{assertions}/.exec(wrap);
|
||||||
if (ident) indentation = ident[0].length - 13;
|
if (ident) indentation = ident[0].length - 13;
|
||||||
wrap = es6template.compile(wrap);
|
wrap = es6template.compile(wrap);
|
||||||
}
|
}
|
||||||
|
@ -94,21 +127,30 @@ export default class TestGenerator extends (PureComponent || Component) {
|
||||||
else i = computedStates.length - 1;
|
else i = computedStates.length - 1;
|
||||||
const startIdx = i > 0 ? i : 1;
|
const startIdx = i > 0 ? i : 1;
|
||||||
|
|
||||||
const addAssertions = ({ path, curState }) => {
|
const addAssertions = ({
|
||||||
r += space + assertion({ path, curState }) + '\n';
|
path,
|
||||||
|
curState,
|
||||||
|
}: {
|
||||||
|
path: string;
|
||||||
|
curState: number | string | undefined;
|
||||||
|
}) => {
|
||||||
|
r += `${space}${(assertion as (locals: AssertionLocals) => string)({
|
||||||
|
path,
|
||||||
|
curState,
|
||||||
|
})}\n`;
|
||||||
};
|
};
|
||||||
|
|
||||||
while (actions[i]) {
|
while (actions[i]) {
|
||||||
if (
|
if (
|
||||||
!isVanilla ||
|
!isVanilla ||
|
||||||
/* eslint-disable-next-line no-useless-escape */
|
/* eslint-disable-next-line no-useless-escape */
|
||||||
/^┗?\s?[a-zA-Z0-9_@.\[\]-]+?$/.test(actions[i].action.type)
|
/^┗?\s?[a-zA-Z0-9_@.\[\]-]+?$/.test(actions[i].action.type as string)
|
||||||
) {
|
) {
|
||||||
if (isFirst) isFirst = false;
|
if (isFirst) isFirst = false;
|
||||||
else r += space;
|
else r += space;
|
||||||
if (!isVanilla || actions[i].action.type[0] !== '@') {
|
if (!isVanilla || (actions[i].action.type as string)[0] !== '@') {
|
||||||
r +=
|
r +=
|
||||||
dispatcher({
|
(dispatcher as (locals: DispatcherLocals) => string)({
|
||||||
action: !isVanilla
|
action: !isVanilla
|
||||||
? this.getAction(actions[i].action)
|
? this.getAction(actions[i].action)
|
||||||
: this.getMethod(actions[i].action),
|
: this.getMethod(actions[i].action),
|
||||||
|
@ -131,7 +173,7 @@ export default class TestGenerator extends (PureComponent || Component) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
if (i > selectedActionId) break;
|
if (i > selectedActionId!) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = r.trim();
|
r = r.trim();
|
||||||
|
@ -139,11 +181,14 @@ export default class TestGenerator extends (PureComponent || Component) {
|
||||||
if (!isVanilla) r = wrap({ name, assertions: r });
|
if (!isVanilla) r = wrap({ name, assertions: r });
|
||||||
else {
|
else {
|
||||||
r = wrap({
|
r = wrap({
|
||||||
name: /^[a-zA-Z0-9_-]+?$/.test(name) ? name : 'Store',
|
name: /^[a-zA-Z0-9_-]+?$/.test(name as string) ? name : 'Store',
|
||||||
actionName:
|
actionName:
|
||||||
(selectedActionId === null || selectedActionId > 0) &&
|
(selectedActionId === null || selectedActionId > 0) &&
|
||||||
actions[startIdx]
|
actions[startIdx]
|
||||||
? actions[startIdx].action.type.replace(/[^a-zA-Z0-9_-]+/, '')
|
? (actions[startIdx].action.type as string).replace(
|
||||||
|
/[^a-zA-Z0-9_-]+/,
|
||||||
|
''
|
||||||
|
)
|
||||||
: 'should return the initial state',
|
: 'should return the initial state',
|
||||||
initialState: stringify(computedStates[startIdx - 1].state),
|
initialState: stringify(computedStates[startIdx - 1].state),
|
||||||
assertions: r,
|
assertions: r,
|
||||||
|
@ -167,25 +212,10 @@ export default class TestGenerator extends (PureComponent || Component) {
|
||||||
|
|
||||||
return <Editor value={code} />;
|
return <Editor value={code} />;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
TestGenerator.propTypes = {
|
static defaultProps = {
|
||||||
name: PropTypes.string,
|
|
||||||
isVanilla: PropTypes.bool,
|
|
||||||
computedStates: PropTypes.array,
|
|
||||||
actions: PropTypes.object,
|
|
||||||
selectedActionId: PropTypes.number,
|
|
||||||
startActionId: PropTypes.number,
|
|
||||||
wrap: PropTypes.oneOfType([PropTypes.func, PropTypes.string]),
|
|
||||||
dispatcher: PropTypes.oneOfType([PropTypes.func, PropTypes.string]),
|
|
||||||
assertion: PropTypes.oneOfType([PropTypes.func, PropTypes.string]),
|
|
||||||
useCodemirror: PropTypes.bool,
|
|
||||||
indentation: PropTypes.number,
|
|
||||||
header: PropTypes.element,
|
|
||||||
};
|
|
||||||
|
|
||||||
TestGenerator.defaultProps = {
|
|
||||||
useCodemirror: true,
|
useCodemirror: true,
|
||||||
selectedActionId: null,
|
selectedActionId: null,
|
||||||
startActionId: null,
|
startActionId: null,
|
||||||
};
|
};
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
declare module 'es6template' {
|
||||||
|
const _default: {
|
||||||
|
compile<Locals>(template: string): (locals: Locals) => string;
|
||||||
|
};
|
||||||
|
export default _default;
|
||||||
|
}
|
|
@ -8,16 +8,22 @@ import {
|
||||||
Notification,
|
Notification,
|
||||||
Dialog,
|
Dialog,
|
||||||
} from 'devui';
|
} from 'devui';
|
||||||
import { formSchema, uiSchema, defaultFormData } from './templateForm';
|
|
||||||
import { MdAdd } from 'react-icons/md';
|
import { MdAdd } from 'react-icons/md';
|
||||||
import { MdEdit } from 'react-icons/md';
|
import { MdEdit } from 'react-icons/md';
|
||||||
|
import { Action } from 'redux';
|
||||||
|
import {
|
||||||
|
DevtoolsInspectorState,
|
||||||
|
TabComponentProps,
|
||||||
|
} from 'redux-devtools-inspector-monitor';
|
||||||
|
import { formSchema, uiSchema, defaultFormData } from './templateForm';
|
||||||
import TestGenerator from './TestGenerator';
|
import TestGenerator from './TestGenerator';
|
||||||
import jestTemplate from './redux/jest/template';
|
import jestTemplate from './redux/jest/template';
|
||||||
import mochaTemplate from './redux/mocha/template';
|
import mochaTemplate from './redux/mocha/template';
|
||||||
import tapeTemplate from './redux/tape/template';
|
import tapeTemplate from './redux/tape/template';
|
||||||
import avaTemplate from './redux/ava/template';
|
import avaTemplate from './redux/ava/template';
|
||||||
|
import { Template } from './types';
|
||||||
|
|
||||||
export const getDefaultTemplates = (/* lib */) =>
|
export const getDefaultTemplates = (/* lib */): Template[] =>
|
||||||
/*
|
/*
|
||||||
if (lib === 'redux') {
|
if (lib === 'redux') {
|
||||||
return [mochaTemplate, tapeTemplate, avaTemplate];
|
return [mochaTemplate, tapeTemplate, avaTemplate];
|
||||||
|
@ -26,15 +32,27 @@ export const getDefaultTemplates = (/* lib */) =>
|
||||||
*/
|
*/
|
||||||
[jestTemplate, mochaTemplate, tapeTemplate, avaTemplate];
|
[jestTemplate, mochaTemplate, tapeTemplate, avaTemplate];
|
||||||
|
|
||||||
export default class TestTab extends Component {
|
interface TestGeneratorMonitorState {
|
||||||
constructor(props) {
|
hideTip?: boolean;
|
||||||
super(props);
|
selected?: number;
|
||||||
this.state = { dialogStatus: null };
|
templates?: Template[];
|
||||||
}
|
}
|
||||||
|
|
||||||
getPersistedState = () => this.props.monitorState.testGenerator || {};
|
interface State {
|
||||||
|
dialogStatus: 'Add' | 'Edit' | null;
|
||||||
|
}
|
||||||
|
|
||||||
handleSelectTemplate = (selectedTemplate) => {
|
export default class TestTab<S, A extends Action<unknown>> extends Component<
|
||||||
|
TabComponentProps<S, A>,
|
||||||
|
State
|
||||||
|
> {
|
||||||
|
state: State = { dialogStatus: null };
|
||||||
|
|
||||||
|
getPersistedState = (): TestGeneratorMonitorState =>
|
||||||
|
(this.props.monitorState as { testGenerator?: TestGeneratorMonitorState })
|
||||||
|
.testGenerator || {};
|
||||||
|
|
||||||
|
handleSelectTemplate = (selectedTemplate: Template) => {
|
||||||
const { templates = getDefaultTemplates() } = this.getPersistedState();
|
const { templates = getDefaultTemplates() } = this.getPersistedState();
|
||||||
this.updateState({ selected: templates.indexOf(selectedTemplate) });
|
this.updateState({ selected: templates.indexOf(selectedTemplate) });
|
||||||
};
|
};
|
||||||
|
@ -47,7 +65,7 @@ export default class TestTab extends Component {
|
||||||
this.setState({ dialogStatus: null });
|
this.setState({ dialogStatus: null });
|
||||||
};
|
};
|
||||||
|
|
||||||
handleSubmit = ({ formData: template }) => {
|
handleSubmit = ({ formData: template }: { formData: Template }) => {
|
||||||
const {
|
const {
|
||||||
templates = getDefaultTemplates(),
|
templates = getDefaultTemplates(),
|
||||||
selected = 0,
|
selected = 0,
|
||||||
|
@ -90,13 +108,15 @@ export default class TestTab extends Component {
|
||||||
this.setState({ dialogStatus: 'Edit' });
|
this.setState({ dialogStatus: 'Edit' });
|
||||||
};
|
};
|
||||||
|
|
||||||
updateState = (newState) => {
|
updateState = (newState: TestGeneratorMonitorState) => {
|
||||||
this.props.updateMonitorState({
|
this.props.updateMonitorState({
|
||||||
testGenerator: {
|
testGenerator: {
|
||||||
...this.props.monitorState.testGenerator,
|
...(this.props.monitorState as {
|
||||||
|
testGenerator?: TestGeneratorMonitorState;
|
||||||
|
}).testGenerator,
|
||||||
...newState,
|
...newState,
|
||||||
},
|
},
|
||||||
});
|
} as Partial<DevtoolsInspectorState>);
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
@ -128,7 +148,7 @@ export default class TestTab extends Component {
|
||||||
{!assertion ? (
|
{!assertion ? (
|
||||||
<Notification>No template for tests specified.</Notification>
|
<Notification>No template for tests specified.</Notification>
|
||||||
) : (
|
) : (
|
||||||
<TestGenerator
|
<TestGenerator<S, A>
|
||||||
isVanilla={false}
|
isVanilla={false}
|
||||||
assertion={assertion}
|
assertion={assertion}
|
||||||
dispatcher={dispatcher}
|
dispatcher={dispatcher}
|
||||||
|
@ -142,7 +162,7 @@ export default class TestTab extends Component {
|
||||||
</Notification>
|
</Notification>
|
||||||
)}
|
)}
|
||||||
{dialogStatus && (
|
{dialogStatus && (
|
||||||
<Dialog
|
<Dialog<Template>
|
||||||
open
|
open
|
||||||
title={`${dialogStatus} test template`}
|
title={`${dialogStatus} test template`}
|
||||||
onDismiss={this.handleCloseDialog}
|
onDismiss={this.handleCloseDialog}
|
||||||
|
@ -164,9 +184,8 @@ export default class TestTab extends Component {
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
TestTab.propTypes = {
|
static propTypes = {
|
||||||
monitorState: PropTypes.shape({
|
monitorState: PropTypes.shape({
|
||||||
testGenerator: PropTypes.shape({
|
testGenerator: PropTypes.shape({
|
||||||
templates: PropTypes.array,
|
templates: PropTypes.array,
|
||||||
|
@ -180,4 +199,5 @@ TestTab.propTypes = {
|
||||||
}).isRequired,
|
}).isRequired,
|
||||||
*/
|
*/
|
||||||
updateMonitorState: PropTypes.func.isRequired,
|
updateMonitorState: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
}
|
|
@ -1,18 +0,0 @@
|
||||||
export const name = 'Ava template';
|
|
||||||
|
|
||||||
export const dispatcher = ({ action, prevState }) =>
|
|
||||||
`state = reducers(${prevState}, ${action});`;
|
|
||||||
|
|
||||||
export const assertion = ({ curState }) => `t.deepEqual(state, ${curState});`;
|
|
||||||
|
|
||||||
export const wrap = ({ assertions }) =>
|
|
||||||
`import test from 'ava';
|
|
||||||
import reducers from '../../reducers';
|
|
||||||
|
|
||||||
test('reducers', (t) => {
|
|
||||||
let state;
|
|
||||||
${assertions}
|
|
||||||
});
|
|
||||||
`;
|
|
||||||
|
|
||||||
export default { name, assertion, dispatcher, wrap };
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
import { AssertionLocals, DispatcherLocals, WrapLocals } from '../../types';
|
||||||
|
|
||||||
|
export const name = 'Ava template';
|
||||||
|
|
||||||
|
export const dispatcher = ({ action, prevState }: DispatcherLocals) =>
|
||||||
|
`state = reducers(${prevState!}, ${action!});`;
|
||||||
|
|
||||||
|
export const assertion = ({ curState }: AssertionLocals) =>
|
||||||
|
`t.deepEqual(state, ${curState!});`;
|
||||||
|
|
||||||
|
export const wrap = ({ assertions }: WrapLocals) =>
|
||||||
|
`import test from 'ava';
|
||||||
|
import reducers from '../../reducers';
|
||||||
|
|
||||||
|
test('reducers', (t) => {
|
||||||
|
let state;
|
||||||
|
${assertions}
|
||||||
|
});
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default { name, assertion, dispatcher, wrap };
|
|
@ -1,18 +0,0 @@
|
||||||
export const name = 'Jest template';
|
|
||||||
|
|
||||||
export const dispatcher = ({ action, prevState }) =>
|
|
||||||
`state = reducers(${prevState}, ${action});`;
|
|
||||||
|
|
||||||
export const assertion = ({ curState }) =>
|
|
||||||
`expect(state).toEqual(${curState});`;
|
|
||||||
|
|
||||||
export const wrap = ({ assertions }) =>
|
|
||||||
`import reducers from '../../reducers';
|
|
||||||
|
|
||||||
test('reducers', () => {
|
|
||||||
let state;
|
|
||||||
${assertions}
|
|
||||||
});
|
|
||||||
`;
|
|
||||||
|
|
||||||
export default { name, assertion, dispatcher, wrap };
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { AssertionLocals, DispatcherLocals, WrapLocals } from '../../types';
|
||||||
|
|
||||||
|
export const name = 'Jest template';
|
||||||
|
|
||||||
|
export const dispatcher = ({ action, prevState }: DispatcherLocals) =>
|
||||||
|
`state = reducers(${prevState!}, ${action!});`;
|
||||||
|
|
||||||
|
export const assertion = ({ curState }: AssertionLocals) =>
|
||||||
|
`expect(state).toEqual(${curState!});`;
|
||||||
|
|
||||||
|
export const wrap = ({ assertions }: WrapLocals) =>
|
||||||
|
`import reducers from '../../reducers';
|
||||||
|
|
||||||
|
test('reducers', () => {
|
||||||
|
let state;
|
||||||
|
${assertions}
|
||||||
|
});
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default { name, assertion, dispatcher, wrap };
|
|
@ -1,21 +0,0 @@
|
||||||
export const name = 'Mocha template';
|
|
||||||
|
|
||||||
export const dispatcher = ({ action, prevState }) =>
|
|
||||||
`state = reducers(${prevState}, ${action});`;
|
|
||||||
|
|
||||||
export const assertion = ({ curState }) =>
|
|
||||||
`expect(state).toEqual(${curState});`;
|
|
||||||
|
|
||||||
export const wrap = ({ assertions }) =>
|
|
||||||
`import expect from 'expect';
|
|
||||||
import reducers from '../../reducers';
|
|
||||||
|
|
||||||
describe('reducers', () => {
|
|
||||||
it('should handle actions', () => {
|
|
||||||
let state;
|
|
||||||
${assertions}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
`;
|
|
||||||
|
|
||||||
export default { name, assertion, dispatcher, wrap };
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { AssertionLocals, DispatcherLocals, WrapLocals } from '../../types';
|
||||||
|
|
||||||
|
export const name = 'Mocha template';
|
||||||
|
|
||||||
|
export const dispatcher = ({ action, prevState }: DispatcherLocals) =>
|
||||||
|
`state = reducers(${prevState!}, ${action!});`;
|
||||||
|
|
||||||
|
export const assertion = ({ curState }: AssertionLocals) =>
|
||||||
|
`expect(state).toEqual(${curState!});`;
|
||||||
|
|
||||||
|
export const wrap = ({ assertions }: WrapLocals) =>
|
||||||
|
`import expect from 'expect';
|
||||||
|
import reducers from '../../reducers';
|
||||||
|
|
||||||
|
describe('reducers', () => {
|
||||||
|
it('should handle actions', () => {
|
||||||
|
let state;
|
||||||
|
${assertions}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default { name, assertion, dispatcher, wrap };
|
|
@ -1,19 +0,0 @@
|
||||||
export const name = 'Tape template';
|
|
||||||
|
|
||||||
export const dispatcher = ({ action, prevState }) =>
|
|
||||||
`state = reducers(${prevState}, ${action});`;
|
|
||||||
|
|
||||||
export const assertion = ({ curState }) => `t.deepEqual(state, ${curState});`;
|
|
||||||
|
|
||||||
export const wrap = ({ assertions }) =>
|
|
||||||
`import test from 'tape';
|
|
||||||
import reducers from '../../reducers';
|
|
||||||
|
|
||||||
test('reducers', (t) => {
|
|
||||||
let state;
|
|
||||||
${assertions}
|
|
||||||
t.end();
|
|
||||||
});
|
|
||||||
`;
|
|
||||||
|
|
||||||
export default { name, assertion, dispatcher, wrap };
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
import { AssertionLocals, DispatcherLocals, WrapLocals } from '../../types';
|
||||||
|
|
||||||
|
export const name = 'Tape template';
|
||||||
|
|
||||||
|
export const dispatcher = ({ action, prevState }: DispatcherLocals) =>
|
||||||
|
`state = reducers(${prevState!}, ${action!});`;
|
||||||
|
|
||||||
|
export const assertion = ({ curState }: AssertionLocals) =>
|
||||||
|
`t.deepEqual(state, ${curState!});`;
|
||||||
|
|
||||||
|
export const wrap = ({ assertions }: WrapLocals) =>
|
||||||
|
`import test from 'tape';
|
||||||
|
import reducers from '../../reducers';
|
||||||
|
|
||||||
|
test('reducers', (t) => {
|
||||||
|
let state;
|
||||||
|
${assertions}
|
||||||
|
t.end();
|
||||||
|
});
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default { name, assertion, dispatcher, wrap };
|
64
packages/redux-devtools-test-generator/src/simple-diff.ts
Normal file
64
packages/redux-devtools-test-generator/src/simple-diff.ts
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
declare module 'simple-diff' {
|
||||||
|
interface AddEvent {
|
||||||
|
oldPath: (string | number)[];
|
||||||
|
newPath: (string | number)[];
|
||||||
|
type: 'add';
|
||||||
|
oldValue: undefined;
|
||||||
|
newValue: unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface RemoveEvent {
|
||||||
|
oldPath: (string | number)[];
|
||||||
|
newPath: (string | number)[];
|
||||||
|
type: 'remove';
|
||||||
|
oldValue: unknown;
|
||||||
|
newValue: undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ChangeEvent {
|
||||||
|
oldPath: (string | number)[];
|
||||||
|
newPath: (string | number)[];
|
||||||
|
type: 'change';
|
||||||
|
oldValue: unknown;
|
||||||
|
newValue: unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AddItemEvent {
|
||||||
|
oldPath: (string | number)[];
|
||||||
|
newPath: (string | number)[];
|
||||||
|
type: 'add-item';
|
||||||
|
oldIndex: -1;
|
||||||
|
curIndex: -1;
|
||||||
|
newIndex: number;
|
||||||
|
newValue: unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface RemoveItemEvent {
|
||||||
|
oldPath: (string | number)[];
|
||||||
|
newPath: (string | number)[];
|
||||||
|
type: 'remove-item';
|
||||||
|
oldIndex: number;
|
||||||
|
curIndex: number;
|
||||||
|
newIndex: -1;
|
||||||
|
oldValue: unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface MoveItemEvent {
|
||||||
|
oldPath: (string | number)[];
|
||||||
|
newPath: (string | number)[];
|
||||||
|
type: 'move-item';
|
||||||
|
oldIndex: number;
|
||||||
|
curIndex: number;
|
||||||
|
newIndex: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Event =
|
||||||
|
| AddEvent
|
||||||
|
| RemoveEvent
|
||||||
|
| ChangeEvent
|
||||||
|
| AddItemEvent
|
||||||
|
| RemoveItemEvent
|
||||||
|
| MoveItemEvent;
|
||||||
|
|
||||||
|
export default function (oldObj: unknown, newObj: unknown): Event[];
|
||||||
|
}
|
|
@ -1,21 +1,23 @@
|
||||||
|
import { Template } from './types';
|
||||||
|
|
||||||
export const formSchema = {
|
export const formSchema = {
|
||||||
type: 'object',
|
type: 'object' as const,
|
||||||
required: ['name'],
|
required: ['name'],
|
||||||
properties: {
|
properties: {
|
||||||
name: {
|
name: {
|
||||||
type: 'string',
|
type: 'string' as const,
|
||||||
title: 'Template name',
|
title: 'Template name',
|
||||||
},
|
},
|
||||||
dispatcher: {
|
dispatcher: {
|
||||||
type: 'string',
|
type: 'string' as const,
|
||||||
title: 'Dispatcher: ({ action, prevState }) => (`<template>`)',
|
title: 'Dispatcher: ({ action, prevState }) => (`<template>`)',
|
||||||
},
|
},
|
||||||
assertion: {
|
assertion: {
|
||||||
type: 'string',
|
type: 'string' as const,
|
||||||
title: 'Assertion: ({ curState }) => (`<template>`)',
|
title: 'Assertion: ({ curState }) => (`<template>`)',
|
||||||
},
|
},
|
||||||
wrap: {
|
wrap: {
|
||||||
type: 'string',
|
type: 'string' as const,
|
||||||
title:
|
title:
|
||||||
'Wrap code: ({ name, initialState, assertions }) => (`<template>`)',
|
'Wrap code: ({ name, initialState, assertions }) => (`<template>`)',
|
||||||
},
|
},
|
||||||
|
@ -34,7 +36,7 @@ export const uiSchema = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const defaultFormData = {
|
export const defaultFormData: Template = {
|
||||||
dispatcher: 'state = reducers(${prevState}, ${action});',
|
dispatcher: 'state = reducers(${prevState}, ${action});',
|
||||||
assertion: 't.deepEqual(state, ${curState});',
|
assertion: 't.deepEqual(state, ${curState});',
|
||||||
wrap: `test('reducers', (t) => {
|
wrap: `test('reducers', (t) => {
|
23
packages/redux-devtools-test-generator/src/types.ts
Normal file
23
packages/redux-devtools-test-generator/src/types.ts
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
export interface DispatcherLocals {
|
||||||
|
action: string | undefined;
|
||||||
|
prevState: string | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AssertionLocals {
|
||||||
|
path: string;
|
||||||
|
curState: number | string | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface WrapLocals {
|
||||||
|
name: string | undefined;
|
||||||
|
assertions: string;
|
||||||
|
actionName?: string;
|
||||||
|
initialState?: string | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Template {
|
||||||
|
name?: string;
|
||||||
|
dispatcher: string;
|
||||||
|
assertion: string;
|
||||||
|
wrap: string;
|
||||||
|
}
|
|
@ -1,18 +0,0 @@
|
||||||
export const name = 'Ava template';
|
|
||||||
|
|
||||||
export const dispatcher = ({ action }) => `${action};`;
|
|
||||||
|
|
||||||
export const assertion = ({ path, curState }) =>
|
|
||||||
`t.deepEqual(state${path}, ${curState});`;
|
|
||||||
|
|
||||||
export const wrap = ({ name, initialState, assertions }) =>
|
|
||||||
`import test from 'ava';
|
|
||||||
import ${name} from '../../stores/${name}';
|
|
||||||
|
|
||||||
test('${name}', (t) => {
|
|
||||||
const store = new ${name}(${initialState});
|
|
||||||
${assertions}
|
|
||||||
});
|
|
||||||
`;
|
|
||||||
|
|
||||||
export default { name, assertion, dispatcher, wrap };
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { AssertionLocals, DispatcherLocals, WrapLocals } from '../../types';
|
||||||
|
|
||||||
|
export const name = 'Ava template';
|
||||||
|
|
||||||
|
export const dispatcher = ({ action }: DispatcherLocals) => `${action!};`;
|
||||||
|
|
||||||
|
export const assertion = ({ path, curState }: AssertionLocals) =>
|
||||||
|
`t.deepEqual(state${path}, ${curState!});`;
|
||||||
|
|
||||||
|
export const wrap = ({ name, initialState, assertions }: WrapLocals) =>
|
||||||
|
`import test from 'ava';
|
||||||
|
import ${name!} from '../../stores/${name!}';
|
||||||
|
|
||||||
|
test('${name!}', (t) => {
|
||||||
|
const store = new ${name!}(${initialState!});
|
||||||
|
${assertions}
|
||||||
|
});
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default { name, assertion, dispatcher, wrap };
|
|
@ -1,18 +0,0 @@
|
||||||
export const name = 'Mocha template';
|
|
||||||
|
|
||||||
export const dispatcher = ({ action }) => `${action};`;
|
|
||||||
|
|
||||||
export const assertion = ({ path, curState }) =>
|
|
||||||
`expect(store${path}).toEqual(${curState});`;
|
|
||||||
|
|
||||||
export const wrap = ({ name, initialState, assertions }) =>
|
|
||||||
`import expect from 'expect';
|
|
||||||
import ${name} from '../../stores/${name}';
|
|
||||||
|
|
||||||
test('${name}', (t) => {
|
|
||||||
const store = new ${name}(${initialState});
|
|
||||||
${assertions}
|
|
||||||
});
|
|
||||||
`;
|
|
||||||
|
|
||||||
export default { name, assertion, dispatcher, wrap };
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { AssertionLocals, DispatcherLocals, WrapLocals } from '../../types';
|
||||||
|
|
||||||
|
export const name = 'Mocha template';
|
||||||
|
|
||||||
|
export const dispatcher = ({ action }: DispatcherLocals) => `${action!};`;
|
||||||
|
|
||||||
|
export const assertion = ({ path, curState }: AssertionLocals) =>
|
||||||
|
`expect(store${path}).toEqual(${curState!});`;
|
||||||
|
|
||||||
|
export const wrap = ({ name, initialState, assertions }: WrapLocals) =>
|
||||||
|
`import expect from 'expect';
|
||||||
|
import ${name!} from '../../stores/${name!}';
|
||||||
|
|
||||||
|
test('${name!}', (t) => {
|
||||||
|
const store = new ${name!}(${initialState!});
|
||||||
|
${assertions}
|
||||||
|
});
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default { name, assertion, dispatcher, wrap };
|
|
@ -1,20 +0,0 @@
|
||||||
export const name = 'Mocha template';
|
|
||||||
|
|
||||||
export const dispatcher = ({ action }) => `${action};`;
|
|
||||||
|
|
||||||
export const assertion = ({ path, curState }) =>
|
|
||||||
`expect(store${path}).toEqual(${curState});`;
|
|
||||||
|
|
||||||
export const wrap = ({ name, actionName, initialState, assertions }) =>
|
|
||||||
`import expect from 'expect';
|
|
||||||
import ${name} from '../../stores/${name}';
|
|
||||||
|
|
||||||
describe('${name}', () => {
|
|
||||||
it('${actionName}', () => {
|
|
||||||
const store = new ${name}(${initialState});
|
|
||||||
${assertions}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
`;
|
|
||||||
|
|
||||||
export default { name, assertion, dispatcher, wrap };
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
import { AssertionLocals, DispatcherLocals, WrapLocals } from '../../types';
|
||||||
|
|
||||||
|
export const name = 'Mocha template';
|
||||||
|
|
||||||
|
export const dispatcher = ({ action }: DispatcherLocals) => `${action!};`;
|
||||||
|
|
||||||
|
export const assertion = ({ path, curState }: AssertionLocals) =>
|
||||||
|
`expect(store${path}).toEqual(${curState!});`;
|
||||||
|
|
||||||
|
export const wrap = ({
|
||||||
|
name,
|
||||||
|
actionName,
|
||||||
|
initialState,
|
||||||
|
assertions,
|
||||||
|
}: WrapLocals) =>
|
||||||
|
`import expect from 'expect';
|
||||||
|
import ${name!} from '../../stores/${name!}';
|
||||||
|
|
||||||
|
describe('${name!}', () => {
|
||||||
|
it('${actionName!}', () => {
|
||||||
|
const store = new ${name!}(${initialState!});
|
||||||
|
${assertions}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default { name, assertion, dispatcher, wrap };
|
|
@ -1,19 +0,0 @@
|
||||||
export const name = 'Tape template';
|
|
||||||
|
|
||||||
export const dispatcher = ({ action }) => `${action};`;
|
|
||||||
|
|
||||||
export const assertion = ({ path, curState }) =>
|
|
||||||
`t.deepEqual(state${path}, ${curState});`;
|
|
||||||
|
|
||||||
export const wrap = ({ name, initialState, assertions }) =>
|
|
||||||
`import test from 'tape';
|
|
||||||
import ${name} from '../../stores/${name}';
|
|
||||||
|
|
||||||
test('${name}', (t) => {
|
|
||||||
const store = new ${name}(${initialState});
|
|
||||||
${assertions}
|
|
||||||
t.end();
|
|
||||||
});
|
|
||||||
`;
|
|
||||||
|
|
||||||
export default { name, assertion, dispatcher, wrap };
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
import { AssertionLocals, DispatcherLocals, WrapLocals } from '../../types';
|
||||||
|
|
||||||
|
export const name = 'Tape template';
|
||||||
|
|
||||||
|
export const dispatcher = ({ action }: DispatcherLocals) => `${action!};`;
|
||||||
|
|
||||||
|
export const assertion = ({ path, curState }: AssertionLocals) =>
|
||||||
|
`t.deepEqual(state${path}, ${curState!});`;
|
||||||
|
|
||||||
|
export const wrap = ({ name, initialState, assertions }: WrapLocals) =>
|
||||||
|
`import test from 'tape';
|
||||||
|
import ${name!} from '../../stores/${name!}';
|
||||||
|
|
||||||
|
test('${name!}', (t) => {
|
||||||
|
const store = new ${name!}(${initialState!});
|
||||||
|
${assertions}
|
||||||
|
t.end();
|
||||||
|
});
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default { name, assertion, dispatcher, wrap };
|
|
@ -1,28 +1,42 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { render } from 'enzyme';
|
import { render } from 'enzyme';
|
||||||
import { renderToJson } from 'enzyme-to-json';
|
import { renderToJson } from 'enzyme-to-json';
|
||||||
|
import { PerformAction } from 'redux-devtools-instrument';
|
||||||
|
import { Action } from 'redux';
|
||||||
import TestGenerator from '../src/TestGenerator';
|
import TestGenerator from '../src/TestGenerator';
|
||||||
import fnTemplate from '../src/redux/mocha';
|
import fnTemplate from '../src/redux/mocha';
|
||||||
import strTemplate from '../src/redux/mocha/template';
|
import strTemplate from '../src/redux/mocha/template';
|
||||||
import fnVanillaTemplate from '../src/vanilla/mocha';
|
import fnVanillaTemplate from '../src/vanilla/mocha';
|
||||||
import strVanillaTemplate from '../src/vanilla/mocha/template';
|
import strVanillaTemplate from '../src/vanilla/mocha/template';
|
||||||
|
|
||||||
const actions = {
|
const actions: { [actionId: number]: PerformAction<Action<unknown>> } = {
|
||||||
0: { type: 'PERFORM_ACTION', action: { type: '@@INIT' } },
|
0: {
|
||||||
1: { type: 'PERFORM_ACTION', action: { type: 'INCREMENT_COUNTER' } },
|
type: 'PERFORM_ACTION',
|
||||||
|
action: { type: '@@INIT' },
|
||||||
|
timestamp: 0,
|
||||||
|
stack: undefined,
|
||||||
|
},
|
||||||
|
1: {
|
||||||
|
type: 'PERFORM_ACTION',
|
||||||
|
action: { type: 'INCREMENT_COUNTER' },
|
||||||
|
timestamp: 0,
|
||||||
|
stack: undefined,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const computedStates = [{ state: { counter: 0 } }, { state: { counter: 1 } }];
|
const computedStates = [{ state: { counter: 0 } }, { state: { counter: 1 } }];
|
||||||
|
|
||||||
|
const TestGeneratorAsAny = TestGenerator as any;
|
||||||
|
|
||||||
describe('TestGenerator component', () => {
|
describe('TestGenerator component', () => {
|
||||||
it('should show warning message when no params provided', () => {
|
it('should show warning message when no params provided', () => {
|
||||||
const component = render(<TestGenerator useCodemirror={false} />);
|
const component = render(<TestGeneratorAsAny useCodemirror={false} />);
|
||||||
expect(renderToJson(component)).toMatchSnapshot();
|
expect(renderToJson(component)).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be empty when no actions provided', () => {
|
it('should be empty when no actions provided', () => {
|
||||||
const component = render(
|
const component = render(
|
||||||
<TestGenerator
|
<TestGeneratorAsAny
|
||||||
assertion={fnTemplate.assertion}
|
assertion={fnTemplate.assertion}
|
||||||
dispatcher={fnTemplate.dispatcher}
|
dispatcher={fnTemplate.dispatcher}
|
||||||
wrap={fnTemplate.wrap}
|
wrap={fnTemplate.wrap}
|
||||||
|
@ -34,7 +48,7 @@ describe('TestGenerator component', () => {
|
||||||
|
|
||||||
it("should match function template's test for first action", () => {
|
it("should match function template's test for first action", () => {
|
||||||
const component = render(
|
const component = render(
|
||||||
<TestGenerator
|
<TestGeneratorAsAny
|
||||||
assertion={fnTemplate.assertion}
|
assertion={fnTemplate.assertion}
|
||||||
dispatcher={fnTemplate.dispatcher}
|
dispatcher={fnTemplate.dispatcher}
|
||||||
wrap={fnTemplate.wrap}
|
wrap={fnTemplate.wrap}
|
||||||
|
@ -49,7 +63,7 @@ describe('TestGenerator component', () => {
|
||||||
|
|
||||||
it("should match string template's test for first action", () => {
|
it("should match string template's test for first action", () => {
|
||||||
const component = render(
|
const component = render(
|
||||||
<TestGenerator
|
<TestGeneratorAsAny
|
||||||
assertion={strTemplate.assertion}
|
assertion={strTemplate.assertion}
|
||||||
dispatcher={strTemplate.dispatcher}
|
dispatcher={strTemplate.dispatcher}
|
||||||
wrap={strTemplate.wrap}
|
wrap={strTemplate.wrap}
|
||||||
|
@ -64,7 +78,7 @@ describe('TestGenerator component', () => {
|
||||||
|
|
||||||
it('should generate test for the last action when selectedActionId not specified', () => {
|
it('should generate test for the last action when selectedActionId not specified', () => {
|
||||||
const component = render(
|
const component = render(
|
||||||
<TestGenerator
|
<TestGeneratorAsAny
|
||||||
assertion={fnTemplate.assertion}
|
assertion={fnTemplate.assertion}
|
||||||
dispatcher={fnTemplate.dispatcher}
|
dispatcher={fnTemplate.dispatcher}
|
||||||
wrap={fnTemplate.wrap}
|
wrap={fnTemplate.wrap}
|
||||||
|
@ -78,7 +92,7 @@ describe('TestGenerator component', () => {
|
||||||
|
|
||||||
it('should generate test for vanilla js class', () => {
|
it('should generate test for vanilla js class', () => {
|
||||||
const component = render(
|
const component = render(
|
||||||
<TestGenerator
|
<TestGeneratorAsAny
|
||||||
assertion={fnVanillaTemplate.assertion}
|
assertion={fnVanillaTemplate.assertion}
|
||||||
dispatcher={fnVanillaTemplate.dispatcher}
|
dispatcher={fnVanillaTemplate.dispatcher}
|
||||||
wrap={fnVanillaTemplate.wrap}
|
wrap={fnVanillaTemplate.wrap}
|
||||||
|
@ -95,7 +109,7 @@ describe('TestGenerator component', () => {
|
||||||
|
|
||||||
it('should generate test for vanilla js class with string template', () => {
|
it('should generate test for vanilla js class with string template', () => {
|
||||||
const component = render(
|
const component = render(
|
||||||
<TestGenerator
|
<TestGeneratorAsAny
|
||||||
assertion={strVanillaTemplate.assertion}
|
assertion={strVanillaTemplate.assertion}
|
||||||
dispatcher={strVanillaTemplate.dispatcher}
|
dispatcher={strVanillaTemplate.dispatcher}
|
||||||
wrap={strVanillaTemplate.wrap}
|
wrap={strVanillaTemplate.wrap}
|
|
@ -12,11 +12,11 @@ const computedStates = [
|
||||||
{ state: [0, 2, 3, 4] },
|
{ state: [0, 2, 3, 4] },
|
||||||
];
|
];
|
||||||
|
|
||||||
const test = (s1, s2) =>
|
const test = (s1: { state: unknown } | undefined, s2: { state: unknown }) =>
|
||||||
compare(s1, s2, ({ path, curState }) =>
|
compare(s1, s2, ({ path, curState }) =>
|
||||||
expect(`expect(store${path}).toEqual(${curState});`).toBe(
|
expect(
|
||||||
assertion({ path, curState })
|
`expect(store${path}).toEqual(${curState as number | string});`
|
||||||
)
|
).toBe(assertion({ path, curState }))
|
||||||
);
|
);
|
||||||
|
|
||||||
describe('Assertions', () => {
|
describe('Assertions', () => {
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"extends": "../../../tsconfig.react.base.json",
|
||||||
|
"include": ["../src", "."]
|
||||||
|
}
|
8
packages/redux-devtools-test-generator/tsconfig.json
Normal file
8
packages/redux-devtools-test-generator/tsconfig.json
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"extends": "../../tsconfig.react.base.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "lib",
|
||||||
|
"resolveJsonModule": true
|
||||||
|
},
|
||||||
|
"include": ["src"]
|
||||||
|
}
|
40
yarn.lock
40
yarn.lock
|
@ -387,14 +387,6 @@
|
||||||
"@babel/helper-plugin-utils" "^7.10.4"
|
"@babel/helper-plugin-utils" "^7.10.4"
|
||||||
"@babel/plugin-syntax-decorators" "^7.10.4"
|
"@babel/plugin-syntax-decorators" "^7.10.4"
|
||||||
|
|
||||||
"@babel/plugin-proposal-do-expressions@^7.10.4":
|
|
||||||
version "7.10.4"
|
|
||||||
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-do-expressions/-/plugin-proposal-do-expressions-7.10.4.tgz#9a5190f3bf4818f83e41d673ee517ff76cf8e4ed"
|
|
||||||
integrity sha512-Gcc2wLVeMceRdP6m9tdDygP01lbUVmaQGBRoIRJZxzPfB5VTiUgmn1jGfORgqbEVgUpG0IQm/z4q5Y/qzG+8JQ==
|
|
||||||
dependencies:
|
|
||||||
"@babel/helper-plugin-utils" "^7.10.4"
|
|
||||||
"@babel/plugin-syntax-do-expressions" "^7.10.4"
|
|
||||||
|
|
||||||
"@babel/plugin-proposal-dynamic-import@^7.10.4":
|
"@babel/plugin-proposal-dynamic-import@^7.10.4":
|
||||||
version "7.10.4"
|
version "7.10.4"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.10.4.tgz#ba57a26cb98b37741e9d5bca1b8b0ddf8291f17e"
|
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.10.4.tgz#ba57a26cb98b37741e9d5bca1b8b0ddf8291f17e"
|
||||||
|
@ -530,13 +522,6 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/helper-plugin-utils" "^7.10.4"
|
"@babel/helper-plugin-utils" "^7.10.4"
|
||||||
|
|
||||||
"@babel/plugin-syntax-do-expressions@^7.10.4":
|
|
||||||
version "7.10.4"
|
|
||||||
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-do-expressions/-/plugin-syntax-do-expressions-7.10.4.tgz#0c7ebb749500c6bfa99a9f926db3bfd6cdbaded9"
|
|
||||||
integrity sha512-HyvaTg1aiwGo2I+Pu0nyurRMjIP7J89GpuZ2mcQ0fhO6Jt3BnyhEPbNJFG1hRE99NAPNfPYh93/7HO+GPVkTKg==
|
|
||||||
dependencies:
|
|
||||||
"@babel/helper-plugin-utils" "^7.10.4"
|
|
||||||
|
|
||||||
"@babel/plugin-syntax-dynamic-import@^7.8.0", "@babel/plugin-syntax-dynamic-import@^7.8.3":
|
"@babel/plugin-syntax-dynamic-import@^7.8.0", "@babel/plugin-syntax-dynamic-import@^7.8.3":
|
||||||
version "7.8.3"
|
version "7.8.3"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3"
|
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3"
|
||||||
|
@ -977,14 +962,6 @@
|
||||||
"@babel/helper-create-regexp-features-plugin" "^7.10.4"
|
"@babel/helper-create-regexp-features-plugin" "^7.10.4"
|
||||||
"@babel/helper-plugin-utils" "^7.10.4"
|
"@babel/helper-plugin-utils" "^7.10.4"
|
||||||
|
|
||||||
"@babel/polyfill@^7.10.4":
|
|
||||||
version "7.10.4"
|
|
||||||
resolved "https://registry.yarnpkg.com/@babel/polyfill/-/polyfill-7.10.4.tgz#915e5bfe61490ac0199008e35ca9d7d151a8e45a"
|
|
||||||
integrity sha512-8BYcnVqQ5kMD2HXoHInBH7H1b/uP3KdnwCYXOqFnXqguOyuu443WXusbIUbWEfY3Z0Txk0M1uG/8YuAMhNl6zg==
|
|
||||||
dependencies:
|
|
||||||
core-js "^2.6.5"
|
|
||||||
regenerator-runtime "^0.13.4"
|
|
||||||
|
|
||||||
"@babel/preset-env@^7.11.0":
|
"@babel/preset-env@^7.11.0":
|
||||||
version "7.11.0"
|
version "7.11.0"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.11.0.tgz#860ee38f2ce17ad60480c2021ba9689393efb796"
|
resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.11.0.tgz#860ee38f2ce17ad60480c2021ba9689393efb796"
|
||||||
|
@ -1192,7 +1169,7 @@
|
||||||
core-js "^2.6.5"
|
core-js "^2.6.5"
|
||||||
regenerator-runtime "^0.13.4"
|
regenerator-runtime "^0.13.4"
|
||||||
|
|
||||||
"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.2", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
|
"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.2", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
|
||||||
version "7.11.2"
|
version "7.11.2"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.11.2.tgz#f549c13c754cc40b87644b9fa9f09a6a95fe0736"
|
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.11.2.tgz#f549c13c754cc40b87644b9fa9f09a6a95fe0736"
|
||||||
integrity sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw==
|
integrity sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw==
|
||||||
|
@ -3653,6 +3630,11 @@
|
||||||
resolved "https://registry.yarnpkg.com/@types/npmlog/-/npmlog-4.1.2.tgz#d070fe6a6b78755d1092a3dc492d34c3d8f871c4"
|
resolved "https://registry.yarnpkg.com/@types/npmlog/-/npmlog-4.1.2.tgz#d070fe6a6b78755d1092a3dc492d34c3d8f871c4"
|
||||||
integrity sha512-4QQmOF5KlwfxJ5IGXFIudkeLCdMABz03RcUXu+LCb24zmln8QW6aDjuGl4d4XPVLf2j+FnjelHTP7dvceAFbhA==
|
integrity sha512-4QQmOF5KlwfxJ5IGXFIudkeLCdMABz03RcUXu+LCb24zmln8QW6aDjuGl4d4XPVLf2j+FnjelHTP7dvceAFbhA==
|
||||||
|
|
||||||
|
"@types/object-path@^0.11.0":
|
||||||
|
version "0.11.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/object-path/-/object-path-0.11.0.tgz#0b744309b2573dc8bf867ef589b6288be998e602"
|
||||||
|
integrity sha512-/tuN8jDbOXcPk+VzEVZzzAgw1Byz7s/itb2YI10qkSyy6nykJH02DuhfrflxVdAdE7AZ91h5X6Cn0dmVdFw2TQ==
|
||||||
|
|
||||||
"@types/overlayscrollbars@^1.9.0":
|
"@types/overlayscrollbars@^1.9.0":
|
||||||
version "1.12.0"
|
version "1.12.0"
|
||||||
resolved "https://registry.yarnpkg.com/@types/overlayscrollbars/-/overlayscrollbars-1.12.0.tgz#98456caceca8ad73bd5bb572632a585074e70764"
|
resolved "https://registry.yarnpkg.com/@types/overlayscrollbars/-/overlayscrollbars-1.12.0.tgz#98456caceca8ad73bd5bb572632a585074e70764"
|
||||||
|
@ -3828,6 +3810,11 @@
|
||||||
"@types/express-serve-static-core" "*"
|
"@types/express-serve-static-core" "*"
|
||||||
"@types/mime" "*"
|
"@types/mime" "*"
|
||||||
|
|
||||||
|
"@types/simple-element-resize-detector@^1.3.0":
|
||||||
|
version "1.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/simple-element-resize-detector/-/simple-element-resize-detector-1.3.0.tgz#19b40d71fefa1876ac5d4ba585197ef438946353"
|
||||||
|
integrity sha512-z89ForrCNg+4uwTHjwBCM9LjcsXYC/4O8u3tSi+82v2LCbfiYFpkjH/qQVkDewFBK6FUG7RRV7jw78EGs2maoQ==
|
||||||
|
|
||||||
"@types/source-list-map@*":
|
"@types/source-list-map@*":
|
||||||
version "0.1.2"
|
version "0.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/@types/source-list-map/-/source-list-map-0.1.2.tgz#0078836063ffaf17412349bba364087e0ac02ec9"
|
resolved "https://registry.yarnpkg.com/@types/source-list-map/-/source-list-map-0.1.2.tgz#0078836063ffaf17412349bba364087e0ac02ec9"
|
||||||
|
@ -11635,11 +11622,6 @@ lodash.isequal@^4.5.0:
|
||||||
resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
|
resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
|
||||||
integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA=
|
integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA=
|
||||||
|
|
||||||
lodash.isequalwith@^4.4.0:
|
|
||||||
version "4.4.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/lodash.isequalwith/-/lodash.isequalwith-4.4.0.tgz#266726ddd528f854f21f4ea98a065606e0fbc6b0"
|
|
||||||
integrity sha1-Jmcm3dUo+FTyH06pigZWBuD7xrA=
|
|
||||||
|
|
||||||
lodash.isinteger@^4.0.4:
|
lodash.isinteger@^4.0.4:
|
||||||
version "4.0.4"
|
version "4.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343"
|
resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user