upkeep/e2e-utils-playwright: Exposing Playwright utils (#51982)

Co-authored-by: github-actions <github-actions@github.com>
This commit is contained in:
Siddharth Thevaril 2024-11-08 16:31:44 +05:30 committed by GitHub
parent 03ec423519
commit 30121f5be6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 267 additions and 3 deletions

View File

@ -0,0 +1,16 @@
{
"name": "@woocommerce/e2e-utils-playwright",
"version": "0.1.0",
"description": "End-To-End (E2E) test Playwright utils for WooCommerce",
"repository": {
"type": "git",
"url": "https://github.com/woocommerce/woocommerce.git"
},
"license": "GPL-3.0+",
"engines": {
"node": "^20.11.1",
"pnpm": "9.1.3"
},
"main": "src/index.js",
"module": "build-module/index.js"
}

View File

@ -0,0 +1,32 @@
/**
* Adds a specified quantity of a product by ID to the WooCommerce cart.
*
* @param page
* @param productId
* @param quantity
*/
export const addAProductToCart = async ( page, productId, quantity = 1 ) => {
for ( let i = 0; i < quantity; i++ ) {
const responsePromise = page.waitForResponse(
'**/wp-json/wc/store/v1/cart?**'
);
await page.goto( `/shop/?add-to-cart=${ productId }` );
await responsePromise;
await page.getByRole( 'alert' ).waitFor( { state: 'visible' } );
}
};
/**
* Util helper made for adding multiple same products to cart
*
* @param page
* @param productName
* @param quantityCount
*/
export async function addOneOrMoreProductToCart( page, productName, quantityCount ) {
await page.goto(
`product/${ productName.replace( / /gi, '-' ).toLowerCase() }`
);
await page.getByLabel( 'Product quantity' ).fill( quantityCount );
await page.locator( 'button[name="add-to-cart"]' ).click();
}

View File

@ -0,0 +1,79 @@
/**
* Util helper made for filling shipping details in the block-based checkout
*
* @param {Object} page
* @param {string} firstName
* @param {string} lastName
* @param {string} address
* @param {string} city
* @param {string} zip
*/
export async function fillShippingCheckoutBlocks(
page,
firstName = 'Homer',
lastName = 'Simpson',
address = '123 Evergreen Terrace',
city = 'Springfield',
zip = '97403'
) {
await page
.getByRole( 'group', { name: 'Shipping address' } )
.getByLabel( 'First name' )
.fill( firstName );
await page
.getByRole( 'group', { name: 'Shipping address' } )
.getByLabel( 'Last name' )
.fill( lastName );
await page
.getByRole( 'group', { name: 'Shipping address' } )
.getByLabel( 'Address', { exact: true } )
.fill( address );
await page
.getByRole( 'group', { name: 'Shipping address' } )
.getByLabel( 'City' )
.fill( city );
await page
.getByRole( 'group', { name: 'Shipping address' } )
.getByLabel( 'ZIP Code' )
.fill( zip );
}
/**
* Util helper made for filling billing details in the block-based checkout
*
* @param {Object} page
* @param {string} firstName
* @param {string} lastName
* @param {string} address
* @param {string} city
* @param {string} zip
*/
export async function fillBillingCheckoutBlocks(
page,
firstName = 'Mister',
lastName = 'Burns',
address = '156th Street',
city = 'Springfield',
zip = '98500'
) {
await page
.getByRole( 'group', { name: 'Billing address' } )
.getByLabel( 'First name' )
.fill( firstName );
await page
.getByRole( 'group', { name: 'Billing address' } )
.getByLabel( 'Last name' )
.fill( lastName );
await page
.getByRole( 'group', { name: 'Billing address' } )
.getByLabel( 'Address', { exact: true } )
.fill( address );
await page
.getByRole( 'group', { name: 'Billing address' } )
.getByLabel( 'City' )
.fill( city );
await page
.getByRole( 'group', { name: 'Billing address' } )
.getByLabel( 'ZIP Code' )
.fill( zip );
}

View File

@ -0,0 +1,119 @@
export const closeChoosePatternModal = async ( { page } ) => {
const closeModal = page
.getByLabel( 'Scrollable section' )
.filter()
.getByRole( 'button', {
name: 'Close',
exact: true,
} );
await page.addLocatorHandler( closeModal, async () => {
await closeModal.click();
} );
};
export const disableWelcomeModal = async ( { page } ) => {
// Further info: https://github.com/woocommerce/woocommerce/pull/45856/
await page.waitForLoadState( 'domcontentloaded' );
const isWelcomeGuideActive = await page.evaluate( () =>
window.wp.data.select( 'core/edit-post' ).isFeatureActive( 'welcomeGuide' )
);
if ( isWelcomeGuideActive ) {
await page.evaluate( () =>
window.wp.data.dispatch( 'core/edit-post' ).toggleFeature( 'welcomeGuide' )
);
}
};
export const openEditorSettings = async ( { page } ) => {
// Open Settings sidebar if closed
if ( await page.getByLabel( 'Editor Settings' ).isVisible() ) {
console.log( 'Editor Settings is open, skipping action.' );
} else {
await page.getByLabel( 'Settings', { exact: true } ).click();
}
};
export const getCanvas = async ( page ) => {
return page.frame( 'editor-canvas' ) || page;
};
export const goToPageEditor = async ( { page } ) => {
await page.goto( 'wp-admin/post-new.php?post_type=page' );
await disableWelcomeModal( { page } );
await closeChoosePatternModal( { page } );
};
export const goToPostEditor = async ( { page } ) => {
await page.goto( 'wp-admin/post-new.php' );
await disableWelcomeModal( { page } );
};
export const insertBlock = async ( page, blockName ) => {
await page
.getByRole( 'button', {
name: 'Toggle block inserter',
expanded: false,
} )
.click();
await page.getByPlaceholder( 'Search', { exact: true } ).fill( blockName );
await page.getByRole( 'option', { name: blockName, exact: true } ).click();
await page
.getByRole( 'button', {
name: 'Close block inserter',
} )
.click();
};
export const insertBlockByShortcut = async ( page, blockName ) => {
const canvas = await getCanvas( page );
await canvas.getByRole( 'button', { name: 'Add default block' } ).click();
await canvas
.getByRole( 'document', {
name: 'Empty block; start writing or type forward slash to choose a block',
} )
.pressSequentially( `/${ blockName }` );
await page.getByRole( 'option', { name: blockName, exact: true } ).click();
};
export const transformIntoBlocks = async ( page ) => {
const canvas = await getCanvas( page );
await canvas
.getByRole( 'button' )
.filter( { hasText: 'Transform into blocks' } )
.click();
};
export const publishPage = async ( page, pageTitle, isPost = false ) => {
await page
.getByRole( 'button', { name: 'Publish', exact: true } )
.dispatchEvent( 'click' );
const createPageResponse = page.waitForResponse( ( response ) => {
return (
response.url().includes( isPost ? '/posts/' : '/pages/' ) &&
response.ok() &&
response.request().method() === 'POST' &&
response
.json()
.then(
( json ) =>
json.title.rendered === pageTitle &&
json.status === 'publish'
)
);
} );
await page
.getByRole( 'region', { name: 'Editor publish' } )
.getByRole( 'button', { name: 'Publish', exact: true } )
.click();
// Validating that page was published via UI elements is not reliable,
// installed plugins (e.g. WooCommerce PayPal Payments) can interfere and add flakiness to the flow.
// In WC context, checking the API response is possibly the most reliable way to ensure the page was published.
await createPageResponse;
};

View File

@ -0,0 +1,4 @@
export * from './cart';
export * from './checkout';
export * from './editor';
export * from './order';

View File

@ -0,0 +1,4 @@
export function getOrderIdFromUrl( page ) {
const regex = /order-received\/(\d+)/;
return page.url().match( regex )[ 1 ];
}

View File

@ -0,0 +1,4 @@
Significance: patch
Type: dev
Comment: Expose Playwright E2E tests utils.

View File

@ -673,6 +673,7 @@
"@woocommerce/e2e-utils": "workspace:*", "@woocommerce/e2e-utils": "workspace:*",
"@woocommerce/eslint-plugin": "workspace:*", "@woocommerce/eslint-plugin": "workspace:*",
"@woocommerce/woocommerce-rest-api": "^1.0.1", "@woocommerce/woocommerce-rest-api": "^1.0.1",
"@woocommerce/e2e-utils-playwright": "workspace:*",
"@wordpress/babel-plugin-import-jsx-pragma": "1.1.3", "@wordpress/babel-plugin-import-jsx-pragma": "1.1.3",
"@wordpress/babel-preset-default": "3.0.2", "@wordpress/babel-preset-default": "3.0.2",
"@wordpress/e2e-test-utils-playwright": "wp-6.6", "@wordpress/e2e-test-utils-playwright": "wp-6.6",

View File

@ -1667,6 +1667,8 @@ importers:
specifier: 0.14.3 specifier: 0.14.3
version: 0.14.3 version: 0.14.3
packages/js/e2e-utils-playwright: {}
packages/js/eslint-plugin: packages/js/eslint-plugin:
dependencies: dependencies:
'@typescript-eslint/eslint-plugin': '@typescript-eslint/eslint-plugin':
@ -3375,6 +3377,9 @@ importers:
'@woocommerce/e2e-utils': '@woocommerce/e2e-utils':
specifier: workspace:* specifier: workspace:*
version: link:../../packages/js/e2e-utils version: link:../../packages/js/e2e-utils
'@woocommerce/e2e-utils-playwright':
specifier: workspace:*
version: link:../../packages/js/e2e-utils-playwright
'@woocommerce/eslint-plugin': '@woocommerce/eslint-plugin':
specifier: workspace:* specifier: workspace:*
version: link:../../packages/js/eslint-plugin version: link:../../packages/js/eslint-plugin
@ -65336,11 +65341,11 @@ snapshots:
'@webassemblyjs/ast': 1.11.6 '@webassemblyjs/ast': 1.11.6
'@webassemblyjs/wasm-edit': 1.11.6 '@webassemblyjs/wasm-edit': 1.11.6
'@webassemblyjs/wasm-parser': 1.11.6 '@webassemblyjs/wasm-parser': 1.11.6
acorn: 8.11.2 acorn: 8.12.1
acorn-import-assertions: 1.9.0(acorn@8.11.2) acorn-import-assertions: 1.9.0(acorn@8.12.1)
browserslist: 4.19.3 browserslist: 4.19.3
chrome-trace-event: 1.0.3 chrome-trace-event: 1.0.3
enhanced-resolve: 5.15.0 enhanced-resolve: 5.16.0
es-module-lexer: 1.4.1 es-module-lexer: 1.4.1
eslint-scope: 5.1.1 eslint-scope: 5.1.1
events: 3.3.0 events: 3.3.0