Skip to content

Commit

Permalink
Write login page test
Browse files Browse the repository at this point in the history
 (#102)
  • Loading branch information
kimurash committed Oct 30, 2024
1 parent e6bb415 commit e0b9bf4
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 12 deletions.
30 changes: 19 additions & 11 deletions frontend/test/helpers/wrapper.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { MantineProvider } from '@mantine/core';
import { Notifications } from '@mantine/notifications';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { render } from '@testing-library/react';
import { render, RenderOptions } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { ReactElement } from 'react';
import { ReactElement, ReactNode } from 'react';

export const renderWithWrapper = (children: ReactElement) => {
const wrappper = ({ children }: { children: ReactNode }) => {
const queryClient = new QueryClient({
defaultOptions: {
queries: {
Expand All @@ -15,15 +15,23 @@ export const renderWithWrapper = (children: ReactElement) => {
},
},
});

return (
<QueryClientProvider client={queryClient}>
<MantineProvider>
<Notifications />
{children}
</MantineProvider>
</QueryClientProvider>
);
};

export const customRender = (
ui: ReactElement,
options?: Omit<RenderOptions, 'wrapper'>,
) => {
return {
user: userEvent.setup(),
...render(
<QueryClientProvider client={queryClient}>
<MantineProvider>
<Notifications />
{children}
</MantineProvider>
</QueryClientProvider>,
),
...render(ui, { wrapper: wrappper, ...options }),
};
};
5 changes: 5 additions & 0 deletions frontend/test/mocks/@remix-run/cloudflare.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const redirect = vi
.fn()
.mockImplementation((url: string, init?: number | ResponseInit) => {
return null;
});
99 changes: 98 additions & 1 deletion frontend/test/routes/auth.login.test.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,123 @@
import type * as remixruncloudflare from '@remix-run/cloudflare';
import { ActionFunctionArgs, LoaderFunctionArgs } from '@remix-run/cloudflare';
import { createRemixStub } from '@remix-run/testing';
import { screen } from '@testing-library/react';
import LoginPage, { action, loader } from '~/routes/auth.login';
import { customRender } from '../helpers/wrapper';
import { redirect } from '../mocks/@remix-run/cloudflare';

vi.mock('@remix-run/cloudflare', async (importOriginal) => {
const actual = await importOriginal<typeof remixruncloudflare>();
return {
...actual,
redirect: (url: string, init?: number | ResponseInit) => {
return redirect(url, init);
},
};
});

const LoginPageStub = createRemixStub([
{
path: '/login',
Component: LoginPage,
async loader({ request }) {
return await loader({ request } as LoaderFunctionArgs);
},
async action({ request }) {
return await action({ request } as ActionFunctionArgs);
},
},
]);

describe('Login page', () => {
it('should login successfully', async () => {
const { user } = customRender(
<LoginPageStub initialEntries={['/login']} />,
);

// メールアドレスを入力
const emailForm = await screen.findByLabelText('メールアドレス');
await user.type(emailForm, 'user@example.com');
expect(emailForm).toHaveValue('user@example.com');

// パスワードを入力
const passwordForm = await screen.findByLabelText('パスワード');
await user.type(passwordForm, 'passw0rd');
expect(passwordForm).toHaveValue('passw0rd');

// ログインボタンをクリック
// ログイン成功の通知が表示される
// prettier-ignore
const submitButton = await screen.findByRole('button', { name: 'ログイン' });
await user.click(submitButton);

// マイページへリダイレクトされる
// prettier-ignore
expect(redirect).toHaveBeenCalledWith(
'/home/mypage',
{
headers: {
'Set-Cookie': expect.any(String),
},
}
);
});

it('should fail to pass when email is invalid', async () => {
const { user } = customRender(
<LoginPageStub initialEntries={['/login']} />,
);

// メールアドレスを入力
const emailForm = await screen.findByLabelText('メールアドレス');
await user.type(emailForm, 'user@invalid');

// ログインボタンをクリック
// prettier-ignore
const submitButton = await screen.findByRole('button', { name: 'ログイン' });
await user.click(submitButton);

// エラーメッセージが表示される
const message = await screen.findByText('有効でないメールアドレスです');
expect(message).toBeInTheDocument();
});

it('should fail to pass when password length is less than 8', async () => {
const { user } = customRender(
<LoginPageStub initialEntries={['/login']} />,
);

// パスワードを入力
const passwordForm = await screen.findByLabelText('パスワード');
await user.type(passwordForm, 'hoge');

// ログインボタンをクリック
// prettier-ignore
const submitButton = await screen.findByRole('button', { name: 'ログイン' });
await user.click(submitButton);

// エラーメッセージが表示される
// prettier-ignore
const message = await screen.findByText('パスワードは8文字以上で入力してください');
expect(message).toBeInTheDocument();
});

it('should fail to pass when password is not alphanumeric', async () => {
const { user } = customRender(
<LoginPageStub initialEntries={['/login']} />,
);

// パスワードを入力
const passwordForm = await screen.findByLabelText('パスワード');
await user.type(passwordForm, 'password');

// ログインボタンをクリック
// prettier-ignore
const submitButton = await screen.findByRole('button', { name: 'ログイン' });
await user.click(submitButton);

// エラーメッセージが表示される
// prettier-ignore
const message = await screen.findByText('パスワードにはアルファベットと数字を含めてください');
expect(message).toBeInTheDocument();
});
});

0 comments on commit e0b9bf4

Please sign in to comment.