-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feat: Implement update user API client and apply it to rename user form #352
Merged
Merged
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
e2526f2
feat: implement update user API client
kanta1207 419485a
fix: fix the function name
kanta1207 ad7ea48
test: test `putUpdateUser` function
kanta1207 d967b4c
refactor: change `username` to `name`
kanta1207 b590bfd
fix: fix profile action to return result Err
kanta1207 5da5de4
test: test profile action
kanta1207 0012bf2
feat: apply action to RenameUserForm
kanta1207 9246983
fix: fix relative path to absolute path
kanta1207 3567782
refactor: add comments and type annotation to action
kanta1207 f99cb51
refactor: refactor params type
kanta1207 491624d
refactor: refactor test file misspell
kanta1207 be22fa7
refactor: remove unnecessary space in test file
kanta1207 5205cf3
refactor: refactor TsDoc comment on `IPutUpdateUserRequestBody`
kanta1207 b2a409c
refactor: remove unnecessary line
kanta1207 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
import { putUpdateUser } from '@/lib/api/user/client'; | ||
|
||
import { Err, Ok } from 'result-ts-type'; | ||
|
||
import { renameUser } from './actions'; | ||
|
||
jest.mock('@/lib/api/user/client', () => ({ | ||
putUpdateUser: jest.fn(), | ||
})); | ||
|
||
// Clear mocks after each test | ||
afterEach(() => { | ||
jest.clearAllMocks(); | ||
}); | ||
|
||
describe('Profile page actions', () => { | ||
describe('renameUser', () => { | ||
// Arrange common mock data | ||
const mockUserId = 'a3kdifut-a520-c2cb-1be7-d90710691861'; | ||
const mockInputs = { | ||
name: 'New Name', | ||
}; | ||
|
||
it('should rename a user successfully', async () => { | ||
// Arrange | ||
(putUpdateUser as jest.Mock).mockResolvedValue(Ok(undefined)); | ||
|
||
// Act | ||
const result = await renameUser(mockUserId, mockInputs); | ||
|
||
// Assert | ||
expect(result.ok).toBeTruthy(); | ||
expect(result.unwrap()).toEqual(undefined); | ||
expect(putUpdateUser).toHaveBeenCalled(); | ||
}); | ||
|
||
it('should return an error if validation fails', async () => { | ||
// Arrange | ||
const mockInvalidInputs = { | ||
name: '', | ||
}; | ||
const mockErrorMessage = 'Validation failed'; | ||
|
||
// Act | ||
const result = await renameUser(mockUserId, mockInvalidInputs); | ||
|
||
// Assert | ||
expect(result.err).toBeTruthy(); | ||
expect(result.unwrapError()).toEqual(mockErrorMessage); | ||
expect(putUpdateUser).not.toHaveBeenCalled(); | ||
}); | ||
|
||
it('should return an error if API request fails', async () => { | ||
// Arrange | ||
// Mock the API request to simulate failure | ||
const mockErrorMessage = 'API request failed'; | ||
(putUpdateUser as jest.Mock).mockResolvedValue(Err(mockErrorMessage)); | ||
|
||
// Act | ||
const result = await renameUser(mockUserId, mockInputs); | ||
|
||
// Assert | ||
expect(result.err).toBeTruthy(); | ||
expect(result.unwrapError()).toEqual(mockErrorMessage); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import { putUpdateUser } from '@/lib/api/user/client'; | ||
import { IUser } from '@/types/definition'; | ||
|
||
import { Err, Ok, Result } from 'result-ts-type'; | ||
|
||
import { renameUserFormSchema, RenameUserInputs } from './schemas'; | ||
|
||
/** | ||
* Validate the inputs and call the API client to rename a user | ||
* @param userId - The ID of the user to rename | ||
* @param inputs - The raw inputs to be validated | ||
* @returns undefined on success, or an error message if the validation or request fails | ||
*/ | ||
export const renameUser = async ( | ||
userId: IUser['id'], | ||
inputs: RenameUserInputs, | ||
): Promise<Result<undefined, string>> => { | ||
const validatedData = renameUserFormSchema.safeParse(inputs); | ||
if (!validatedData.success) return Err('Validation failed'); | ||
const result = await putUpdateUser(userId, { name: validatedData.data.name }); | ||
|
||
if (result.ok) return Ok(undefined); | ||
return Err(result.error); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
import { z } from 'zod'; | ||
|
||
export const renameUserFormSchema = z.object({ | ||
userName: z.string().min(1, { message: 'Name is required' }), | ||
name: z.string().min(1, { message: 'Name is required' }), | ||
}); | ||
|
||
export type RenameUserInputs = z.infer<typeof renameUserFormSchema>; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { putUpdateUser } from './userApiClient.client'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import { request } from '@/lib/api/common/client'; | ||
import { putUpdateUser } from '@/lib/api/user/client'; | ||
|
||
jest.mock('@/lib/api/common/client', () => ({ | ||
request: jest.fn(), | ||
})); | ||
|
||
/** | ||
* Create mock data for request function | ||
* @param mockData | ||
* @returns mocked request function | ||
*/ | ||
const setUpMockSuccessRequest = <T>(mockData: T) => { | ||
return (request as jest.MockedFunction<typeof request>).mockResolvedValue(mockData); | ||
}; | ||
|
||
/** | ||
* Create mock error data for request function | ||
* @param mockData | ||
* @returns mocked request function | ||
*/ | ||
const setUpMockErrorRequest = <T>(mockData: T) => { | ||
return (request as jest.MockedFunction<typeof request>).mockRejectedValue(mockData); | ||
}; | ||
|
||
describe('API Function Tests', () => { | ||
afterEach(() => { | ||
jest.clearAllMocks(); | ||
}); | ||
|
||
describe('putUpdateUser', () => { | ||
// Arrange mock data | ||
const mockUserId = 'a3kdifut-a520-c2cb-1be7-d90710691861'; | ||
const mockRequestBody = { name: 'New name' }; | ||
|
||
it('successfully update user data', async () => { | ||
// mock response,request and expected value | ||
const mockRequest = setUpMockSuccessRequest({}); | ||
|
||
// Act | ||
const result = await putUpdateUser(mockUserId, mockRequestBody); | ||
|
||
// Assert | ||
expect(result.ok).toBeTruthy(); | ||
expect(result.unwrap()).toEqual(undefined); | ||
expect(mockRequest).toHaveBeenCalledWith({ | ||
url: expect.stringContaining(`/users/${mockUserId}`), | ||
method: 'PUT', | ||
options: { | ||
body: JSON.stringify(mockRequestBody), | ||
}, | ||
}); | ||
}); | ||
|
||
it('throws an error on API failure', async () => { | ||
// Arrange mock error and request | ||
const mockError = new Error('API error'); | ||
setUpMockErrorRequest(mockError); | ||
|
||
// Act | ||
const result = await putUpdateUser(mockUserId, mockRequestBody); | ||
|
||
// Assert | ||
expect(result.err).toBeTruthy(); | ||
expect(result.unwrapError()).toEqual(mockError.message); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
'use client'; | ||
|
||
import { request } from '@/lib/api/common/client'; | ||
import { IUser } from '@/types/definition'; | ||
|
||
import { Err, Ok, Result } from 'result-ts-type'; | ||
|
||
const API_BASE_URL = process.env.NEXT_PUBLIC_API_BASE_URL || ''; | ||
|
||
/** | ||
* Interface representing the request body for the function to update user's data. | ||
*/ | ||
interface IPutUpdateUserRequestBody { | ||
/** | ||
* The new name of the user. | ||
*/ | ||
name: IUser['name']; | ||
} | ||
|
||
/** | ||
* Function to update user's data | ||
* @param requestBody - The payload for the function. | ||
*/ | ||
export const putUpdateUser = async ( | ||
userId: IUser['id'], | ||
requestBody: IPutUpdateUserRequestBody, | ||
): Promise<Result<undefined, string>> => { | ||
try { | ||
await request({ | ||
url: `${API_BASE_URL}/users/${userId}`, | ||
method: 'PUT', | ||
options: { body: JSON.stringify(requestBody) }, | ||
}); | ||
return Ok(undefined); | ||
} catch (err) { | ||
if (err instanceof Error) { | ||
return Err(err.message); | ||
} | ||
return Err('API response is invalid'); | ||
} | ||
}; |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you rewrite the TSDoc, please? This is not the official way.
#247
Instead, please add a description to the line right above each property.