@arbor-education/design-system.components 0.1.4 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/release.yml +17 -18
- package/CHANGELOG.md +6 -0
- package/dist/components/icon/Icon.test.js +6 -3
- package/dist/components/icon/Icon.test.js.map +1 -1
- package/dist/utils/hooks/useComponentDidMount.test.d.ts +2 -0
- package/dist/utils/hooks/useComponentDidMount.test.d.ts.map +1 -0
- package/dist/utils/hooks/useComponentDidMount.test.js +43 -0
- package/dist/utils/hooks/useComponentDidMount.test.js.map +1 -0
- package/dist/utils/hooks/useGridApi.test.d.ts +2 -0
- package/dist/utils/hooks/useGridApi.test.d.ts.map +1 -0
- package/dist/utils/hooks/useGridApi.test.js +48 -0
- package/dist/utils/hooks/useGridApi.test.js.map +1 -0
- package/dist/utils/hooks/useIsMounted.test.d.ts +2 -0
- package/dist/utils/hooks/useIsMounted.test.d.ts.map +1 -0
- package/dist/utils/hooks/useIsMounted.test.js +46 -0
- package/dist/utils/hooks/useIsMounted.test.js.map +1 -0
- package/dist/utils/hooks/useMemoGenerateUuid.d.ts +1 -1
- package/dist/utils/hooks/useMemoGenerateUuid.d.ts.map +1 -1
- package/dist/utils/hooks/useMemoGenerateUuid.js +1 -1
- package/dist/utils/hooks/useMemoGenerateUuid.js.map +1 -1
- package/dist/utils/hooks/useMemoGenerateUuid.test.d.ts +2 -0
- package/dist/utils/hooks/useMemoGenerateUuid.test.d.ts.map +1 -0
- package/dist/utils/hooks/useMemoGenerateUuid.test.js +55 -0
- package/dist/utils/hooks/useMemoGenerateUuid.test.js.map +1 -0
- package/dist/utils/hooks/usePubSub.test.d.ts +2 -0
- package/dist/utils/hooks/usePubSub.test.d.ts.map +1 -0
- package/dist/utils/hooks/usePubSub.test.js +81 -0
- package/dist/utils/hooks/usePubSub.test.js.map +1 -0
- package/package.json +2 -1
- package/src/components/icon/Icon.test.tsx +6 -3
- package/src/utils/hooks/useComponentDidMount.test.tsx +59 -0
- package/src/utils/hooks/useGridApi.test.tsx +79 -0
- package/src/utils/hooks/useIsMounted.test.tsx +63 -0
- package/src/utils/hooks/useMemoGenerateUuid.test.tsx +80 -0
- package/src/utils/hooks/useMemoGenerateUuid.ts +1 -1
- package/src/utils/hooks/usePubSub.test.tsx +100 -0
- package/vitest.config.ts +9 -0
|
@@ -8,18 +8,9 @@ permissions:
|
|
|
8
8
|
id-token: write # Required for OIDC authentication
|
|
9
9
|
|
|
10
10
|
on:
|
|
11
|
-
push:
|
|
12
|
-
branches:
|
|
13
|
-
- DOPS-17000-fix-git-ops # Temporary: trigger on feature branch push
|
|
14
11
|
schedule:
|
|
15
12
|
- cron: '0 7 * * 1-5' # 7 AM UTC, Monday-Friday
|
|
16
|
-
workflow_dispatch:
|
|
17
|
-
inputs:
|
|
18
|
-
force_publish:
|
|
19
|
-
description: 'Force publish current version (skip changeset version step)'
|
|
20
|
-
required: false
|
|
21
|
-
default: false
|
|
22
|
-
type: boolean
|
|
13
|
+
workflow_dispatch: # Allow manual trigger
|
|
23
14
|
|
|
24
15
|
concurrency: ${{ github.workflow }}-${{ github.ref }}
|
|
25
16
|
|
|
@@ -55,7 +46,6 @@ jobs:
|
|
|
55
46
|
|
|
56
47
|
- name: Version packages
|
|
57
48
|
id: version
|
|
58
|
-
if: ${{ !inputs.force_publish && github.event_name != 'push' }}
|
|
59
49
|
env:
|
|
60
50
|
GITHUB_TOKEN: ${{ secrets.ARBOR_AUTOMATION_ORG_GHA_TOKEN }}
|
|
61
51
|
run: |
|
|
@@ -70,13 +60,12 @@ jobs:
|
|
|
70
60
|
git commit -m "chore: version packages"
|
|
71
61
|
git push
|
|
72
62
|
fi
|
|
73
|
-
|
|
74
63
|
- name: Publish to npm
|
|
75
|
-
if: steps.version.outputs.changed == 'true'
|
|
64
|
+
if: steps.version.outputs.changed == 'true'
|
|
76
65
|
run: npm publish
|
|
77
66
|
|
|
78
67
|
- name: Get changelog for current release
|
|
79
|
-
if: steps.version.outputs.changed == 'true'
|
|
68
|
+
if: steps.version.outputs.changed == 'true'
|
|
80
69
|
id: get-changelog
|
|
81
70
|
run: |
|
|
82
71
|
changelog=$(python "${GITHUB_WORKSPACE}/.github/workflows/scripts/python/changelog_utils.py")
|
|
@@ -85,21 +74,21 @@ jobs:
|
|
|
85
74
|
echo "EOF" >> $GITHUB_ENV
|
|
86
75
|
|
|
87
76
|
- name: Get version
|
|
88
|
-
if: steps.version.outputs.changed == 'true'
|
|
77
|
+
if: steps.version.outputs.changed == 'true'
|
|
89
78
|
id: get-version
|
|
90
79
|
run: |
|
|
91
80
|
version=$(node -p "require('./package.json').version")
|
|
92
81
|
echo "version=${version}" >> $GITHUB_OUTPUT
|
|
93
82
|
|
|
94
83
|
- name: Create tarball
|
|
95
|
-
if: steps.version.outputs.changed == 'true'
|
|
84
|
+
if: steps.version.outputs.changed == 'true'
|
|
96
85
|
run: |
|
|
97
86
|
mkdir -p release
|
|
98
87
|
npm pack
|
|
99
88
|
mv *.tgz release/design-system.components.tgz
|
|
100
89
|
|
|
101
90
|
- name: Create GitHub Release
|
|
102
|
-
if: steps.version.outputs.changed == 'true'
|
|
91
|
+
if: steps.version.outputs.changed == 'true'
|
|
103
92
|
env:
|
|
104
93
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
105
94
|
run: |
|
|
@@ -114,7 +103,7 @@ jobs:
|
|
|
114
103
|
"./release/design-system.components.tgz"
|
|
115
104
|
|
|
116
105
|
- name: Send Slack Success Message
|
|
117
|
-
if: steps.version.outputs.changed == 'true'
|
|
106
|
+
if: steps.version.outputs.changed == 'true'
|
|
118
107
|
uses: rtCamp/action-slack-notify@v2
|
|
119
108
|
env:
|
|
120
109
|
SLACK_COLOR: good
|
|
@@ -133,3 +122,13 @@ jobs:
|
|
|
133
122
|
SLACK_LINK_NAMES: true
|
|
134
123
|
MSG_MINIMAL: true
|
|
135
124
|
SLACK_WEBHOOK: ${{ secrets.ARBOR_FRONTEND_RELEASE_SLACK_WEBHOOK }}
|
|
125
|
+
|
|
126
|
+
- name: Run component tests
|
|
127
|
+
if: steps.version.outputs.changed == 'true'
|
|
128
|
+
run: yarn test:coverage
|
|
129
|
+
- name: Coveralls
|
|
130
|
+
if: steps.version.outputs.changed == 'true'
|
|
131
|
+
uses: coverallsapp/github-action@v2
|
|
132
|
+
continue-on-error: true
|
|
133
|
+
with:
|
|
134
|
+
github-token: ${{ secrets.ARBOR_AUTOMATION_ORG_GHA_TOKEN }}
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
## 0.1.4
|
|
2
2
|
|
|
3
|
+
## 0.1.5
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#93](https://github.com/arbor-education/design-system.components/pull/93) [`38e0e33`](https://github.com/arbor-education/design-system.components/commit/38e0e3315bb65becd546a5e6305f55ef7076bdab) Thanks [@AmeeMorris](https://github.com/AmeeMorris)! - MIS-67805 coveralls and add missing tests
|
|
8
|
+
|
|
3
9
|
### Patch Changes
|
|
4
10
|
|
|
5
11
|
- [#80](https://github.com/arbor-education/design-system.components/pull/80) [`592c5b2`](https://github.com/arbor-education/design-system.components/commit/592c5b2a4a5f32d6da5d21c45c3a4d23ff935fea) Thanks [@AmeeMorris](https://github.com/AmeeMorris)! - MIS-66551 remove browser default margins from ds headings
|
|
@@ -3,10 +3,13 @@ import { describe, expect, test } from 'vitest';
|
|
|
3
3
|
import { render, screen } from '@testing-library/react';
|
|
4
4
|
import { Icon } from './Icon';
|
|
5
5
|
import '@testing-library/jest-dom/vitest';
|
|
6
|
+
import { allowedIcons } from './allowedIcons';
|
|
6
7
|
describe('Icon', () => {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
Object.keys(allowedIcons).forEach((icon) => {
|
|
9
|
+
test(`Icon ${icon} renders`, () => {
|
|
10
|
+
render(_jsx(Icon, { name: icon }));
|
|
11
|
+
expect(screen.getByRole('img', { hidden: true })).toBeInTheDocument();
|
|
12
|
+
});
|
|
10
13
|
});
|
|
11
14
|
test('Screen reader text', () => {
|
|
12
15
|
render(_jsx(Icon, { name: "arrow-right", screenReaderText: "foobar" }));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Icon.test.js","sourceRoot":"","sources":["../../../src/components/icon/Icon.test.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,kCAAkC,CAAC;
|
|
1
|
+
{"version":3,"file":"Icon.test.js","sourceRoot":"","sources":["../../../src/components/icon/Icon.test.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,kCAAkC,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAiB,MAAM,gBAAgB,CAAC;AAE7D,QAAQ,CAAC,MAAM,EAAE,GAAG,EAAE;IACpB,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;QACzC,IAAI,CAAC,QAAQ,IAAI,UAAU,EAAE,GAAG,EAAE;YAChC,MAAM,CAAC,KAAC,IAAI,IAAC,IAAI,EAAE,IAAgB,GAAI,CAAC,CAAC;YACzC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,iBAAiB,EAAE,CAAC;QACxE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,oBAAoB,EAAE,GAAG,EAAE;QAC9B,MAAM,CAAC,KAAC,IAAI,IAAC,IAAI,EAAC,aAAa,EAAC,gBAAgB,EAAC,QAAQ,GAAG,CAAC,CAAC;QAC9D,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,iBAAiB,EAAE,CAAC;QACvD,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useComponentDidMount.test.d.ts","sourceRoot":"","sources":["../../../src/utils/hooks/useComponentDidMount.test.tsx"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { describe, expect, test, vi, beforeEach } from 'vitest';
|
|
3
|
+
import { render } from '@testing-library/react';
|
|
4
|
+
import { useComponentDidMount } from './useComponentDidMount';
|
|
5
|
+
describe('useComponentDidMount', () => {
|
|
6
|
+
beforeEach(() => {
|
|
7
|
+
vi.clearAllMocks();
|
|
8
|
+
});
|
|
9
|
+
test('calls callback on mount', () => {
|
|
10
|
+
const callback = vi.fn();
|
|
11
|
+
const TestComponent = () => {
|
|
12
|
+
useComponentDidMount(callback);
|
|
13
|
+
return _jsx("div", { children: "Test" });
|
|
14
|
+
};
|
|
15
|
+
render(_jsx(TestComponent, {}));
|
|
16
|
+
expect(callback).toHaveBeenCalledTimes(1);
|
|
17
|
+
});
|
|
18
|
+
test('does not call callback on re-render', () => {
|
|
19
|
+
const callback = vi.fn();
|
|
20
|
+
const TestComponent = ({ count }) => {
|
|
21
|
+
useComponentDidMount(callback);
|
|
22
|
+
return (_jsxs("div", { children: ["Test", count] }));
|
|
23
|
+
};
|
|
24
|
+
const { rerender } = render(_jsx(TestComponent, { count: 1 }));
|
|
25
|
+
expect(callback).toHaveBeenCalledTimes(1);
|
|
26
|
+
rerender(_jsx(TestComponent, { count: 2 }));
|
|
27
|
+
expect(callback).toHaveBeenCalledTimes(1);
|
|
28
|
+
});
|
|
29
|
+
test('calls cleanup function on unmount', () => {
|
|
30
|
+
const cleanup = vi.fn();
|
|
31
|
+
const callback = vi.fn(() => cleanup);
|
|
32
|
+
const TestComponent = () => {
|
|
33
|
+
useComponentDidMount(callback);
|
|
34
|
+
return _jsx("div", { children: "Test" });
|
|
35
|
+
};
|
|
36
|
+
const { unmount } = render(_jsx(TestComponent, {}));
|
|
37
|
+
expect(callback).toHaveBeenCalledTimes(1);
|
|
38
|
+
expect(cleanup).not.toHaveBeenCalled();
|
|
39
|
+
unmount();
|
|
40
|
+
expect(cleanup).toHaveBeenCalledTimes(1);
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
//# sourceMappingURL=useComponentDidMount.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useComponentDidMount.test.js","sourceRoot":"","sources":["../../../src/utils/hooks/useComponentDidMount.test.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAChE,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAE9D,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;IACpC,UAAU,CAAC,GAAG,EAAE;QACd,EAAE,CAAC,aAAa,EAAE,CAAC;IACrB,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,yBAAyB,EAAE,GAAG,EAAE;QACnC,MAAM,QAAQ,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QAEzB,MAAM,aAAa,GAAG,GAAG,EAAE;YACzB,oBAAoB,CAAC,QAAQ,CAAC,CAAC;YAC/B,OAAO,iCAAe,CAAC;QACzB,CAAC,CAAC;QAEF,MAAM,CAAC,KAAC,aAAa,KAAG,CAAC,CAAC;QAE1B,MAAM,CAAC,QAAQ,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,qCAAqC,EAAE,GAAG,EAAE;QAC/C,MAAM,QAAQ,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QAEzB,MAAM,aAAa,GAAG,CAAC,EAAE,KAAK,EAAqB,EAAE,EAAE;YACrD,oBAAoB,CAAC,QAAQ,CAAC,CAAC;YAC/B,OAAO,CACL,kCAEG,KAAK,IACF,CACP,CAAC;QACJ,CAAC,CAAC;QAEF,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,CAAC,KAAC,aAAa,IAAC,KAAK,EAAE,CAAC,GAAI,CAAC,CAAC;QACzD,MAAM,CAAC,QAAQ,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAE1C,QAAQ,CAAC,KAAC,aAAa,IAAC,KAAK,EAAE,CAAC,GAAI,CAAC,CAAC;QACtC,MAAM,CAAC,QAAQ,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,mCAAmC,EAAE,GAAG,EAAE;QAC7C,MAAM,OAAO,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QACxB,MAAM,QAAQ,GAAG,EAAE,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,CAAC;QAEtC,MAAM,aAAa,GAAG,GAAG,EAAE;YACzB,oBAAoB,CAAC,QAAQ,CAAC,CAAC;YAC/B,OAAO,iCAAe,CAAC;QACzB,CAAC,CAAC;QAEF,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC,KAAC,aAAa,KAAG,CAAC,CAAC;QAC9C,MAAM,CAAC,QAAQ,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAC1C,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;QAEvC,OAAO,EAAE,CAAC;QACV,MAAM,CAAC,OAAO,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useGridApi.test.d.ts","sourceRoot":"","sources":["../../../src/utils/hooks/useGridApi.test.tsx"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { describe, expect, test, vi } from 'vitest';
|
|
3
|
+
import { render } from '@testing-library/react';
|
|
4
|
+
import { useGridApi } from './useGridApi';
|
|
5
|
+
import { GridApiContext } from '../../components/table/GridApiContext';
|
|
6
|
+
describe('useGridApi', () => {
|
|
7
|
+
test('returns null gridApi and false isGridApiReady when context is null', () => {
|
|
8
|
+
let result = { gridApi: null, isGridApiReady: false };
|
|
9
|
+
const TestComponent = () => {
|
|
10
|
+
result = useGridApi();
|
|
11
|
+
return _jsx("div", { children: "Test" });
|
|
12
|
+
};
|
|
13
|
+
render(_jsx(GridApiContext.Provider, { value: null, children: _jsx(TestComponent, {}) }));
|
|
14
|
+
expect(result).not.toBeNull();
|
|
15
|
+
expect(result?.gridApi).toBeNull();
|
|
16
|
+
expect(result?.isGridApiReady).toBe(false);
|
|
17
|
+
});
|
|
18
|
+
test('returns gridApi and true isGridApiReady when context provides gridApi', () => {
|
|
19
|
+
const mockGridApi = {
|
|
20
|
+
getDisplayedRowCount: vi.fn(),
|
|
21
|
+
};
|
|
22
|
+
let result = { gridApi: null, isGridApiReady: false };
|
|
23
|
+
const TestComponent = () => {
|
|
24
|
+
result = useGridApi();
|
|
25
|
+
return _jsx("div", { children: "Test" });
|
|
26
|
+
};
|
|
27
|
+
render(_jsx(GridApiContext.Provider, { value: mockGridApi, children: _jsx(TestComponent, {}) }));
|
|
28
|
+
expect(result).not.toBeNull();
|
|
29
|
+
expect(result?.gridApi).toBe(mockGridApi);
|
|
30
|
+
expect(result?.isGridApiReady).toBe(true);
|
|
31
|
+
});
|
|
32
|
+
test('updates isGridApiReady when gridApi changes from null to provided', () => {
|
|
33
|
+
const mockGridApi = {
|
|
34
|
+
getDisplayedRowCount: vi.fn(),
|
|
35
|
+
};
|
|
36
|
+
let result = { gridApi: null, isGridApiReady: false };
|
|
37
|
+
const TestComponent = () => {
|
|
38
|
+
result = useGridApi();
|
|
39
|
+
return _jsx("div", { children: "Test" });
|
|
40
|
+
};
|
|
41
|
+
const { rerender } = render(_jsx(GridApiContext.Provider, { value: null, children: _jsx(TestComponent, {}) }));
|
|
42
|
+
expect(result?.isGridApiReady).toBe(false);
|
|
43
|
+
rerender(_jsx(GridApiContext.Provider, { value: mockGridApi, children: _jsx(TestComponent, {}) }));
|
|
44
|
+
expect(result?.isGridApiReady).toBe(true);
|
|
45
|
+
expect(result?.gridApi).toBe(mockGridApi);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
//# sourceMappingURL=useGridApi.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useGridApi.test.js","sourceRoot":"","sources":["../../../src/utils/hooks/useGridApi.test.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AACpD,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAGjE,QAAQ,CAAC,YAAY,EAAE,GAAG,EAAE;IAC1B,IAAI,CAAC,oEAAoE,EAAE,GAAG,EAAE;QAC9E,IAAI,MAAM,GAAyD,EAAE,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC;QAE5G,MAAM,aAAa,GAAG,GAAG,EAAE;YACzB,MAAM,GAAG,UAAU,EAAE,CAAC;YACtB,OAAO,iCAAe,CAAC;QACzB,CAAC,CAAC;QAEF,MAAM,CACJ,KAAC,cAAc,CAAC,QAAQ,IAAC,KAAK,EAAE,IAAI,YAClC,KAAC,aAAa,KAAG,GACO,CAC3B,CAAC;QAEF,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;QAC9B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,QAAQ,EAAE,CAAC;QACnC,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,uEAAuE,EAAE,GAAG,EAAE;QACjF,MAAM,WAAW,GAAG;YAClB,oBAAoB,EAAE,EAAE,CAAC,EAAE,EAAE;SACR,CAAC;QAExB,IAAI,MAAM,GAAyD,EAAE,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC;QAE5G,MAAM,aAAa,GAAG,GAAG,EAAE;YACzB,MAAM,GAAG,UAAU,EAAE,CAAC;YACtB,OAAO,iCAAe,CAAC;QACzB,CAAC,CAAC;QAEF,MAAM,CACJ,KAAC,cAAc,CAAC,QAAQ,IAAC,KAAK,EAAE,WAAW,YACzC,KAAC,aAAa,KAAG,GACO,CAC3B,CAAC;QAEF,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;QAC9B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC1C,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,mEAAmE,EAAE,GAAG,EAAE;QAC7E,MAAM,WAAW,GAAG;YAClB,oBAAoB,EAAE,EAAE,CAAC,EAAE,EAAE;SACR,CAAC;QAExB,IAAI,MAAM,GAAyD,EAAE,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC;QAE5G,MAAM,aAAa,GAAG,GAAG,EAAE;YACzB,MAAM,GAAG,UAAU,EAAE,CAAC;YACtB,OAAO,iCAAe,CAAC;QACzB,CAAC,CAAC;QAEF,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,CACzB,KAAC,cAAc,CAAC,QAAQ,IAAC,KAAK,EAAE,IAAI,YAClC,KAAC,aAAa,KAAG,GACO,CAC3B,CAAC;QAEF,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAE3C,QAAQ,CACN,KAAC,cAAc,CAAC,QAAQ,IAAC,KAAK,EAAE,WAAW,YACzC,KAAC,aAAa,KAAG,GACO,CAC3B,CAAC;QAEF,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1C,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useIsMounted.test.d.ts","sourceRoot":"","sources":["../../../src/utils/hooks/useIsMounted.test.tsx"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { describe, expect, test } from 'vitest';
|
|
3
|
+
import { render } from '@testing-library/react';
|
|
4
|
+
import { useIsMounted } from './useIsMounted';
|
|
5
|
+
describe('useIsMounted', () => {
|
|
6
|
+
test('returns a ref with current value true when component is mounted', () => {
|
|
7
|
+
let mountedRef = null;
|
|
8
|
+
const TestComponent = () => {
|
|
9
|
+
mountedRef = useIsMounted();
|
|
10
|
+
return _jsx("div", { children: "Test" });
|
|
11
|
+
};
|
|
12
|
+
render(_jsx(TestComponent, {}));
|
|
13
|
+
expect(mountedRef).not.toBeNull();
|
|
14
|
+
expect(mountedRef.current).toBe(true);
|
|
15
|
+
});
|
|
16
|
+
test('returns the same ref instance across re-renders', () => {
|
|
17
|
+
let mountedRef1 = null;
|
|
18
|
+
let mountedRef2 = null;
|
|
19
|
+
const TestComponent = ({ count }) => {
|
|
20
|
+
const ref = useIsMounted();
|
|
21
|
+
if (count === 1) {
|
|
22
|
+
mountedRef1 = ref;
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
mountedRef2 = ref;
|
|
26
|
+
}
|
|
27
|
+
return (_jsxs("div", { children: ["Test", count] }));
|
|
28
|
+
};
|
|
29
|
+
const { rerender } = render(_jsx(TestComponent, { count: 1 }));
|
|
30
|
+
rerender(_jsx(TestComponent, { count: 2 }));
|
|
31
|
+
expect(mountedRef1).toBe(mountedRef2);
|
|
32
|
+
expect(mountedRef1.current).toBe(true);
|
|
33
|
+
});
|
|
34
|
+
test('sets current to false when component unmounts', () => {
|
|
35
|
+
let mountedRef = null;
|
|
36
|
+
const TestComponent = () => {
|
|
37
|
+
mountedRef = useIsMounted();
|
|
38
|
+
return _jsx("div", { children: "Test" });
|
|
39
|
+
};
|
|
40
|
+
const { unmount } = render(_jsx(TestComponent, {}));
|
|
41
|
+
expect(mountedRef.current).toBe(true);
|
|
42
|
+
unmount();
|
|
43
|
+
expect(mountedRef.current).toBe(false);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
//# sourceMappingURL=useIsMounted.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useIsMounted.test.js","sourceRoot":"","sources":["../../../src/utils/hooks/useIsMounted.test.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;IAC5B,IAAI,CAAC,iEAAiE,EAAE,GAAG,EAAE;QAC3E,IAAI,UAAU,GAA2C,IAAI,CAAC;QAE9D,MAAM,aAAa,GAAG,GAAG,EAAE;YACzB,UAAU,GAAG,YAAY,EAAE,CAAC;YAC5B,OAAO,iCAAe,CAAC;QACzB,CAAC,CAAC;QAEF,MAAM,CAAC,KAAC,aAAa,KAAG,CAAC,CAAC;QAE1B,MAAM,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;QAClC,MAAM,CAAC,UAAW,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,iDAAiD,EAAE,GAAG,EAAE;QAC3D,IAAI,WAAW,GAA2C,IAAI,CAAC;QAC/D,IAAI,WAAW,GAA2C,IAAI,CAAC;QAE/D,MAAM,aAAa,GAAG,CAAC,EAAE,KAAK,EAAqB,EAAE,EAAE;YACrD,MAAM,GAAG,GAAG,YAAY,EAAE,CAAC;YAC3B,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;gBAChB,WAAW,GAAG,GAAG,CAAC;YACpB,CAAC;iBACI,CAAC;gBACJ,WAAW,GAAG,GAAG,CAAC;YACpB,CAAC;YACD,OAAO,CACL,kCAEG,KAAK,IACF,CACP,CAAC;QACJ,CAAC,CAAC;QAEF,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,CAAC,KAAC,aAAa,IAAC,KAAK,EAAE,CAAC,GAAI,CAAC,CAAC;QACzD,QAAQ,CAAC,KAAC,aAAa,IAAC,KAAK,EAAE,CAAC,GAAI,CAAC,CAAC;QAEtC,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACtC,MAAM,CAAC,WAAY,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,+CAA+C,EAAE,GAAG,EAAE;QACzD,IAAI,UAAU,GAA2C,IAAI,CAAC;QAE9D,MAAM,aAAa,GAAG,GAAG,EAAE;YACzB,UAAU,GAAG,YAAY,EAAE,CAAC;YAC5B,OAAO,iCAAe,CAAC;QACzB,CAAC,CAAC;QAEF,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC,KAAC,aAAa,KAAG,CAAC,CAAC;QAE9C,MAAM,CAAC,UAAW,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAEvC,OAAO,EAAE,CAAC;QAEV,MAAM,CAAC,UAAW,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -3,6 +3,6 @@ type Args = {
|
|
|
3
3
|
deps?: DependencyList;
|
|
4
4
|
prefix?: string;
|
|
5
5
|
};
|
|
6
|
-
export declare const useMemoGenerateUuid: ({ deps, prefix }
|
|
6
|
+
export declare const useMemoGenerateUuid: ({ deps, prefix }?: Args) => string;
|
|
7
7
|
export {};
|
|
8
8
|
//# sourceMappingURL=useMemoGenerateUuid.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useMemoGenerateUuid.d.ts","sourceRoot":"","sources":["../../../src/utils/hooks/useMemoGenerateUuid.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,KAAK,cAAc,EAAE,MAAM,OAAO,CAAC;AAGrD,KAAK,IAAI,GAAG;IACV,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAAI,
|
|
1
|
+
{"version":3,"file":"useMemoGenerateUuid.d.ts","sourceRoot":"","sources":["../../../src/utils/hooks/useMemoGenerateUuid.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,KAAK,cAAc,EAAE,MAAM,OAAO,CAAC;AAGrD,KAAK,IAAI,GAAG;IACV,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAAI,mBAAuB,IAAS,WAInE,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useMemo } from 'react';
|
|
2
2
|
import { generateUuid } from '../generateUuid';
|
|
3
|
-
export const useMemoGenerateUuid = ({ deps = [], prefix }) => {
|
|
3
|
+
export const useMemoGenerateUuid = ({ deps = [], prefix } = {}) => {
|
|
4
4
|
return useMemo(() => {
|
|
5
5
|
return generateUuid(prefix);
|
|
6
6
|
}, deps);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useMemoGenerateUuid.js","sourceRoot":"","sources":["../../../src/utils/hooks/useMemoGenerateUuid.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAuB,MAAM,OAAO,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAO/C,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,EAAE,IAAI,GAAG,EAAE,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"useMemoGenerateUuid.js","sourceRoot":"","sources":["../../../src/utils/hooks/useMemoGenerateUuid.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAuB,MAAM,OAAO,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAO/C,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,EAAE,IAAI,GAAG,EAAE,EAAE,MAAM,KAAW,EAAE,EAAE,EAAE;IACtE,OAAO,OAAO,CAAC,GAAG,EAAE;QAClB,OAAO,YAAY,CAAC,MAAM,CAAC,CAAC;IAC9B,CAAC,EAAE,IAAI,CAAC,CAAC;AACX,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useMemoGenerateUuid.test.d.ts","sourceRoot":"","sources":["../../../src/utils/hooks/useMemoGenerateUuid.test.tsx"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { describe, expect, test, vi, beforeEach } from 'vitest';
|
|
3
|
+
import { render } from '@testing-library/react';
|
|
4
|
+
import { useMemoGenerateUuid } from './useMemoGenerateUuid';
|
|
5
|
+
import { generateUuid } from '../generateUuid';
|
|
6
|
+
vi.mock('../generateUuid', () => ({
|
|
7
|
+
generateUuid: vi.fn((prefix) => {
|
|
8
|
+
const uuid = '123e4567-e89b-12d3-a456-426614174000';
|
|
9
|
+
return prefix ? `${prefix}-${uuid}` : uuid;
|
|
10
|
+
}),
|
|
11
|
+
}));
|
|
12
|
+
describe('useMemoGenerateUuid', () => {
|
|
13
|
+
beforeEach(() => {
|
|
14
|
+
vi.clearAllMocks();
|
|
15
|
+
});
|
|
16
|
+
test('generates a UUID without prefix', () => {
|
|
17
|
+
let uuid = null;
|
|
18
|
+
const TestComponent = () => {
|
|
19
|
+
uuid = useMemoGenerateUuid();
|
|
20
|
+
return _jsx("div", { children: "Test" });
|
|
21
|
+
};
|
|
22
|
+
render(_jsx(TestComponent, {}));
|
|
23
|
+
expect(uuid).toBe('123e4567-e89b-12d3-a456-426614174000');
|
|
24
|
+
expect(generateUuid).toHaveBeenCalledWith(undefined);
|
|
25
|
+
});
|
|
26
|
+
test('generates a UUID with prefix', () => {
|
|
27
|
+
let uuid = null;
|
|
28
|
+
const TestComponent = () => {
|
|
29
|
+
uuid = useMemoGenerateUuid({ prefix: 'test' });
|
|
30
|
+
return _jsx("div", { children: "Test" });
|
|
31
|
+
};
|
|
32
|
+
render(_jsx(TestComponent, {}));
|
|
33
|
+
expect(uuid).toBe('test-123e4567-e89b-12d3-a456-426614174000');
|
|
34
|
+
expect(generateUuid).toHaveBeenCalledWith('test');
|
|
35
|
+
});
|
|
36
|
+
test('does not generate a new UUID when the dependencies do not change', () => {
|
|
37
|
+
const TestComponent = ({ count }) => {
|
|
38
|
+
const uuid = useMemoGenerateUuid();
|
|
39
|
+
return (_jsxs("div", { children: ["Test", count, uuid] }));
|
|
40
|
+
};
|
|
41
|
+
const { rerender } = render(_jsx(TestComponent, { count: 1 }));
|
|
42
|
+
rerender(_jsx(TestComponent, { count: 2 }));
|
|
43
|
+
expect(generateUuid).toHaveBeenCalledTimes(1);
|
|
44
|
+
});
|
|
45
|
+
test('generates a new UUID when the dependencies change', () => {
|
|
46
|
+
const TestComponent = ({ dep1, dep2 }) => {
|
|
47
|
+
const uuid = useMemoGenerateUuid({ deps: [dep1, dep2] });
|
|
48
|
+
return (_jsxs("div", { children: ["Test", uuid] }));
|
|
49
|
+
};
|
|
50
|
+
const { rerender } = render(_jsx(TestComponent, { dep1: 1, dep2: "a" }));
|
|
51
|
+
rerender(_jsx(TestComponent, { dep1: 2, dep2: "b" }));
|
|
52
|
+
expect(generateUuid).toHaveBeenCalledTimes(2);
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
//# sourceMappingURL=useMemoGenerateUuid.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useMemoGenerateUuid.test.js","sourceRoot":"","sources":["../../../src/utils/hooks/useMemoGenerateUuid.test.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usePubSub.test.d.ts","sourceRoot":"","sources":["../../../src/utils/hooks/usePubSub.test.tsx"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { describe, expect, test, vi, afterEach } from 'vitest';
|
|
3
|
+
import { render } from '@testing-library/react';
|
|
4
|
+
import { usePubSub } from './usePubSub';
|
|
5
|
+
import PubSub from '../PubSub';
|
|
6
|
+
import { generateUuid } from '../generateUuid';
|
|
7
|
+
const mockSubscriptions = {};
|
|
8
|
+
vi.mock('Utils/PubSub', () => {
|
|
9
|
+
return {
|
|
10
|
+
default: {
|
|
11
|
+
subscribe: vi.fn((eventName, handler) => {
|
|
12
|
+
const subscriptionId = generateUuid('pubsub-subscription');
|
|
13
|
+
if (!mockSubscriptions[eventName]) {
|
|
14
|
+
mockSubscriptions[eventName] = {};
|
|
15
|
+
}
|
|
16
|
+
mockSubscriptions[eventName][subscriptionId] = handler;
|
|
17
|
+
return subscriptionId;
|
|
18
|
+
}),
|
|
19
|
+
unsubscribe: vi.fn((eventName, subscriptionId) => {
|
|
20
|
+
if (mockSubscriptions[eventName]) {
|
|
21
|
+
delete mockSubscriptions[eventName][subscriptionId];
|
|
22
|
+
}
|
|
23
|
+
}),
|
|
24
|
+
publish: vi.fn((eventName, data) => {
|
|
25
|
+
if (mockSubscriptions[eventName]) {
|
|
26
|
+
Object.values(mockSubscriptions[eventName]).forEach((handler) => {
|
|
27
|
+
handler(data);
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
}),
|
|
31
|
+
// Helper to clear subscriptions for testing
|
|
32
|
+
_clearSubscriptions: () => {
|
|
33
|
+
Object.keys(mockSubscriptions).forEach((key) => {
|
|
34
|
+
delete mockSubscriptions[key];
|
|
35
|
+
});
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
});
|
|
40
|
+
describe('usePubSub', () => {
|
|
41
|
+
afterEach(() => {
|
|
42
|
+
// @ts-expect-error - Accessing private method for testing
|
|
43
|
+
PubSub._clearSubscriptions?.();
|
|
44
|
+
vi.clearAllMocks();
|
|
45
|
+
vi.resetAllMocks();
|
|
46
|
+
vi.restoreAllMocks();
|
|
47
|
+
});
|
|
48
|
+
test('subscribes to event on mount', () => {
|
|
49
|
+
const handler = vi.fn();
|
|
50
|
+
const TestComponent = () => {
|
|
51
|
+
usePubSub('test-event', handler);
|
|
52
|
+
return _jsx("div", { children: "Test" });
|
|
53
|
+
};
|
|
54
|
+
render(_jsx(TestComponent, {}));
|
|
55
|
+
expect(PubSub.subscribe).toHaveBeenCalledTimes(1);
|
|
56
|
+
expect(PubSub.subscribe).toHaveBeenCalledWith('test-event', handler);
|
|
57
|
+
});
|
|
58
|
+
test('unsubscribes from event on unmount', () => {
|
|
59
|
+
const handler = vi.fn();
|
|
60
|
+
const TestComponent = () => {
|
|
61
|
+
usePubSub('test-event', handler);
|
|
62
|
+
return _jsx("div", { children: "Test" });
|
|
63
|
+
};
|
|
64
|
+
const { unmount } = render(_jsx(TestComponent, {}));
|
|
65
|
+
expect(PubSub.subscribe).toHaveBeenCalledTimes(1);
|
|
66
|
+
unmount();
|
|
67
|
+
expect(PubSub.unsubscribe).toHaveBeenCalledWith('test-event', expect.any(String));
|
|
68
|
+
});
|
|
69
|
+
test('does not resubscribe on re-render', () => {
|
|
70
|
+
const handler = vi.fn();
|
|
71
|
+
const TestComponent = ({ count }) => {
|
|
72
|
+
usePubSub('test-event', handler);
|
|
73
|
+
return (_jsxs("div", { children: ["Test", count] }));
|
|
74
|
+
};
|
|
75
|
+
const { rerender } = render(_jsx(TestComponent, { count: 1 }));
|
|
76
|
+
expect(PubSub.subscribe).toHaveBeenCalledTimes(1);
|
|
77
|
+
rerender(_jsx(TestComponent, { count: 2 }));
|
|
78
|
+
expect(PubSub.subscribe).toHaveBeenCalledTimes(1);
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
//# sourceMappingURL=usePubSub.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usePubSub.test.js","sourceRoot":"","sources":["../../../src/utils/hooks/usePubSub.test.tsx"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arbor-education/design-system.components",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "The component library for the design system (the baby)",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"repository": {
|
|
@@ -78,6 +78,7 @@
|
|
|
78
78
|
"tsc-watch-command": "tsc-alias && yalc push --private --sig",
|
|
79
79
|
"watch": "sass --watch src/index.scss dist/index.css & tsc-watch --onSuccess \"yarn tsc-watch-command\"",
|
|
80
80
|
"test": "vitest",
|
|
81
|
+
"test:coverage": "vitest run --coverage",
|
|
81
82
|
"create-component": "./bin/createComponent.sh",
|
|
82
83
|
"prepare": "husky",
|
|
83
84
|
"prepublishOnly": "yarn build",
|
|
@@ -2,11 +2,14 @@ import { describe, expect, test } from 'vitest';
|
|
|
2
2
|
import { render, screen } from '@testing-library/react';
|
|
3
3
|
import { Icon } from './Icon';
|
|
4
4
|
import '@testing-library/jest-dom/vitest';
|
|
5
|
+
import { allowedIcons, type IconName } from './allowedIcons';
|
|
5
6
|
|
|
6
7
|
describe('Icon', () => {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
Object.keys(allowedIcons).forEach((icon) => {
|
|
9
|
+
test(`Icon ${icon} renders`, () => {
|
|
10
|
+
render(<Icon name={icon as IconName} />);
|
|
11
|
+
expect(screen.getByRole('img', { hidden: true })).toBeInTheDocument();
|
|
12
|
+
});
|
|
10
13
|
});
|
|
11
14
|
|
|
12
15
|
test('Screen reader text', () => {
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { describe, expect, test, vi, beforeEach } from 'vitest';
|
|
2
|
+
import { render } from '@testing-library/react';
|
|
3
|
+
import { useComponentDidMount } from './useComponentDidMount';
|
|
4
|
+
|
|
5
|
+
describe('useComponentDidMount', () => {
|
|
6
|
+
beforeEach(() => {
|
|
7
|
+
vi.clearAllMocks();
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
test('calls callback on mount', () => {
|
|
11
|
+
const callback = vi.fn();
|
|
12
|
+
|
|
13
|
+
const TestComponent = () => {
|
|
14
|
+
useComponentDidMount(callback);
|
|
15
|
+
return <div>Test</div>;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
render(<TestComponent />);
|
|
19
|
+
|
|
20
|
+
expect(callback).toHaveBeenCalledTimes(1);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test('does not call callback on re-render', () => {
|
|
24
|
+
const callback = vi.fn();
|
|
25
|
+
|
|
26
|
+
const TestComponent = ({ count }: { count: number }) => {
|
|
27
|
+
useComponentDidMount(callback);
|
|
28
|
+
return (
|
|
29
|
+
<div>
|
|
30
|
+
Test
|
|
31
|
+
{count}
|
|
32
|
+
</div>
|
|
33
|
+
);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const { rerender } = render(<TestComponent count={1} />);
|
|
37
|
+
expect(callback).toHaveBeenCalledTimes(1);
|
|
38
|
+
|
|
39
|
+
rerender(<TestComponent count={2} />);
|
|
40
|
+
expect(callback).toHaveBeenCalledTimes(1);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test('calls cleanup function on unmount', () => {
|
|
44
|
+
const cleanup = vi.fn();
|
|
45
|
+
const callback = vi.fn(() => cleanup);
|
|
46
|
+
|
|
47
|
+
const TestComponent = () => {
|
|
48
|
+
useComponentDidMount(callback);
|
|
49
|
+
return <div>Test</div>;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const { unmount } = render(<TestComponent />);
|
|
53
|
+
expect(callback).toHaveBeenCalledTimes(1);
|
|
54
|
+
expect(cleanup).not.toHaveBeenCalled();
|
|
55
|
+
|
|
56
|
+
unmount();
|
|
57
|
+
expect(cleanup).toHaveBeenCalledTimes(1);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { describe, expect, test, vi } from 'vitest';
|
|
2
|
+
import { render } from '@testing-library/react';
|
|
3
|
+
import { useGridApi } from './useGridApi';
|
|
4
|
+
import { GridApiContext } from 'Components/table/GridApiContext';
|
|
5
|
+
import type { GridApi } from 'ag-grid-community';
|
|
6
|
+
|
|
7
|
+
describe('useGridApi', () => {
|
|
8
|
+
test('returns null gridApi and false isGridApiReady when context is null', () => {
|
|
9
|
+
let result: { gridApi: GridApi | null; isGridApiReady: boolean } = { gridApi: null, isGridApiReady: false };
|
|
10
|
+
|
|
11
|
+
const TestComponent = () => {
|
|
12
|
+
result = useGridApi();
|
|
13
|
+
return <div>Test</div>;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
render(
|
|
17
|
+
<GridApiContext.Provider value={null}>
|
|
18
|
+
<TestComponent />
|
|
19
|
+
</GridApiContext.Provider>,
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
expect(result).not.toBeNull();
|
|
23
|
+
expect(result?.gridApi).toBeNull();
|
|
24
|
+
expect(result?.isGridApiReady).toBe(false);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
test('returns gridApi and true isGridApiReady when context provides gridApi', () => {
|
|
28
|
+
const mockGridApi = {
|
|
29
|
+
getDisplayedRowCount: vi.fn(),
|
|
30
|
+
} as unknown as GridApi;
|
|
31
|
+
|
|
32
|
+
let result: { gridApi: GridApi | null; isGridApiReady: boolean } = { gridApi: null, isGridApiReady: false };
|
|
33
|
+
|
|
34
|
+
const TestComponent = () => {
|
|
35
|
+
result = useGridApi();
|
|
36
|
+
return <div>Test</div>;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
render(
|
|
40
|
+
<GridApiContext.Provider value={mockGridApi}>
|
|
41
|
+
<TestComponent />
|
|
42
|
+
</GridApiContext.Provider>,
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
expect(result).not.toBeNull();
|
|
46
|
+
expect(result?.gridApi).toBe(mockGridApi);
|
|
47
|
+
expect(result?.isGridApiReady).toBe(true);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test('updates isGridApiReady when gridApi changes from null to provided', () => {
|
|
51
|
+
const mockGridApi = {
|
|
52
|
+
getDisplayedRowCount: vi.fn(),
|
|
53
|
+
} as unknown as GridApi;
|
|
54
|
+
|
|
55
|
+
let result: { gridApi: GridApi | null; isGridApiReady: boolean } = { gridApi: null, isGridApiReady: false };
|
|
56
|
+
|
|
57
|
+
const TestComponent = () => {
|
|
58
|
+
result = useGridApi();
|
|
59
|
+
return <div>Test</div>;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const { rerender } = render(
|
|
63
|
+
<GridApiContext.Provider value={null}>
|
|
64
|
+
<TestComponent />
|
|
65
|
+
</GridApiContext.Provider>,
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
expect(result?.isGridApiReady).toBe(false);
|
|
69
|
+
|
|
70
|
+
rerender(
|
|
71
|
+
<GridApiContext.Provider value={mockGridApi}>
|
|
72
|
+
<TestComponent />
|
|
73
|
+
</GridApiContext.Provider>,
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
expect(result?.isGridApiReady).toBe(true);
|
|
77
|
+
expect(result?.gridApi).toBe(mockGridApi);
|
|
78
|
+
});
|
|
79
|
+
});
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vitest';
|
|
2
|
+
import { render } from '@testing-library/react';
|
|
3
|
+
import { useIsMounted } from './useIsMounted';
|
|
4
|
+
|
|
5
|
+
describe('useIsMounted', () => {
|
|
6
|
+
test('returns a ref with current value true when component is mounted', () => {
|
|
7
|
+
let mountedRef: ReturnType<typeof useIsMounted> | null = null;
|
|
8
|
+
|
|
9
|
+
const TestComponent = () => {
|
|
10
|
+
mountedRef = useIsMounted();
|
|
11
|
+
return <div>Test</div>;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
render(<TestComponent />);
|
|
15
|
+
|
|
16
|
+
expect(mountedRef).not.toBeNull();
|
|
17
|
+
expect(mountedRef!.current).toBe(true);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
test('returns the same ref instance across re-renders', () => {
|
|
21
|
+
let mountedRef1: ReturnType<typeof useIsMounted> | null = null;
|
|
22
|
+
let mountedRef2: ReturnType<typeof useIsMounted> | null = null;
|
|
23
|
+
|
|
24
|
+
const TestComponent = ({ count }: { count: number }) => {
|
|
25
|
+
const ref = useIsMounted();
|
|
26
|
+
if (count === 1) {
|
|
27
|
+
mountedRef1 = ref;
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
mountedRef2 = ref;
|
|
31
|
+
}
|
|
32
|
+
return (
|
|
33
|
+
<div>
|
|
34
|
+
Test
|
|
35
|
+
{count}
|
|
36
|
+
</div>
|
|
37
|
+
);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const { rerender } = render(<TestComponent count={1} />);
|
|
41
|
+
rerender(<TestComponent count={2} />);
|
|
42
|
+
|
|
43
|
+
expect(mountedRef1).toBe(mountedRef2);
|
|
44
|
+
expect(mountedRef1!.current).toBe(true);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
test('sets current to false when component unmounts', () => {
|
|
48
|
+
let mountedRef: ReturnType<typeof useIsMounted> | null = null;
|
|
49
|
+
|
|
50
|
+
const TestComponent = () => {
|
|
51
|
+
mountedRef = useIsMounted();
|
|
52
|
+
return <div>Test</div>;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const { unmount } = render(<TestComponent />);
|
|
56
|
+
|
|
57
|
+
expect(mountedRef!.current).toBe(true);
|
|
58
|
+
|
|
59
|
+
unmount();
|
|
60
|
+
|
|
61
|
+
expect(mountedRef!.current).toBe(false);
|
|
62
|
+
});
|
|
63
|
+
});
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { describe, expect, test, vi, beforeEach } from 'vitest';
|
|
2
|
+
import { render } from '@testing-library/react';
|
|
3
|
+
import { useMemoGenerateUuid } from './useMemoGenerateUuid';
|
|
4
|
+
import { generateUuid } from '../generateUuid';
|
|
5
|
+
|
|
6
|
+
vi.mock('../generateUuid', () => ({
|
|
7
|
+
generateUuid: vi.fn((prefix?: string) => {
|
|
8
|
+
const uuid = '123e4567-e89b-12d3-a456-426614174000';
|
|
9
|
+
return prefix ? `${prefix}-${uuid}` : uuid;
|
|
10
|
+
}),
|
|
11
|
+
}));
|
|
12
|
+
|
|
13
|
+
describe('useMemoGenerateUuid', () => {
|
|
14
|
+
beforeEach(() => {
|
|
15
|
+
vi.clearAllMocks();
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
test('generates a UUID without prefix', () => {
|
|
19
|
+
let uuid: string | null = null;
|
|
20
|
+
|
|
21
|
+
const TestComponent = () => {
|
|
22
|
+
uuid = useMemoGenerateUuid();
|
|
23
|
+
return <div>Test</div>;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
render(<TestComponent />);
|
|
27
|
+
|
|
28
|
+
expect(uuid).toBe('123e4567-e89b-12d3-a456-426614174000');
|
|
29
|
+
expect(generateUuid).toHaveBeenCalledWith(undefined);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
test('generates a UUID with prefix', () => {
|
|
33
|
+
let uuid: string | null = null;
|
|
34
|
+
|
|
35
|
+
const TestComponent = () => {
|
|
36
|
+
uuid = useMemoGenerateUuid({ prefix: 'test' });
|
|
37
|
+
return <div>Test</div>;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
render(<TestComponent />);
|
|
41
|
+
|
|
42
|
+
expect(uuid).toBe('test-123e4567-e89b-12d3-a456-426614174000');
|
|
43
|
+
expect(generateUuid).toHaveBeenCalledWith('test');
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
test('does not generate a new UUID when the dependencies do not change', () => {
|
|
47
|
+
const TestComponent = ({ count }: { count: number }) => {
|
|
48
|
+
const uuid = useMemoGenerateUuid();
|
|
49
|
+
return (
|
|
50
|
+
<div>
|
|
51
|
+
Test
|
|
52
|
+
{count}
|
|
53
|
+
{uuid}
|
|
54
|
+
</div>
|
|
55
|
+
);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const { rerender } = render(<TestComponent count={1} />);
|
|
59
|
+
rerender(<TestComponent count={2} />);
|
|
60
|
+
expect(generateUuid).toHaveBeenCalledTimes(1);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
test('generates a new UUID when the dependencies change', () => {
|
|
64
|
+
const TestComponent = ({ dep1, dep2 }: { dep1: number; dep2: string }) => {
|
|
65
|
+
const uuid = useMemoGenerateUuid({ deps: [dep1, dep2] });
|
|
66
|
+
|
|
67
|
+
return (
|
|
68
|
+
<div>
|
|
69
|
+
Test
|
|
70
|
+
{uuid}
|
|
71
|
+
</div>
|
|
72
|
+
);
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const { rerender } = render(<TestComponent dep1={1} dep2="a" />);
|
|
76
|
+
rerender(<TestComponent dep1={2} dep2="b" />);
|
|
77
|
+
|
|
78
|
+
expect(generateUuid).toHaveBeenCalledTimes(2);
|
|
79
|
+
});
|
|
80
|
+
});
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { describe, expect, test, vi, afterEach } from 'vitest';
|
|
2
|
+
import { render } from '@testing-library/react';
|
|
3
|
+
import { usePubSub } from './usePubSub';
|
|
4
|
+
import PubSub from 'Utils/PubSub';
|
|
5
|
+
import { generateUuid } from 'Utils/generateUuid';
|
|
6
|
+
|
|
7
|
+
const mockSubscriptions: Record<string, Record<string, (...args: unknown[]) => void>> = {};
|
|
8
|
+
vi.mock('Utils/PubSub', () => {
|
|
9
|
+
return {
|
|
10
|
+
default: {
|
|
11
|
+
subscribe: vi.fn((eventName: string, handler: (...args: unknown[]) => void) => {
|
|
12
|
+
const subscriptionId = generateUuid('pubsub-subscription');
|
|
13
|
+
if (!mockSubscriptions[eventName]) {
|
|
14
|
+
mockSubscriptions[eventName] = {};
|
|
15
|
+
}
|
|
16
|
+
mockSubscriptions[eventName][subscriptionId] = handler;
|
|
17
|
+
return subscriptionId;
|
|
18
|
+
}),
|
|
19
|
+
unsubscribe: vi.fn((eventName: string, subscriptionId: string) => {
|
|
20
|
+
if (mockSubscriptions[eventName]) {
|
|
21
|
+
delete mockSubscriptions[eventName][subscriptionId];
|
|
22
|
+
}
|
|
23
|
+
}),
|
|
24
|
+
publish: vi.fn((eventName: string, data?: unknown) => {
|
|
25
|
+
if (mockSubscriptions[eventName]) {
|
|
26
|
+
Object.values(mockSubscriptions[eventName]).forEach((handler) => {
|
|
27
|
+
handler(data);
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
}),
|
|
31
|
+
// Helper to clear subscriptions for testing
|
|
32
|
+
_clearSubscriptions: () => {
|
|
33
|
+
Object.keys(mockSubscriptions).forEach((key) => {
|
|
34
|
+
delete mockSubscriptions[key];
|
|
35
|
+
});
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
describe('usePubSub', () => {
|
|
42
|
+
afterEach(() => {
|
|
43
|
+
// @ts-expect-error - Accessing private method for testing
|
|
44
|
+
PubSub._clearSubscriptions?.();
|
|
45
|
+
vi.clearAllMocks();
|
|
46
|
+
vi.resetAllMocks();
|
|
47
|
+
vi.restoreAllMocks();
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test('subscribes to event on mount', () => {
|
|
51
|
+
const handler = vi.fn();
|
|
52
|
+
|
|
53
|
+
const TestComponent = () => {
|
|
54
|
+
usePubSub('test-event', handler);
|
|
55
|
+
return <div>Test</div>;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
render(<TestComponent />);
|
|
59
|
+
|
|
60
|
+
expect(PubSub.subscribe).toHaveBeenCalledTimes(1);
|
|
61
|
+
expect(PubSub.subscribe).toHaveBeenCalledWith('test-event', handler);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
test('unsubscribes from event on unmount', () => {
|
|
65
|
+
const handler = vi.fn();
|
|
66
|
+
|
|
67
|
+
const TestComponent = () => {
|
|
68
|
+
usePubSub('test-event', handler);
|
|
69
|
+
return <div>Test</div>;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const { unmount } = render(<TestComponent />);
|
|
73
|
+
|
|
74
|
+
expect(PubSub.subscribe).toHaveBeenCalledTimes(1);
|
|
75
|
+
|
|
76
|
+
unmount();
|
|
77
|
+
|
|
78
|
+
expect(PubSub.unsubscribe).toHaveBeenCalledWith('test-event', expect.any(String));
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
test('does not resubscribe on re-render', () => {
|
|
82
|
+
const handler = vi.fn();
|
|
83
|
+
|
|
84
|
+
const TestComponent = ({ count }: { count: number }) => {
|
|
85
|
+
usePubSub('test-event', handler);
|
|
86
|
+
return (
|
|
87
|
+
<div>
|
|
88
|
+
Test
|
|
89
|
+
{count}
|
|
90
|
+
</div>
|
|
91
|
+
);
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const { rerender } = render(<TestComponent count={1} />);
|
|
95
|
+
expect(PubSub.subscribe).toHaveBeenCalledTimes(1);
|
|
96
|
+
|
|
97
|
+
rerender(<TestComponent count={2} />);
|
|
98
|
+
expect(PubSub.subscribe).toHaveBeenCalledTimes(1);
|
|
99
|
+
});
|
|
100
|
+
});
|
package/vitest.config.ts
CHANGED
|
@@ -8,6 +8,15 @@ export default defineConfig({
|
|
|
8
8
|
environment: 'jsdom',
|
|
9
9
|
globals: true,
|
|
10
10
|
setupFiles: ['./setupTestRuntime.ts'],
|
|
11
|
+
coverage: {
|
|
12
|
+
reporter: ['lcov'],
|
|
13
|
+
include: ['src/**/*.{ts,tsx}'],
|
|
14
|
+
exclude: [
|
|
15
|
+
'src/**/*.mdx',
|
|
16
|
+
'src/**/*.{stories,story,test}.{ts,tsx}',
|
|
17
|
+
'src/**/types.ts',
|
|
18
|
+
],
|
|
19
|
+
},
|
|
11
20
|
},
|
|
12
21
|
resolve: {
|
|
13
22
|
alias: {
|