Skip to content

Commit

Permalink
Merge pull request #614 from Automattic/update/calendar-schedule
Browse files Browse the repository at this point in the history
Allow scheduled posts to be shifted around on calendar
  • Loading branch information
cojennin committed May 4, 2020
2 parents f50b8f3 + 9697797 commit 9eb902a
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 108 deletions.
9 changes: 9 additions & 0 deletions modules/calendar/calendar.php
Expand Up @@ -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
*/
Expand Down
2 changes: 1 addition & 1 deletion modules/calendar/lib/calendar.css
Expand Up @@ -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;
Expand Down
102 changes: 0 additions & 102 deletions tests/e2e/config/setup-test-framework.js
Expand Up @@ -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.
Expand Down
8 changes: 4 additions & 4 deletions tests/e2e/jest.config.js
Expand Up @@ -3,10 +3,10 @@ module.exports = {
setupFilesAfterEnv: [
'<rootDir>/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"
*/
Expand Down
98 changes: 98 additions & 0 deletions 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');
});
});
18 changes: 17 additions & 1 deletion tests/e2e/utils/index.js
Expand Up @@ -51,4 +51,20 @@ const publishPost = async() => {

}

export { addCategoryToPost, publishPost }
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 }

0 comments on commit 9eb902a

Please sign in to comment.