Skip to content

Commit

Permalink
Merge pull request #647 from woowacourse-teams/feat/636-e2e-init
Browse files Browse the repository at this point in the history
핵심기능 E2E 테스트 - 템플릿, 인증/인가
  • Loading branch information
vi-wolhwa authored Sep 23, 2024
2 parents daeca6f + d968b6e commit f64ad48
Show file tree
Hide file tree
Showing 14 changed files with 384 additions and 144 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
### Environment Variable ###
.env

### playwright authentication context
.auth

*.crt
*.csr
*.key
Expand Down
95 changes: 0 additions & 95 deletions frontend/e2eTests/category.spec.ts

This file was deleted.

32 changes: 0 additions & 32 deletions frontend/e2eTests/utils.ts

This file was deleted.

2 changes: 1 addition & 1 deletion frontend/jest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const config: Config = {
'react-syntax-highlighter/dist/esm': 'react-syntax-highlighter/dist/cjs',
},
transformIgnorePatterns: ['/node_modules/(?!react-syntax-highlighter)'],
testPathIgnorePatterns: ['/node_modules/', '/e2eTests/', '/tests-examples/'],
testPathIgnorePatterns: ['/playwright/'],
};

export default config;
2 changes: 2 additions & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
"main": "index.js",
"scripts": {
"test": "jest",
"e2e": "playwright test",
"e2e:ui": "playwright test --ui",
"dev": "webpack-dev-server --config webpack.dev.js --open",
"tsc": "tsc --noEmit",
"build": "webpack --mode production --config webpack.prod.js",
Expand Down
12 changes: 8 additions & 4 deletions frontend/playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ dotenv.config({ path: './.env.development' });
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
testDir: './e2eTests',
testDir: './playwright',
/* Run tests in files in parallel */
fullyParallel: true,
/* Fail the build on CI if you accidentally left test.only in the source code. */
Expand All @@ -34,19 +34,23 @@ export default defineConfig({

/* Configure projects for major browsers */
projects: [
{ name: 'setup', testMatch: /.*\.setup\.ts/ },
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
use: { ...devices['Desktop Chrome'], storageState: 'playwright/.auth/user.json' },
dependencies: ['setup'],
},

{
name: 'firefox',
use: { ...devices['Desktop Firefox'] },
use: { ...devices['Desktop Firefox'], storageState: 'playwright/.auth/user.json' },
dependencies: ['setup'],
},

{
name: 'webkit',
use: { ...devices['Desktop Safari'] },
use: { ...devices['Desktop Safari'], storageState: 'playwright/.auth/user.json' },
dependencies: ['setup'],
},

/* Test against mobile viewports. */
Expand Down
20 changes: 20 additions & 0 deletions frontend/playwright/tests/auth.setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { test as setup } from '@playwright/test';
import path from 'path';

const authFile = path.join(__dirname, '../.auth/user.json');

setup('authenticate', async ({ page }) => {
const username = process.env.PLAYWRIGHT_TEST_USERNAME || '';
const password = process.env.PLAYWRIGHT_TEST_PASSWORD || '';

await page.goto('/');
await page.getByRole('button', { name: '로그인', exact: true }).click();
await page.locator('input[type="text"]').fill(username);
await page.locator('input[type="text"]').press('Tab');
await page.locator('input[type="password"]').fill(password);
await page.locator('form').getByRole('button', { name: '로그인' }).click();

await page.waitForURL('/my-templates');

await page.context().storageState({ path: authFile });
});
File renamed without changes.
109 changes: 109 additions & 0 deletions frontend/playwright/tests/category.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import { test, expect } from '@playwright/test';

import { createCategory, deleteCategory, getCategoryButton } from './category.actions';
import { waitForSuccess } from './utils';

test('카테고리 편집 모달에서 새 카테고리를 추가 및 삭제할 수 있다.', async ({ page, browserName }) => {
await page.goto('/my-templates');

const newCategoryName = `생성테스트-${browserName}`;

try {
await createCategory({ page, categoryName: newCategoryName });

await waitForSuccess({ page, apiUrl: '/categories' });

const newCategoryButton = getCategoryButton({ page, categoryName: newCategoryName });

await expect(newCategoryButton).toBeVisible();
} catch (error) {
throw Error(error);
} finally {
await deleteCategory({ page, categoryName: newCategoryName });

await waitForSuccess({ page, apiUrl: '/categories' });

const newCategoryButton = getCategoryButton({ page, categoryName: newCategoryName });

await expect(newCategoryButton).not.toBeVisible();
}
});

test('카테고리 편집 모달에서 카테고리명을 수정 및 삭제할 수 있다.', async ({ page, browserName }) => {
await page.goto('/my-templates');

const newCategoryName = `수정테스트-${browserName}`;
const editedCategoryName = `수정완료-${browserName}`;

try {
// 수정할 카테고리 생성
await createCategory({ page, categoryName: newCategoryName });

await waitForSuccess({ page, apiUrl: '/categories' });

const newCategoryButton = getCategoryButton({ page, categoryName: newCategoryName });

await expect(newCategoryButton).toBeVisible();

// 카테고리 수정
await page.getByRole('button', { name: '카테고리 편집' }).click();

const newCategoryInEditModal = page.getByText(newCategoryName).nth(1);

await newCategoryInEditModal.hover();
await page.getByRole('button', { name: '카테고리 이름 변경' }).click();
await page.getByPlaceholder('카테고리 입력').click();
await page.getByPlaceholder('카테고리 입력').fill(editedCategoryName);
await page.getByRole('button', { name: '저장' }).click();

const editedCategoryButton = getCategoryButton({ page, categoryName: editedCategoryName });

await expect(editedCategoryButton).toBeVisible();
} catch (error) {
throw Error(error);
} finally {
// 다음 테스트를 위해 테스트용 카테고리 삭제
await deleteCategory({ page, categoryName: editedCategoryName });

const editedCategoryButton = getCategoryButton({ page, categoryName: editedCategoryName });

await waitForSuccess({ page, apiUrl: '/categories' });
await expect(editedCategoryButton).not.toBeVisible();
}
});

test('카테고리는 최대 15글자까지만 입력할 수 있다.', async ({ page, browserName }) => {
await page.goto('/my-templates');
const rawCategoryName = `최대글자수테스트-${browserName}`;
const expectedCategoryName = rawCategoryName.slice(0, 15);

try {
await page.getByRole('button', { name: '카테고리 편집' }).click();
await page.getByRole('button', { name: '+ 카테고리 추가' }).click();
const categoryInput = page.getByPlaceholder('카테고리 입력');

await categoryInput.click();

for (const char of rawCategoryName) {
await page.keyboard.type(char);
}

await page.getByRole('button', { name: '저장' }).click();

await waitForSuccess({ page, apiUrl: '/categories' });

const newCategoryButton = getCategoryButton({ page, categoryName: expectedCategoryName });

await expect(newCategoryButton).toBeVisible();
} catch (error) {
throw Error(error);
} finally {
// 다음 테스트를 위해 테스트용 카테고리 삭제
await deleteCategory({ page, categoryName: expectedCategoryName });

const newCategoryButton = getCategoryButton({ page, categoryName: expectedCategoryName });

await waitForSuccess({ page, apiUrl: '/categories' });
await expect(newCategoryButton).not.toBeVisible();
}
});
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,26 +1,24 @@
import { test, expect } from '@playwright/test';

import { searchTemplates } from './search.actions';
import { loginToCodezap, waitForSuccess } from './utils';

test.beforeEach(async ({ page }) => {
await loginToCodezap({
page,
id: process.env.PLAYWRIGHT_TEST_ID || '',
password: process.env.PLAYWRIGHT_TEST_PASSWORD || '',
});
});
import { waitForSuccess } from './utils';

test('검색창에 `검색테스트`를 입력하면 `검색테스트`가 내용에 포함된 템플릿 목록을 확인할 수 있다.', async ({
page,
}) => {
await page.goto('/my-templates');

test('검색창에 `테스트`를 입력하면 `테스트`가 내용에 포함된 템플릿 목록을 확인할 수 있다.', async ({ page }) => {
const keyword = '테스트';
const keyword = '검색테스트';

await searchTemplates({ page, keyword });

await waitForSuccess({ page, apiUrl: '/templates?keyword' });
await expect(page.getByRole('link', { name: /테스트/ })).toBeVisible();
await expect(page.getByRole('link', { name: /검색테스트/ })).toBeVisible();
});

test('검색창에 `ㅁㅅㅌㅇ`를 입력할 경우 `검색 결과가 없습니다`가 나온다.', async ({ page }) => {
await page.goto('/my-templates');

const keyword = 'ㅁㅅㅌㅇ';

await searchTemplates({ page, keyword });
Expand Down
Loading

0 comments on commit f64ad48

Please sign in to comment.