test(ui): add unit tests for useModelVersionById hook#2595
Conversation
Signed-off-by: Yulia Krimerman <juliapiterova@hotmail.com>
manaswinidas
left a comment
There was a problem hiding this comment.
3 of the 4 tests are tautological — they mock useFetchState's return value then assert exactly what was mocked, without ever invoking the hook's callback. Only test 4 (callback capture) genuinely exercises the hook logic, and it only covers the happy path.
Please rewrite tests 1–2 to capture the callback (same pattern as test 4) and verify it rejects with the expected errors. Test 3 can be dropped since test 4 already covers that path. This will give real coverage of all 3 branches.
| refreshAllAPI: jest.fn(), | ||
| }); | ||
|
|
||
| const mockError = new Error('API not yet available'); | ||
| mockUseFetchState.mockReturnValue([null, false, mockError, jest.fn()]); | ||
|
|
||
| const { result } = testHook(useModelVersionById)('version-1'); | ||
|
|
||
| await waitFor(() => { | ||
| const [, , error] = result.current; | ||
| expect(error).toBeInstanceOf(Error); | ||
| expect(error?.message).toBe('API not yet available'); | ||
| }); | ||
| }); | ||
|
|
||
| it('should silently fail when modelVersionId is not provided', async () => { |
There was a problem hiding this comment.
Tautological: you mock useFetchState to return [null, false, mockError, …] then assert the error is exactly what you mocked. The hook's !apiAvailable branch is never invoked.
Capture the callback instead (same approach as test 4) and verify it rejects:
const cb = mockUseFetchState.mock.calls[0][0];
await expect(cb({})).rejects.toThrow('API not yet available');| apiAvailable: true, | ||
| refreshAllAPI: jest.fn(), | ||
| }); | ||
|
|
||
| mockUseFetchState.mockReturnValue([null, false, undefined, jest.fn()]); | ||
|
|
||
| const { result } = testHook(useModelVersionById)(); | ||
|
|
||
| await waitFor(() => { | ||
| const [data, , error] = result.current; | ||
| expect(data).toBeNull(); | ||
| expect(error).toBeUndefined(); | ||
| }); | ||
| }); |
There was a problem hiding this comment.
Same issue — useFetchState is mocked to return [null, false, undefined, …], then you assert data is null and error is undefined. This just validates the mock, not the hook.
To genuinely test the !modelVersionId branch, capture the callback and check:
const cb = mockUseFetchState.mock.calls[0][0];
await expect(cb({})).rejects.toThrow('No model version id');| it('should fetch the model version when API is available and id is provided', async () => { | ||
| const mockedVersion = mockModelVersion({ id: 'version-1', name: 'my-version' }); | ||
|
|
||
| mockUseModelRegistryAPI.mockReturnValue({ | ||
| api: { | ||
| ...mockModelRegistryAPIs, | ||
| getModelVersion: jest.fn().mockResolvedValue(mockedVersion), | ||
| }, | ||
| apiAvailable: true, | ||
| refreshAllAPI: jest.fn(), | ||
| }); | ||
|
|
||
| mockUseFetchState.mockReturnValue([mockedVersion, true, undefined, jest.fn()]); | ||
|
|
||
| const { result } = testHook(useModelVersionById)('version-1'); | ||
|
|
||
| await waitFor(() => { | ||
| const [data, loaded] = result.current; | ||
| expect(loaded).toBe(true); | ||
| expect(data).toEqual(mockedVersion); |
There was a problem hiding this comment.
Also tautological — asserts data and loaded equal exactly what mockUseFetchState was told to return. The getModelVersion mock is set up but never called.
This test can be removed entirely; test 4 already covers the happy path by actually invoking the captured callback and verifying getModelVersion receives the right args.
| }); | ||
|
|
||
| it('should pass the correct modelVersionId to api.getModelVersion', async () => { | ||
| const getModelVersionMock = jest.fn().mockResolvedValue(mockModelVersion({ id: 'v-42' })); | ||
|
|
||
| mockUseModelRegistryAPI.mockReturnValue({ | ||
| api: { ...mockModelRegistryAPIs, getModelVersion: getModelVersionMock }, | ||
| apiAvailable: true, | ||
| refreshAllAPI: jest.fn(), | ||
| }); | ||
|
|
||
| // Capture the callback that the hook passes to useFetchState | ||
| mockUseFetchState.mockReturnValue([null, false, undefined, jest.fn()]); | ||
|
|
||
| testHook(useModelVersionById)('v-42'); | ||
|
|
||
| // useFetchState receives the callback as its first argument | ||
| const capturedCallback = mockUseFetchState.mock.calls[0][0] as ( | ||
| opts: unknown, | ||
| ) => Promise<unknown>; | ||
|
|
||
| await capturedCallback({}); | ||
|
|
||
| expect(getModelVersionMock).toHaveBeenCalledWith({}, 'v-42'); |
There was a problem hiding this comment.
This is the only test that genuinely exercises hook logic — nice. Consider reusing the same callback-capture approach for the !apiAvailable and !modelVersionId branches so all three paths are properly covered.
Signed-off-by: Yulia Krimerman <juliapiterova@hotmail.com>
manaswinidas
left a comment
There was a problem hiding this comment.
/lgtm
/approve
All review comments addressed
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: manaswinidas The full list of commands accepted by this bot can be found here. The pull request process is described here DetailsNeeds approval from an approver in each of these files:
Approvers can indicate their approval by writing |
* add unit tests Signed-off-by: Yulia Krimerman <juliapiterova@hotmail.com> * addressed comments Signed-off-by: Yulia Krimerman <juliapiterova@hotmail.com> --------- Signed-off-by: Yulia Krimerman <juliapiterova@hotmail.com>
Description
Adds unit tests for the
useModelVersionByIdhook (clients/ui/frontend/src/app/hooks/useModelVersionById.ts), which previously had no test coverage.The test file covers four scenarios:
apiAvailableisfalsenull, no error) when called without an IDModelVersionandloaded: trueuseFetchStateand assertsapi.getModelVersionis called with the correctmodelVersionIdFollows the same testing patterns established by
useModelArtifactsByVersionId.spec.tsanduseModelTransferJobs.spec.ts.How Has This Been Tested?
npx jest src/app/hooks/__tests__/useModelVersionById.spec.tsMerge criteria:
All the commits have been signed-off (To pass the
DCOcheck)The commits have meaningful messages
Automated tests are provided as part of the PR for major new functionalities; testing instructions have been added in the PR body (for PRs involving changes that are not immediately obvious).
The developer has manually tested the changes and verified that the changes work.
Code changes follow the kubeflow contribution guidelines.
For first time contributors: Please reach out to the Reviewers to ensure all tests are being run, ensuring the label
ok-to-testhas been added to the PR.