mirror of
https://github.com/reduxjs/redux-devtools.git
synced 2025-07-27 08:30:02 +03:00
chore(rtk-query): add few integration tests to rtk-query-monitor #1126
This commit is contained in:
parent
8154bde35b
commit
19f8b5eabb
|
@ -1,2 +1,3 @@
|
||||||
demo
|
demo
|
||||||
lib
|
lib
|
||||||
|
dist
|
||||||
|
|
|
@ -9,5 +9,13 @@ module.exports = {
|
||||||
project: ['./tsconfig.json'],
|
project: ['./tsconfig.json'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
files: ['test/**/*.ts', 'test/**/*.tsx'],
|
||||||
|
extends: '../../eslintrc.ts.react.jest.base.json',
|
||||||
|
parserOptions: {
|
||||||
|
tsconfigRootDir: __dirname,
|
||||||
|
project: ['./tsconfig.test.json'],
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
12
packages/redux-devtools-rtk-query-monitor/jest.config.js
Normal file
12
packages/redux-devtools-rtk-query-monitor/jest.config.js
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
module.exports = {
|
||||||
|
preset: 'ts-jest',
|
||||||
|
testEnvironment: 'jsdom',
|
||||||
|
moduleNameMapper: {
|
||||||
|
'\\.css$': '<rootDir>/test/__mocks__/styleMock.ts',
|
||||||
|
},
|
||||||
|
globals: {
|
||||||
|
'ts-jest': {
|
||||||
|
tsconfig: 'tsconfig.test.json',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
|
@ -39,6 +39,7 @@
|
||||||
"clean": "rimraf lib",
|
"clean": "rimraf lib",
|
||||||
"lint": "eslint . --ext .ts,.tsx",
|
"lint": "eslint . --ext .ts,.tsx",
|
||||||
"type-check": "tsc --noEmit",
|
"type-check": "tsc --noEmit",
|
||||||
|
"test": "jest",
|
||||||
"prepack": "yarn run clean && yarn run build",
|
"prepack": "yarn run clean && yarn run build",
|
||||||
"prepublish": "yarn run type-check && yarn run lint"
|
"prepublish": "yarn run type-check && yarn run lint"
|
||||||
},
|
},
|
||||||
|
@ -67,18 +68,27 @@
|
||||||
"@babel/preset-typescript": "^7.16.7",
|
"@babel/preset-typescript": "^7.16.7",
|
||||||
"@redux-devtools/core": "^3.11.0",
|
"@redux-devtools/core": "^3.11.0",
|
||||||
"@reduxjs/toolkit": "^1.8.1",
|
"@reduxjs/toolkit": "^1.8.1",
|
||||||
|
"@testing-library/jest-dom": "^5.16.3",
|
||||||
|
"@testing-library/react": "^12.1.4",
|
||||||
"@types/hex-rgba": "^1.0.1",
|
"@types/hex-rgba": "^1.0.1",
|
||||||
|
"@types/jest": "^27.4.1",
|
||||||
"@types/lodash.debounce": "^4.0.6",
|
"@types/lodash.debounce": "^4.0.6",
|
||||||
"@types/react": "^17.0.43",
|
"@types/react": "^17.0.43",
|
||||||
|
"@types/react-redux": "^7.1.23",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.17.0",
|
"@typescript-eslint/eslint-plugin": "^5.17.0",
|
||||||
"@typescript-eslint/parser": "^5.17.0",
|
"@typescript-eslint/parser": "^5.17.0",
|
||||||
"eslint": "^8.12.0",
|
"eslint": "^8.12.0",
|
||||||
"eslint-config-prettier": "^8.5.0",
|
"eslint-config-prettier": "^8.5.0",
|
||||||
|
"eslint-plugin-jest": "^26.1.3",
|
||||||
"eslint-plugin-react": "~7.28.0",
|
"eslint-plugin-react": "~7.28.0",
|
||||||
"eslint-plugin-react-hooks": "^4.4.0",
|
"eslint-plugin-react-hooks": "^4.4.0",
|
||||||
|
"jest": "^27.5.1",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
|
"react-dom": "^17.0.2",
|
||||||
|
"react-redux": "^7.2.8",
|
||||||
"redux": "^4.1.2",
|
"redux": "^4.1.2",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
|
"ts-jest": "^27.1.4",
|
||||||
"typescript": "~4.5.5"
|
"typescript": "~4.5.5"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import React, { ReactNode } from 'react';
|
import React, { ReactNode } from 'react';
|
||||||
import { StyleUtilsContext } from '../styles/createStylingFromTheme';
|
import { StyleUtilsContext } from '../styles/createStylingFromTheme';
|
||||||
import { QueryPreviewTabs, TabOption } from '../types';
|
import { QueryPreviewTabs, TabOption } from '../types';
|
||||||
import { renderTabPanelButtonId, renderTabPanelId } from '../utils/a11y';
|
import { renderTabPanelButtonId } from '../utils/a11y';
|
||||||
import { emptyArray } from '../utils/object';
|
import { emptyArray } from '../utils/object';
|
||||||
|
|
||||||
export interface QueryPreviewHeaderProps {
|
export interface QueryPreviewHeaderProps {
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
export default {};
|
|
@ -0,0 +1,7 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import { createDevTools } from '@redux-devtools/core';
|
||||||
|
import { RtkQueryMonitor } from '../src';
|
||||||
|
|
||||||
|
const MonitorAsAny = RtkQueryMonitor as any;
|
||||||
|
|
||||||
|
export const ReduxDevTools = createDevTools(<MonitorAsAny />);
|
|
@ -0,0 +1,119 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import { Provider } from 'react-redux';
|
||||||
|
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
|
||||||
|
import { ReduxDevTools } from './devtools.mocks';
|
||||||
|
import { BaseQueryJestMockFunction, setupStore } from './rtk-query.mocks';
|
||||||
|
|
||||||
|
function Providers({
|
||||||
|
store,
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
store: ReturnType<typeof setupStore>['store'];
|
||||||
|
children?: React.ComponentProps<typeof Provider>['children'];
|
||||||
|
}) {
|
||||||
|
const AnyProvider = Provider as any;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div id="app-root">
|
||||||
|
<AnyProvider store={store}>
|
||||||
|
{children}
|
||||||
|
<ReduxDevTools />
|
||||||
|
</AnyProvider>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('rtk-query-monitor standalone integration', () => {
|
||||||
|
// Hushes symbol.observable warning
|
||||||
|
// @see https://github.com/reduxjs/redux-devtools/issues/1002
|
||||||
|
jest.spyOn(console, 'warn');
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||||
|
(console.warn as jest.Mock<void>).mockImplementation(() => {});
|
||||||
|
|
||||||
|
const dataPanelDomId = '#rtk-query-monitor-tab-panel-0';
|
||||||
|
|
||||||
|
const childrenTextContent = 'Renders children';
|
||||||
|
const fetchBaseQueryMock: BaseQueryJestMockFunction<Record<string, unknown>> =
|
||||||
|
jest.fn((...fetchArgs) =>
|
||||||
|
Promise.resolve({
|
||||||
|
data: {
|
||||||
|
name: fetchArgs[0],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
const { store, pokemonApi } = setupStore(fetchBaseQueryMock, ReduxDevTools);
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
// let's populate api
|
||||||
|
(store.dispatch as any)(
|
||||||
|
pokemonApi.endpoints.getPokemonByName.initiate('bulbasaur')
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fetchBaseQueryMock.mockClear();
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(() => {
|
||||||
|
(console.warn as jest.Mock<void>).mockRestore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders on a standalone app without crashing', () => {
|
||||||
|
const { container } = render(
|
||||||
|
<Providers store={store}>
|
||||||
|
<div data-testid="children">{childrenTextContent}</div>
|
||||||
|
</Providers>
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(screen.getByTestId('children').textContent).toBe(
|
||||||
|
childrenTextContent
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
screen
|
||||||
|
.getByRole('tab', { name: /actions/i })
|
||||||
|
?.textContent?.toLowerCase()
|
||||||
|
.trim()
|
||||||
|
).toBe('actions');
|
||||||
|
expect(
|
||||||
|
screen
|
||||||
|
.getByRole('tab', { name: /data/i })
|
||||||
|
?.textContent?.toLowerCase()
|
||||||
|
.trim()
|
||||||
|
).toBe('data');
|
||||||
|
expect(
|
||||||
|
screen
|
||||||
|
.getByRole('tab', { name: /api/i })
|
||||||
|
?.textContent?.toLowerCase()
|
||||||
|
.trim()
|
||||||
|
).toBe('api');
|
||||||
|
expect(
|
||||||
|
container.querySelector(
|
||||||
|
'form[id="rtk-query-monitor-query-selection-form"]'
|
||||||
|
)
|
||||||
|
).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('displays query data tab content', async () => {
|
||||||
|
// `Promise.resolve()` hushes `@typescript-eslint/await-thenable`
|
||||||
|
await Promise.resolve(pokemonApi.util.getRunningOperationPromises());
|
||||||
|
|
||||||
|
const { container } = render(
|
||||||
|
<Providers store={store}>
|
||||||
|
<div data-testid="children">{childrenTextContent}</div>
|
||||||
|
</Providers>
|
||||||
|
);
|
||||||
|
|
||||||
|
// We need to select the query & the correct tab
|
||||||
|
fireEvent.click(screen.getByRole('tab', { name: /data/i }));
|
||||||
|
fireEvent.click(screen.getByText(/bulbasaur/i));
|
||||||
|
|
||||||
|
await waitFor(() =>
|
||||||
|
expect(container.querySelector(dataPanelDomId)).not.toBeNull()
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(container.querySelector(dataPanelDomId)?.textContent).toMatch(
|
||||||
|
/name\W+pokemon\/bulbasaur/i
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,84 @@
|
||||||
|
import {
|
||||||
|
combineReducers,
|
||||||
|
configureStore,
|
||||||
|
EnhancedStore,
|
||||||
|
Middleware,
|
||||||
|
} from '@reduxjs/toolkit';
|
||||||
|
import { createApi } from '@reduxjs/toolkit/query/react';
|
||||||
|
import type { BaseQueryFn, FetchArgs } from '@reduxjs/toolkit/query';
|
||||||
|
import type { ReduxDevTools } from './devtools.mocks';
|
||||||
|
|
||||||
|
export type MockBaseQuery<
|
||||||
|
Result,
|
||||||
|
Args = string | FetchArgs,
|
||||||
|
Meta = { status?: number }
|
||||||
|
> = BaseQueryFn<Args, Result, unknown, Meta>;
|
||||||
|
|
||||||
|
export type BaseQueryJestMockFunction<Result> = jest.Mock<
|
||||||
|
ReturnType<MockBaseQuery<Result>>,
|
||||||
|
Parameters<MockBaseQuery<Result>>
|
||||||
|
>;
|
||||||
|
|
||||||
|
export function createMockBaseQuery<Result>(
|
||||||
|
jestMockFn: BaseQueryJestMockFunction<Result>
|
||||||
|
): MockBaseQuery<Result> {
|
||||||
|
return async function mockBaseQuery(param, api, extra) {
|
||||||
|
try {
|
||||||
|
const output = await jestMockFn(param, api, extra);
|
||||||
|
|
||||||
|
return output;
|
||||||
|
} catch (error) {
|
||||||
|
return {
|
||||||
|
error,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createPokemonApi(
|
||||||
|
jestMockFn: BaseQueryJestMockFunction<Record<string, any>>
|
||||||
|
) {
|
||||||
|
return createApi({
|
||||||
|
reducerPath: 'pokemonApi',
|
||||||
|
keepUnusedDataFor: 9999,
|
||||||
|
baseQuery: createMockBaseQuery(jestMockFn),
|
||||||
|
tagTypes: ['pokemon'],
|
||||||
|
endpoints: (builder) => ({
|
||||||
|
getPokemonByName: builder.query<Record<string, any>, string>({
|
||||||
|
query: (name: string) => `pokemon/${name}`,
|
||||||
|
providesTags: (result, error, name: string) => [
|
||||||
|
{ type: 'pokemon' },
|
||||||
|
{ type: 'pokemon', id: name },
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setupStore(
|
||||||
|
jestMockFn: BaseQueryJestMockFunction<Record<string, any>>,
|
||||||
|
devTools: typeof ReduxDevTools
|
||||||
|
) {
|
||||||
|
const pokemonApi = createPokemonApi(jestMockFn);
|
||||||
|
|
||||||
|
const reducer = combineReducers({
|
||||||
|
[pokemonApi.reducerPath]: pokemonApi.reducer,
|
||||||
|
});
|
||||||
|
|
||||||
|
const store: EnhancedStore<ReturnType<typeof reducer>> = configureStore({
|
||||||
|
reducer,
|
||||||
|
devTools: false,
|
||||||
|
// adding the api middleware enables caching, invalidation, polling and other features of `rtk-query`
|
||||||
|
middleware: (getDefaultMiddleware) =>
|
||||||
|
getDefaultMiddleware().concat([pokemonApi.middleware]) as Middleware[],
|
||||||
|
enhancers: [devTools.instrument()],
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
jestMockFn,
|
||||||
|
devTools,
|
||||||
|
store,
|
||||||
|
reducer,
|
||||||
|
pokemonApi,
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"extends": "../../tsconfig.react.base.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"types": ["jest"]
|
||||||
|
},
|
||||||
|
"include": ["src", "test"],
|
||||||
|
"exclude": ["dist"]
|
||||||
|
}
|
|
@ -5403,29 +5403,38 @@ __metadata:
|
||||||
"@redux-devtools/core": ^3.11.0
|
"@redux-devtools/core": ^3.11.0
|
||||||
"@redux-devtools/ui": ^1.2.1
|
"@redux-devtools/ui": ^1.2.1
|
||||||
"@reduxjs/toolkit": ^1.8.1
|
"@reduxjs/toolkit": ^1.8.1
|
||||||
|
"@testing-library/jest-dom": ^5.16.3
|
||||||
|
"@testing-library/react": ^12.1.4
|
||||||
"@types/hex-rgba": ^1.0.1
|
"@types/hex-rgba": ^1.0.1
|
||||||
|
"@types/jest": ^27.4.1
|
||||||
"@types/lodash.debounce": ^4.0.6
|
"@types/lodash.debounce": ^4.0.6
|
||||||
"@types/prop-types": ^15.7.4
|
"@types/prop-types": ^15.7.4
|
||||||
"@types/react": ^17.0.43
|
"@types/react": ^17.0.43
|
||||||
|
"@types/react-redux": ^7.1.23
|
||||||
"@types/redux-devtools-themes": ^1.0.0
|
"@types/redux-devtools-themes": ^1.0.0
|
||||||
"@typescript-eslint/eslint-plugin": ^5.17.0
|
"@typescript-eslint/eslint-plugin": ^5.17.0
|
||||||
"@typescript-eslint/parser": ^5.17.0
|
"@typescript-eslint/parser": ^5.17.0
|
||||||
eslint: ^8.12.0
|
eslint: ^8.12.0
|
||||||
eslint-config-prettier: ^8.5.0
|
eslint-config-prettier: ^8.5.0
|
||||||
|
eslint-plugin-jest: ^26.1.3
|
||||||
eslint-plugin-react: ~7.28.0
|
eslint-plugin-react: ~7.28.0
|
||||||
eslint-plugin-react-hooks: ^4.4.0
|
eslint-plugin-react-hooks: ^4.4.0
|
||||||
hex-rgba: ^1.0.2
|
hex-rgba: ^1.0.2
|
||||||
immutable: ^4.0.0
|
immutable: ^4.0.0
|
||||||
|
jest: ^27.5.1
|
||||||
jss: ^10.9.0
|
jss: ^10.9.0
|
||||||
jss-preset-default: ^10.9.0
|
jss-preset-default: ^10.9.0
|
||||||
lodash.debounce: ^4.0.8
|
lodash.debounce: ^4.0.8
|
||||||
prop-types: ^15.8.1
|
prop-types: ^15.8.1
|
||||||
react: ^17.0.2
|
react: ^17.0.2
|
||||||
react-base16-styling: ^0.9.1
|
react-base16-styling: ^0.9.1
|
||||||
|
react-dom: ^17.0.2
|
||||||
react-json-tree: ^0.16.1
|
react-json-tree: ^0.16.1
|
||||||
|
react-redux: ^7.2.8
|
||||||
redux: ^4.1.2
|
redux: ^4.1.2
|
||||||
redux-devtools-themes: ^1.0.0
|
redux-devtools-themes: ^1.0.0
|
||||||
rimraf: ^3.0.2
|
rimraf: ^3.0.2
|
||||||
|
ts-jest: ^27.1.4
|
||||||
typescript: ~4.5.5
|
typescript: ~4.5.5
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
"@redux-devtools/core": ^3.7.0
|
"@redux-devtools/core": ^3.7.0
|
||||||
|
|
Loading…
Reference in New Issue
Block a user