Skip to content

Commit 668923b

Browse files
authored
Updated e2e scheduled publishing tests (#27092)
ref #27087 ref https://linear.app/ghost/issue/PLA-18/ The above commit disabled the scheduling tests to patch a fix. In effect, we should never have the scheduler point to anything but an admin API endpoint. While the scheduler was kept flexible, at this point there doesn't seem to be a reason to not enforce more rigidity/safety. W/r to testing, it's difficult to test the full scheduling workflow. I've updated the tests to successfully emit the scheduler request - we don't ensure that the scheduler pushes a message back to Ghost, though we may be able to do that with a standalone SchedulerService in the future, or something of the like. Right now, Docker communication is difficult, and that's what caused the original issue.
1 parent 05c81f8 commit 668923b

1 file changed

Lines changed: 74 additions & 68 deletions

File tree

e2e/tests/admin/posts/publishing.test.ts

Lines changed: 74 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,9 @@ async function expectFrontendStatus(page: Page, slug: string, status: number, ti
2020
}).toBe(status);
2121
}
2222

23-
function formatDateInput(date: Date): string {
24-
const year = date.getFullYear();
25-
const month = String(date.getMonth() + 1).padStart(2, '0');
26-
const day = String(date.getDate()).padStart(2, '0');
27-
28-
return `${year}-${month}-${day}`;
29-
}
30-
31-
function getAsapSchedule() {
32-
const yesterday = new Date();
33-
yesterday.setDate(yesterday.getDate() - 1);
34-
23+
function getFutureSchedule() {
3524
return {
36-
date: formatDateInput(yesterday),
37-
time: '00:00'
25+
date: '2050-01-01'
3826
};
3927
}
4028

@@ -55,6 +43,49 @@ async function expectPostStatus(editor: PostEditorPage, status: string | RegExp,
5543
}
5644
}
5745

