Skip to content
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

핵심기능 E2E 테스트 - 템플릿, 인증/인가 #647

Merged
merged 26 commits into from
Sep 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
09c5619
feat(e2eTests): 템플릿 관련 핵심기능 E2E 테스트 작성
Jaymyong66 Sep 15, 2024
195b782
chore: jest.config - testIgnorePattern에 e2eTests 폴더만 명시적으로 적용
Jaymyong66 Sep 15, 2024
641304e
refactor(e2eTests): waitForSuccess 유틸함수를 활용, 파일명 오타 수정(공백제거_
Jaymyong66 Sep 19, 2024
bbd8417
refactor(e2eTests): templates 관련 공통 로직을 actions 파일로 분리
Jaymyong66 Sep 19, 2024
c7c2d8d
refactor(e2eTests): templates - Locator를 의미있는 네이밍을 가진 변수에 할당
Jaymyong66 Sep 19, 2024
dc9f86e
refactor(e2eTests): templates - 템플릿 업로드 action에서 요청 success, redirect…
Jaymyong66 Sep 19, 2024
ffa04e8
refactor(e2eTests): utill - waitForSuccess에 201 status 추가, login 요청 s…
Jaymyong66 Sep 19, 2024
691f355
refactor(e2eTests): templates - 수정을 위한 템플릿 생성 케이스 제거, 테스트 변수명 변경
Jaymyong66 Sep 19, 2024
8f57161
refactor(e2eTests): 테스트에 불필요한 click 이벤트 제거
Jaymyong66 Sep 19, 2024
ee0c2f5
Merge branch 'dev/fe' of https://github.com/woowacourse-teams/2024-co…
Jaymyong66 Sep 20, 2024
33e4190
refactor(e2eTests): templates - waitForSuccess의 인자 변수명을 apiUrl로 변경
Jaymyong66 Sep 20, 2024
2108363
refactor(e2eTests): 테스트 아이디 환경변수 적용
Jaymyong66 Sep 20, 2024
4d6a1f1
refactor(e2eTests): templates - 템플릿 업로드 전 카테고리 목록 요청 응답을 기다리도록 변경
Jaymyong66 Sep 20, 2024
288f483
feat(playwright): 테스트 전 로그인을 authentication page context로 저장
Jaymyong66 Sep 20, 2024
1e0b106
refactor(playwright): e2eTests -> playwright로 폴더 변경, 로그인 beforeEach 제거
Jaymyong66 Sep 20, 2024
f417b61
refactor(tests): authentication - 로그인 테스트 제거
Jaymyong66 Sep 20, 2024
77b1a5b
feat(tests): category, search - 테스트 전, page 이동
Jaymyong66 Sep 20, 2024
3ff4404
chore: package.json - e2e 관련 스크립트 추가
Jaymyong66 Sep 20, 2024
6b4f993
chore: jest.config - CI에서 playwright 제외
Jaymyong66 Sep 20, 2024
5eefd65
refactor(tests): templates.actions - categories waitForSuccess 오류를 wa…
Jaymyong66 Sep 20, 2024
262d293
refactor(tests): search 테스트에서 검색 테스트의 키워드 '테스트'=>'검색테스트'로 변경
Hain-tain Sep 20, 2024
2a6c8b1
refactor(tests): templates - 테스트로 만들어진 템플릿 삭제 처리
Jaymyong66 Sep 20, 2024
8a3c479
refactor(tests): templates - 생성하는 템플릿 정보에 테스트 브라우저 환경 추가
Jaymyong66 Sep 20, 2024
ad02ef6
Merge branch 'feat/636-e2e-init' of https://github.com/woowacourse-te…
Jaymyong66 Sep 20, 2024
a14702f
refactor(playwright): templates - 테스트 중 에러 발생 시, 생성한 템플릿 제거를 finally로 처리
Jaymyong66 Sep 20, 2024
d968b6e
refactor(playwright): category - 테스트 중 에러 발생 시, 생성한 템플릿 제거를 finally로 처리
Jaymyong66 Sep 20, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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",
Comment on lines +8 to +9
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

굿굿! 스크립트 추가하니까 훨씬 편하고 좋네요! 👍

"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 });
});
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();
}
});
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