Skip to content

Commit

Permalink
Add basic tests for admin panel mange role pages (#179)
Browse files Browse the repository at this point in the history
  • Loading branch information
byn9826 authored Oct 9, 2024
1 parent bdb9aca commit 23e699b
Show file tree
Hide file tree
Showing 18 changed files with 2,653 additions and 81 deletions.
1 change: 1 addition & 0 deletions .github/workflows/pr-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,4 @@ jobs:
- run: cd ./server && npm run test:check:node-key-rotate
- run: cd ./server && npm run node:build
- run: cd ./admin-panel && npm run build
- run: cd ./admin-panel && npm run test:check
110 changes: 110 additions & 0 deletions admin-panel/app/[lang]/roles/[id]/page.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import {
fireEvent, screen,
} from '@testing-library/react'
import {
describe, it, expect, vi, beforeEach, Mock,
} from 'vitest'
import Page from 'app/[lang]/roles/[id]/page'
import { roles } from 'tests/roleMock'
import { render } from 'vitest.setup'
import {
useGetApiV1RolesByIdQuery,
usePutApiV1RolesByIdMutation,
useDeleteApiV1RolesByIdMutation,
} from 'services/auth/api'

vi.mock(
'next/navigation',
() => ({
useParams: vi.fn().mockReturnValue({ id: '2' }),
useRouter: vi.fn().mockReturnValue({ push: () => {} }),
}),
)

vi.mock(
'services/auth/api',
() => ({
useGetApiV1RolesByIdQuery: vi.fn(),
usePutApiV1RolesByIdMutation: vi.fn(),
useDeleteApiV1RolesByIdMutation: vi.fn(),
}),
)

const mockUpdate = vi.fn()
const mockDelete = vi.fn()
describe(
'Page Component',
() => {
beforeEach(() => {
(useGetApiV1RolesByIdQuery as Mock).mockReturnValue({ data: { role: roles[1] } });
(usePutApiV1RolesByIdMutation as Mock).mockReturnValue([mockUpdate, { isLoading: false }]);
(useDeleteApiV1RolesByIdMutation as Mock).mockReturnValue([mockDelete, { isLoading: false }])
})

it(
'render role',
async () => {
render(<Page />)

const nameInput = screen.queryByTestId('nameInput') as HTMLInputElement
const noteInput = screen.queryByTestId('noteInput') as HTMLInputElement
const saveBtn = screen.queryByTestId('saveButton') as HTMLButtonElement
const deleteBtn = screen.queryByTestId('deleteButton')
expect(nameInput?.value).toBe(roles[1].name)
expect(noteInput?.value).toBe(roles[1].note)
expect(saveBtn?.disabled).toBeTruthy()
expect(deleteBtn).toBeInTheDocument()
},
)

it(
'update role',
async () => {
render(<Page />)

const nameInput = screen.queryByTestId('nameInput') as HTMLInputElement
const noteInput = screen.queryByTestId('noteInput') as HTMLInputElement
const saveBtn = screen.queryByTestId('saveButton') as HTMLButtonElement

fireEvent.change(
nameInput,
{ target: { value: 'new name' } },
)
fireEvent.change(
noteInput,
{ target: { value: 'new note' } },
)

expect(nameInput?.value).toBe('new name')
expect(noteInput?.value).toBe('new note')
expect(saveBtn?.disabled).toBeFalsy()
fireEvent.click(saveBtn)

expect(mockUpdate).toHaveBeenLastCalledWith({
id: 2,
putRoleReq: {
name: 'new name',
note: 'new note',
},
})
},
)

it(
'delete role',
async () => {
render(<Page />)

const deleteBtn = screen.queryByTestId('deleteButton') as HTMLButtonElement
expect(screen.queryByRole('dialog')).not.toBeInTheDocument()

fireEvent.click(deleteBtn)
expect(screen.queryByRole('dialog')).toBeInTheDocument()

fireEvent.click(screen.queryByTestId('confirmButton') as HTMLButtonElement)

expect(mockDelete).toHaveBeenLastCalledWith({ id: 2 })
},
)
},
)
2 changes: 2 additions & 0 deletions admin-panel/app/[lang]/roles/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ const Page = () => {
<Table.Cell>{t('roles.name')}</Table.Cell>
<Table.Cell>
<TextInput
data-testid='nameInput'
onChange={(e) => onChange(
'name',
e.target.value,
Expand All @@ -85,6 +86,7 @@ const Page = () => {
<Table.Cell>{t('common.note')}</Table.Cell>
<Table.Cell>
<TextInput
data-testid='noteInput'
onChange={(e) => onChange(
'note',
e.target.value,
Expand Down
72 changes: 72 additions & 0 deletions admin-panel/app/[lang]/roles/new/page.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import {
fireEvent, screen,
} from '@testing-library/react'
import {
describe, it, expect, vi, beforeEach, Mock,
} from 'vitest'
import Page from 'app/[lang]/roles/new/page'
import { render } from 'vitest.setup'
import { usePostApiV1RolesMutation } from 'services/auth/api'

vi.mock(
'next/navigation',
() => ({ useRouter: vi.fn().mockReturnValue({ push: () => {} }) }),
)

vi.mock(
'services/auth/api',
() => ({ usePostApiV1RolesMutation: vi.fn() }),
)

const mockCreate = vi.fn().mockReturnValue({ data: { role: { id: 1 } } })
describe(
'Page Component',
() => {
beforeEach(() => {
(usePostApiV1RolesMutation as Mock).mockReturnValue([mockCreate, { isLoading: false }])
})

it(
'render page',
async () => {
render(<Page />)

const nameInput = screen.queryByTestId('nameInput') as HTMLInputElement
const noteInput = screen.queryByTestId('noteInput') as HTMLInputElement
const saveBtn = screen.queryByTestId('saveButton') as HTMLButtonElement
expect(nameInput?.value).toBe('')
expect(noteInput?.value).toBe('')
expect(saveBtn).toBeInTheDocument()
},
)

it(
'create role',
async () => {
render(<Page />)

const nameInput = screen.queryByTestId('nameInput') as HTMLInputElement
const noteInput = screen.queryByTestId('noteInput') as HTMLInputElement
const saveBtn = screen.queryByTestId('saveButton') as HTMLButtonElement

fireEvent.change(
nameInput,
{ target: { value: 'new name' } },
)
fireEvent.change(
noteInput,
{ target: { value: 'new note' } },
)

fireEvent.click(saveBtn)

expect(mockCreate).toHaveBeenLastCalledWith({
postRoleReq: {
name: 'new name',
note: 'new note',
},
})
},
)
},
)
5 changes: 4 additions & 1 deletion admin-panel/app/[lang]/roles/new/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,18 +55,21 @@ const Page = () => {
<Table.Cell>{t('roles.name')}</Table.Cell>
<Table.Cell>
<TextInput
data-testid='nameInput'
onChange={(e) => onChange(
'name',
e.target.value,
)}
value={values.name} />
value={values.name}
/>
{showErrors && <FieldError error={errors.name} />}
</Table.Cell>
</Table.Row>
<Table.Row>
<Table.Cell>{t('common.note')}</Table.Cell>
<Table.Cell>
<TextInput
data-testid='noteInput'
onChange={(e) => onChange(
'note',
e.target.value,
Expand Down
47 changes: 47 additions & 0 deletions admin-panel/app/[lang]/roles/page.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import {
describe, it, expect, vi, beforeEach, Mock,
} from 'vitest'
import {
waitFor, screen,
} from '@testing-library/react'
import { render } from '../../../vitest.setup'
import Page from 'app/[lang]/roles/page'
import { roles } from 'tests/roleMock'
import { useGetApiV1RolesQuery } from 'services/auth/api'

vi.mock(
'services/auth/api',
() => ({ useGetApiV1RolesQuery: vi.fn() }),
)

describe(
'Page Component',
() => {
beforeEach(() => {
(useGetApiV1RolesQuery as Mock).mockReturnValue({ data: { roles } })
})

it(
'render roles',
async () => {
render(<Page />)

await waitFor(() => {
const rows = screen.queryAllByTestId('roleRow')
expect(rows.length).toBe(2)
expect(rows[0].querySelector('td')?.innerHTML).toContain(roles[0].name)
const editLinks = rows[0].querySelector('td')?.getElementsByTagName('a')
expect(editLinks?.length).toBe(0)

expect(rows[1].querySelector('td')?.innerHTML).toContain(roles[1].name)
const editLinks1 = rows[1].querySelector('td')?.getElementsByTagName('a')
expect(editLinks1?.length).toBe(1)
expect(editLinks1?.[0].getAttribute('href')).toBe('/en/roles/2')

const createButton = screen.getByTestId('createButton')
expect(createButton.getAttribute('href')).toBe('/en/roles/new')
})
},
)
},
)
4 changes: 3 additions & 1 deletion admin-panel/app/[lang]/roles/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,9 @@ const Page = () => {
</Table.Head>
<Table.Body className='divide-y md:hidden'>
{roles.map((role) => (
<Table.Row key={role.id}>
<Table.Row
key={role.id}
data-testid='roleRow'>
<Table.Cell>
<section className='flex justify-between items-center'>
<div className='flex flex-col gap-2'>
Expand Down
1 change: 0 additions & 1 deletion admin-panel/app/api/v1/roles/[id]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ export async function PUT (
const id = context.params.id

const reqBody = await request.json()
console.log(reqBody)
if (!reqBody) return throwForbiddenError()

return sendS2SRequest({
Expand Down
1 change: 1 addition & 0 deletions admin-panel/components/ConfirmModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const ConfirmModal = ({
<Modal.Header>{title}</Modal.Header>
<Modal.Footer>
<Button
data-testid='confirmButton'
color='failure'
onClick={onConfirm}>
{confirmButtonText || t('common.deleteConfirmBtn')}
Expand Down
1 change: 1 addition & 0 deletions admin-panel/components/CreateButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const CreateButton = ({ href }: {
color='gray'
href={href}
size='sm'
data-testid='createButton'
>
<div className='flex items-center gap-2'>
<PlusIcon className='w-4 h-4' />
Expand Down
1 change: 1 addition & 0 deletions admin-panel/components/DeleteButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ const DeleteButton = ({
confirmButtonText={buttonText}
/>
<Button
data-testid='deleteButton'
disabled={isLoading || disabled}
className={className}
onClick={handleClick}
Expand Down
4 changes: 3 additions & 1 deletion admin-panel/components/EditLink.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ const EditLink = ({ href }: {
as={Link}
href={href}
color='gray'
size='sm'>
size='sm'
data-testid='editLink'
>
<PencilSquareIcon className='w-4 h-4' />
</Button>
)
Expand Down
1 change: 1 addition & 0 deletions admin-panel/components/SaveButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const SaveButton = ({

return (
<Button
data-testid='saveButton'
disabled={disabled || isLoading}
className={className}
onClick={onClick}
Expand Down
Loading

0 comments on commit 23e699b

Please sign in to comment.