@@ -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+
5889function 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' , / t o b e p u b l i s h e d \s + a t .* 2 0 5 0 / 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' , / p u b l i s h e d a n d s e n t / i) ;
268- await expectPostStatus ( editor , 'Scheduled' , / f e w s e c o n d s / i) ;
296+ await expectPostStatus ( editor , 'Scheduled' , / 2 0 5 0 / 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' , / t o b e s e n t / i) ;
332+ await expectPostStatus ( editor , 'Scheduled' , / 2 0 5 0 / 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' , / S e n t \s + t o / 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' , / f e w s e c o n d s / i) ;
355+ await expectPostStatus ( editor , 'Scheduled' , / t o b e p u b l i s h e d \s + a t . * 2 0 5 0 / 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