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

e2e Tests: Add basic Site Title block coverage #32868

Merged
merged 13 commits into from
Jul 9, 2021
111 changes: 111 additions & 0 deletions packages/e2e-tests/specs/editor/blocks/site-title.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/**
* WordPress dependencies
*/
import {
createNewPost,
createUser,
deleteUser,
insertBlock,
loginUser,
pressKeyWithModifier,
switchUserToAdmin,
switchUserToTest,
visitAdminPage,
} from '@wordpress/e2e-test-utils';

async function getOption( setting ) {
await switchUserToAdmin();
await visitAdminPage( 'options.php' );

const value = await page.$eval(
`#${ setting }`,
( element ) => element.value
);
await switchUserToTest();
return value;
}

async function setOption( setting, value ) {
await switchUserToAdmin();
await visitAdminPage( 'options-general.php' );

await page.focus( `#${ setting }` );
await pressKeyWithModifier( 'primary', 'a' );
await page.type( `#${ setting }`, value );

await Promise.all( [
page.click( '#submit' ),
page.waitForNavigation( { waitUntil: 'networkidle0' } ),
] );

await switchUserToTest();
}

const saveEntities = async () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're starting to have these multi-entities saving steps in a couple of tests (multi-entities, reusable-blocks...), it looks like we'd probably need to factorize these in some utility.

const savePostSelector = '.editor-post-publish-button__button';
const savePanelSelector = '.entities-saved-states__panel';
const entitiesSaveSelector = '.editor-entities-saved-states__save-button';
const publishPanelSelector = '.editor-post-publish-panel';
const closePanelButtonSelector =
'.editor-post-publish-panel__header-cancel-button button';

await page.click( savePostSelector );
await page.waitForSelector( savePanelSelector );
await page.click( entitiesSaveSelector );
await page.waitForSelector( publishPanelSelector );
await page.waitForSelector(
'.editor-post-publish-panel__header-cancel-button button:not([disabled])'
);
await page.click( closePanelButtonSelector );
};

describe( 'Site Title block', () => {
let originalSiteTitle, password;
const username = 'testuser';
beforeAll( async () => {
originalSiteTitle = await getOption( 'blogname' );
password = await createUser( username, { role: 'editor' } );
} );

afterAll( async () => {
await deleteUser( username );
await setOption( 'blogname', originalSiteTitle );
} );

it( 'Can edit the site title as admin', async () => {
await createNewPost();
await insertBlock( 'Site Title' );
const editableSiteTitleSelector =
'[aria-label="Block: Site Title"] a[contenteditable="true"]';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Honestly this selector seems possibly less stable than the class name, also could be fragile if we start running tests with i18n.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought that aria-label based block selectors were championed by some as more "user-facing" (and that we thus have a few of those across the codebase), but I don't mind going with the class name. We should probably put some guidelines into writing (if we don't have them already) 😄

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I'm not sure that's a super robust guideline in practice :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder why it's less stable? We should probably stick to one language when running e2e tests. Why would we want to change to another language? If there's something specific in some languages that needs to be tested, we can always special-case it and write our updated queries for that language.

Class names are mostly considered to be implementation details, they could change without notices, and the users could still see the completely same result.

aria-label, contenteditable attributes, and even tag name are also considered implementation details though, but less likely to change. Ideally, we should only rely on actual computed accessible properties, such as role and name. puppeteer-testing-library does exactly that and is being experimented in widgets tests.

At the very least, test ids (data-testid) will still be better than class names. IMO, we should avoid using class names as selectors as much as possible.

await page.waitForSelector( editableSiteTitleSelector );
await page.focus( editableSiteTitleSelector );
await pressKeyWithModifier( 'primary', 'a' );

await page.keyboard.type( 'New Site Title' );

await saveEntities();

const siteTitle = await getOption( 'blogname' );
expect( siteTitle ).toEqual( 'New Site Title' );
} );

// FIXME: Fix https://github.com/WordPress/gutenberg/issues/33003 and enable this test.
// I tried adding an `expect( console ).toHaveErroredWith()` as a workaround, but
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess we should intercept the request on this test. I gave it it try now but needs more work. I will look at it better probably next week.

// the error occurs only sporadically (e.g. locally in interactive mode, but not in
// headless mode).
it.skip( 'Cannot edit the site title as editor', async () => {
await loginUser( username, password );

await createNewPost();
await insertBlock( 'Site Title' );

const editableSiteTitleSelector = '[aria-label="Block: Site Title"] a';
await page.waitForSelector( editableSiteTitleSelector );

const editable = await page.$eval(
editableSiteTitleSelector,
( element ) => element.contentEditable
);
expect( editable ).toBe( 'inherit' );
} );
} );