2022-12-07 14:03:56 +03:00
|
|
|
const {expect, test} = require('@playwright/test');
|
2022-12-07 21:18:21 +03:00
|
|
|
const {DateTime} = require('luxon');
|
2022-12-07 14:03:56 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Start a post draft with a filled in title and body. We can consider to move this to utils later.
|
|
|
|
* @param {import('@playwright/test').Page} page
|
2022-12-07 17:13:23 +03:00
|
|
|
* @param {Object} options
|
|
|
|
* @param {String} [options.title]
|
|
|
|
* @param {String} [options.body]
|
2022-12-07 14:03:56 +03:00
|
|
|
*/
|
2022-12-07 17:13:23 +03:00
|
|
|
const createPost = async (page, {title = 'Hello world', body = 'This is my post body.'} = {}) => {
|
2022-12-07 14:03:56 +03:00
|
|
|
await page.locator('.gh-nav a[href="#/posts/"]').click();
|
|
|
|
|
|
|
|
// Create a new post
|
|
|
|
await page.locator('[data-test-new-post-button]').click();
|
|
|
|
|
|
|
|
// Fill in the post title
|
|
|
|
await page.locator('[data-test-editor-title-input]').click();
|
2022-12-07 17:13:23 +03:00
|
|
|
await page.locator('[data-test-editor-title-input]').fill(title);
|
2022-12-07 14:03:56 +03:00
|
|
|
|
|
|
|
// Continue to the body by pressing enter
|
|
|
|
await page.keyboard.press('Enter');
|
|
|
|
|
2022-12-07 17:13:23 +03:00
|
|
|
await page.waitForTimeout(100); // allow new->draft switch to occur fully, without this some initial typing events can be missed
|
|
|
|
await page.keyboard.type(body);
|
2022-12-07 14:03:56 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param {import('@playwright/test').Page} page
|
|
|
|
*/
|
|
|
|
const openPublishFlow = async (page) => {
|
|
|
|
await page.locator('[data-test-button="publish-flow"]').click();
|
|
|
|
};
|
|
|
|
|
2022-12-07 17:13:23 +03:00
|
|
|
/**
|
|
|
|
* @param {import('@playwright/test').Page} page
|
|
|
|
*/
|
|
|
|
const closePublishFlow = async (page) => {
|
2022-12-07 19:29:36 +03:00
|
|
|
await page.locator('[data-test-button="close-publish-flow"]').click();
|
2022-12-07 17:13:23 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @typedef {Object} PublishOptions
|
|
|
|
* @property {'publish'|'publish+send'|'send'} [type]
|
|
|
|
* @property {String} [recipientFilter]
|
|
|
|
* @property {String} [newsletter]
|
|
|
|
* @property {String} [date]
|
2022-12-07 19:29:36 +03:00
|
|
|
* @property {String} [time]
|
2022-12-07 17:13:23 +03:00
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Open and complete publish flow, filling in all necessary fields based on publish options
|
|
|
|
* @param {import('@playwright/test').Page} page
|
|
|
|
* @param {PublishOptions} options
|
|
|
|
*/
|
2022-12-07 19:29:36 +03:00
|
|
|
const publishPost = async (page, {type = 'publish', time} = {}) => {
|
2022-12-07 17:13:23 +03:00
|
|
|
await openPublishFlow(page);
|
|
|
|
|
|
|
|
// set the publish type
|
|
|
|
await page.locator('[data-test-setting="publish-type"] > button').click();
|
2022-12-08 10:38:59 +03:00
|
|
|
|
|
|
|
// NOTE: the if/else below should be reworked into data-test-publish style selectors
|
|
|
|
// await page.locator(`[data-test-publish-type="${type}"]`).setChecked(true);
|
|
|
|
if (type === 'publish') {
|
|
|
|
await page.getByText('Publish only').click();
|
|
|
|
} else if (type === 'publish+send') {
|
|
|
|
await page.getByText('Publish and email').click();
|
|
|
|
} else if (type === 'send') {
|
|
|
|
await page.getByText('Email only').click();
|
|
|
|
}
|
2022-12-07 17:13:23 +03:00
|
|
|
|
2022-12-07 19:29:36 +03:00
|
|
|
if (time) {
|
|
|
|
await page.locator('[data-test-setting="publish-at"] > button').click();
|
|
|
|
await page.locator('[data-test-radio="schedule"] + label').click();
|
|
|
|
await page.locator('[data-test-date-time-picker-time-input]').fill(time);
|
|
|
|
}
|
|
|
|
|
2022-12-07 17:13:23 +03:00
|
|
|
// TODO: set other publish options
|
|
|
|
|
|
|
|
// continue to confirmation step
|
|
|
|
await page.locator('[data-test-modal="publish-flow"] [data-test-button="continue"]').click();
|
|
|
|
|
|
|
|
// TODO: assert publish flow has expected confirmation details
|
|
|
|
|
|
|
|
// (we need force because the button is animating)
|
|
|
|
await page.locator('[data-test-modal="publish-flow"] [data-test-button="confirm-publish"]').click({force: true});
|
|
|
|
|
|
|
|
// TODO: assert publish flow has expected completion details
|
|
|
|
|
|
|
|
// open the published post in a new tab
|
|
|
|
const [frontendPage] = await Promise.all([
|
|
|
|
page.waitForEvent('popup'),
|
|
|
|
page.locator('[data-test-complete-bookmark]').click()
|
|
|
|
]);
|
|
|
|
|
|
|
|
await closePublishFlow(page);
|
|
|
|
return frontendPage;
|
|
|
|
};
|
|
|
|
|
2022-12-07 14:03:56 +03:00
|
|
|
test.describe('Publishing', () => {
|
|
|
|
test.describe('Publish post', () => {
|
|
|
|
test('Post should only be available on web', async ({page}) => {
|
|
|
|
await page.goto('/ghost');
|
|
|
|
await createPost(page);
|
2022-12-07 17:13:23 +03:00
|
|
|
const frontendPage = await publishPost(page);
|
2022-12-07 14:03:56 +03:00
|
|
|
|
2022-12-07 17:13:23 +03:00
|
|
|
// Check if 'This is my post body.' is present on page1
|
|
|
|
await expect(frontendPage.locator('.gh-canvas .article-title')).toHaveText('Hello world');
|
|
|
|
await expect(frontendPage.locator('.gh-content.gh-canvas > p')).toHaveText('This is my post body.');
|
|
|
|
});
|
|
|
|
});
|
2022-12-07 14:03:56 +03:00
|
|
|
|
2022-12-07 17:13:23 +03:00
|
|
|
test.describe('Update post', () => {
|
|
|
|
test('Can update a published post', async ({page: adminPage, browser}) => {
|
|
|
|
await adminPage.goto('/ghost');
|
2022-12-07 14:03:56 +03:00
|
|
|
|
2022-12-07 21:18:21 +03:00
|
|
|
const date = DateTime.now();
|
|
|
|
|
2022-12-07 17:13:23 +03:00
|
|
|
await createPost(adminPage, {title: 'Testing publish update', body: 'This is the initial published text.'});
|
|
|
|
const frontendPage = await publishPost(adminPage);
|
|
|
|
const frontendBody = frontendPage.getByRole('main');
|
2022-12-07 14:03:56 +03:00
|
|
|
|
2022-12-07 17:13:23 +03:00
|
|
|
// check front-end post has the initial body text
|
|
|
|
await expect(frontendBody).toContainText('This is the initial published text.');
|
2022-12-07 21:18:21 +03:00
|
|
|
await expect(frontendBody).toContainText(date.toFormat('LLL d, yyyy'));
|
2022-12-07 14:03:56 +03:00
|
|
|
|
2022-12-07 17:13:23 +03:00
|
|
|
// add some extra text to the post
|
|
|
|
await adminPage.locator('[data-kg="editor"]').click();
|
|
|
|
await adminPage.keyboard.press('Enter');
|
|
|
|
await adminPage.keyboard.type('This is some updated text.');
|
2022-12-07 14:03:56 +03:00
|
|
|
|
2022-12-07 21:18:21 +03:00
|
|
|
// change some post settings
|
|
|
|
await adminPage.locator('[data-test-psm-trigger]').click();
|
|
|
|
await adminPage.fill('[data-test-date-time-picker-date-input]', '2022-01-07');
|
|
|
|
await adminPage.fill('[data-test-field="custom-excerpt"]', 'Short description and meta');
|
|
|
|
|
2022-12-07 17:13:23 +03:00
|
|
|
// save
|
|
|
|
await adminPage.locator('[data-test-button="publish-save"]').click();
|
2022-12-07 14:03:56 +03:00
|
|
|
|
2022-12-07 17:13:23 +03:00
|
|
|
// check front-end has new text after reloading
|
|
|
|
await frontendPage.waitForTimeout(100); // let save go through
|
|
|
|
await frontendPage.reload();
|
|
|
|
await expect(frontendBody).toContainText('This is some updated text.');
|
2022-12-07 21:18:21 +03:00
|
|
|
await expect(frontendBody).toContainText('Jan 7, 2022');
|
|
|
|
const metaDescription = frontendPage.locator('meta[name="description"]');
|
|
|
|
await expect(metaDescription).toHaveAttribute('content', 'Short description and meta');
|
2022-12-07 14:03:56 +03:00
|
|
|
});
|
|
|
|
});
|
2022-12-07 19:29:36 +03:00
|
|
|
|
|
|
|
test.describe('Schedule post', () => {
|
|
|
|
test('Post should be published to web only at the scheduled time', async ({page}) => {
|
|
|
|
await page.goto('/ghost');
|
|
|
|
await createPost(page, {
|
|
|
|
title: 'Scheduled post test',
|
|
|
|
body: 'This is my scheduled post body.'
|
|
|
|
});
|
|
|
|
|
|
|
|
// Schedule the post to publish asap (by setting it to 00:00, it will get auto corrected to the minimum time possible - 5 seconds in the future)
|
|
|
|
await publishPost(page, {time: '00:00'});
|
|
|
|
|
|
|
|
// Go to the homepage and check if the post is not yet visible there
|
|
|
|
await page.goto('/');
|
|
|
|
|
|
|
|
let lastPost = await page.locator('.post-card-content-link').first();
|
|
|
|
await expect(lastPost).not.toHaveAttribute('href', '/scheduled-post-test/');
|
|
|
|
|
|
|
|
// Now wait for 5 seconds
|
|
|
|
await page.waitForTimeout(5000);
|
|
|
|
|
|
|
|
// Check again, now it should have been added to the page
|
|
|
|
await page.reload();
|
|
|
|
lastPost = await page.locator('.post-card-content-link').first();
|
|
|
|
await expect(lastPost).toHaveAttribute('href', '/scheduled-post-test/');
|
|
|
|
|
|
|
|
// Go to the page
|
|
|
|
await lastPost.click();
|
|
|
|
|
|
|
|
// Check if the title and body are present on this page
|
|
|
|
await expect(page.locator('.gh-canvas .article-title')).toHaveText('Scheduled post test');
|
|
|
|
await expect(page.locator('.gh-content.gh-canvas > p')).toHaveText('This is my scheduled post body.');
|
|
|
|
});
|
|
|
|
});
|
2022-12-07 14:03:56 +03:00
|
|
|
});
|
2022-12-08 07:26:44 +03:00
|
|
|
|
|
|
|
test.describe('Updating post access', () => {
|
|
|
|
test.describe('Change post visibility to members-only', () => {
|
|
|
|
test('Only logged-in members (free or paid) can see', async ({page}) => {
|
|
|
|
await page.goto('/ghost');
|
|
|
|
|
|
|
|
// Create a post
|
|
|
|
await createPost(page);
|
|
|
|
|
|
|
|
// Open the Post Settings Menu
|
|
|
|
await page.locator('[data-test-psm-trigger]').click();
|
|
|
|
|
|
|
|
// Change the Post access setting to 'Members only'
|
|
|
|
await page.locator('[data-test-select="post-visibility"]').selectOption('members');
|
|
|
|
|
|
|
|
// Publish the post
|
|
|
|
const frontendPage = await publishPost(page);
|
|
|
|
|
|
|
|
// Check if content gate for members is present on front-end
|
|
|
|
await expect(frontendPage.locator('.gh-post-upgrade-cta-content h2')).toHaveText('This post is for subscribers only');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
test.describe('Change post visibility to paid-members-only', () => {
|
|
|
|
test('Only logged-in, paid members can see', async ({page}) => {
|
|
|
|
await page.goto('/ghost');
|
|
|
|
|
|
|
|
// Create a post
|
|
|
|
await createPost(page);
|
|
|
|
|
|
|
|
// Open the Post Settings Menu
|
|
|
|
await page.locator('[data-test-psm-trigger]').click();
|
|
|
|
|
|
|
|
// Change the Post access setting to 'Paid-members only'
|
|
|
|
await page.locator('[data-test-select="post-visibility"]').selectOption('paid');
|
|
|
|
|
|
|
|
// Publish the post
|
|
|
|
const frontendPage = await publishPost(page);
|
|
|
|
|
|
|
|
// Check if content gate for paid members is present on front-end
|
|
|
|
await expect(frontendPage.locator('.gh-post-upgrade-cta-content h2')).toHaveText('This post is for paying subscribers only');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
test.describe('Change post visibility to public', () => {
|
|
|
|
test('Everyone can see', async ({page}) => {
|
|
|
|
await page.goto('/ghost');
|
|
|
|
|
|
|
|
// Create a post
|
|
|
|
await createPost(page);
|
|
|
|
|
|
|
|
// Open the Post Settings Menu
|
|
|
|
await page.locator('[data-test-psm-trigger]').click();
|
|
|
|
|
|
|
|
// Change the Post access setting to 'Public'
|
|
|
|
await page.locator('[data-test-select="post-visibility"]').selectOption('public');
|
|
|
|
|
|
|
|
// Publish the post
|
|
|
|
const frontendPage = await publishPost(page);
|
|
|
|
|
|
|
|
// Check if post content is publicly visible on front-end
|
|
|
|
await expect(frontendPage.locator('.gh-content.gh-canvas > p')).toHaveText('This is my post body.');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|