Files
sori.studio/tests/playwright/e2e/admin-regressions.spec.js

131 lines
4.5 KiB
JavaScript

import { expect, test } from '@playwright/test'
const adminEmail = 'playwright-admin@example.com'
const adminPassword = 'playwright-admin-password'
/**
* 관리자 화면에 로그인한다.
* @param {import('@playwright/test').Page} page - 브라우저 페이지
* @returns {Promise<void>}
*/
const loginAdmin = async (page) => {
await page.goto('/admin/login')
await page.waitForLoadState('networkidle')
await page.getByLabel('이메일').fill(adminEmail)
await page.locator('input[type="password"]').fill(adminPassword)
await Promise.all([
page.waitForResponse((response) =>
response.url().endsWith('/admin/api/auth/login') && response.status() === 200
),
page.getByRole('button', { name: '로그인', exact: true }).click()
])
await page.waitForURL(/\/admin(?:\/)?$/)
}
/**
* 관리자 API로 태그를 만든다.
* @param {import('@playwright/test').APIRequestContext} request - API 요청 컨텍스트
* @param {{ name: string, slug: string }} tag - 태그 입력값
* @returns {Promise<void>}
*/
const createTag = async (request, tag) => {
const response = await request.post('/admin/api/tags', {
data: {
name: tag.name,
slug: tag.slug,
description: '',
color: '#15171a',
tagType: 'managed'
}
})
expect([200, 409]).toContain(response.status())
}
/**
* 관리자 API로 공개 게시물을 만든다.
* @param {import('@playwright/test').APIRequestContext} request - API 요청 컨텍스트
* @param {Object} post - 게시물 입력값
* @returns {Promise<Object>} 생성된 게시물
*/
const createPublishedPost = async (request, post) => {
const response = await request.post('/admin/api/posts', {
data: {
title: post.title,
slug: post.slug,
content: post.content,
excerpt: '',
featuredImage: null,
showFeaturedImage: false,
status: 'published',
publishedAt: new Date().toISOString(),
tags: post.tags || [],
tagNames: post.tagNames || {}
}
})
expect(response.status()).toBe(200)
return await response.json()
}
test('태그 추천을 선택한 뒤에도 다음 후보를 바로 선택할 수 있다', async ({ page }) => {
await loginAdmin(page)
await createTag(page.request, {
name: 'Regression Recent',
slug: 'regression-recent'
})
await createTag(page.request, {
name: 'Regression Next',
slug: 'regression-next'
})
await createPublishedPost(page.request, {
title: 'Regression Tag Seed',
slug: 'regression-tag-seed',
content: '태그 추천 회귀 테스트용 게시물',
tags: ['regression-recent'],
tagNames: {
'regression-recent': 'Regression Recent'
}
})
await page.goto('/admin/posts/new')
await page.waitForLoadState('networkidle')
await page.getByLabel('태그 추천 목록 열기').click()
await page.getByRole('option', { name: /Regression Recent/ }).click()
await expect(page.getByRole('option', { name: /Regression Next/ })).toBeVisible()
await page.getByRole('option', { name: /Regression Next/ }).click()
await expect(page.getByLabel('Regression Recent 태그 삭제')).toBeVisible()
await expect(page.getByLabel('Regression Next 태그 삭제')).toBeVisible()
})
test('미디어 파생 탭에는 역할 배지가 표시되지 않는다', async ({ page }) => {
await loginAdmin(page)
await page.goto('/admin/media')
await page.waitForLoadState('networkidle')
await page.getByRole('button', { name: '대표 이미지' }).click()
await expect(page.locator('.admin-media__usage-badge')).toHaveCount(0)
await page.getByRole('button', { name: '본문 이미지' }).click()
await expect(page.locator('.admin-media__usage-badge')).toHaveCount(0)
})
test('단일 이미지 size 옵션이 공개 화면과 관리자 미리보기에 반영된다', async ({ page }) => {
await loginAdmin(page)
const post = await createPublishedPost(page.request, {
title: 'Regression Image Width',
slug: 'regression-image-width',
content: '![](https://example.com/playwright-width.png){size=180}'
})
await page.goto('/post/regression-image-width')
const publicImage = page.locator('.prose-image').first()
await expect(publicImage).toHaveCSS('max-width', '180px')
await page.goto(`/admin/posts/${post.id}`)
await page.waitForLoadState('networkidle')
await page.getByLabel('미리보기로 전환').click()
const previewImage = page.locator('.admin-markdown-editor__preview .prose-image').first()
await expect(previewImage).toHaveCSS('max-width', '180px')
})