Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid saving metaboxes before a preview #14877

Merged
merged 3 commits into from
Apr 9, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
155 changes: 120 additions & 35 deletions packages/e2e-tests/specs/preview.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,47 +12,79 @@ import {
createURL,
publishPost,
saveDraft,
clickOnMoreMenuItem,
pressKeyWithModifier,
} from '@wordpress/e2e-test-utils';

describe( 'Preview', () => {
beforeEach( async () => {
await createNewPost();
} );
async function openPreviewPage( editorPage ) {
let openTabs = await browser.pages();
const expectedTabsCount = openTabs.length + 1;
await editorPage.click( '.editor-post-preview' );

async function openPreviewPage( editorPage ) {
let openTabs = await browser.pages();
const expectedTabsCount = openTabs.length + 1;
await editorPage.click( '.editor-post-preview' );

// Wait for the new tab to open.
while ( openTabs.length < expectedTabsCount ) {
await editorPage.waitFor( 1 );
openTabs = await browser.pages();
}

const previewPage = last( openTabs );
// Wait for the preview to load. We can't do interstitial detection here,
// because it might load too quickly for us to pick up, so we wait for
// the preview to load by waiting for the title to appear.
await previewPage.waitForSelector( '.entry-title' );
return previewPage;
// Wait for the new tab to open.
while ( openTabs.length < expectedTabsCount ) {
await editorPage.waitFor( 1 );
openTabs = await browser.pages();
}

/**
* Given a Puppeteer Page instance for a preview window, clicks Preview, and
* awaits the window navigation.
*
* @param {puppeteer.Page} previewPage Page on which to await navigation.
*
* @return {Promise} Promise resolving once navigation completes.
*/
async function waitForPreviewNavigation( previewPage ) {
const navigationCompleted = previewPage.waitForNavigation();
await page.click( '.editor-post-preview' );
return navigationCompleted;
const previewPage = last( openTabs );
// Wait for the preview to load. We can't do interstitial detection here,
// because it might load too quickly for us to pick up, so we wait for
// the preview to load by waiting for the title to appear.
await previewPage.waitForSelector( '.entry-title' );
return previewPage;
}

/**
* Given a Puppeteer Page instance for a preview window, clicks Preview, and
* awaits the window navigation.
*
* @param {puppeteer.Page} previewPage Page on which to await navigation.
*
* @return {Promise} Promise resolving once navigation completes.
*/
async function waitForPreviewNavigation( previewPage ) {
const navigationCompleted = previewPage.waitForNavigation();
await page.click( '.editor-post-preview' );
return navigationCompleted;
}

/**
* Enables or disables the custom fields option.
*
* Note that this is implemented separately from the `toggleScreenOptions`
* utility, since the custom fields option triggers a page reload and requires
* extra async logic to wait for navigation to complete.
*
* @param {boolean} shouldBeChecked If true, turns the option on. If false, off.
*/
async function toggleCustomFieldsOption( shouldBeChecked ) {
const checkboxXPath = '//*[contains(@class, "edit-post-options-modal")]//label[contains(text(), "Custom Fields")]';
await clickOnMoreMenuItem( 'Options' );
await page.waitForXPath( checkboxXPath );
const [ checkboxHandle ] = await page.$x( checkboxXPath );

const isChecked = await page.evaluate(
( element ) => element.control.checked,
checkboxHandle
);

if ( isChecked !== shouldBeChecked ) {
const navigationCompleted = page.waitForNavigation();
await checkboxHandle.click();
await navigationCompleted;
return;
}

it( 'Should open a preview window for a new post', async () => {
await page.click( '.edit-post-options-modal button[aria-label="Close dialog"]' );
}

describe( 'Preview', () => {
beforeEach( async () => {
await createNewPost();
} );

it( 'should open a preview window for a new post', async () => {
const editorPage = page;

// Disabled until content present.
Expand Down Expand Up @@ -129,7 +161,7 @@ describe( 'Preview', () => {
await previewPage.close();
} );

it( 'Should not revert title during a preview right after a save draft', async () => {
it( 'should not revert title during a preview right after a save draft', async () => {
const editorPage = page;

// Type aaaaa in the title filed.
Expand Down Expand Up @@ -166,3 +198,56 @@ describe( 'Preview', () => {
await previewPage.close();
} );
} );

describe( 'Preview with Custom Fields enabled', async () => {
beforeEach( async () => {
await createNewPost();
await toggleCustomFieldsOption( true );
} );

afterEach( async () => {
await toggleCustomFieldsOption( false );
} );

// Catch regressions of https://github.com/WordPress/gutenberg/issues/12617
it( 'displays edits to the post title and content in the preview', async () => {
const editorPage = page;

// Add an initial title and content.
await editorPage.type( '.editor-post-title__input', 'title 1' );
await editorPage.keyboard.press( 'Tab' );
await editorPage.keyboard.type( 'content 1' );

// Open the preview page.
const previewPage = await openPreviewPage( editorPage );

// Check the title and preview match.
let previewTitle = await previewPage.$eval( '.entry-title', ( node ) => node.textContent );
expect( previewTitle ).toBe( 'title 1' );
let previewContent = await previewPage.$eval( '.entry-content p', ( node ) => node.textContent );
expect( previewContent ).toBe( 'content 1' );

// Return to editor and modify the title and content.
await editorPage.bringToFront();
await editorPage.click( '.editor-post-title__input' );
await pressKeyWithModifier( 'shift', 'Home' );
await editorPage.keyboard.press( 'Delete' );
await editorPage.keyboard.type( 'title 2' );
await editorPage.keyboard.press( 'Tab' );
await pressKeyWithModifier( 'shift', 'Home' );
await editorPage.keyboard.press( 'Delete' );
await editorPage.keyboard.type( 'content 2' );

// Open the preview page.
await waitForPreviewNavigation( previewPage );

// Title in preview should match input.
previewTitle = await previewPage.$eval( '.entry-title', ( node ) => node.textContent );
expect( previewTitle ).toBe( 'title 2' );
previewContent = await previewPage.$eval( '.entry-content p', ( node ) => node.textContent );
expect( previewContent ).toBe( 'content 2' );

// Make sure the editor is active for the afterEach function.
await editorPage.bringToFront();
} );
} );
6 changes: 1 addition & 5 deletions packages/edit-post/src/store/effects.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,26 +45,22 @@ const effects = {

let wasSavingPost = select( 'core/editor' ).isSavingPost();
let wasAutosavingPost = select( 'core/editor' ).isAutosavingPost();
let wasPreviewingPost = select( 'core/editor' ).isPreviewingPost();
// Save metaboxes when performing a full save on the post.
subscribe( () => {
const isSavingPost = select( 'core/editor' ).isSavingPost();
const isAutosavingPost = select( 'core/editor' ).isAutosavingPost();
const isPreviewingPost = select( 'core/editor' ).isPreviewingPost();
const hasActiveMetaBoxes = select( 'core/edit-post' ).hasMetaBoxes();

// Save metaboxes on save completion, except for autosaves that are not a post preview.
const shouldTriggerMetaboxesSave = (
hasActiveMetaBoxes && (
( wasSavingPost && ! isSavingPost && ! wasAutosavingPost ) ||
( wasAutosavingPost && wasPreviewingPost && ! isPreviewingPost )
( wasSavingPost && ! isSavingPost && ! wasAutosavingPost )
)
);

// Save current state for next inspection.
wasSavingPost = isSavingPost;
wasAutosavingPost = isAutosavingPost;
wasPreviewingPost = isPreviewingPost;

if ( shouldTriggerMetaboxesSave ) {
store.dispatch( requestMetaBoxUpdates() );
Expand Down