From 9697797d1ce52400677b47d8c1e08d92f0447c56 Mon Sep 17 00:00:00 2001 From: Connor Jennings Date: Fri, 1 May 2020 22:23:28 -0400 Subject: [PATCH] Allow scheduled posts to be shifted around on calendar --- modules/calendar/calendar.php | 9 ++ modules/calendar/lib/calendar.css | 2 +- tests/e2e/config/setup-test-framework.js | 102 ----------------------- tests/e2e/jest.config.js | 8 +- tests/e2e/specs/calendar-body.test.js | 98 ++++++++++++++++++++++ tests/e2e/utils/index.js | 18 +++- 6 files changed, 129 insertions(+), 108 deletions(-) create mode 100644 tests/e2e/specs/calendar-body.test.js diff --git a/modules/calendar/calendar.php b/modules/calendar/calendar.php index e386e147f..19815ac95 100644 --- a/modules/calendar/calendar.php +++ b/modules/calendar/calendar.php @@ -23,6 +23,15 @@ class EF_Calendar extends EF_Module { private $post_date_cache = array(); private static $post_li_html_cache_key = 'ef_calendar_post_li_html'; + /** + * Calendar published statuses are the same as other + * components but without the future + */ + public $published_statuses = array( + 'publish', + 'private', + ); + /** * Construct the EF_Calendar class */ diff --git a/modules/calendar/lib/calendar.css b/modules/calendar/lib/calendar.css index eb4021b79..72b7c9de7 100644 --- a/modules/calendar/lib/calendar.css +++ b/modules/calendar/lib/calendar.css @@ -210,7 +210,7 @@ table#ef-calendar-view .day-unit ul li .item-status { line-height: 13px; color: #999999; word-wrap: break-word; - width: 55px; + width: 60px; float: right; padding-right: 2px; text-align: right; diff --git a/tests/e2e/config/setup-test-framework.js b/tests/e2e/config/setup-test-framework.js index 5a1b35019..41c0d7a5c 100644 --- a/tests/e2e/config/setup-test-framework.js +++ b/tests/e2e/config/setup-test-framework.js @@ -203,108 +203,6 @@ async function runAxeTestsForBlockEditor() { } ); } -/** - * The following is copied from @wordpress/jest-console. - * There are existing console warnings that Edit Flow causing that need to be resolved before this can be turned back on. - * In the meantime, we'll configure this ourselves and ignore warnings that are thrown for the time being - */ - -const supportedMatchers = { - error: 'toHaveErrored', - info: 'toHaveInformed', - log: 'toHaveLogged', - // warn: 'toHaveWarned', // Removing this because Edit Flow is emitting warnings that need to be fixed -}; - -const createToBeCalledMatcher = ( matcherName, methodName ) => -( received ) => { - const spy = received[ methodName ]; - const calls = spy.mock.calls; - const pass = calls.length > 0; - const message = pass ? - () => - matcherHint( `.not${ matcherName }`, spy.getMockName() ) + - '\n\n' + - 'Expected mock function not to be called but it was called with:\n' + - calls.map( printReceived ) : - () => - matcherHint( matcherName, spy.getMockName() ) + - '\n\n' + - 'Expected mock function to be called.'; - - spy.assertionsNumber += 1; - - return { - message, - pass, - }; -}; - -const createToBeCalledWithMatcher = ( matcherName, methodName ) => -( received, ...expected ) => { - const spy = received[ methodName ]; - const calls = spy.mock.calls; - const pass = some( - calls, - ( objects ) => isEqual( objects, expected ) - ); - const message = pass ? - () => - matcherHint( `.not${ matcherName }`, spy.getMockName() ) + - '\n\n' + - 'Expected mock function not to be called with:\n' + - printExpected( expected ) : - () => - matcherHint( matcherName, spy.getMockName() ) + - '\n\n' + - 'Expected mock function to be called with:\n' + - printExpected( expected ) + '\n' + - 'but it was called with:\n' + - calls.map( printReceived ); - - spy.assertionsNumber += 1; - - return { - message, - pass, - }; -}; - -expect.extend( -reduce( supportedMatchers, ( result, matcherName, methodName ) => { - const matcherNameWith = `${ matcherName }With`; - - return { - ...result, - [ matcherName ]: createToBeCalledMatcher( `.${ matcherName }`, methodName ), - [ matcherNameWith ]: createToBeCalledWithMatcher( `.${ matcherNameWith }`, methodName ), - }; -}, {} ) -); - -/** - * Sets spy on the console object's method to make it possible to fail test when method called without assertion. - * - * @param {string} matcherName Name of Jest matcher. - * @param {string} methodName Name of console method. - */ -const setConsoleMethodSpy = ( matcherName, methodName ) => { - const spy = jest.spyOn( console, methodName ).mockName( `console.${ methodName }` ); - - beforeEach( () => { - spy.mockReset(); - spy.assertionsNumber = 0; - } ); - - afterEach( () => { - if ( spy.assertionsNumber === 0 && spy.mock.calls.length > 0 ) { - expect( console ).not[ matcherName ](); - } - } ); -}; - -forEach( supportedMatchers, setConsoleMethodSpy ); - // Before every test suite run, delete all content created by the test. This ensures // other posts/comments/etc. aren't dirtying tests and tests don't depend on // each other's side-effects. diff --git a/tests/e2e/jest.config.js b/tests/e2e/jest.config.js index e7dbf8f5d..a80f43554 100644 --- a/tests/e2e/jest.config.js +++ b/tests/e2e/jest.config.js @@ -3,10 +3,10 @@ module.exports = { setupFilesAfterEnv: [ '/config/setup-test-framework.js', /** - * There are existing console warnings that Edit Flow causing - * that need to be resolved before this can be turned back on. - * In the meantime, we'll configure this ourselves - * and ignore warnings that are thrown for the time being + * Sometimes Edit Flow causes a console warning/error + * and sometimes core does, irrespective of the test being + * run. So we're not going to enable `jest-console` for the time + * being. * * ex: "[DOM] Found 2 elements with non-unique id #_wpnonce: (More info: https://goo.gl/9p2vKq) %o %o"],["[DOM] Found 2 elements with non-unique id #_wpnonce: (More info: https://goo.gl/9p2vKq) %o %o" */ diff --git a/tests/e2e/specs/calendar-body.test.js b/tests/e2e/specs/calendar-body.test.js new file mode 100644 index 000000000..6d91ad28d --- /dev/null +++ b/tests/e2e/specs/calendar-body.test.js @@ -0,0 +1,98 @@ +/** + * WordPress dependencies + */ + +import { createNewPost, visitAdminPage, saveDraft } from "@wordpress/e2e-test-utils"; +import { publishPost, schedulePost } from '../utils'; + +describe("Calendar Body", () => { + + it("expects a published post cannot be dragged and dropped", async () => { + await createNewPost({title: 'Published Post' }); + await publishPost(); + + await visitAdminPage("index.php", "page=calendar"); + + await page.waitForSelector('.ef-calendar-header'); + + const dayUnit = await page.$('.day-unit'); + const dayUnitBoundingBox = await dayUnit.boundingBox(); + + const publishedPost = (await page.$x('//strong[text()="Published Post"]'))[0]; + const publishedPostParent = await publishedPost.evaluateHandle((node) => node.closest('.day-item')); + const publishedPostParentBounding = await publishedPostParent.boundingBox(); + const publishedPostDay = await publishedPost.evaluateHandle((node) => node.closest('.post-list')); + const publishedPostDayBounding = await publishedPostDay.boundingBox(); + + await page.mouse.move(publishedPostParentBounding.x + publishedPostParentBounding.width / 2, publishedPostParentBounding.y + publishedPostParentBounding.height / 2); + await page.mouse.down(); + await page.mouse.move(publishedPostParentBounding.x, publishedPostParentBounding.y + publishedPostDayBounding.height); + await page.mouse.up(); + + + expect(await publishedPostDay.evaluate((node) => { + return Array.prototype.slice.call(node.querySelectorAll('.item-headline.post-title strong')).map((n) => n.innerText) + })).toContain('Published Post'); + }); + + it("expects an unpublished post can be dragged and dropped", async () => { + await createNewPost({title: 'Unpublished Post' }); + await saveDraft(); + + await visitAdminPage("index.php", "page=calendar"); + + await page.waitForSelector('.ef-calendar-header'); + + const unpublishedPost = (await page.$x('//strong[text()="Unpublished Post"]'))[0]; + const unpublishedPostParent = await unpublishedPost.evaluateHandle((node) => node.closest('.day-item')); + const unpublishedPostParentBounding = await unpublishedPostParent.boundingBox(); + const unpublishedPostDay = await unpublishedPost.evaluateHandle((node) => node.closest('.post-list')); + const unpublishedPostDayBounding = await unpublishedPostDay.boundingBox(); + + /** + * Simulate drag and drop + */ + await page.mouse.move(unpublishedPostParentBounding.x + unpublishedPostParentBounding.width / 2, unpublishedPostParentBounding.y + unpublishedPostParentBounding.height / 2); + await page.mouse.down(); + await page.mouse.move(unpublishedPostParentBounding.x + unpublishedPostParentBounding.width / 2, unpublishedPostParentBounding.y + unpublishedPostDayBounding.height + 20); + await page.mouse.up(); + + await page.waitFor(200); + + expect(await unpublishedPostDay.evaluate((node) => { + return Array.prototype.slice.call(node.querySelectorAll('.item-headline.post-title strong')).map((n) => n.innerText) + })).not.toContain('Unpublished Post'); + }); + + it("expects a scheduled post can be dragged and dropped", async () => { + await createNewPost({title: 'Scheduled Post' }); + await schedulePost(); + + await visitAdminPage("index.php", "page=calendar"); + + await page.waitForSelector('.ef-calendar-header'); + + const scheduledPost = (await page.$x('//strong[text()="Scheduled Post"]'))[0]; + const scheduledPostParent = await scheduledPost.evaluateHandle((node) => node.closest('.day-item')); + const scheduledPostParentBounding = await scheduledPostParent.boundingBox(); + const scheduledPostDay = await scheduledPost.evaluateHandle((node) => node.closest('.post-list')); + const scheduledPostDayBounding = await scheduledPostDay.boundingBox(); + + /** + * Simulate drag and drop + */ + await page.mouse.move(scheduledPostParentBounding.x + scheduledPostParentBounding.width / 2, scheduledPostParentBounding.y + scheduledPostParentBounding.height / 2); + await page.mouse.down(); + await page.waitFor(3000); + await page.mouse.move(scheduledPostParentBounding.x + scheduledPostParentBounding.width / 2, scheduledPostParentBounding.y - scheduledPostDayBounding.height - 20); + await page.waitFor(3000); + await page.mouse.up(); + await page.waitFor(3000); + + await page.waitFor(200); + + expect(await scheduledPostDay.evaluate((node) => { + return Array.prototype.slice.call(node.querySelectorAll('.item-headline.post-title strong')).map((n) => n.innerText) + })).not.toContain('Scheduled Post'); + }); +}); \ No newline at end of file diff --git a/tests/e2e/utils/index.js b/tests/e2e/utils/index.js index d5706c5a1..672520202 100644 --- a/tests/e2e/utils/index.js +++ b/tests/e2e/utils/index.js @@ -51,4 +51,20 @@ const publishPost = async() => { } -export { addCategoryToPost, publishPost } \ No newline at end of file +const schedulePost = async() => { + await page.waitForSelector( '.edit-post-post-schedule__toggle' ); + + await page.click( '.edit-post-post-schedule__toggle' ); + + // wait for popout animation + await page.waitFor(200); + + await page.click( 'div[aria-label="Move forward to switch to the next month."]' ); + + await page.click( '.CalendarDay_1' ); + + await publishPost(); + +} + +export { addCategoryToPost, publishPost, schedulePost } \ No newline at end of file