Added test for hooks - useSortableIndexedList, usePagination (admin-x-design-system)

Ref ENG-1351 ENG-1373
This commit is contained in:
Princi Vershwal 2024-07-11 14:02:55 +05:30 committed by GitHub
parent c6717a4ebd
commit 2cace2987d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 286 additions and 2 deletions

View File

@ -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",

View File

@ -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);
}); });
}); });

View 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);
});
});

View File

@ -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);
});
});

View File

@ -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"