v1.12.23 대시보드 간소화 및 멤버 작성 이력 탭 추가

This commit is contained in:
2026-10-21 16:37:55 +09:00
parent c8e00c1190
commit 7c95797fd2
18 changed files with 287 additions and 251 deletions

View File

@@ -254,6 +254,11 @@ test('관리자 댓글 조회는 인증·입력 검증과 멤버별 페이지·
expect(first.items[0]).toMatchObject({ body: '회원 답글', parentId: parent.id, postId: post.id, postTitle: post.title, postSlug: post.slug })
const second = await (await adminApi.get(`/admin/api/comments?memberId=${adminUser.userId}&pageSize=1&page=2`)).json()
expect(second.items[0].body).toBe('회원 댓글')
const searched = await (await adminApi.get(`/admin/api/comments?memberId=${adminUser.userId}&q=${encodeURIComponent('회원 답글')}`)).json()
expect(searched.pagination.total).toBe(1)
expect(searched.items[0].body).toBe('회원 답글')
const literal = await (await adminApi.get(`/admin/api/comments?memberId=${adminUser.userId}&q=%25`)).json()
expect(literal.items).toEqual([])
const last = await (await adminApi.get(`/admin/api/comments?memberId=${adminUser.userId}&pageSize=1&page=999`)).json()
expect(last.pagination.page).toBe(2)
const recent = await (await adminApi.get('/admin/api/comments?pageSize=5')).json()
@@ -270,6 +275,45 @@ test('관리자 댓글 조회는 인증·입력 검증과 멤버별 페이지·
}
})
test('멤버 작성 글 조회는 작성자를 분리하고 전체 이력을 검색·페이지 조회한다', async ({ request: anonymousApi }) => {
const url = `/admin/api/members/${adminUser.userId}/posts`
expect((await anonymousApi.get(url)).status()).toBe(401)
for (const query of ['page=0', 'pageSize=101']) {
expect((await adminApi.get(`${url}?${query}`)).status()).toBe(400)
}
expect((await adminApi.get('/admin/api/members/invalid/posts')).status()).toBe(400)
const [author] = await database`
INSERT INTO users (username, email, password_hash)
VALUES ('작성 글 검증', 'author-history@example.com', 'unused') RETURNING id
`
try {
await database`
INSERT INTO posts (title, slug, content, status, author_id, created_at)
SELECT '작성 이력 ' || index, 'author-history-' || index, '검색 본문 ' || index,
'draft', ${author.id}, now() + index * interval '1 second'
FROM generate_series(1, 11) AS index
`
const authorUrl = `/admin/api/members/${author.id}/posts`
const first = await (await adminApi.get(authorUrl)).json()
expect(first.pagination).toMatchObject({ total: 11, pageCount: 2, page: 1 })
expect(first.items).toHaveLength(10)
expect(first.items[0].title).toBe('작성 이력 11')
const last = await (await adminApi.get(`${authorUrl}?page=999`)).json()
expect(last.pagination.page).toBe(2)
expect(last.items[0].title).toBe('작성 이력 1')
const search = await (await adminApi.get(`${authorUrl}?q=${encodeURIComponent('검색 본문 11')}`)).json()
expect(search.pagination.total).toBe(1)
expect(search.items[0].title).toBe('작성 이력 11')
const empty = await (await adminApi.get(`${authorUrl}?q=%25`)).json()
expect(empty.items).toEqual([])
const others = await (await adminApi.get(url)).json()
expect(others.items.some((item) => item.slug.startsWith('author-history-'))).toBe(false)
} finally {
await database`DELETE FROM posts WHERE author_id = ${author.id}`
await database`DELETE FROM users WHERE id = ${author.id}`
}
})
test('CSP 수집은 잘못된 형식과 32KB 초과 본문을 거부한다', async ({ request: anonymousApi }) => {
const unsupportedResponse = await anonymousApi.post('/api/csp-report', {
headers: {

View File

@@ -23,18 +23,37 @@ test('멤버 댓글 페이지 이동·게시물 링크와 대시보드 최근
}
await page.goto(`/admin/members/${admin.userId}`)
await page.waitForLoadState('networkidle')
const list = page.locator('.admin-comment-list')
await expect(list.locator('.admin-comment-list__item')).toHaveCount(10)
await expect(list.locator('.admin-comment-list__body').first()).toHaveText('화면 댓글 10')
await expect(page.locator('.admin-member-activity')).toHaveCount(0)
await page.getByRole('button', { name: '작성한 댓글', exact: true }).click()
const list = page.locator('.admin-member-activity')
await expect(list.locator('.admin-member-activity__item')).toHaveCount(10)
await expect(list.locator('.admin-member-activity__body').first()).toHaveText('화면 댓글 10')
await expect(list.getByRole('link', { name: '게시물 보기' }).first()).toHaveAttribute('href', '/post/comments-ui-test#comments')
await list.getByRole('button', { name: '다음' }).click()
await expect(list.locator('.admin-comment-list__item')).toHaveCount(1)
await expect(list.locator('.admin-comment-list__body')).toHaveText('화면 댓글 0')
await list.getByRole('button', { name: '이전' }).click()
await expect(list.locator('.admin-comment-list__item')).toHaveCount(10)
await list.getByRole('button', { name: '다음 페이지' }).click()
await expect(list.locator('.admin-member-activity__item')).toHaveCount(1)
await expect(list.locator('.admin-member-activity__body')).toHaveText('화면 댓글 0')
await list.getByRole('button', { name: '이전 페이지' }).click()
await expect(list.locator('.admin-member-activity__item')).toHaveCount(10)
await list.getByLabel('작성한 댓글 검색').fill('화면 댓글 0')
await list.getByRole('button', { name: '검색', exact: true }).click()
await expect(list.locator('.admin-member-activity__item')).toHaveCount(1)
await expect(list.locator('.admin-member-activity__body')).toHaveText('화면 댓글 0')
await list.getByLabel('작성한 댓글 검색').fill('결과없음')
await list.getByRole('button', { name: '검색', exact: true }).click()
await expect(list).toContainText('검색 결과가 없습니다.')
await page.getByRole('button', { name: '작성한 글', exact: true }).click()
await expect(page.locator('.admin-member-activity__item')).toHaveCount(1)
await page.getByLabel('작성한 글 검색').fill('없는글')
await page.locator('.admin-member-activity').getByRole('button', { name: '검색', exact: true }).click()
await expect(page.locator('.admin-member-activity')).toContainText('검색 결과가 없습니다.')
await page.getByRole('button', { name: '정보', exact: true }).click()
await expect(page.locator('.admin-member-form__body')).toBeVisible()
await page.goto('/admin')
await expect(page.locator('.admin-comment-list__item')).toHaveCount(5)
await expect(page.locator('.admin-comment-list__body').first()).toHaveText('화면 댓글 10')
await expect(page.locator('.admin-dashboard__csp')).toHaveCount(0)
const recentBox = await page.locator('.admin-comment-list').boundingBox()
expect(recentBox.height).toBeLessThan(250)
await page.goto('/admin/posts')
const row = page.locator('.admin-posts__row').filter({ hasText: '댓글 화면 검증 게시물' })
await expect(row.locator('.admin-posts__comment-count')).toHaveText('11')