46+
async function waitForScheduledSaveResponse(page: Page, resource: 'posts' | 'pages') {
47+
const response = await page.waitForResponse((networkResponse) => {
48+
if (networkResponse.request().method() !== 'PUT' || networkResponse.status() !== 200) {
49+
return false;
50+
}
51+
52+
const pathname = new URL(networkResponse.url()).pathname;
53+
if (!new RegExp(`/ghost/api/admin/${resource}/[^/]+/?$`).test(pathname)) {
54+
return false;
55+
}
56+
57+
const postData = networkResponse.request().postData();
58+
if (!postData) {
59+
return false;
60+
}
61+
62+
try {
63+
const payload = JSON.parse(postData) as Record<string, unknown>;
64+
const resources = payload[resource];
65+
66+
if (!Array.isArray(resources)) {
67+
return false;
68+
}
69+
70+
return resources.some((item) => {
71+
if (!item || typeof item !== 'object') {
72+
return false;
73+
}
74+
75+
const resourcePayload = item as Record<string, unknown>;
76+
return resourcePayload.status === 'scheduled' ||
77+
(typeof resourcePayload.published_at === 'string' &&
78+
resourcePayload.status !== 'published' &&
79+
resourcePayload.status !== 'sent');
80+
});
81+
} catch {
82+
return false;
83+
}
84+
});
85+
86+
expect(response.status()).toBe(200);
87+
}
88+
5889
function buildLexicalWithBody(body: string): string {
5990
return JSON.stringify({
6091
root: {
@@ -206,7 +237,7 @@ test.describe('Ghost Admin - Publishing', () => {
206237
await expectFrontendStatus(frontendPage, slug, 404);
207238
});
208239

209-
test.skip('scheduled publish only - post becomes visible on frontend', async ({page}) => {
240+
test('scheduled publish only - post is scheduled', async ({page}) => {
210241
const title = `scheduled-publish-only-${Date.now()}`;
211242
const body = 'This is my scheduled post body.';
212243
const slug = generateSlug(title);
@@ -219,26 +250,20 @@ test.describe('Ghost Admin - Publishing', () => {
219250
await editor.createDraft({title, body});
220251

221252
await editor.publishFlow.open();
222-
await editor.publishFlow.schedule(getAsapSchedule());
223-
await editor.publishFlow.confirm();
253+
await editor.publishFlow.schedule(getFutureSchedule());
254+
await Promise.all([
255+
waitForScheduledSaveResponse(page, 'posts'),
256+
editor.publishFlow.confirm()
257+
]);
224258
await editor.publishFlow.close();
225259

226-
await expect(editor.postStatus.first()).toContainText('Scheduled');
227-
await expectFrontendStatus(page, slug, 200, 20000);
260+
await expectPostStatus(editor, 'Scheduled', /to be published\s+at .*2050/i);
228261

229262
const frontendPage = await page.context().newPage();
230-
const publicPage = new PostPage(frontendPage);
231-
232-
await publicPage.gotoPost(slug);
233-
await expect(publicPage.articleTitle).toHaveText(title);
234-
await expect(publicPage.articleBody).toHaveText(body);
235-
236-
await postsPage.goto();
237-
await postsPage.getPostByTitle(title).click();
238-
await expectPostStatus(editor, 'Published');
263+
await expectFrontendStatus(frontendPage, slug, 404);
239264
});
240265

241-
test.skip('scheduled publish and email - post becomes visible on frontend', async ({page}) => {
266+
test('scheduled publish and email - post is scheduled', async ({page}) => {
242267
const title = `scheduled-publish-email-${Date.now()}`;
243268
const body = 'This is my scheduled publish and email post body.';
244269
const slug = generateSlug(title);
@@ -260,29 +285,21 @@ test.describe('Ghost Admin - Publishing', () => {
260285

261286
await editor.publishFlow.open();
262287
await editor.publishFlow.selectPublishType('publish+send');
263-
await editor.publishFlow.schedule(getAsapSchedule());
264-
await editor.publishFlow.confirm();
288+
await editor.publishFlow.schedule(getFutureSchedule());
289+
await Promise.all([
290+
waitForScheduledSaveResponse(page, 'posts'),
291+
editor.publishFlow.confirm()
292+
]);
265293
await editor.publishFlow.close();
266294

267295
await expectPostStatus(editor, 'Scheduled', /published and sent/i);
268-
await expectPostStatus(editor, 'Scheduled', /few seconds/i);
296+
await expectPostStatus(editor, 'Scheduled', /2050/i);
269297

270298
const frontendPage = await page.context().newPage();
271-
const publicPage = new PostPage(frontendPage);
272-
273299
await expectFrontendStatus(frontendPage, slug, 404);
274-
await expectFrontendStatus(frontendPage, slug, 200, 20000);
275-
276-
await publicPage.gotoPost(slug);
277-
await expect(publicPage.articleTitle).toHaveText(title);
278-
await expect(publicPage.articleBody).toHaveText(body);
279-
280-
await postsPage.goto();
281-
await postsPage.getPostByTitle(title).click();
282-
await expectPostStatus(editor, 'Published');
283300
});
284301

285-
test.skip('scheduled email only - post is not visible on frontend', async ({page}) => {
302+
test('scheduled email only - post is scheduled and not visible on frontend', async ({page}) => {
286303
const title = `scheduled-email-only-${Date.now()}`;
287304
const body = 'This is my scheduled email-only post body.';
288305
const slug = generateSlug(title);
@@ -304,28 +321,21 @@ test.describe('Ghost Admin - Publishing', () => {
304321

305322
await editor.publishFlow.open();
306323
await editor.publishFlow.selectPublishType('send');
307-
await editor.publishFlow.schedule(getAsapSchedule());
308-
await editor.publishFlow.confirm();
324+
await editor.publishFlow.schedule(getFutureSchedule());
325+
await Promise.all([
326+
waitForScheduledSaveResponse(page, 'posts'),
327+
editor.publishFlow.confirm()
328+
]);
309329
await editor.publishFlow.close();
310330

311331
await expectPostStatus(editor, 'Scheduled', /to be sent/i);
332+
await expectPostStatus(editor, 'Scheduled', /2050/i);
312333

313334
const frontendPage = await page.context().newPage();
314335
await expectFrontendStatus(frontendPage, slug, 404);
315-
316-
await postsPage.goto();
317-
await postsPage.getPostByTitle(title).click();
318-
await expect.poll(async () => {
319-
await page.reload();
320-
return await editor.postStatus.first().textContent();
321-
}, {
322-
timeout: 15000
323-
}).toContain('Sent');
324-
await expectPostStatus(editor, 'Sent', /Sent\s+to/i);
325-
await expectFrontendStatus(frontendPage, slug, 404);
326336
});
327337

328-
test.skip('scheduled publish only - page becomes visible on frontend', async ({page}) => {
338+
test('scheduled publish only - page is scheduled', async ({page}) => {
329339
const title = `scheduled-page-only-${Date.now()}`;
330340
const body = 'This is my scheduled page body.';
331341
const slug = generateSlug(title);
@@ -335,21 +345,17 @@ test.describe('Ghost Admin - Publishing', () => {
335345
await editor.createDraft({title, body});
336346

337347
await editor.publishFlow.open();
338-
await editor.publishFlow.schedule(getAsapSchedule());
339-
await editor.publishFlow.confirm();
348+
await editor.publishFlow.schedule(getFutureSchedule());
349+
await Promise.all([
350+
waitForScheduledSaveResponse(page, 'pages'),
351+
editor.publishFlow.confirm()
352+
]);
340353
await editor.publishFlow.close();
341354

342-
await expectPostStatus(editor, 'Scheduled', /few seconds/i);
355+
await expectPostStatus(editor, 'Scheduled', /to be published\s+at .*2050/i);
343356

344357
const frontendPage = await page.context().newPage();
345-
const publicPage = new PostPage(frontendPage);
346-
347358
await expectFrontendStatus(frontendPage, slug, 404);
348-
await expectFrontendStatus(frontendPage, slug, 200, 20000);
349-
350-
await publicPage.gotoPost(slug);
351-
await expect(publicPage.articleTitle).toHaveText(title);
352-
await expect(publicPage.articleBody).toHaveText(body);
353359
});
354360

355361
test('publish only - page is visible on frontend', async ({page}) => {

0 commit comments

Comments
 (0)