diff --git a/tests/e2e/specs/notifications/notifications-schedule.test.js b/tests/e2e/specs/notifications/notifications-schedule.test.js index d9a31419e2..837f611a0d 100644 --- a/tests/e2e/specs/notifications/notifications-schedule.test.js +++ b/tests/e2e/specs/notifications/notifications-schedule.test.js @@ -37,6 +37,10 @@ let page = null; const actionSchedulerLink = 'wp-admin/admin.php?page=wc-status&tab=action-scheduler&orderby=schedule&order=desc'; +const getASJobRowName = ( itemId, notificationType, status = 'Pending' ) => { + return `gla/jobs/notifications/products/process_item Run | Cancel ${ status } 0 => array ( 'item_id' => ${ itemId }, 'topic' => '${ notificationType }'`; +}; + test.describe( 'Notifications Schedule', () => { test.beforeAll( async ( { browser } ) => { page = await browser.newPage(); @@ -60,7 +64,7 @@ test.describe( 'Notifications Schedule', () => { await page.close(); } ); - test( 'When access is granted Notifications are scheduled', async () => { + test( 'When Notifications are ready. Notifications are scheduled', async () => { // Create a new fresh product await productEditor.gotoAddProductPage(); await productEditor.fillProductName(); @@ -70,7 +74,7 @@ test.describe( 'Notifications Schedule', () => { // Check the product.create job is scheduled. await page.goto( actionSchedulerLink ); let row = page.getByRole( 'row', { - name: `gla/jobs/notifications/products/process_item Run | Cancel Pending 0 => array ( 'item_id' => ${ id }, 'topic' => 'product.create'`, + name: getASJobRowName( id, 'product.create' ), } ); await expect( row ).toBeVisible(); @@ -91,7 +95,7 @@ test.describe( 'Notifications Schedule', () => { // Check if the product.update job is there. await page.goto( actionSchedulerLink ); row = page.getByRole( 'row', { - name: `gla/jobs/notifications/products/process_item Run | Cancel Pending 0 => array ( 'item_id' => ${ id }, 'topic' => 'product.update'`, + name: getASJobRowName( id, 'product.update' ), } ); await expect( row ).toBeVisible(); await row.hover( { force: true } ); @@ -103,10 +107,11 @@ test.describe( 'Notifications Schedule', () => { await productEditor.gotoEditProductPage( id ); await productEditor.changeToExternalProduct(); await productEditor.save(); + // Check if the product.delete job is there. await page.goto( actionSchedulerLink ); row = page.getByRole( 'row', { - name: `gla/jobs/notifications/products/process_item Run | Cancel Pending 0 => array ( 'item_id' => ${ id }, 'topic' => 'product.delete'`, + name: getASJobRowName( id, 'product.delete' ), } ); await expect( row ).toBeVisible(); await row.hover( { force: true } ); @@ -114,4 +119,182 @@ test.describe( 'Notifications Schedule', () => { await page.waitForURL( actionSchedulerLink ); await expect( row ).not.toBeVisible(); } ); + + test( 'When Notifications are not ready. Notifications are not scheduled', async () => { + await clearNotificationsReady(); + // Create a new fresh product + await productEditor.gotoAddProductPage(); + await productEditor.fillProductName(); + await productEditor.publish(); + const id = productEditor.getPostID(); + + // Check the product.create job is not scheduled. + await page.goto( actionSchedulerLink ); + const row = page.getByRole( 'row', { + name: getASJobRowName( id, 'product.create' ), + } ); + await expect( row ).not.toBeVisible(); + await setNotificationsReady(); + } ); + + test( 'When Merchant Center has not completed setup. Notifications are not scheduled', async () => { + await clearOnboardedMerchant(); + // Create a new fresh product + await productEditor.gotoAddProductPage(); + await productEditor.fillProductName(); + await productEditor.publish(); + const id = productEditor.getPostID(); + + // Check the product.create job is not scheduled. + await page.goto( actionSchedulerLink ); + const row = page.getByRole( 'row', { + name: getASJobRowName( id, 'product.create' ), + } ); + await expect( row ).not.toBeVisible(); + await setOnboardedMerchant(); + } ); + + test( 'When product has not notified creation. Notifications for product.update and product.delete are not scheduled.', async () => { + await productEditor.gotoAddProductPage(); + await productEditor.fillProductName(); + await productEditor.publish(); + const id = productEditor.getPostID(); + + // Check the product.update job is not scheduled. + await page.goto( actionSchedulerLink ); + let row = page.getByRole( 'row', { + name: getASJobRowName( id, 'product.update' ), + } ); + await expect( row ).not.toBeVisible(); + + await productEditor.gotoEditProductPage( id ); + await productEditor.unpublish(); + + // Check the product.delete job is not scheduled. + await page.goto( actionSchedulerLink ); + row = page.getByRole( 'row', { + name: getASJobRowName( id, 'product.delete' ), + } ); + await expect( row ).not.toBeVisible(); + } ); + + test( 'Unpublish a notified product schedules product.delete notification.', async () => { + await productEditor.gotoAddProductPage(); + await productEditor.fillProductName(); + await productEditor.publish(); + const id = productEditor.getPostID(); + + await productEditor.gotoEditProductPage( id ); + await productEditor.mockNotificationStatus( 'created' ); + await productEditor.unpublish(); + + // Check the product.update job is scheduled. + await page.goto( actionSchedulerLink ); + let row = page.getByRole( 'row', { + name: getASJobRowName( id, 'product.delete' ), + } ); + await expect( row ).toBeVisible(); + + // Simulate that delete notification was successful and publish the product again. + await productEditor.gotoEditProductPage( id ); + await productEditor.mockNotificationStatus( 'deleted' ); + await productEditor.publish(); + + // Check the product.create job is scheduled again. + await page.goto( actionSchedulerLink ); + row = page.getByRole( 'row', { + name: getASJobRowName( id, 'product.create' ), + } ); + await expect( row ).toBeVisible(); + } ); + + test( 'Set as "Dont sync and show" a notified product schedules product.delete notification.', async () => { + await productEditor.gotoAddProductPage(); + await productEditor.fillProductName(); + await productEditor.publish(); + const id = productEditor.getPostID(); + + // Check the product.create job is scheduled. + await page.goto( actionSchedulerLink ); + let row = page.getByRole( 'row', { + name: getASJobRowName( id, 'product.create' ), + } ); + await expect( row ).toBeVisible(); + // Hover the row, so the Run button gets visible + await row.hover( { force: true } ); + await row.getByRole( 'link' ).first().click(); + + await productEditor.gotoEditProductPage( id ); + await productEditor.mockNotificationStatus( 'created' ); + await productEditor.setChannelVisibility( "Don't Sync and show" ); + await productEditor.save(); + // Check the product.delete job is scheduled. + await page.goto( actionSchedulerLink ); + row = page.getByRole( 'row', { + name: getASJobRowName( id, 'product.delete' ), + } ); + await expect( row ).toBeVisible(); + + // Hover the row, so the Run button gets visible + await row.hover( { force: true } ); + await row.getByRole( 'link' ).first().click(); + + // Simulate that delete notification was successful and set as "Sync and show" the product again. + await productEditor.gotoEditProductPage( id ); + await productEditor.mockNotificationStatus( 'deleted' ); + await productEditor.setChannelVisibility( 'Sync and show' ); + await productEditor.save(); + + // Check the product.create job is scheduled. + await page.goto( actionSchedulerLink ); + row = page.getByRole( 'row', { + name: getASJobRowName( id, 'product.create' ), + } ); + await expect( row ).toBeVisible(); + } ); + + test( 'Set a notified product visibility as "Not Public" schedules product.delete notification.', async () => { + await productEditor.gotoAddProductPage(); + await productEditor.fillProductName(); + await productEditor.publish(); + const id = productEditor.getPostID(); + + // Check the product.create job is scheduled. + await page.goto( actionSchedulerLink ); + let row = page.getByRole( 'row', { + name: getASJobRowName( id, 'product.create' ), + } ); + await expect( row ).toBeVisible(); + // Hover the row, so the Run button gets visible + await row.hover( { force: true } ); + await row.getByRole( 'link' ).first().click(); + + await productEditor.gotoEditProductPage( id ); + await productEditor.mockNotificationStatus( 'created' ); + await productEditor.setVisibility( 'Private' ); + await productEditor.save(); + // Check the product.delete job is scheduled. + await page.goto( actionSchedulerLink ); + row = page.getByRole( 'row', { + name: getASJobRowName( id, 'product.delete' ), + } ); + await expect( row ).toBeVisible(); + + // Hover the row, so the Run button gets visible + await row.hover( { force: true } ); + await row.getByRole( 'link' ).first().click(); + + // Simulate that delete notification was successful and set as "Visibility: Public" the product again. + await productEditor.gotoEditProductPage( id ); + await productEditor.mockNotificationStatus( 'deleted' ); + await productEditor.setVisibility( 'Public' ); + await productEditor.save(); + + // Check the product.create job is scheduled. + await page.goto( actionSchedulerLink ); + row = page.getByRole( 'row', { + name: getASJobRowName( id, 'product.create' ), + } ); + await expect( row ).toBeVisible(); + } ); } ); diff --git a/tests/e2e/utils/product-editor.js b/tests/e2e/utils/product-editor.js index d5f61b6fcb..0340274120 100644 --- a/tests/e2e/utils/product-editor.js +++ b/tests/e2e/utils/product-editor.js @@ -244,6 +244,17 @@ export function getClassicProductEditorUtils( page ) { await this.waitForInteractionReady(); }, + async unpublish() { + const btn = page.getByRole( 'button', { name: 'Edit status' } ); + + await btn.click(); + await page + .getByLabel( 'Set status' ) + .selectOption( { label: 'Draft' } ); + await this.clickSave(); + await this.waitForInteractionReady(); + }, + waitForInteractionReady() { // Avoiding tests may start to operate the UI before jQuery interactions are initialized, // leading to random failures. @@ -288,6 +299,18 @@ export function getClassicProductEditorUtils( page ) { await expect( page.locator( '#sample-permalink' ) ).toBeVisible(); }, + async setChannelVisibility( label = 'Sync and show' ) { + const channelVisibilityMetabox = + await locators.getChannelVisibility().selection; + await channelVisibilityMetabox.selectOption( { label } ); + }, + + async setVisibility( visibility = 'Public' ) { + const btn = page.getByRole( 'button', { name: 'Edit visibility' } ); + await btn.click(); + await page.getByLabel( visibility ).check(); + }, + evaluateValidity( input ) { return input.evaluate( ( element ) => element.validity.valid ); },