Skip to content

✨ [FEAT] 새소식 페이지 테스트 작성 #414

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

Open
wants to merge 7 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 3 additions & 1 deletion app/[locale]/community/news/[id]/NewsViewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ export default async function NewsViewer({ news }: NewsPostPageProps) {
wrapperClassName="mb-10"
/>
<StraightNode />
<Tags tags={news.tags} margin="mt-3 ml-6" searchPath={newsPath} />
<div id="news-post-tags">
<Tags tags={news.tags} margin="mt-3 ml-6" searchPath={newsPath} />
</div>
<PostFooter
post={news}
id={news.id.toString()}
Expand Down
2 changes: 1 addition & 1 deletion components/common/search/SelectedTags.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export default function SelectedTags({ tags, search, disabled }: SelectedTagsPro
};

return (
<div className="flex items-start justify-between gap-3 px-2.5">
<div id="selected-tags" className="flex items-start justify-between gap-3 px-2.5">
<Tags
tags={isTagExist ? tags : ['전체']}
onDelete={isTagExist ? deleteTag : undefined}
Expand Down
1 change: 1 addition & 0 deletions components/common/search/TagFilter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export default function TagFilter({ tags, selectedTags, disabled, searchTags }:
<div>
<h5 className="mb-3 mr-6 whitespace-nowrap text-md font-bold tracking-wide">{t('태그')}</h5>
<div
id="tag-filter"
className={`grid gap-x-7 gap-y-2.5 pl-2.5`}
{...useStyle(
(style) => {
Expand Down
13 changes: 13 additions & 0 deletions e2e/fixtures/pages.fixture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,17 @@

import { Page } from '@playwright/test';

import { NewsCreatePage } from '../pages/community/news/create.page';
import { NewsPage } from '../pages/community/news/index.page';
import { NoticeCreatePage } from '../pages/community/notice/create.page';
import { NoticePage } from '../pages/community/notice/index.page';
import { test as base } from './role.fixture';

type PagesFixtures = {
noticePage: NoticePage;
noticeCreatePage: NoticeCreatePage;
newsPage: NewsPage;
newsCreatePage: NewsCreatePage;
};

export const test = base.extend<PagesFixtures>({
Expand All @@ -22,4 +26,13 @@ export const test = base.extend<PagesFixtures>({
) => {
await use(new NoticeCreatePage(page));
},
newsPage: async ({ page }: { page: Page }, use: (page: NewsPage) => Promise<void>) => {
await use(new NewsPage(page));
},
newsCreatePage: async (
{ page }: { page: Page },
use: (page: NewsCreatePage) => Promise<void>,
) => {
await use(new NewsCreatePage(page));
},
});
31 changes: 31 additions & 0 deletions e2e/pages/community/news/create.page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import type { Locator, Page } from '@playwright/test';

export class NewsCreatePage {
readonly page: Page;
readonly titleInput: Locator;
readonly contentEditor: Locator;
readonly submitButton: Locator;

constructor(page: Page) {
this.page = page;
this.titleInput = page.getByPlaceholder('제목을 입력하세요.');
this.contentEditor = page.locator('div.sun-editor-editable');
this.submitButton = page.getByRole('button', { name: /게시/ });
}

async goto() {
await this.page.goto('/community/news/create');
}

async fillTitle(title: string) {
await this.titleInput.fill(title);
}

async fillContent(content: string) {
await this.contentEditor.fill(content);
}

async clickSubmitButton() {
await this.submitButton.click();
}
}
49 changes: 49 additions & 0 deletions e2e/pages/community/news/index.page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import type { Locator, Page } from '@playwright/test';

export const TAGS = [
'행사',
'연구',
'수상',
'채용',
'칼럼',
'강연',
'교육',
'인터뷰',
'진로',
'과거 미분류',
];

export class NewsPage {
readonly page: Page;
readonly newPostButton: Locator;
readonly tagFilterBox: Locator;
readonly selectedTags: Locator;

constructor(page: Page) {
this.page = page;
this.newPostButton = page.getByRole('button', { name: '새 게시글' });
this.tagFilterBox = page.locator('#tag-filter');
this.selectedTags = page.locator('#selected-tags');
}

async goto() {
await this.page.goto('/community/news');
}

async clickNewPostButton() {
await this.newPostButton.click();
}

async clickTag(tagName: string) {
await this.tagFilterBox.locator(`label[for="${tagName}"]`).click();
}

// To click the close button of the selected tag. (It shows as 'X' in the UI)
async removeTag(tagName: string) {
await this.selectedTags.locator(`span:has-text("${tagName}") button`).click();
}

async resetTags() {
await this.selectedTags.locator('button:has-text("태그 초기화")').click();
}
}
67 changes: 67 additions & 0 deletions e2e/tests/community/news.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { expect } from '@playwright/test';

import { test } from '../../fixtures';
import { TAGS } from '../../pages/community/news/index.page';

test.describe('News', () => {
test('should allow STAFF to create a new news post with tags', async ({
page,
loginAs,
newsPage,
newsCreatePage,
}) => {
// 1. Arrange
await newsPage.goto();
const newsTitle = `[Test] New News - ${Date.now()}`;
const newsContent = 'This is a test news content.';
const selectedTagsBox = page.locator('.flex.flex-wrap.items-center.gap-2\\.5.mt-3.ml-6');
await loginAs('STAFF');

// 2. Act
await newsPage.clickNewPostButton();
await expect(page).toHaveURL('/community/news/create');
await newsCreatePage.fillTitle(newsTitle);
await newsCreatePage.fillContent(newsContent);

// 태그 선택
await newsCreatePage.page.click(`label[for="${TAGS[0]}"]`);
await newsCreatePage.page.click(`label[for="${TAGS[1]}"]`);

await page.waitForTimeout(1000);
await newsCreatePage.clickSubmitButton();

// 3. Assert
await expect(page.getByText(newsTitle).first()).toBeVisible();
await expect(selectedTagsBox.getByText(TAGS[0])).toBeVisible();
await expect(selectedTagsBox.getByText(TAGS[1])).toBeVisible();

// To check the post is visible in the news list with selected tags
await newsPage.goto();
await newsPage.clickTag(TAGS[0]);
await newsPage.clickTag(TAGS[1]);

await expect(page.getByText(newsTitle)).toBeVisible();
});

test('should allow basic user to remove selected tags and reset all tags', async ({
page,
newsPage,
}) => {
await newsPage.goto();

const selectedTagsBox = page.locator('#selected-tags');

for (const tag of TAGS.slice(0, 3)) {
await newsPage.clickTag(tag);
await expect(selectedTagsBox.getByText(tag)).toBeVisible();
}

await newsPage.removeTag(TAGS[0]);
await expect(selectedTagsBox.getByText(TAGS[0])).not.toBeVisible();

await newsPage.resetTags();
for (const tag of TAGS.slice(1, 3)) {
await expect(selectedTagsBox.getByText(tag)).not.toBeVisible();
}
});
});