Skip to content

Commit

Permalink
test(useUrlState): refactor test (#1802)
Browse files Browse the repository at this point in the history
* test(useUrlState): refactor test

* chore: add `@types/react-router`

* test(useUrlState): refactor test
  • Loading branch information
miracles1919 authored Aug 10, 2022
1 parent 3e68cc6 commit eb00e87
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 103 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"@types/lodash.debounce": "^4.0.6",
"@types/lodash.isequal": "^4.5.5",
"@types/lodash.throttle": "^4.1.6",
"@types/react-router": "^5.1.18",
"@umijs/fabric": "^2.1.0",
"@umijs/plugin-sass": "^1.1.1",
"antd": "^4.3.3",
Expand Down
151 changes: 49 additions & 102 deletions packages/use-url-state/src/__tests__/browser.test.tsx
Original file line number Diff line number Diff line change
@@ -1,113 +1,60 @@
import type { RenderHookResult } from '@testing-library/react-hooks';
import { act, renderHook } from '@testing-library/react-hooks';
import routeData from 'react-router';
import useUrlState, { Options } from '../index';

/* 暂时关闭 act 警告 见:https://github.com/testing-library/react-testing-library/issues/281#issuecomment-480349256 */
const originalError = console.error;

beforeAll(() => {
console.error = (...args: any) => {
if (/Warning.*not wrapped in act/.test(args[0])) {
return;
}
originalError.call(console, ...args);
};
});

afterAll(() => {
console.error = originalError;
});
const replaceFn = jest.fn();

function makeMockLocation(search?: string) {
const mockLocation = {
pathname: '/',
hash: '',
search: search ? `${search}` : '',
state: '',
};

const mockHistory: any = {
push: ({ search }) => {
replaceFn();
mockLocation.search = search;
},
};

jest.spyOn(routeData, 'useLocation').mockReturnValue(mockLocation);
jest.spyOn(routeData, 'useHistory').mockReturnValue(mockHistory);

return mockLocation;
}
import { act } from '@testing-library/react-hooks/dom';
import { setup } from '.';

describe('useUrlState', () => {
it('should be defined', () => {
expect(useUrlState).toBeDefined();
it('state should be url search params', () => {
const res = setup([
{
pathname: '/index',
search: '?count=1',
},
]);
expect(res.state).toMatchObject({ count: '1' });
});

describe('test url', () => {
let hook: RenderHookResult<
[string, number],
[number, ((s: any) => void) | (() => (s: any) => any)]
>;

function setup(key: string, value: string, config?: Options) {
hook = renderHook(() => {
return useUrlState({ [key]: value }, config);
}) as any;
hook.rerender();
}

afterEach(() => {
hook.unmount();
it('url shoule be changed when use setState', () => {
const res = setup(['/index']);
expect(res.state).toMatchObject({});
act(() => {
res.setState({ count: 1 });
});
expect(res.state).toMatchObject({ count: '1' });
});

it('history replace should work', async () => {
const mockLocation = makeMockLocation();
act(() => {
setup('mock', '0');
});

expect(replaceFn).toBeCalledTimes(0);
expect(hook.result.current[0]).toEqual({ mock: '0' });
expect(mockLocation.search).toEqual('');

act(() => {
hook.result.current[1]({ mock: 1 });
});
expect(replaceFn).toBeCalledTimes(1);
expect(mockLocation.search).toEqual('mock=1');
act(() => {
hook.result.current[1]({ mock: 2, test: 3 });
});

expect(mockLocation.search).toEqual('mock=2&test=3');
it('multiple states should be work', () => {
const res = setup(['/index']);
act(() => {
res.setState({ page: 1 });
});
act(() => {
res.setState({ pageSize: 10 });
});
expect(res.state).toMatchObject({ page: '1', pageSize: '10' });
});

it('query-string options should work', async () => {
const mockLocation = makeMockLocation();

act(() => {
setup('mock', '0', {
parseOptions: {
arrayFormat: 'comma',
},
stringifyOptions: {
arrayFormat: 'comma',
},
});
});
expect(replaceFn).toBeCalledTimes(0);
expect(hook.result.current[0]).toEqual({ mock: '0' });
expect(mockLocation.search).toEqual('');

act(() => {
hook.result.current[1]({ mock: 1, test: [1, 2, 3] });
});
expect(replaceFn).toBeCalledTimes(1);
expect(hook.result.current[0]).toEqual({ mock: '1', test: ['1', '2', '3'] });
expect(mockLocation.search).toEqual('mock=1&test=1,2,3');
it('query-string options should work', async () => {
const res = setup(
[
{
pathname: '/index',
search: '?foo=1,2,3',
},
],
{},
{
parseOptions: {
arrayFormat: 'comma',
},
stringifyOptions: {
arrayFormat: 'comma',
},
},
);
expect(res.state).toMatchObject({ foo: ['1', '2', '3'] });

act(() => {
res.setState({ foo: ['4', '5', '6'] });
});
expect(res.state).toMatchObject({ foo: ['4', '5', '6'] });
});
});
32 changes: 32 additions & 0 deletions packages/use-url-state/src/__tests__/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React from 'react';
import { render } from '@testing-library/react';
import type { MemoryRouterProps } from 'react-router';
import { MemoryRouter } from 'react-router';
import useUrlState from '..';
import type { Options } from '..';

export const setup = (
initialEntries: MemoryRouterProps['initialEntries'],
initialState: any = {},
options?: Options,
) => {
const res = {} as any;

const Component = () => {
const [state, setState] = useUrlState(initialState, options);
Object.assign(res, { state, setState });
return null;
};

render(
<MemoryRouter initialEntries={initialEntries}>
<Component />
</MemoryRouter>,
);

return res;
};

it('useUrlState should be defined', () => {
expect(useUrlState).toBeDefined();
});
22 changes: 22 additions & 0 deletions packages/use-url-state/src/__tests__/router.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { act } from '@testing-library/react-hooks/dom';
import { setup } from '.';

const navigate = jest.fn();
jest.mock('react-router', () => {
return {
...jest.requireActual('react-router'),
useNavigate: () => navigate,
};
});

describe('React Router V6', () => {
it('useUrlState should be work', () => {
const res = setup(['/index']);
act(() => {
res.setState({ count: 1 });
});

expect(res.state).toMatchObject({ count: '1' });
expect(navigate).toBeCalledWith({ hash: '', search: 'count=1' }, { replace: false });
});
});
4 changes: 3 additions & 1 deletion pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit eb00e87

Please sign in to comment.