mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-10 23:36:14 -05:00
Added Playwright test for comment reply pagination
refs https://github.com/TryGhost/Team/issues/3504
This commit is contained in:
parent
9035a87e50
commit
9135ca92e0
3 changed files with 147 additions and 7 deletions
|
@ -58,5 +58,60 @@ test.describe('Pagination', async () => {
|
||||||
// Check the pagination button is not visible
|
// Check the pagination button is not visible
|
||||||
await expect(frame.getByTestId('pagination-component')).not.toBeVisible();
|
await expect(frame.getByTestId('pagination-component')).not.toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('Shows pagination button for replies', async ({page}) => {
|
||||||
|
const mockedApi = new MockedApi({});
|
||||||
|
|
||||||
|
mockedApi.addComment({
|
||||||
|
html: '<p>This is comment 1</p>',
|
||||||
|
replies: [
|
||||||
|
mockedApi.buildReply({
|
||||||
|
html: '<p>This is reply 1</p>'
|
||||||
|
}),
|
||||||
|
mockedApi.buildReply({
|
||||||
|
html: '<p>This is reply 2</p>'
|
||||||
|
}),
|
||||||
|
mockedApi.buildReply({
|
||||||
|
html: '<p>This is reply 3</p>'
|
||||||
|
}),
|
||||||
|
mockedApi.buildReply({
|
||||||
|
html: '<p>This is reply 4</p>'
|
||||||
|
})
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
const {frame} = await initialize({
|
||||||
|
mockedApi,
|
||||||
|
page,
|
||||||
|
publication: 'Publisher Weekly'
|
||||||
|
});
|
||||||
|
|
||||||
|
await expect(frame.getByTestId('reply-pagination-button')).toBeVisible();
|
||||||
|
|
||||||
|
// Check text in pagination button
|
||||||
|
await expect(frame.getByTestId('reply-pagination-button')).toContainText('Show 1 more reply');
|
||||||
|
|
||||||
|
await expect(frame.getByTestId('comment-component')).toHaveCount(4);
|
||||||
|
|
||||||
|
// Check only the first 5 comments are visible
|
||||||
|
await expect(frame.getByText('This is comment 1')).toBeVisible();
|
||||||
|
await expect(frame.getByText('This is reply 1')).toBeVisible();
|
||||||
|
await expect(frame.getByText('This is reply 2')).toBeVisible();
|
||||||
|
await expect(frame.getByText('This is reply 3')).toBeVisible();
|
||||||
|
await expect(frame.getByText('This is reply 4')).not.toBeVisible();
|
||||||
|
|
||||||
|
// Click the pagination button
|
||||||
|
await frame.getByTestId('reply-pagination-button').click();
|
||||||
|
|
||||||
|
// No longer visible
|
||||||
|
await expect(frame.getByTestId('reply-pagination-button')).not.toBeVisible();
|
||||||
|
|
||||||
|
await expect(frame.getByTestId('comment-component')).toHaveCount(5);
|
||||||
|
await expect(frame.getByText('This is comment 1')).toBeVisible();
|
||||||
|
await expect(frame.getByText('This is reply 1')).toBeVisible();
|
||||||
|
await expect(frame.getByText('This is reply 2')).toBeVisible();
|
||||||
|
await expect(frame.getByText('This is reply 3')).toBeVisible();
|
||||||
|
await expect(frame.getByText('This is reply 4')).toBeVisible();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import nql from '@tryghost/nql';
|
import nql from '@tryghost/nql';
|
||||||
import {buildComment, buildMember} from './fixtures';
|
import {buildComment, buildMember, buildReply} from './fixtures';
|
||||||
|
|
||||||
export class MockedApi {
|
export class MockedApi {
|
||||||
comments: any[];
|
comments: any[];
|
||||||
|
@ -27,6 +27,18 @@ export class MockedApi {
|
||||||
this.comments.push(fixture);
|
this.comments.push(fixture);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buildReply(overrides: any = {}) {
|
||||||
|
if (!overrides.created_at) {
|
||||||
|
overrides.created_at = this.#lastCommentDate.toISOString();
|
||||||
|
this.#lastCommentDate = new Date(this.#lastCommentDate.getTime() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return buildReply({
|
||||||
|
...overrides,
|
||||||
|
post_id: this.postId
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
addComments(count, overrides = {}) {
|
addComments(count, overrides = {}) {
|
||||||
for (let i = 0; i < count; i += 1) {
|
for (let i = 0; i < count; i += 1) {
|
||||||
this.addComment(overrides);
|
this.addComment(overrides);
|
||||||
|
@ -72,7 +84,16 @@ export class MockedApi {
|
||||||
const comments = filteredComments.slice(startIndex, endIndex);
|
const comments = filteredComments.slice(startIndex, endIndex);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
comments,
|
comments: comments.map((comment) => {
|
||||||
|
return {
|
||||||
|
...comment,
|
||||||
|
replies: comment.replies.slice(0, 3),
|
||||||
|
count: {
|
||||||
|
...comment.count,
|
||||||
|
replies: comment.replies.length
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}),
|
||||||
meta: {
|
meta: {
|
||||||
pagination: {
|
pagination: {
|
||||||
pages: Math.ceil(filteredComments.length / limit),
|
pages: Math.ceil(filteredComments.length / limit),
|
||||||
|
@ -84,6 +105,51 @@ export class MockedApi {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
browseReplies({commentId, filter, limit = 5}: {commentId: string, filter?: string, limit?: number}) {
|
||||||
|
const comment = this.comments.find(c => c.id === commentId);
|
||||||
|
if (!comment) {
|
||||||
|
return {
|
||||||
|
error: 'Comment ' + commentId + ' not found'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
let replies: any[] = comment.replies;
|
||||||
|
|
||||||
|
// Sort replies on created at + id
|
||||||
|
replies.sort((a, b) => {
|
||||||
|
const aDate = new Date(a.created_at).getTime();
|
||||||
|
const bDate = new Date(b.created_at).getTime();
|
||||||
|
|
||||||
|
if (aDate === bDate) {
|
||||||
|
return a.id > b.id ? 1 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return aDate > bDate ? 1 : -1;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Parse NQL filter
|
||||||
|
if (filter) {
|
||||||
|
const parsed = nql(filter);
|
||||||
|
replies = replies.filter((reply) => {
|
||||||
|
return parsed.queryJSON(reply);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const limitedReplies = replies.slice(0, limit);
|
||||||
|
|
||||||
|
return {
|
||||||
|
comments: limitedReplies,
|
||||||
|
meta: {
|
||||||
|
pagination: {
|
||||||
|
pages: Math.ceil(replies.length / limit),
|
||||||
|
total: replies.length,
|
||||||
|
page: 1,
|
||||||
|
limit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
async listen({page, path}: {page: any, path: string}) {
|
async listen({page, path}: {page: any, path: string}) {
|
||||||
await page.route(`${path}/members/api/member/`, async (route) => {
|
await page.route(`${path}/members/api/member/`, async (route) => {
|
||||||
if (!this.member) {
|
if (!this.member) {
|
||||||
|
@ -105,13 +171,32 @@ export class MockedApi {
|
||||||
const p = parseInt(url.searchParams.get('page') ?? '1');
|
const p = parseInt(url.searchParams.get('page') ?? '1');
|
||||||
const limit = parseInt(url.searchParams.get('limit') ?? '5');
|
const limit = parseInt(url.searchParams.get('limit') ?? '5');
|
||||||
const order = url.searchParams.get('order') ?? '';
|
const order = url.searchParams.get('order') ?? '';
|
||||||
|
const filter = url.searchParams.get('filter') ?? '';
|
||||||
|
|
||||||
await route.fulfill({
|
await route.fulfill({
|
||||||
status: 200,
|
status: 200,
|
||||||
body: JSON.stringify(this.browseComments({
|
body: JSON.stringify(this.browseComments({
|
||||||
page: p,
|
page: p,
|
||||||
limit,
|
limit,
|
||||||
order
|
order,
|
||||||
|
filter
|
||||||
|
}))
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
await page.route(`${path}/members/api/comments/*/replies/*`, async (route) => {
|
||||||
|
const url = new URL(route.request().url());
|
||||||
|
|
||||||
|
const limit = parseInt(url.searchParams.get('limit') ?? '5');
|
||||||
|
const commentId = url.pathname.split('/').reverse()[2];
|
||||||
|
const filter = url.searchParams.get('filter') ?? '';
|
||||||
|
|
||||||
|
await route.fulfill({
|
||||||
|
status: 200,
|
||||||
|
body: JSON.stringify(this.browseReplies({
|
||||||
|
limit,
|
||||||
|
filter,
|
||||||
|
commentId
|
||||||
}))
|
}))
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -5,11 +5,11 @@ export function buildMember(override: any = {}) {
|
||||||
memberCounter += 1;
|
memberCounter += 1;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
id: ObjectId().toString(),
|
||||||
avatar_image: 'https://www.gravatar.com/avatar/7a68f69cc9c9e9b45d97ecad6f24184a?s=250&r=g&d=blank',
|
avatar_image: 'https://www.gravatar.com/avatar/7a68f69cc9c9e9b45d97ecad6f24184a?s=250&r=g&d=blank',
|
||||||
expertise: 'Head of Testing',
|
expertise: 'Head of Testing',
|
||||||
id: ObjectId(),
|
|
||||||
name: 'Test Member ' + memberCounter,
|
name: 'Test Member ' + memberCounter,
|
||||||
uuid: ObjectId(),
|
uuid: ObjectId().toString(),
|
||||||
paid: override.status === 'paid',
|
paid: override.status === 'paid',
|
||||||
status: 'free',
|
status: 'free',
|
||||||
...override
|
...override
|
||||||
|
@ -18,7 +18,7 @@ export function buildMember(override: any = {}) {
|
||||||
|
|
||||||
export function buildComment(override: any = {}) {
|
export function buildComment(override: any = {}) {
|
||||||
return {
|
return {
|
||||||
id: ObjectId(),
|
id: ObjectId().toString(),
|
||||||
html: '<p>Empty</p>',
|
html: '<p>Empty</p>',
|
||||||
replies: [],
|
replies: [],
|
||||||
count: {
|
count: {
|
||||||
|
@ -36,7 +36,7 @@ export function buildComment(override: any = {}) {
|
||||||
|
|
||||||
export function buildReply(override: any = {}) {
|
export function buildReply(override: any = {}) {
|
||||||
return {
|
return {
|
||||||
id: ObjectId(),
|
id: ObjectId().toString(),
|
||||||
html: '<p>Empty</p>',
|
html: '<p>Empty</p>',
|
||||||
count: {
|
count: {
|
||||||
likes: 0
|
likes: 0
|
||||||
|
|
Loading…
Add table
Reference in a new issue