-
Notifications
You must be signed in to change notification settings - Fork 4.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Experiment] Use REST API in e2e tests to build up states (#33414)
- Loading branch information
1 parent
32f4af8
commit 7d8e740
Showing
12 changed files
with
278 additions
and
105 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
import { kebabCase } from 'lodash'; | ||
|
||
/** | ||
* Internal dependencies | ||
*/ | ||
import { rest } from './rest-api'; | ||
|
||
const pluginsMapPromise = ( async function getPluginsMap() { | ||
const plugins = await rest( { path: '/wp/v2/plugins' } ); | ||
const map = {}; | ||
for ( const plugin of plugins ) { | ||
// Ideally, we should be using sanitize_title() in PHP rather than kebabCase(), | ||
// but we don't have the exact port of it in JS. | ||
map[ kebabCase( plugin.name ) ] = plugin.plugin; | ||
} | ||
return map; | ||
} )(); | ||
|
||
/** | ||
* Activates an installed plugin. | ||
* | ||
* @param {string} slug Plugin slug. | ||
*/ | ||
async function activatePlugin( slug ) { | ||
const pluginsMap = await pluginsMapPromise; | ||
const plugin = pluginsMap[ slug ]; | ||
|
||
await rest( { | ||
method: 'PUT', | ||
path: `/wp/v2/plugins/${ plugin }`, | ||
data: { status: 'active' }, | ||
} ); | ||
} | ||
|
||
/** | ||
* Deactivates an active plugin. | ||
* | ||
* @param {string} slug Plugin slug. | ||
*/ | ||
async function deactivatePlugin( slug ) { | ||
const pluginsMap = await pluginsMapPromise; | ||
const plugin = pluginsMap[ slug ]; | ||
|
||
await rest( { | ||
method: 'PUT', | ||
path: `/wp/v2/plugins/${ plugin }`, | ||
data: { status: 'inactive' }, | ||
} ); | ||
} | ||
|
||
export { activatePlugin, deactivatePlugin }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
import fetch from 'node-fetch'; | ||
import FormData from 'form-data'; | ||
|
||
/** | ||
* WordPress dependencies | ||
*/ | ||
import apiFetch from '@wordpress/api-fetch'; | ||
|
||
/** | ||
* Internal dependencies | ||
*/ | ||
import { WP_BASE_URL } from './shared/config'; | ||
import { createURL } from './create-url'; | ||
|
||
// `apiFetch` expects `window.fetch` to be available in its default handler. | ||
global.window = global.window || {}; | ||
global.window.fetch = fetch; | ||
|
||
const setAPIRootURL = ( async () => { | ||
// Discover the API root url using link header. | ||
// See https://developer.wordpress.org/rest-api/using-the-rest-api/discovery/#link-header | ||
const res = await fetch( WP_BASE_URL, { method: 'HEAD' } ); | ||
const links = res.headers.get( 'link' ); | ||
const restLink = links.match( /<([^>]+)>; rel="https:\/\/api\.w\.org\/"/ ); | ||
|
||
if ( ! restLink ) { | ||
throw new Error( `Failed to discover REST API endpoint. | ||
Link header: ${ links }` ); | ||
} | ||
|
||
const [ , rootURL ] = restLink; | ||
apiFetch.use( apiFetch.createRootURLMiddleware( rootURL ) ); | ||
} )(); | ||
|
||
const setNonce = ( async () => { | ||
const formData = new FormData(); | ||
formData.append( 'log', 'admin' ); | ||
This comment has been minimized.
Sorry, something went wrong. |
||
formData.append( 'pwd', 'password' ); | ||
|
||
// Login to admin using fetch. | ||
const loginResponse = await fetch( createURL( 'wp-login.php' ), { | ||
method: 'POST', | ||
headers: formData.getHeaders(), | ||
body: formData, | ||
redirect: 'manual', | ||
} ); | ||
|
||
// Retrieve the cookies. | ||
const cookies = loginResponse.headers.get( 'set-cookie' ); | ||
const cookie = cookies | ||
.split( ',' ) | ||
.map( ( setCookie ) => setCookie.split( ';' )[ 0 ] ) | ||
.join( ';' ); | ||
|
||
apiFetch.nonceEndpoint = createURL( | ||
'wp-admin/admin-ajax.php', | ||
'action=rest-nonce' | ||
); | ||
|
||
// Get the initial nonce. | ||
const res = await fetch( apiFetch.nonceEndpoint, { | ||
headers: { cookie }, | ||
} ); | ||
const nonce = await res.text(); | ||
|
||
// Register the nonce middleware. | ||
apiFetch.use( apiFetch.createNonceMiddleware( nonce ) ); | ||
|
||
// For the nonce to work we have to also pass the cookies. | ||
apiFetch.use( function setCookieMiddleware( request, next ) { | ||
return next( { | ||
...request, | ||
headers: { | ||
...request.headers, | ||
cookie, | ||
}, | ||
} ); | ||
} ); | ||
} )(); | ||
|
||
/** | ||
* Call REST API using `apiFetch` to build and clear test states. | ||
* | ||
* @param {Object} options `apiFetch` options. | ||
* @return {Promise<any>} The response value. | ||
*/ | ||
async function rest( options = {} ) { | ||
// Only need to set them once but before any requests. | ||
await Promise.all( [ setAPIRootURL, setNonce ] ); | ||
|
||
return await apiFetch( options ); | ||
} | ||
|
||
/** | ||
* Call a set of REST APIs in batch. | ||
* See https://make.wordpress.org/core/2020/11/20/rest-api-batch-framework-in-wordpress-5-6/ | ||
* Note that calling GET requests in batch is not supported. | ||
* | ||
* @param {Array<Object>} requests The request objects. | ||
* @return {Promise<any>} The response value. | ||
*/ | ||
async function batch( requests ) { | ||
return await rest( { | ||
method: 'POST', | ||
path: '/batch/v1', | ||
data: { | ||
requests, | ||
validation: 'require-all-validate', | ||
}, | ||
} ); | ||
} | ||
|
||
export { rest, batch }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,32 +1,29 @@ | ||
/** | ||
* Internal dependencies | ||
*/ | ||
import { activatePlugin } from './activate-plugin'; | ||
import { deactivatePlugin } from './deactivate-plugin'; | ||
import { visitAdminPage } from './visit-admin-page'; | ||
import { rest, batch } from './rest-api'; | ||
|
||
/** | ||
* Delete all the widgets in the widgets screen. | ||
*/ | ||
export async function deleteAllWidgets() { | ||
// TODO: Deleting widgets in the new widgets screen is cumbersome and slow. | ||
// To workaround this for now, we visit the old widgets screen to delete them. | ||
await activatePlugin( 'gutenberg-test-classic-widgets' ); | ||
const [ widgets, sidebars ] = await Promise.all( [ | ||
rest( { path: '/wp/v2/widgets' } ), | ||
rest( { path: '/wp/v2/sidebars' } ), | ||
] ); | ||
|
||
await visitAdminPage( 'widgets.php' ); | ||
await batch( | ||
widgets.map( ( widget ) => ( { | ||
method: 'DELETE', | ||
path: `/wp/v2/widgets/${ widget.id }?force=true`, | ||
} ) ) | ||
); | ||
|
||
let widget = await page.$( '.widgets-sortables .widget' ); | ||
|
||
// We have to do this one-by-one since there might be race condition when deleting multiple widgets at once. | ||
while ( widget ) { | ||
const deleteButton = await widget.$( 'button.widget-control-remove' ); | ||
const id = await widget.evaluate( ( node ) => node.id ); | ||
await deleteButton.evaluate( ( node ) => node.click() ); | ||
// Wait for the widget to be removed from DOM. | ||
await page.waitForSelector( `#${ id }`, { hidden: true } ); | ||
|
||
widget = await page.$( '.widgets-sortables .widget' ); | ||
} | ||
|
||
await deactivatePlugin( 'gutenberg-test-classic-widgets' ); | ||
await batch( | ||
sidebars.map( ( sidebar ) => ( { | ||
method: 'POST', | ||
path: `/wp/v2/sidebars/${ sidebar.id }`, | ||
body: { id: sidebar.id, widgets: [] }, | ||
} ) ) | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,22 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
const path = require( 'path' ); | ||
|
||
const { ENVIRONMENT_DIRECTORY = '<rootDir>' } = process.env; | ||
|
||
module.exports = { | ||
...require( '@wordpress/scripts/config/jest-e2e.config' ), | ||
testMatch: [ '**/performance/*.test.js' ], | ||
setupFiles: [ '<rootDir>/config/gutenberg-phase.js' ], | ||
moduleNameMapper: { | ||
// Use different versions of e2e-test-utils for different environments | ||
// rather than always using the latest. | ||
[ `@wordpress\\/e2e-test-utils$` ]: path.join( | ||
ENVIRONMENT_DIRECTORY, | ||
This comment has been minimized.
Sorry, something went wrong.
senadir
Contributor
|
||
'packages/e2e-test-utils/src' | ||
), | ||
}, | ||
setupFilesAfterEnv: [ | ||
'<rootDir>/config/setup-performance-test.js', | ||
'@wordpress/jest-console', | ||
|
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
while running the test on a custom wordpress environment, this step fails because the custom wordpress environment does not support admin user.
Shouldn't this be configurable.