-
Notifications
You must be signed in to change notification settings - Fork 4.7k
Avatar: Add test to ensure that user image updates when user switched. #42657
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
Changes from 1 commit
f1f4c78
db68608
fb35688
f7e3ac3
7ff1221
48fe5d9
d5304eb
5b022d0
00477e3
d73113b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
…hes when set to a new user.
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,102 @@ | ||
| /** | ||
| * Internal dependencies | ||
| */ | ||
| import type { RequestUtils } from './index'; | ||
|
|
||
| export interface User { | ||
| id: number; | ||
| email: string; | ||
| } | ||
|
|
||
| export interface UserData { | ||
| username: string; | ||
| email: string; | ||
| firstName: string; | ||
| lastName: string; | ||
| password: string; | ||
| roles: string[]; | ||
| } | ||
|
|
||
| /** | ||
| * List all users. | ||
| * | ||
| * @see https://developer.wordpress.org/rest-api/reference/users/#list-users | ||
| * @param this | ||
| */ | ||
| async function listUsers( this: RequestUtils ) { | ||
| const response = await this.rest< User[] >( { | ||
| method: 'GET', | ||
| path: '/wp/v2/users', | ||
| params: { | ||
| per_page: 100, | ||
| }, | ||
| } ); | ||
|
|
||
| return response; | ||
| } | ||
|
|
||
| /** | ||
| * Add a test user. | ||
| * | ||
| * @see https://developer.wordpress.org/rest-api/reference/users/#create-a-user | ||
| * @param this | ||
| * @param user User data to create. | ||
| */ | ||
| async function createUser( this: RequestUtils, user: UserData ) { | ||
| const response = await this.rest< User >( { | ||
| method: 'POST', | ||
| path: '/wp/v2/users', | ||
| data: { | ||
| username: user.username, | ||
| email: user.email, | ||
| first_name: user.firstName, | ||
| last_name: user.lastName, | ||
| password: user.password, | ||
| roles: user.roles, | ||
|
||
| }, | ||
| } ); | ||
|
|
||
| return response; | ||
| } | ||
|
|
||
| /** | ||
| * Delete a user. | ||
| * | ||
| * @see https://developer.wordpress.org/rest-api/reference/users/#delete-a-user | ||
| * @param this | ||
| * @param userId The ID of the user. | ||
| */ | ||
| async function deleteUser( this: RequestUtils, userId: number ) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. #43064 is also implementing this function, and generally I prefer the way that version allows deleting a single user by passing a It's a difficult line to tread, whether the function is an exact facsimile of the REST API, or whether there are some convenience features built-in to make writing tests easier. Though perhaps in both cases
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think only exposing |
||
| // Do not delete main user account. | ||
| if ( userId === 1 ) { | ||
|
||
| return new Promise( ( resolve ) => { | ||
| resolve( true ); | ||
| } ); | ||
| } | ||
|
|
||
| const response = await this.rest( { | ||
| method: 'DELETE', | ||
| path: `/wp/v2/users/${ userId }`, | ||
| params: { force: true, reassign: 1 }, | ||
| } ); | ||
|
|
||
| return response; | ||
| } | ||
|
|
||
| /** | ||
| * Delete all users except main root user. | ||
| * | ||
| * @param this | ||
| */ | ||
| async function deleteAllUsers( this: RequestUtils ) { | ||
| const users = await this.listUsers(); | ||
|
|
||
| // The users endpoint doesn't support batch request yet. | ||
| const responses = await Promise.all( | ||
| users.map( ( user ) => this.deleteUser( user.id ) ) | ||
| ); | ||
|
|
||
| return responses; | ||
| } | ||
|
|
||
| export { listUsers, createUser, deleteAllUsers, deleteUser }; | ||
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,87 @@ | ||||||
| /** | ||||||
| * WordPress dependencies | ||||||
| */ | ||||||
|
|
||||||
| const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' ); | ||||||
|
|
||||||
| test.describe( 'Avatar', () => { | ||||||
| test.beforeAll( async ( { requestUtils } ) => { | ||||||
| await requestUtils.deleteAllUsers(); | ||||||
| } ); | ||||||
|
|
||||||
| test.beforeEach( async ( { admin, requestUtils } ) => { | ||||||
| await requestUtils.createUser( { | ||||||
| username: 'user', | ||||||
| email: 'gravatartest@gmail.com', | ||||||
| firstName: 'Gravatar', | ||||||
| lastName: 'Gravatar', | ||||||
| roles: [ 'author' ], | ||||||
| password: 'gravatargravatar123magic', | ||||||
| } ); | ||||||
|
|
||||||
| await admin.createNewPost(); | ||||||
| } ); | ||||||
|
|
||||||
| test.afterEach( async ( { requestUtils } ) => { | ||||||
| await requestUtils.deleteAllUsers(); | ||||||
| } ); | ||||||
|
Comment on lines
+8
to
+27
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's ok to structure this as:
|
||||||
|
|
||||||
| test( 'should change image when user is changed', async ( { | ||||||
| editor, | ||||||
| page, | ||||||
| } ) => { | ||||||
| // Inserting a quote block | ||||||
| await editor.insertBlock( { | ||||||
| name: 'core/avatar', | ||||||
| } ); | ||||||
|
|
||||||
| const username = 'Gravatar Gravatar'; | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the variable could be called |
||||||
|
|
||||||
| const avatarBlock = page.locator( | ||||||
| 'role=document[name="Block: Avatar"]' | ||||||
|
||||||
| 'role=document[name="Block: Avatar"]' | |
| 'role=document[name="Block: Avatar"i]' |
The i flag is good, it makes it case insensitive. That's useful as if the casing is changed in the code the test will still pass.
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line shouldn't be needed, as there's already await expect( avatarImage ).toBeVisible(); below, which will assert that the block is visible.
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally, there's no need to worry about all the intermediate elements being visible. An action like click will implicitly check that an element is visible.
Another thing is that it's good to prefer role selectors over css selectors. This practice will go some way to helping make sure Gutenberg is using accessible HTML.
You should be able to achieve the same sort of thing by doing:
const userInput = page.locator( 'role=region[name="Editor settings"i] >> role=combobox[name="User"i]' );
await userInput.click()The accessibility inspector in the browser dev tools is pretty good for figuring this stuff out:

There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good, thank you for the info.
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actions like click will always implicitly wait for an element to be visible in Playwright, so there's no need to make the assertion here.
There's a handy table showing how that works here - https://playwright.dev/docs/actionability
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this final assertion is needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not every property is required by the REST API. I think email is the only one. A question mark can be used to mark something as optional: