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": {
|
"scripts": {
|
||||||
"build": "concurrently \"vite build\" \"tsc -p tsconfig.declaration.json\"",
|
"build": "concurrently \"vite build\" \"tsc -p tsconfig.declaration.json\"",
|
||||||
"prepare": "yarn build",
|
"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",
|
"test:types": "tsc --noEmit",
|
||||||
"lint:code": "eslint --ext .js,.ts,.cjs,.tsx src/ --cache",
|
"lint:code": "eslint --ext .js,.ts,.cjs,.tsx src/ --cache",
|
||||||
"lint": "yarn lint:code && yarn lint:test",
|
"lint": "yarn lint:code && yarn lint:test",
|
||||||
@ -36,6 +37,7 @@
|
|||||||
"@storybook/react-vite": "7.6.4",
|
"@storybook/react-vite": "7.6.4",
|
||||||
"@storybook/testing-library": "0.2.2",
|
"@storybook/testing-library": "0.2.2",
|
||||||
"@testing-library/react": "14.1.0",
|
"@testing-library/react": "14.1.0",
|
||||||
|
"@testing-library/react-hooks" : "8.0.1",
|
||||||
"@vitejs/plugin-react": "4.2.1",
|
"@vitejs/plugin-react": "4.2.1",
|
||||||
"c8": "8.0.1",
|
"c8": "8.0.1",
|
||||||
"eslint-plugin-react-hooks": "4.6.0",
|
"eslint-plugin-react-hooks": "4.6.0",
|
||||||
@ -43,6 +45,7 @@
|
|||||||
"eslint-plugin-tailwindcss": "3.13.0",
|
"eslint-plugin-tailwindcss": "3.13.0",
|
||||||
"jsdom": "24.1.0",
|
"jsdom": "24.1.0",
|
||||||
"mocha": "10.2.0",
|
"mocha": "10.2.0",
|
||||||
|
"chai": "4.3.8",
|
||||||
"react": "18.3.1",
|
"react": "18.3.1",
|
||||||
"react-dom": "18.3.1",
|
"react-dom": "18.3.1",
|
||||||
"rollup-plugin-node-builtins": "2.1.2",
|
"rollup-plugin-node-builtins": "2.1.2",
|
||||||
|
@ -3,6 +3,6 @@ import assert from 'assert/strict';
|
|||||||
describe('Hello world', function () {
|
describe('Hello world', function () {
|
||||||
it('Runs a test', function () {
|
it('Runs a test', function () {
|
||||||
// TODO: Write me!
|
// 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"
|
lodash "^4.17.15"
|
||||||
redent "^3.0.0"
|
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":
|
"@testing-library/react@12.1.5":
|
||||||
version "12.1.5"
|
version "12.1.5"
|
||||||
resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-12.1.5.tgz#bb248f72f02a5ac9d949dea07279095fa577963b"
|
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"
|
is-plain-object "5.0.0"
|
||||||
react-is "18.1.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:
|
react-hot-toast@2.4.1:
|
||||||
version "2.4.1"
|
version "2.4.1"
|
||||||
resolved "https://registry.yarnpkg.com/react-hot-toast/-/react-hot-toast-2.4.1.tgz#df04295eda8a7b12c4f968e54a61c8d36f4c0994"
|
resolved "https://registry.yarnpkg.com/react-hot-toast/-/react-hot-toast-2.4.1.tgz#df04295eda8a7b12c4f968e54a61c8d36f4c0994"
|
||||||
|
Loading…
Reference in New Issue
Block a user