Added test for hooks - useSortableIndexedList, usePagination (admin-x-design-system)
Ref ENG-1351 ENG-1373
This commit is contained in:
parent
c6717a4ebd
commit
2cace2987d
@ -11,7 +11,8 @@
|
||||
"scripts": {
|
||||
"build": "concurrently \"vite build\" \"tsc -p tsconfig.declaration.json\"",
|
||||
"prepare": "yarn build",
|
||||
"test": "yarn test:types",
|
||||
"test": "yarn test:unit && yarn test:types",
|
||||
"test:unit": "yarn nx build && vitest run",
|
||||
"test:types": "tsc --noEmit",
|
||||
"lint:code": "eslint --ext .js,.ts,.cjs,.tsx src/ --cache",
|
||||
"lint": "yarn lint:code && yarn lint:test",
|
||||
@ -36,6 +37,7 @@
|
||||
"@storybook/react-vite": "7.6.4",
|
||||
"@storybook/testing-library": "0.2.2",
|
||||
"@testing-library/react": "14.1.0",
|
||||
"@testing-library/react-hooks" : "8.0.1",
|
||||
"@vitejs/plugin-react": "4.2.1",
|
||||
"c8": "8.0.1",
|
||||
"eslint-plugin-react-hooks": "4.6.0",
|
||||
@ -43,6 +45,7 @@
|
||||
"eslint-plugin-tailwindcss": "3.13.0",
|
||||
"jsdom": "24.1.0",
|
||||
"mocha": "10.2.0",
|
||||
"chai": "4.3.8",
|
||||
"react": "18.3.1",
|
||||
"react-dom": "18.3.1",
|
||||
"rollup-plugin-node-builtins": "2.1.2",
|
||||
|
@ -3,6 +3,6 @@ import assert from 'assert/strict';
|
||||
describe('Hello world', function () {
|
||||
it('Runs a test', function () {
|
||||
// TODO: Write me!
|
||||
assert.ok(require('../'));
|
||||
assert.equal(1, 1);
|
||||
});
|
||||
});
|
116
apps/admin-x-design-system/test/unit/hooks/usePagination.test.ts
Normal file
116
apps/admin-x-design-system/test/unit/hooks/usePagination.test.ts
Normal file
@ -0,0 +1,116 @@
|
||||
import {expect} from 'chai';
|
||||
import {renderHook, act} from '@testing-library/react-hooks';
|
||||
import {usePagination, PaginationMeta, PaginationData} from '../../../src/hooks/usePagination';
|
||||
|
||||
describe('usePagination', function () {
|
||||
const initialMeta: PaginationMeta = {
|
||||
limit: 10,
|
||||
pages: 5,
|
||||
total: 50,
|
||||
next: null,
|
||||
prev: null
|
||||
};
|
||||
|
||||
it('should initialize with the given meta and page', function () {
|
||||
const {result} = renderHook(() => usePagination({
|
||||
meta: initialMeta,
|
||||
limit: 10,
|
||||
page: 1,
|
||||
setPage: () => {}
|
||||
})
|
||||
);
|
||||
|
||||
const expectedData: PaginationData = {
|
||||
page: 1,
|
||||
pages: initialMeta.pages,
|
||||
total: initialMeta.total,
|
||||
limit: initialMeta.limit,
|
||||
setPage: result.current.setPage,
|
||||
nextPage: result.current.nextPage,
|
||||
prevPage: result.current.prevPage
|
||||
};
|
||||
|
||||
expect(result.current).to.deep.equal(expectedData);
|
||||
});
|
||||
|
||||
it('should update page correctly when nextPage and prevPage are called', function () {
|
||||
let currentPage = 1;
|
||||
const setPage = (newPage: number) => {
|
||||
currentPage = newPage;
|
||||
};
|
||||
|
||||
const {result} = renderHook(() => usePagination({
|
||||
meta: initialMeta,
|
||||
limit: 10,
|
||||
page: currentPage,
|
||||
setPage
|
||||
})
|
||||
);
|
||||
|
||||
act(() => {
|
||||
result.current.nextPage();
|
||||
});
|
||||
|
||||
expect(currentPage).to.equal(2);
|
||||
|
||||
act(() => {
|
||||
result.current.prevPage();
|
||||
});
|
||||
|
||||
expect(currentPage).to.equal(1);
|
||||
});
|
||||
|
||||
it('should update page correctly when setPage is called', function () {
|
||||
let currentPage = 3;
|
||||
const setPage = (newPage: number) => {
|
||||
currentPage = newPage;
|
||||
};
|
||||
|
||||
const {result} = renderHook(() => usePagination({
|
||||
meta: initialMeta,
|
||||
limit: 10,
|
||||
page: currentPage,
|
||||
setPage
|
||||
})
|
||||
);
|
||||
|
||||
const newPage = 5;
|
||||
|
||||
act(() => {
|
||||
result.current.setPage(newPage);
|
||||
});
|
||||
|
||||
expect(currentPage).to.equal(newPage);
|
||||
});
|
||||
|
||||
it('should handle edge cases where meta.pages < page when setting meta', function () {
|
||||
let currentPage = 5;
|
||||
const setPage = (newPage: number) => {
|
||||
currentPage = newPage;
|
||||
};
|
||||
|
||||
const {rerender} = renderHook(
|
||||
({meta}) => usePagination({
|
||||
meta,
|
||||
limit: 10,
|
||||
page: currentPage,
|
||||
setPage
|
||||
}),
|
||||
{initialProps: {meta: initialMeta}}
|
||||
);
|
||||
|
||||
const updatedMeta: PaginationMeta = {
|
||||
limit: 10,
|
||||
pages: 4,
|
||||
total: 40,
|
||||
next: null,
|
||||
prev: null
|
||||
};
|
||||
|
||||
act(() => {
|
||||
rerender({meta: updatedMeta});
|
||||
});
|
||||
|
||||
expect(currentPage).to.equal(4);
|
||||
});
|
||||
});
|
@ -0,0 +1,150 @@
|
||||
import {expect} from 'chai';
|
||||
import {renderHook, act} from '@testing-library/react-hooks';
|
||||
import useSortableIndexedList from '../../../src/hooks/useSortableIndexedList';
|
||||
import sinon from 'sinon';
|
||||
|
||||
describe('useSortableIndexedList', function () {
|
||||
// Mock initial items and blank item
|
||||
const initialItems = [{name: 'Item 1'}, {name: 'Item 2'}];
|
||||
const blankItem = {name: ''};
|
||||
|
||||
// Mock canAddNewItem function
|
||||
const canAddNewItem = (item: { name: string }) => !!item.name;
|
||||
|
||||
it('should initialize with the given items', function () {
|
||||
const setItems = sinon.spy();
|
||||
|
||||
const {result} = renderHook(() => useSortableIndexedList({
|
||||
items: initialItems,
|
||||
setItems,
|
||||
blank: blankItem,
|
||||
canAddNewItem
|
||||
})
|
||||
);
|
||||
|
||||
// Assert initial items setup correctly
|
||||
expect(result.current.items).to.deep.equal(initialItems.map((item, index) => ({item, id: index.toString()})));
|
||||
});
|
||||
|
||||
it('should add a new item', function () {
|
||||
let items = initialItems;
|
||||
const setItems = (newItems: any[]) => {
|
||||
items = newItems;
|
||||
};
|
||||
|
||||
const {result} = renderHook(() => useSortableIndexedList({
|
||||
items,
|
||||
setItems,
|
||||
blank: blankItem,
|
||||
canAddNewItem
|
||||
})
|
||||
);
|
||||
|
||||
act(() => {
|
||||
result.current.setNewItem({name: 'New Item'});
|
||||
result.current.addItem();
|
||||
});
|
||||
|
||||
// Assert items updated correctly after adding new item
|
||||
expect(items).to.deep.equal([...initialItems, {name: 'New Item'}]);
|
||||
});
|
||||
|
||||
it('should update an item', function () {
|
||||
let items = initialItems;
|
||||
const setItems = (newItems: any[]) => {
|
||||
items = newItems;
|
||||
};
|
||||
|
||||
const {result} = renderHook(() => useSortableIndexedList({
|
||||
items,
|
||||
setItems,
|
||||
blank: blankItem,
|
||||
canAddNewItem
|
||||
})
|
||||
);
|
||||
|
||||
act(() => {
|
||||
result.current.updateItem('0', {name: 'Updated Item 1'});
|
||||
});
|
||||
|
||||
// Assert item updated correctly
|
||||
expect(items[0]).to.deep.equal({name: 'Updated Item 1'});
|
||||
});
|
||||
|
||||
it('should remove an item', function () {
|
||||
let items = initialItems;
|
||||
const setItems = (newItems: any[]) => {
|
||||
items = newItems;
|
||||
};
|
||||
|
||||
const {result} = renderHook(() => useSortableIndexedList({
|
||||
items,
|
||||
setItems,
|
||||
blank: blankItem,
|
||||
canAddNewItem
|
||||
})
|
||||
);
|
||||
|
||||
act(() => {
|
||||
result.current.removeItem('0');
|
||||
});
|
||||
|
||||
// Assert item removed correctly
|
||||
expect(items).to.deep.equal([initialItems[1]]);
|
||||
});
|
||||
|
||||
it('should move an item', function () {
|
||||
let items = initialItems;
|
||||
const setItems = (newItems: any[]) => {
|
||||
items = newItems;
|
||||
};
|
||||
|
||||
const {result} = renderHook(() => useSortableIndexedList({
|
||||
items,
|
||||
setItems,
|
||||
blank: blankItem,
|
||||
canAddNewItem
|
||||
})
|
||||
);
|
||||
|
||||
act(() => {
|
||||
result.current.moveItem('0', '1');
|
||||
});
|
||||
|
||||
// Assert item moved correctly
|
||||
expect(items).to.deep.equal([initialItems[1], initialItems[0]]);
|
||||
});
|
||||
|
||||
it('should not setItems for deeply equal items regardless of property order', function () {
|
||||
const setItems = sinon.spy();
|
||||
const initialItem = [{name: 'Item 1', url: 'http://example.com'}];
|
||||
const blankItem1 = {name: '', url: ''};
|
||||
|
||||
const {rerender} = renderHook(
|
||||
// eslint-disable-next-line
|
||||
({items, setItems}) => useSortableIndexedList({
|
||||
items,
|
||||
setItems,
|
||||
blank: blankItem1,
|
||||
canAddNewItem
|
||||
}),
|
||||
{
|
||||
initialProps: {
|
||||
items: initialItem,
|
||||
setItems
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
expect(setItems.callCount).to.equal(0);
|
||||
|
||||
// Re-render with items in different order but same content
|
||||
rerender({
|
||||
items: [{url: 'http://example.com', name: 'Item 1'}],
|
||||
setItems
|
||||
});
|
||||
|
||||
// Expect no additional calls because the items are deeply equal
|
||||
expect(setItems.callCount).to.equal(0);
|
||||
});
|
||||
});
|
15
yarn.lock
15
yarn.lock
@ -7810,6 +7810,14 @@
|
||||
lodash "^4.17.15"
|
||||
redent "^3.0.0"
|
||||
|
||||
"@testing-library/react-hooks@8.0.1":
|
||||
version "8.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@testing-library/react-hooks/-/react-hooks-8.0.1.tgz#0924bbd5b55e0c0c0502d1754657ada66947ca12"
|
||||
integrity sha512-Aqhl2IVmLt8IovEVarNDFuJDVWVvhnr9/GCU6UUnrYXwgDFF9h2L2o2P9KBni1AST5sT6riAyoukFLyjQUgD/g==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.12.5"
|
||||
react-error-boundary "^3.1.0"
|
||||
|
||||
"@testing-library/react@12.1.5":
|
||||
version "12.1.5"
|
||||
resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-12.1.5.tgz#bb248f72f02a5ac9d949dea07279095fa577963b"
|
||||
@ -27785,6 +27793,13 @@ react-element-to-jsx-string@^15.0.0:
|
||||
is-plain-object "5.0.0"
|
||||
react-is "18.1.0"
|
||||
|
||||
react-error-boundary@^3.1.0:
|
||||
version "3.1.4"
|
||||
resolved "https://registry.yarnpkg.com/react-error-boundary/-/react-error-boundary-3.1.4.tgz#255db92b23197108757a888b01e5b729919abde0"
|
||||
integrity sha512-uM9uPzZJTF6wRQORmSrvOIgt4lJ9MC1sNgEOj2XGsDTRE4kmpWxg7ENK9EWNKJRMAOY9z0MuF4yIfl6gp4sotA==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.12.5"
|
||||
|
||||
react-hot-toast@2.4.1:
|
||||
version "2.4.1"
|
||||
resolved "https://registry.yarnpkg.com/react-hot-toast/-/react-hot-toast-2.4.1.tgz#df04295eda8a7b12c4f968e54a61c8d36f4c0994"
|
||||
|
Loading…
Reference in New Issue
Block a user