Ghost/apps/comments-ui/test/e2e/auth-frame.test.ts
Kevin Ansfield ef143978e7
🎨 Reduced requests and 403 responses for comments auth check (#19840)
closes https://linear.app/tryghost/issue/ENG-721
ref https://linear.app/tryghost/issue/ENG-708

Comments-UI loads `/ghost/admin-frame/` in an iframe to check if a Staff User is authenticated in order to  show moderation options. That iframe request loads a HTML page which in turn contains a script that fires off an API request that attempts to fetch the logged-in user details, resulting in a 403 "error" showing up when not authenticated. In the vast majority of cases there will be no staff user authenticated so lots of extra requests and "errors" are seen unnecessarily.

- adjusted the `/ghost/auth-frame/` endpoint to check if the request contains an Admin session cookie
  - if it does, continue as before with rendering the HTML page so the script is loaded
  - if it doesn't, return an empty 204 response avoiding the script request and subsequent 403-generating API request
- eliminates the 403 error being generated for all typical visitor traffic, the error should only be seen when an Admin was previously logged in but their cookie is no longer valid (either from logging out, or going past the 6month validity period)
2024-03-12 12:27:18 +00:00

188 lines
6.0 KiB
TypeScript

import {MOCKED_SITE_URL, MockedApi, initialize, mockAdminAuthFrame, mockAdminAuthFrame204} from '../utils/e2e';
import {expect, test} from '@playwright/test';
const admin = MOCKED_SITE_URL + '/ghost/';
test.describe('Auth Frame', async () => {
test('skips rendering the auth frame with no comments', async ({page}) => {
const mockedApi = new MockedApi({});
await initialize({
mockedApi,
page,
publication: 'Publisher Weekly',
admin
});
const iframeElement = await page.locator('iframe[data-frame="admin-auth"]');
await expect(iframeElement).toHaveCount(0);
});
test('renders the auth frame when there are comments', async ({page}) => {
const mockedApi = new MockedApi({});
mockedApi.addComment({
html: '<p>This is comment 1</p>'
});
await initialize({
mockedApi,
page,
publication: 'Publisher Weekly',
admin
});
const iframeElement = await page.locator('iframe[data-frame="admin-auth"]');
await expect(iframeElement).toHaveCount(1);
});
test('has no admin options when not signed in to Ghost admin', async ({page}) => {
await mockAdminAuthFrame204({page, admin});
const mockedApi = new MockedApi({});
mockedApi.addComment({
html: '<p>This is comment 1</p>'
});
mockedApi.addComment({
html: '<p>This is comment 2</p>'
});
mockedApi.addComment({
html: '<p>This is comment 3</p>'
});
mockedApi.addComment({
html: '<p>This is comment 4</p>'
});
mockedApi.addComment({
html: '<p>This is comment 5</p>'
});
const {frame} = await initialize({
mockedApi,
page,
publication: 'Publisher Weekly',
admin
});
const iframeElement = await page.locator('iframe[data-frame="admin-auth"]');
await expect(iframeElement).toHaveCount(1);
const comments = await frame.getByTestId('comment-component');
await expect(comments).toHaveCount(5);
const moreButtons = await frame.getByTestId('more-button');
await expect(moreButtons).toHaveCount(0);
});
test('has admin options when signed in to Ghost admin', async ({page}) => {
const mockedApi = new MockedApi({});
mockedApi.addComment({
html: '<p>This is comment 1</p>'
});
mockedApi.addComment({
html: '<p>This is comment 2</p>'
});
mockedApi.addComment({
html: '<p>This is comment 3</p>'
});
mockedApi.addComment({
html: '<p>This is comment 4</p>'
});
mockedApi.addComment({
html: '<p>This is comment 5</p>'
});
await mockAdminAuthFrame({
admin,
page
});
const {frame} = await initialize({
mockedApi,
page,
publication: 'Publisher Weekly',
admin
});
const iframeElement = await page.locator('iframe[data-frame="admin-auth"]');
await expect(iframeElement).toHaveCount(1);
// Check if more actions button is visible on each comment
const comments = await frame.getByTestId('comment-component');
await expect(comments).toHaveCount(5);
const moreButtons = await frame.getByTestId('more-button');
await expect(moreButtons).toHaveCount(5);
// Click the 2nd button
await moreButtons.nth(1).click();
await moreButtons.nth(1).getByText('Hide comment').click();
// Check comment2 is replaced with a hidden message
const secondComment = comments.nth(1);
await expect(secondComment).toHaveText('This comment has been hidden.');
await expect(secondComment).not.toContainText('This is comment 2');
// Check can show it again
await moreButtons.nth(1).click();
await moreButtons.nth(1).getByText('Show comment').click();
await expect(secondComment).toContainText('This is comment 2');
});
test('has admin options when signed in to Ghost admin and as a member', async ({page}) => {
const mockedApi = new MockedApi({});
mockedApi.setMember({});
mockedApi.addComment({
html: '<p>This is comment 1</p>'
});
mockedApi.addComment({
html: '<p>This is comment 2</p>'
});
mockedApi.addComment({
html: '<p>This is comment 3</p>'
});
mockedApi.addComment({
html: '<p>This is comment 4</p>'
});
mockedApi.addComment({
html: '<p>This is comment 5</p>'
});
await mockAdminAuthFrame({
admin,
page
});
const {frame} = await initialize({
mockedApi,
page,
publication: 'Publisher Weekly',
admin
});
const iframeElement = await page.locator('iframe[data-frame="admin-auth"]');
await expect(iframeElement).toHaveCount(1);
// Check if more actions button is visible on each comment
const comments = await frame.getByTestId('comment-component');
await expect(comments).toHaveCount(5);
const moreButtons = await frame.getByTestId('more-button');
await expect(moreButtons).toHaveCount(5);
// Click the 2nd button
await moreButtons.nth(1).click();
await moreButtons.nth(1).getByText('Hide comment').click();
// Check comment2 is replaced with a hidden message
const secondComment = comments.nth(1);
await expect(secondComment).toHaveText('This comment has been hidden.');
await expect(secondComment).not.toContainText('This is comment 2');
// Check can show it again
await moreButtons.nth(1).click();
await moreButtons.nth(1).getByText('Show comment').click();
await expect(secondComment).toContainText('This is comment 2');
});
});