Blocks E2E: Streamline E2E utils implementation (#47660)

This commit is contained in:
Bart Kalisz 2024-05-27 16:54:06 +02:00 committed by GitHub
parent 012f0d3418
commit 460d73eee0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
127 changed files with 1615 additions and 2122 deletions

View File

@ -167,10 +167,7 @@ module.exports = {
'@wordpress/keycodes',
'@wordpress/url',
'@woocommerce/blocks-test-utils',
'@woocommerce/e2e-mocks',
'@woocommerce/e2e-types',
'@woocommerce/e2e-utils',
'@woocommerce/e2e-playwright-utils',
'babel-jest',
'dotenv',
'jest-environment-puppeteer',

View File

@ -8,28 +8,18 @@
"env": {
"tests": {
"mappings": {
"wp-cli.yml": "./wp-cli.yml",
"wp-content/mu-plugins": "./node_modules/@wordpress/e2e-tests/mu-plugins",
"wp-content/plugins/gutenberg-test-plugins": "./node_modules/@wordpress/e2e-tests/plugins",
"wp-content/plugins/woocommerce-blocks-test-plugins": "./tests/e2e/plugins",
"wp-cli.yml": "./wp-cli.yml",
"wp-content/plugins/woocommerce/blocks-bin": "./bin",
"wp-content/plugins/woocommerce/blocks-bin/playwright": "./tests/e2e/bin"
"wp-content/plugins/woocommerce/blocks-bin/playwright": "./tests/e2e/bin",
"wp-content/themes": "./tests/e2e/themes",
"wp-content/themes/storefront": "https://downloads.wordpress.org/theme/storefront.latest-stable.zip",
"wp-content/themes/twentytwentyfour": "https://downloads.wordpress.org/theme/twentytwentyfour.latest-stable.zip"
}
}
},
"themes": [
"https://downloads.wordpress.org/theme/storefront.latest-stable.zip",
"https://downloads.wordpress.org/theme/twentytwentyone.latest-stable.zip",
"https://downloads.wordpress.org/theme/twentytwentyfour.latest-stable.zip",
"./tests/e2e/themes/emptytheme",
"./tests/e2e/themes/storefront-child__block-notices-filter",
"./tests/e2e/themes/storefront-child__block-notices-template",
"./tests/e2e/themes/storefront-child__classic-notices-template",
"./tests/e2e/themes/theme-with-woo-templates",
"./tests/e2e/themes/twentytwentyfour-child__block-notices-filter",
"./tests/e2e/themes/twentytwentyfour-child__block-notices-template",
"./tests/e2e/themes/twentytwentyfour-child__classic-notices-template"
],
"config": {
"JETPACK_AUTOLOAD_DEV": true,
"SCRIPT_DEBUG": false,

Binary file not shown.

After

Width:  |  Height:  |  Size: 347 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 258 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

View File

@ -1,68 +1,287 @@
# E2E Guidelines <!-- omit in toc -->
# WooCommerce Blocks End-to-End Tests
## Table of contents <!-- omit in toc -->
This living document serves as a guide for writing end-to-end (E2E) tests with Playwright in the WooCommerce Blocks project.
- [Structure](#structure)
- [Playwright](#playwright)
- [Structure](#structure-1)
## Preparing the environment
This living document serves to prescribe coding guidelines specific to the WooCommerce Blocks project E2E tests. For more information on how to run Playwright end-to-end (E2E) tests, please refer to the [dedicated resource](../../tests/e2e/README.md).
Please refer to [the Getting Started section of the main `README.md`](https://github.com/woocommerce/woocommerce/blob/trunk/README.md) for a general-purpose guide on getting started. The rest of this document will assume that you've installed all of the prequisites and setup described there.
## Structure
Run the following command from the repository root to build the WooCommerce plugin:
There are two folders dedicated to E2E tests.
```sh
pnpm --filter='@woocommerce/plugin-woocommerce' watch:build
```
The first folder is named "e2e-jest" and it contains all the E2E tests that were created with the deprecated infrastructure Jest + Puppetter. The "e2e" folder contains all the E2E tests that were created with the current infrastructure: Playwright. These tests are actively maintained and should be used for all new E2E testing.
Next, run the following command from the [`woocommerce-blocks` plugin folder](../../../woocommerce-blocks/) to start a `wp-env` instance and install all the testing products, languages, etc.:
### Playwright
```shell
cd plugins/woocommerce-blocks/
pnpm env:start
```
#### Structure
> [!TIP]
> If you want to start/stop the environment without running the whole setup, use the native `wp-env` commands directly, e.g. `npx wp-env start` and `npx wp-env stop`.
There are three Playwright projects configuration:
The testing environment should now be ready under [localhost:8889](http://localhost:8889).
- blockTheme
- blockThemeWithGlobalSideEffects
- classicTheme
### Resetting the environment
The blockTheme project runs the tests with the suffix _block_theme_. In this case, the theme is a block theme. The block theme is the default WordPress theme. Currently, it is Twenty-Twenty Three. You should use this configuration if you want test the block with the Site Editor.
Occasionally, you'll need to reset the environment, e.g., when testing products have been updated. To do that, run the following command and go make yourself some coffee:
The blockThemeWithGlobalSideEffects project runs the tests with the suffix _block_theme.side_effects_. These tests have side effects that can potentially impact other end-to-end (E2E) tests. Due to the nature of these tests and their potential impact, they are not executed in parallel with other tests.
```shell
pnpm env:restart
```
The classicTheme project runs the tests with the suffix _classic_theme_. In this case, the theme is a Twenty Twenty-One. You should use this configuration if you want test the block with a classic theme.
## Running and debugging tests
Each block should have a dedicated folder with a scoped util file if you want share some logic related to the block.
> [!NOTE]
> If you're using VSCode, we recommend using the [Playwright Test](https://marketplace.visualstudio.com/items?itemName=ms-playwright.playwright) extension to run and debug the tests.
#### Code Guidelines
Here is a basic set of commands to quickly start running and debugging the tests. For full documentation, see the official Playwright guide on [Running and Debugging Tests](https://playwright.dev/docs/running-tests).
##### Make tests as isolated as possible - Avoid side effects
```shell
# Run all available tests.
pnpm test:e2e
Each test should be completely isolated from another test and should run independently with its own local storage, session storage, data, cookies etc. Test isolation improves reproducibility, makes debugging easier and prevents cascading test failures.
# Run in headed mode.
pnpm test:e2e --headed
In order to avoid repetition for a particular part of your test you can use before and after hooks. Within your test file add a before hook to run a part of your test before each test such as going to a particular URL or logging in to a part of your app. This keeps your tests isolated as no test relies on another. However it is also ok to have a little duplication when tests are simple enough especially if it keeps your tests clearer and easier to read and maintain. Avoid using functions that impact other tests, such as the `deleteAllTemplates` function, which restores all templates and can break other tests since E2E tests run in parallel. After running a suite of tests for a specific block, it is important to clean up any changes made during the tests to ensure a clean slate for subsequent test runs.
# Run/Debug in UI mode.
pnpm test:e2e --ui
For more detail see [Make Tests as Isolated as Possible](https://playwright.dev/docs/best-practices#make-tests-as-isolated-as-possible).
# Run a single test file.
pnpm run test:e2e cart-block.spec.ts
##### Use Locators
# Run a set of files from a different directories.
pnpm run test:e2e tests/cart/ tests/products/
In order to write end to end tests we need to first find elements on the webpage. We can do this by using Playwright's built in locators. Locators come with auto waiting and retry-ability. Auto waiting means that Playwright performs a range of actionability checks on the elements, such as ensuring the element is visible and enabled before it performs the click. To make tests resilient, we recommend prioritizing user-facing attributes and explicit contracts. For more detail see [Use Locators](https://playwright.dev/docs/best-practices#use-locators).
# Run files that have `cart` or `checkout` in the file name.
pnpm run test:e2e cart checkout
##### Avoid Using Relative Imports
# Run a single test via its line number.
pnpm run test:e2e cart-block.spec.ts:38
In order to make the codebase cleaner, you should import the function from the packages:
# Run/Debug a test with a specific title.
pnpm run test:e2e -g "should display a discount label" --ui
```
- "@woocommerce/e2e-utils": Contains generic utils for interactive with the page.
- "@woocommerce/e2e-types": Contains generic types.
- "@woocommerce/e2e-playwright-utils": Contains utils for playwright for example custom hooks.
> [!TIP]
> When a test fails, it leaves a trace info at the bottom. You can quickly jump into debugging mode by running the generated trace view command, for example:
>
> ![Playwright failed test report](../.media/images/e2e-open-trace-cmd.png)
By using these packages, you can make your code more modular and easier to maintain.
### Debugging tests in CI
<!-- FEEDBACK -->
When a test fails in CI, a failure artifact is zipped and uploaded to the Summary page of the current job:
---
![Summary page of the Blocks end-to-end tests job](../.media/images/e2e-download-failure-artifacts.png)
[We're hiring!](https://woocommerce.com/careers/) Come work with us!
Once you download and extract that zip, you'll see dedicated folders for the failed test artifacts. In CI, we retry running a failed test twice before considering it a failure, so there can be up to three folders per failed test. Each of those folders should contain a Playwright trace zip file and a screenshot from the failure moment. On the first retry, we also record the entire test, so the first retry folder should contain a video recording as well. To view a trace, head to the [Playwright Trace Viewer](https://trace.playwright.dev) page and drag and drop the trace zip file there, or run it from the command line:
🐞 Found a mistake, or have a suggestion? [Leave feedback about this document here.](https://github.com/woocommerce/woocommerce-blocks/issues/new?assignees=&labels=type%3A+documentation&template=--doc-feedback.md&title=Feedback%20on%20./docs/contributors/e2e-guidelines.md)
```shell
npx playwright show-trace <path-to-the-trace>
```
<!-- /FEEDBACK -->
## Writing Tests
We're using the [`@wordpress/e2e-test-utils-playwright`](https://github.com/WordPress/gutenberg/tree/HEAD/packages/e2e-test-utils-playwright) package as our framework base, so we generally follow Gutenberg E2E's [best practices](https://github.com/WordPress/gutenberg/blob/trunk/docs/contributors/code/e2e/README.md#best-practices) to reduce the framework entry threshold and necessary maintenance. However, our framework has specific aspects, which you can learn about in this section.
> [!TIP]
> Using the right selectors can be a daunting task, so let Playwright pick the right selector for you. Open the page you're testing against via `npx playwright open localhost:8889/path-to-the-page`. From there, you can use Playwright Inspector to generate the recommended locators:
>
> ![Playwright Inspector example usage](../.media/images/e2e-playwright-inspector.png)
>
> Read more about generating tests with Playwright in the [Generating Tests](https://playwright.dev/docs/codegen-intro) guide.
### Setup and teardown
We isolate our tests from each other by resetting the database to its initial state **for every test**. Since every test starts with a clean slate, and there's no need to manually reset the environment, we only allow the `beforeEach` hook as there's no point in using `beforeAll`, `afterAll`, or `afterEach`. This approach might seem like a limitation at first, but ultimately it makes tests more stable and easier to write. This convention is enforced by an ESLint rule, so you don't need to worry about it.
### Plugins
To use a custom plugin with your tests, first create the plugin PHP file and save it to the [test plugins folder](../../tests/e2e/plugins/). Here's a handy snippet to help you get started:
```php
// plugins/my-fancy-plugin.php
<?php
/**
* Plugin Name: WooCommerce Blocks Test My Fancy Plugin
* Plugin URI: https://github.com/woocommerce/woocommerce
* Author: WooCommerce
*
* @package woocommerce-blocks-test-my-fancy-plugin
*/
function my_fancy_plugin() {
echo 'Howdy!';
}
add_action('wp_footer', 'my_fancy_plugin');
```
Once the plugin is saved, it will be automatically picked up by `wp-env` - no need to restart the environment. To activate your plugin, use the `RequestUtils.activatePlugin()` API, for example:
```ts
// tests/my-fancy-plugin.spec.ts
import { test, expect } from '@woocommerce/e2e-utils';
test( 'My fancy plugin', async ( { page, requestUtils } ) => {
await requestUtils.activatePlugin(
'woocommerce-blocks-test-my-fancy-plugin'
);
await page.goto( '/shop' );
await expect( page.getByText( 'Howdy!' ) ).toBeVisible();
} );
```
> [!IMPORTANT]
> A plugin's slug is created automatically **from the plugin's name**, not from the `@package` statement as you might think. So, if your plugin is named `WooCommerce Blocks Test Bazzinga`, you'll need to activate it by `woocommerce-blocks-test-bazzinga`.
### Themes
Currently, the default theme is Twenty Twenty Four. Activating other themes is done by the `RequestUtils.activateTheme()` API, for example:
```ts
test.beforeEach( async ( { page, requestUtils } ) => {
await requestUtils.activateTheme( 'storefront' );
} );
```
> [!NOTE]
> Unless it's a one-off thing, remember to use the `beforeEach` hook to activate your theme. Each test starts with a clean database, which means the theme will be reset to the default one as well.
#### Adding a new theme
If you've created a custom theme and want to use it in your tests, save it in the [test themes folder](../../tests/e2e/themes/). Check out the themes that are already there for inspiration. The activation part was explained above, so you're good to go!
### Utilities
We have a handful of [custom utilities](../../tests/e2e/utils/) built on top of core's [`@wordpress/e2e-test-utils-playwright`](https://github.com/WordPress/gutenberg/tree/HEAD/packages/e2e-test-utils-playwright), so make sure to familiarize yourself with them.
#### Creating new utilities
Most of the time, it's better to do a little repetition instead of creating a utility, as over-abstracting can make the code too vague, complicated, or confusing. However, if the piece is complex and repeated enough, we recommend abstracting it into a [POM (Page Object Model)](https://playwright.dev/docs/pom), for example:
```ts
import { test as base, expect, Editor } from '@woocommerce/e2e-utils';
class CartUtils {
editor: Editor
constructor( { editor }: { editor: Editor } ) {
this.editor = editor;
}
async addClothes( list ) {
// Add clothes from the list.
}
async addBooks( list ) {
// Add books from the list.
}
}
const test = base.extend< { cartUtils: CartUtils } >( {
cartUtils: async ( { editor }, use ) => {
await use( new CartUtils( { editor } ) );
},
} );
test( 'Add products', async( { admin, cartUtils } ) => {
await admin.createNewPost();
await cartUtils.addClotes( [ 'Shirt', 'Cap', 'Pants' ] );
await cartUtils.addBooks( [ 'Cooking with Woo' ] )
await page.goto( '/cart' );
await expect( this.page.getByLabel( 'Shirt' ) ).toBeVisible();
// etc.
} );
```
#### Extending Core utilities
If you've come up with a utility that you think should be a part of the Core utilities (`Admin`, `Editor`, `RequestUtils`, etc.), go ahead and make a PR in Gutenberg - it's best to move as much as possible upstream. If you think that the utility still fits under, e.g., `Editor` but is Woo-specific, you'll need to write an extension, for example:
```ts
// utils/editor/index.ts
import { Editor as CoreEditor } from '@wordpress/e2e-test-utils-playwright';
export class Editor extends CoreEditor {
async insertAllWooBlocks() {
for ( const wooBlock of [ 'all', 'woo', 'blocks' ] ) {
await this.insertBlock( wooBlock );
}
}
}
```
### Content Templates
We have created `RequestUtils.createPostFromFile()` and `RequestUtils.createTemplateFromFile()` utilities that enable creating complex content testing scenarios with Handlebars templates. The template files are kept in the [content-templates](../../tests/e2e/content-templates/) folder, so you can head there for some inspiration.
> [!IMPORTANT]
> The Handlebars template filenames must be prefixed with the entity type. For posts, an example filename would be `post_with-filters.handlebars`, and for templates `template_archive-product_with-filters.handlebars`. Notice that the latter contains the slug of the template (`archive-product`) before the name (`with-filters`), separated with an underscore - it's necessary for the template to be properly loaded and created.
When you have the template ready, we recommend creating a [test fixture](https://playwright.dev/docs/test-fixtures) that will be used to compile and create your template with given data, for example:
```ts
// tests/product-collection.spec.ts
import { test as base, expect, TemplateCompiler } from '@woocommerce/e2e-utils';
const test = base.extend< {
filteredProductsTemplate: TemplateCompiler
} >( {
filteredProductsTemplate: async ( { requestUtils }, use ) => {
const compiler = await requestUtils.createTemplateFromFile(
'archive-product_with-filters'
);
await use( compiler );
},
} );
test( 'Renders correct products for $10-$99 price range', async ( {
page,
filteredProductsTemplate,
} ) => {
await filteredProductsTemplate.compile( {
price: {
from: '$10',
to: '$99',
},
} );
await page.goto( '/shop' );
await expect( page.getByLabel( 'Products' ) ).toHaveText( [
'Socks',
'T-Shirt',
] );
} );
test( 'Renders correct products for $100-$999 price range', async ( {
page,
filteredProductsTemplate,
} ) => {
await filteredProductsTemplate.compile( {
price: {
from: '$100',
to: '$990',
},
} );
await page.goto( '/shop' );
await expect( page.getByLabel( 'Products' ) ).toHaveText( [
'Rolex',
'Lambo',
] );
} );
```

View File

@ -1,224 +1,45 @@
# WooCommerce Blocks Playwright End to End Tests
# WooCommerce Blocks End-to-End Tests
This is the documentation for the new E2E testing setup based on Playwright and wp-env. Over time, these playwright E2E tests should replace the current [Puppeteer E2E tests](../e2e-jest/).
This document provides an overview of the WooCommerce Blocks end-to-end testing process. For detailed instructions and comprehensive guidelines, please refer to the [contributor guidelines document](../../docs/contributors/e2e-guidelines.md).
## Table of contents <!-- omit in toc -->
## Quick Start
- [Pre-requisites](#pre-requisites)
- [Introduction](#introduction)
- [Running tests for the first time](#running-tests-for-the-first-time)
- [To run the test again, re-create the environment to start with a fresh state](#to-run-the-test-again-re-create-the-environment-to-start-with-a-fresh-state)
- [Other ways of running tests](#other-ways-of-running-tests)
- [Troubleshooting](#troubleshooting)
### Preparing the Environment
## Pre-requisites
1. Build the WooCommerce Plugin:
- Node.js ([Installation instructions](https://nodejs.org/en/download/))
- NVM ([Installation instructions](https://github.com/nvm-sh/nvm))
- Docker and Docker Compose ([Installation instructions](https://docs.docker.com/engine/install/))
```sh
pnpm --filter='@woocommerce/plugin-woocommerce' watch:build
```
Note, that if you are on Mac and you install docker through other methods such as homebrew, for example, your steps to set it up might be different. The commands listed in steps below may also vary.
2. Go to the WooCommerce Blocks plugin folder:
If you are using Windows, we recommend using [Windows Subsystem for Linux (WSL)](https://docs.microsoft.com/en-us/windows/wsl/) for running E2E tests. Follow the [WSL Setup Instructions](../tests/e2e-jest/WSL_SETUP_INSTRUCTIONS.md) first before proceeding with the steps below.
```sh
cd plugins/woocommerce-blocks/
```
## Introduction
3. Start the environment:
End-to-end tests are powered by Playwright. The test site is spun up using `wp-env` (recommended), but we will continue to support `e2e-environment` in the meantime.
```sh
pnpm env:start
```
### Running tests for the first time
### Running the Tests
In the root directory, run:
1. Run all tests:
```sh
nvm use
```
```sh
pnpm test:e2e
```
```sh
pnpm install
```
2. Run a single test file:
Now change directory to `plugins/woocommerce-blocks/`:
```sh
pnpm test:e2e path/to/the/file.spec.ts
```
```sh
cd plugins/woocommerce-blocks/
```
3. Run/Debug in UI mode:
Ensure necessary browsers are installed:
```sh
npx playwright install
```
```sh
pnpm run env:start
```
```sh
pnpm run test:e2e
```
If you have any problems running the tests, check out the [Troubleshooting](#troubleshooting) section for help.
### To run the test again, re-create the environment to start with a fresh state
```sh
pnpm run env:restart
```
```sh
pnpm run test:e2e
```
### Adding posts for testing block content
During test setup posts are automatically created from all the html files contained in `./bin/posts`. All posts are given a title like `File Name Block` which generates a url like `file-name-block`.
e.g. `my-test.html` will generate a post with the title `My Test Block` and permalink `my-test-block`. You'll be able to navigate to that page in your test like:
```ts
await page.goto( '/my-test-block/' );
```
Please also note that the posts are generated during initial environment setup, so if you add or edit a post file you'll need to restart the environment to see the changes.
### Tests with side effects
We call tests that affect other tests (ones that modify the site settings, using custom plugins) are tests with side effects and we [split](https://github.com/woocommerce/woocommerce-blocks/pull/10508) those tests to a separate test suite:
```sh
pnpm run test:e2e:side-effects
```
_Note: All command parameters of `test:e2e` can be used for
`test:e2e:side-effects`._
### Tests with a classic theme and a block theme with custom templates
By default, e2e tests run in a non-customized block theme. However, we also have some e2e tests which run specifically in a classic theme and in a block theme with custom templates. They can be run like this:
```sh
pnpm run test:e2e:classic-theme
```
```sh
pnpm run test:e2e:block-theme-with-templates
```
\_Note: All command parameters of `test:e2e` can be used for these commands too.
### Other ways of running tests
Headless mode:
```sh
pnpm run test:e2e
```
Interactive UI mode:
```sh
pnpm run test:e2e --ui
```
Headed mode:
```sh
pnpm run test:e2e --headed
```
Debug mode:
```sh
pnpm run test:e2e --debug
```
Running a single test:
```sh
pnpm run test:e2e ./tests/e2e/tests/example.spec.ts
```
To see all options, run the following command:
```sh
npx playwright test --help
```
### Generating dynamic posts to test block variations
Testing a single block can be daunting considering all the different attribute combinations that could be
considered valid for a single block. The basic templating system available in this test suite allows for
the generation of dynamic posts that can be used to test block variations.
Templates use the Handlebars templating system and you can put them anywhere. It's simplest to co-locate them
with the test. You can easily pass custom attributes to a block in your template using the wp-block helper
we've defined.
It looks like this in the template:
```handlebars
{{#> wp-block name="woocommerce/featured-category" attributes=attributes /}}
You can nest content here if you want to test the block with some content.
{{/wp-block}}
```
In your tests you can use `createPostFromTemplate` to create a post containing your template. If you use it
more than once in your test you can extend the test suite and provide the posts as fixtures, like in the example
below
```js
import { test as base } from '@playwright/test';
const test = base.extend< {
dropdownBlockPost: Post;
defaultBlockPost: Post;
} >( {
defaultBlockPost: async ( { requestUtils }, use ) => {
const testingPost = await requestUtils.createPostFromTemplate(
requestUtils,
{ title: 'Product Filter Stock Status Block' },
TEMPLATE_PATH,
{}
);
await use( testingPost );
await requestUtils.deletePost( post.id );
},
dropdownBlockPost: async ( { requestUtils }, use ) => {
const testingPost = await requestUtils.createPostFromTemplate(
requestUtils,
{ title: 'Product Filter Stock Status Block' },
TEMPLATE_PATH,
{
attributes: {
displayStyle: 'dropdown',
},
}
);
await use( testingPost );
await requestUtils.deletePost( post.id );
},
} );
```
In your test you can navigate to the page. You won't need to clean it up, because
the fixture will take care of that for you.
```js
test( 'Test the block', async ( { page, defaultBlockPost } ) => {
await page.goto( defaultBlockPost.link );
// do your tests here
} );
```
### Troubleshooting
If you run into problems the first time you try to run the tests, please run the following command before starting the test suite:
```sh
pnpm wp-env:config
```
This helps set up your environment correctly and can prevent some of the usual issues from happening.
```sh
pnpm test:e2e --ui
```

View File

@ -1 +0,0 @@
export * from './test';

View File

@ -3,7 +3,7 @@ module.exports = {
type: 'problem',
docs: {
description:
'advise using @woocommerce/e2e-playwright-utils for importing test or expect functions',
'advise using @woocommerce/e2e-utils for importing test or expect functions',
category: 'Possible Errors',
recommended: true,
},
@ -11,7 +11,7 @@ module.exports = {
schema: [],
messages: {
unexpected:
"Prefer importing { test, expect } from '@woocommerce/e2e-playwright-utils'.",
"Prefer importing { test, expect } from '@woocommerce/e2e-utils'.",
},
},
create( context ) {
@ -34,12 +34,12 @@ module.exports = {
context.report( {
node,
message:
'Import test or expect from @woocommerce/e2e-playwright-utils instead of @playwright/test for additional utilities.',
'Import test or expect from @woocommerce/e2e-utils instead of @playwright/test for additional utilities.',
fix( fixer ) {
return [
fixer.replaceText(
node.source,
"'@woocommerce/e2e-playwright-utils'"
"'@woocommerce/e2e-utils'"
),
];
},

View File

@ -1,9 +1,12 @@
/**
* External dependencies
*/
import { BlockData } from '@woocommerce/e2e-types';
import { expect, test } from '@woocommerce/e2e-playwright-utils';
import { EditorUtils } from '@woocommerce/e2e-utils';
import {
test as base,
expect,
Editor,
BlockData,
} from '@woocommerce/e2e-utils';
/**
* Internal dependencies
@ -19,45 +22,62 @@ const blockData: BlockData = {
},
};
const configureSingleProductBlock = async ( editorUtils: EditorUtils ) => {
const singleProductBlock = await editorUtils.getBlockByName(
class BlockUtils {
editor: Editor;
constructor( { editor }: { editor: Editor } ) {
this.editor = editor;
}
async configureSingleProductBlock() {
const singleProductBlock = await this.editor.getBlockByName(
'woocommerce/single-product'
);
await singleProductBlock.locator( 'input[type="radio"]' ).nth( 0 ).click();
await singleProductBlock
.locator( 'input[type="radio"]' )
.nth( 0 )
.click();
await singleProductBlock.getByText( 'Done' ).click();
};
}
}
const test = base.extend< { blockUtils: BlockUtils } >( {
blockUtils: async ( { editor }, use ) => {
await use( new BlockUtils( { editor } ) );
},
} );
test.describe( `${ blockData.name } Block`, () => {
test( 'can be added in the Post Editor only as inner block of the Single Product Block', async ( {
admin,
editor,
editorUtils,
blockUtils,
} ) => {
// Add to Cart with Options in the Post Editor is only available as inner block of the Single Product Block.
await admin.createNewPost();
await editor.insertBlock( { name: 'woocommerce/single-product' } );
await configureSingleProductBlock( editorUtils );
await blockUtils.configureSingleProductBlock();
await expect(
await editorUtils.getBlockByName( blockData.slug )
await editor.getBlockByName( blockData.slug )
).toBeVisible();
// When the block is registered as ancestor, the function doesn't throw an error, but the block is not added.
// So we check that only one instance of the block is present.
await editor.insertBlock( { name: blockData.slug } );
await expect(
await editorUtils.getBlockByName( blockData.slug )
await editor.getBlockByName( blockData.slug )
).toBeVisible();
} );
test( 'can be added in the Site Editor only as inner block of the Single Product Block - Product Catalog Template', async ( {
admin,
editor,
editorUtils,
requestUtils,
blockUtils,
} ) => {
// Add to Cart with Options in the Site Editor is only available as
// inner block of the Single Product Block except for the Single Product
@ -78,24 +98,23 @@ test.describe( `${ blockData.name } Block`, () => {
await editor.insertBlock( { name: 'woocommerce/single-product' } );
await configureSingleProductBlock( editorUtils );
await blockUtils.configureSingleProductBlock();
await expect(
await editorUtils.getBlockByName( blockData.slug )
await editor.getBlockByName( blockData.slug )
).toBeVisible();
// When the block is registered as ancestor, the function doesn't throw an error, but the block is not added.
// So we check that only one instance of the block is present.
await editor.insertBlock( { name: blockData.slug } );
await expect(
await editorUtils.getBlockByName( blockData.slug )
await editor.getBlockByName( blockData.slug )
).toBeVisible();
} );
test( 'can be added in the Post Editor - Single Product Template', async ( {
admin,
editor,
editorUtils,
requestUtils,
} ) => {
const template = await requestUtils.createTemplate( 'wp_template', {
@ -115,7 +134,7 @@ test.describe( `${ blockData.name } Block`, () => {
await editor.insertBlock( { name: blockData.slug } );
await expect(
await editorUtils.getBlockByName( blockData.slug )
await editor.getBlockByName( blockData.slug )
).toBeVisible();
} );
} );

View File

@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { expect, test } from '@woocommerce/e2e-playwright-utils';
import { expect, test } from '@woocommerce/e2e-utils';
/**
* Internal dependencies
@ -16,10 +16,10 @@ test.describe( `${ BLOCK_NAME } Block`, () => {
} );
test( 'block can be inserted and it is rendered on the frontend', async ( {
editorUtils,
editor,
page,
} ) => {
await editorUtils.publishAndVisitPost();
await editor.publishAndVisitPost();
await expect(
page.locator( '.wc-block-grid__product.wc-block-layout' )

View File

@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { expect, test } from '@woocommerce/e2e-playwright-utils';
import { expect, test } from '@woocommerce/e2e-utils';
/**
* Internal dependencies
@ -29,11 +29,11 @@ test.describe( `${ BLOCK_NAME } Block`, () => {
test( 'block can be inserted and it sorts reviews by most recent by default', async ( {
frontendUtils,
page,
editorUtils,
editor,
} ) => {
await expect( page.getByText( allReviews[ 0 ].review ) ).toBeVisible();
await editorUtils.publishAndVisitPost();
await editor.publishAndVisitPost();
const block = await frontendUtils.getBlockByName( BLOCK_NAME );
const reviews = block.locator(
@ -46,9 +46,9 @@ test.describe( `${ BLOCK_NAME } Block`, () => {
test( 'can sort by highest rating in the frontend', async ( {
page,
frontendUtils,
editorUtils,
editor,
} ) => {
await editorUtils.publishAndVisitPost();
await editor.publishAndVisitPost();
const block = await frontendUtils.getBlockByName( BLOCK_NAME );
const reviews = block.locator(
@ -66,9 +66,9 @@ test.describe( `${ BLOCK_NAME } Block`, () => {
test( 'can sort by lowest rating in the frontend', async ( {
page,
frontendUtils,
editorUtils,
editor,
} ) => {
await editorUtils.publishAndVisitPost();
await editor.publishAndVisitPost();
const block = await frontendUtils.getBlockByName( BLOCK_NAME );
const reviews = block.locator(

View File

@ -1,15 +1,12 @@
/**
* External dependencies
*/
import { test, expect } from '@woocommerce/e2e-playwright-utils';
import { cli } from '@woocommerce/e2e-utils';
import path from 'path';
const PRODUCT_CATALOG_LINK = '/shop';
const TEMPLATE_PATH = path.join(
__dirname,
'../shared/filters-with-product-collection.handlebars'
);
import {
test as base,
expect,
cli,
TemplateCompiler,
} from '@woocommerce/e2e-utils';
const blockData = {
name: 'Filter by Attribute',
@ -17,8 +14,17 @@ const blockData = {
urlSearchParamWhenFilterIsApplied: 'filter_size=small&query_type_size=or',
};
const test = base.extend< { templateCompiler: TemplateCompiler } >( {
templateCompiler: async ( { requestUtils }, use ) => {
const compiler = await requestUtils.createTemplateFromFile(
'archive-product_filters-with-product-collection'
);
await use( compiler );
},
} );
test.describe( `${ blockData.name } Block`, () => {
test.beforeEach( async ( { admin, editor, editorUtils } ) => {
test.beforeEach( async ( { admin, editor } ) => {
await admin.createNewPost();
await editor.insertBlock( {
name: 'woocommerce/filter-wrapper',
@ -27,9 +33,7 @@ test.describe( `${ blockData.name } Block`, () => {
heading: 'Filter By Attribute',
},
} );
const attributeFilter = await editorUtils.getBlockByName(
blockData.slug
);
const attributeFilter = await editor.getBlockByName( blockData.slug );
await attributeFilter.getByText( 'Size' ).click();
await attributeFilter.getByText( 'Done' ).click();
@ -49,12 +53,9 @@ test.describe( `${ blockData.name } Block`, () => {
test( 'should allow changing the display style', async ( {
page,
editorUtils,
editor,
} ) => {
const attributeFilter = await editorUtils.getBlockByName(
blockData.slug
);
const attributeFilter = await editor.getBlockByName( blockData.slug );
await editor.selectBlocks( attributeFilter );
await expect(
@ -78,12 +79,9 @@ test.describe( `${ blockData.name } Block`, () => {
test( 'should allow toggling the visibility of the filter button', async ( {
page,
editorUtils,
editor,
} ) => {
const attributeFilter = await editorUtils.getBlockByName(
blockData.slug
);
const attributeFilter = await editor.getBlockByName( blockData.slug );
await editor.selectBlocks( attributeFilter );
await expect(
@ -103,7 +101,7 @@ test.describe( `${ blockData.name } Block`, () => {
} );
test.describe( `${ blockData.name } Block - with PHP classic template`, () => {
test.beforeEach( async ( { admin, page, editor, editorUtils } ) => {
test.beforeEach( async ( { admin, page, editor } ) => {
await cli(
'npm run wp-env run tests-cli -- wp option update wc_blocks_use_blockified_product_grid_block_as_template false'
);
@ -113,7 +111,7 @@ test.describe( `${ blockData.name } Block - with PHP classic template`, () => {
postType: 'wp_template',
} );
await editorUtils.enterEditMode();
await editor.enterEditMode();
await editor.insertBlock( {
name: 'woocommerce/filter-wrapper',
attributes: {
@ -121,15 +119,13 @@ test.describe( `${ blockData.name } Block - with PHP classic template`, () => {
heading: 'Filter By Attribute',
},
} );
const attributeFilter = await editorUtils.getBlockByName(
blockData.slug
);
const attributeFilter = await editor.getBlockByName( blockData.slug );
await attributeFilter.getByText( 'Size' ).click();
await attributeFilter.getByText( 'Done' ).click();
await editor.saveSiteEditorEntities();
await page.goto( PRODUCT_CATALOG_LINK );
await page.goto( '/shop' );
} );
test( 'should show all products', async ( { frontendUtils, page } ) => {
@ -179,16 +175,10 @@ test.describe( `${ blockData.name } Block - with PHP classic template`, () => {
} );
test.describe( `${ blockData.name } Block - with Product Collection`, () => {
test.beforeEach( async ( { requestUtils } ) => {
await requestUtils.updateTemplateContents(
'woocommerce/woocommerce//archive-product',
TEMPLATE_PATH,
{}
);
} );
test( 'should show all products', async ( { page, templateCompiler } ) => {
await templateCompiler.compile();
test( 'should show all products', async ( { page } ) => {
await page.goto( PRODUCT_CATALOG_LINK );
await page.goto( '/shop' );
const products = page
.locator( '.wp-block-woocommerce-product-template' )
.getByRole( 'listitem' );
@ -198,8 +188,11 @@ test.describe( `${ blockData.name } Block - with Product Collection`, () => {
test( 'should show only products that match the filter', async ( {
page,
templateCompiler,
} ) => {
await page.goto( PRODUCT_CATALOG_LINK );
await templateCompiler.compile();
await page.goto( '/shop' );
await page.getByRole( 'checkbox', { name: 'Small' } ).click();
await expect( page ).toHaveURL(
@ -217,15 +210,17 @@ test.describe( `${ blockData.name } Block - with Product Collection`, () => {
page,
admin,
editor,
editorUtils,
templateCompiler,
} ) => {
const template = await templateCompiler.compile();
await admin.visitSiteEditor( {
postId: 'woocommerce/woocommerce//archive-product',
postType: 'wp_template',
postId: template.id,
postType: template.type,
} );
await editorUtils.enterEditMode();
const attributeFilterControl = await editorUtils.getBlockByName(
await editor.enterEditMode();
const attributeFilterControl = await editor.getBlockByName(
blockData.slug
);
await expect( attributeFilterControl ).toBeVisible();
@ -235,7 +230,7 @@ test.describe( `${ blockData.name } Block - with Product Collection`, () => {
await page.getByText( "Show 'Apply filters' button" ).click();
await editor.saveSiteEditorEntities();
await page.goto( PRODUCT_CATALOG_LINK );
await page.goto( '/shop' );
await page.getByRole( 'checkbox', { name: 'Small' } ).click();
await page.getByRole( 'button', { name: 'Apply' } ).click();

View File

@ -1,41 +1,30 @@
/**
* External dependencies
*/
import { test as base, expect } from '@woocommerce/e2e-playwright-utils';
import { Post } from '@wordpress/e2e-test-utils-playwright/build-types/request-utils/posts';
import path from 'path';
const TEMPLATE_PATH = path.join(
__dirname,
'./filters-with-all-products.handlebars'
);
import { test as base, expect, PostCompiler } from '@woocommerce/e2e-utils';
const test = base.extend< {
defaultBlockPost: Post;
postCompiler: PostCompiler;
} >( {
defaultBlockPost: async ( { requestUtils }, use ) => {
const testingPost = await requestUtils.createPostFromTemplate(
{ title: 'Active Filters Block' },
TEMPLATE_PATH,
{}
postCompiler: async ( { requestUtils }, use ) => {
const post = await requestUtils.createPostFromFile(
'filters-with-all-products'
);
await use( testingPost );
await requestUtils.deletePost( testingPost.id );
await use( post );
},
} );
test.describe( 'Filter by Attributes Block - with All products Block', () => {
test( 'should show correct attrs count (color=blue|query_type_color=or)', async ( {
page,
defaultBlockPost,
postCompiler,
} ) => {
await page.goto(
`${ defaultBlockPost.link }?filter_color=blue&query_type_color=or`
);
const post = await postCompiler.compile( {} );
// Check if the page has loaded successfully.
await expect( page.getByText( 'Active Filters block' ) ).toBeVisible();
await page.goto(
`${ post.link }?filter_color=blue&query_type_color=or`
);
const expectedValues = [ '4', '2', '3', '4', '1' ];
@ -51,14 +40,13 @@ test.describe( 'Filter by Attributes Block - with All products Block', () => {
test( 'should show correct attrs count (color=blue,gray|query_type_color=or)', async ( {
page,
defaultBlockPost,
postCompiler,
} ) => {
await page.goto(
`${ defaultBlockPost.link }?filter_color=blue,gray&query_type_color=or`
);
const post = await postCompiler.compile( {} );
// Check if the page has loaded successfully.
await expect( page.getByText( 'Active Filters block' ) ).toBeVisible();
await page.goto(
`${ post.link }?filter_color=blue,gray&query_type_color=or`
);
const expectedValues = [ '4', '2', '3', '4', '1' ];
@ -74,14 +62,13 @@ test.describe( 'Filter by Attributes Block - with All products Block', () => {
test( 'should show correct attrs count (color=blue|query_type_color=or|min_price=15|max_price=40)', async ( {
page,
defaultBlockPost,
postCompiler,
} ) => {
await page.goto(
`${ defaultBlockPost.link }?filter_color=blue&query_type_color=or&min_price=15&max_price=40`
);
const post = await postCompiler.compile( {} );
// Check if the page has loaded successfully.
await expect( page.getByText( 'Active Filters block' ) ).toBeVisible();
await page.goto(
`${ post.link }?filter_color=blue&query_type_color=or&min_price=15&max_price=40`
);
const expectedValues = [ '2', '2', '2', '3', '1' ];

View File

@ -1,8 +1,7 @@
/**
* External dependencies
*/
import { test, expect } from '@woocommerce/e2e-playwright-utils';
import { customerFile, guestFile } from '@woocommerce/e2e-utils';
import { test, expect, customerFile, guestFile } from '@woocommerce/e2e-utils';
test.describe( 'Basic role-based functionality tests', () => {
test.describe( 'As admin', () => {

View File

@ -1,11 +1,7 @@
/**
* External dependencies
*/
import { expect, test } from '@woocommerce/e2e-playwright-utils';
/**
* Internal dependencies
*/
import { expect, test } from '@woocommerce/e2e-utils';
const blockData = {
slug: 'woocommerce/breadcrumbs',
@ -28,7 +24,6 @@ test.describe( `${ blockData.slug } Block`, () => {
test( 'block can be inserted in the Site Editor', async ( {
admin,
requestUtils,
editorUtils,
editor,
} ) => {
const template = await requestUtils.createTemplate( 'wp_template', {
@ -49,7 +44,7 @@ test.describe( `${ blockData.slug } Block`, () => {
name: blockData.slug,
} );
const block = await editorUtils.getBlockByName( blockData.slug );
const block = await editor.getBlockByName( blockData.slug );
await expect( block ).toHaveText( 'Breadcrumbs / Navigation / Path' );
} );

View File

@ -1,8 +1,7 @@
/**
* External dependencies
*/
import { BlockData } from '@woocommerce/e2e-types';
import { test, expect } from '@woocommerce/e2e-playwright-utils';
import { test, expect, BlockData } from '@woocommerce/e2e-utils';
const blockData: BlockData = {
name: 'Cart',
@ -25,24 +24,22 @@ test.describe( 'Merchant → Cart', () => {
const blockSelectorInEditor = blockData.selectors.editor.block as string;
test.describe( 'in page editor', () => {
test.beforeEach( async ( { editorUtils, admin } ) => {
test.beforeEach( async ( { editor, admin } ) => {
await admin.visitSiteEditor( {
postId: 'woocommerce/woocommerce//page-cart',
postType: 'wp_template',
} );
await editorUtils.enterEditMode();
await editor.enterEditMode();
} );
test( 'renders without crashing and can only be inserted once', async ( {
page,
editorUtils,
editor,
} ) => {
const blockPresence = await editorUtils.getBlockByName(
blockData.slug
);
const blockPresence = await editor.getBlockByName( blockData.slug );
expect( blockPresence ).toBeTruthy();
await editorUtils.openGlobalBlockInserter();
await editor.openGlobalBlockInserter();
await page.getByPlaceholder( 'Search' ).fill( blockData.slug );
const cartBlockButton = page.getByRole( 'option', {
name: blockData.name,
@ -57,7 +54,6 @@ test.describe( 'Merchant → Cart', () => {
test( 'inner blocks can be added/removed by filters', async ( {
page,
editor,
editorUtils,
} ) => {
// Begin by removing the block.
await editor.selectBlocks( blockSelectorInEditor );
@ -71,7 +67,7 @@ test.describe( 'Merchant → Cart', () => {
await removeButton.click();
// Expect block to have been removed.
await expect(
await editorUtils.getBlockByName( blockData.slug )
await editor.getBlockByName( blockData.slug )
).toHaveCount( 0 );
// Register a checkout filter to allow `core/table` block in the Checkout block's inner blocks, add
@ -91,7 +87,7 @@ test.describe( 'Merchant → Cart', () => {
await editor.insertBlock( { name: 'woocommerce/cart' } );
await expect(
await editorUtils.getBlockByName( blockData.slug )
await editor.getBlockByName( blockData.slug )
).not.toHaveCount( 0 );
// Select the cart-order-summary-block block and try to insert a block. Check the Table block is available.
@ -146,7 +142,6 @@ test.describe( 'Merchant → Cart', () => {
test( 'shows empty cart when changing the view', async ( {
page,
editor,
editorUtils,
} ) => {
await editor.selectBlocks( blockSelectorInEditor );
await editor.page
@ -160,10 +155,10 @@ test.describe( 'Merchant → Cart', () => {
await emptyCartButton.focus();
await emptyCartButton.dispatchEvent( 'click' );
const filledCartBlock = await editorUtils.getBlockByName(
const filledCartBlock = await editor.getBlockByName(
'woocommerce/filled-cart-block'
);
const emptyCartBlock = await editorUtils.getBlockByName(
const emptyCartBlock = await editor.getBlockByName(
'woocommerce/empty-cart-block'
);
await expect( filledCartBlock ).toBeHidden();

View File

@ -1,8 +1,7 @@
/**
* External dependencies
*/
import { CLASSIC_THEME_SLUG } from '@woocommerce/e2e-utils';
import { test, expect } from '@woocommerce/e2e-playwright-utils';
import { test, expect, CLASSIC_THEME_SLUG } from '@woocommerce/e2e-utils';
test.describe( 'Merchant → Cart', () => {
test.beforeEach( async ( { requestUtils } ) => {
@ -11,17 +10,16 @@ test.describe( 'Merchant → Cart', () => {
test.describe( 'in widget editor', () => {
test( "can't be inserted in a widget area", async ( {
editorUtils,
page,
admin,
editor,
} ) => {
await page.goto( '/wp-admin/widgets.php' );
await editorUtils.closeModalByName( 'Welcome to block Widgets' );
await admin.visitWidgetEditor();
await editorUtils.openGlobalBlockInserter();
await editorUtils.page
await editor.openGlobalBlockInserter();
await editor.page
.getByLabel( 'Search for blocks and patterns' )
.fill( 'woocommerce/cart' );
const cartButton = editorUtils.page.getByRole( 'option', {
const cartButton = editor.page.getByRole( 'option', {
name: 'Cart',
exact: true,
} );

View File

@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { test as base, expect } from '@woocommerce/e2e-playwright-utils';
import { test as base, expect } from '@woocommerce/e2e-utils';
/**
* Internal dependencies

View File

@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { test as base, expect } from '@woocommerce/e2e-playwright-utils';
import { test as base, expect } from '@woocommerce/e2e-utils';
/**
* Internal dependencies

View File

@ -1,8 +1,7 @@
/**
* External dependencies
*/
import { expect, test as base } from '@woocommerce/e2e-playwright-utils';
import { cli } from '@woocommerce/e2e-utils';
import { expect, test as base, cli } from '@woocommerce/e2e-utils';
/**
* Internal dependencies

View File

@ -1,14 +1,16 @@
/**
* External dependencies
*/
import { expect, test as base } from '@woocommerce/e2e-playwright-utils';
import {
expect,
test as base,
cli,
BLOCK_THEME_SLUG,
BLOCK_CHILD_THEME_WITH_BLOCK_NOTICES_FILTER_SLUG,
BLOCK_CHILD_THEME_WITH_BLOCK_NOTICES_TEMPLATE_SLUG,
BLOCK_CHILD_THEME_WITH_CLASSIC_NOTICES_TEMPLATE_SLUG,
} from '@woocommerce/e2e-utils';
/**
* Internal dependencies
*/

View File

@ -1,8 +1,9 @@
/**
* External dependencies
*/
import { expect, test as base } from '@woocommerce/e2e-playwright-utils';
import {
expect,
test as base,
cli,
CLASSIC_THEME_SLUG,
CLASSIC_CHILD_THEME_WITH_CLASSIC_NOTICES_TEMPLATE_SLUG,

View File

@ -1,8 +1,7 @@
/**
* External dependencies
*/
import { expect, test as base } from '@woocommerce/e2e-playwright-utils';
import { FrontendUtils } from '@woocommerce/e2e-utils';
import { expect, test as base, FrontendUtils } from '@woocommerce/e2e-utils';
/**
* Internal dependencies

View File

@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { expect, test as base } from '@woocommerce/e2e-playwright-utils';
import { expect, test as base } from '@woocommerce/e2e-utils';
/**
* Internal dependencies

View File

@ -1,8 +1,7 @@
/**
* External dependencies
*/
import { expect, test as base } from '@woocommerce/e2e-playwright-utils';
import { cli } from '@woocommerce/e2e-utils';
import { expect, test as base, cli } from '@woocommerce/e2e-utils';
/**
* Internal dependencies

View File

@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { expect, test } from '@woocommerce/e2e-playwright-utils';
import { expect, test } from '@woocommerce/e2e-utils';
const blockData = {
name: 'Catalog Sorting',
@ -25,7 +25,6 @@ test.describe( `${ blockData.slug } Block`, () => {
test( 'block can be inserted in the Site Editor', async ( {
admin,
requestUtils,
editorUtils,
editor,
} ) => {
const template = await requestUtils.createTemplate( 'wp_template', {
@ -46,7 +45,7 @@ test.describe( `${ blockData.slug } Block`, () => {
name: blockData.slug,
} );
const block = await editorUtils.getBlockByName( blockData.slug );
const block = await editor.getBlockByName( blockData.slug );
await expect( block ).toHaveText( 'Default sorting' );
} );
} );

View File

@ -1,8 +1,7 @@
/**
* External dependencies
*/
import { expect, test as base } from '@woocommerce/e2e-playwright-utils';
import { guestFile } from '@woocommerce/e2e-utils';
import { expect, test as base, guestFile } from '@woocommerce/e2e-utils';
/**
* Internal dependencies

View File

@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { expect, test as base } from '@woocommerce/e2e-playwright-utils';
import { expect, test as base } from '@woocommerce/e2e-utils';
/**
* Internal dependencies

View File

@ -1,8 +1,7 @@
/**
* External dependencies
*/
import { expect, test as base } from '@woocommerce/e2e-playwright-utils';
import { customerFile } from '@woocommerce/e2e-utils';
import { expect, test as base, customerFile } from '@woocommerce/e2e-utils';
/**
* Internal dependencies

View File

@ -1,8 +1,7 @@
/**
* External dependencies
*/
import { BlockData } from '@woocommerce/e2e-types';
import { test as base, expect } from '@woocommerce/e2e-playwright-utils';
import { test as base, expect, BlockData } from '@woocommerce/e2e-utils';
/**
* Internal dependencies
@ -42,32 +41,42 @@ test.describe( 'Merchant → Checkout', () => {
// `as string` is safe here because we know the variable is a string, it is defined above.
const blockSelectorInEditor = blockData.selectors.editor.block as string;
test.beforeEach( async ( { editorUtils, admin, editor } ) => {
test.beforeEach( async ( { admin, editor } ) => {
await admin.visitSiteEditor( {
postId: 'woocommerce/woocommerce//page-checkout',
postType: 'wp_template',
} );
await editorUtils.enterEditMode();
await editor.enterEditMode();
await editor.openDocumentSettingsSidebar();
} );
test( 'renders without crashing and can only be inserted once', async ( {
page,
editorUtils,
editor,
} ) => {
const blockPresence = await editorUtils.getBlockByName(
blockData.slug
);
const blockPresence = await editor.getBlockByName( blockData.slug );
expect( blockPresence ).toBeTruthy();
await editorUtils.openGlobalBlockInserter();
await editor.openGlobalBlockInserter();
await page.getByPlaceholder( 'Search' ).fill( blockData.slug );
const checkoutBlockButton = page.getByRole( 'option', {
name: blockData.name,
exact: true,
} );
expect( await editorUtils.ensureNoErrorsOnBlockPage() ).toBe( true );
const errorMessages = [
/This block contains unexpected or invalid content/gi,
/Your site doesnt include support for/gi,
/There was an error whilst rendering/gi,
/This block has encountered an error and cannot be previewed/gi,
];
for ( const errorMessage of errorMessages ) {
await expect(
editor.canvas.getByText( errorMessage )
).toBeHidden();
}
await expect(
editor.canvas.locator( blockSelectorInEditor )
).toBeVisible();
@ -140,7 +149,6 @@ test.describe( 'Merchant → Checkout', () => {
test( 'Merchant can see T&S and Privacy Policy links with checkbox', async ( {
frontendUtils,
checkoutPageObject,
editorUtils,
admin,
editor,
} ) => {
@ -148,7 +156,7 @@ test.describe( 'Merchant → Checkout', () => {
postId: 'woocommerce/woocommerce//page-checkout',
postType: 'wp_template',
} );
await editorUtils.enterEditMode();
await editor.enterEditMode();
await editor.openDocumentSettingsSidebar();
await editor.selectBlocks(
blockSelectorInEditor +
@ -191,7 +199,7 @@ test.describe( 'Merchant → Checkout', () => {
postId: 'woocommerce/woocommerce//page-checkout',
postType: 'wp_template',
} );
await editorUtils.enterEditMode();
await editor.enterEditMode();
await editor.openDocumentSettingsSidebar();
await editor.selectBlocks(
blockSelectorInEditor +
@ -208,7 +216,6 @@ test.describe( 'Merchant → Checkout', () => {
test( 'inner blocks can be added/removed by filters', async ( {
page,
editor,
editorUtils,
} ) => {
// Begin by removing the block.
await editor.selectBlocks( blockSelectorInEditor );
@ -222,7 +229,7 @@ test.describe( 'Merchant → Checkout', () => {
await removeButton.click();
// Expect block to have been removed.
await expect(
await editorUtils.getBlockByName( blockData.slug )
await editor.getBlockByName( blockData.slug )
).toHaveCount( 0 );
// Register a checkout filter to allow `core/table` block in the Checkout block's inner blocks, add
@ -241,7 +248,7 @@ test.describe( 'Merchant → Checkout', () => {
await editor.insertBlock( { name: 'woocommerce/checkout' } );
await expect(
await editorUtils.getBlockByName( blockData.slug )
await editor.getBlockByName( blockData.slug )
).not.toHaveCount( 0 );
// Select the checkout-fields-block block and try to insert a block. Check the Table block is available.
@ -293,14 +300,11 @@ test.describe( 'Merchant → Checkout', () => {
await editor.selectBlocks( blockSelectorInEditor );
} );
test( 'can enable dark mode inputs', async ( {
editorUtils,
page,
} ) => {
test( 'can enable dark mode inputs', async ( { editor, page } ) => {
const toggleLabel = page.getByLabel( 'Dark mode inputs' );
await toggleLabel.check();
const shippingAddressBlock = await editorUtils.getBlockByName(
const shippingAddressBlock = await editor.getBlockByName(
'woocommerce/checkout'
);
@ -320,14 +324,13 @@ test.describe( 'Merchant → Checkout', () => {
test( 'Company input visibility and optional and required can be toggled', async ( {
editor,
editorUtils,
} ) => {
await editor.selectBlocks(
blockSelectorInEditor +
' [data-type="woocommerce/checkout-shipping-address-block"]'
);
const shippingAddressBlock = await editorUtils.getBlockByName(
const shippingAddressBlock = await editor.getBlockByName(
'woocommerce/checkout-shipping-address-block'
);
@ -385,7 +388,7 @@ test.describe( 'Merchant → Checkout', () => {
' [data-type="woocommerce/checkout-billing-address-block"]'
);
const billingAddressBlock = await editorUtils.getBlockByName(
const billingAddressBlock = await editor.getBlockByName(
'woocommerce/checkout-billing-address-block'
);
@ -438,14 +441,13 @@ test.describe( 'Merchant → Checkout', () => {
test( 'Apartment input visibility and optional and required can be toggled', async ( {
editor,
editorUtils,
} ) => {
await editor.selectBlocks(
blockSelectorInEditor +
' [data-type="woocommerce/checkout-shipping-address-block"]'
);
const shippingAddressBlock = await editorUtils.getBlockByName(
const shippingAddressBlock = await editor.getBlockByName(
'woocommerce/checkout-shipping-address-block'
);
@ -508,7 +510,7 @@ test.describe( 'Merchant → Checkout', () => {
' [data-type="woocommerce/checkout-billing-address-block"]'
);
const billingAddressBlock = await editorUtils.getBlockByName(
const billingAddressBlock = await editor.getBlockByName(
'woocommerce/checkout-billing-address-block'
);
@ -573,14 +575,13 @@ test.describe( 'Merchant → Checkout', () => {
test( 'Phone input visibility and optional and required can be toggled', async ( {
editor,
editorUtils,
} ) => {
await editor.selectBlocks(
blockSelectorInEditor +
' [data-type="woocommerce/checkout-shipping-address-block"]'
);
const shippingAddressBlock = await editorUtils.getBlockByName(
const shippingAddressBlock = await editor.getBlockByName(
'woocommerce/checkout-shipping-address-block'
);
@ -632,7 +633,7 @@ test.describe( 'Merchant → Checkout', () => {
' [data-type="woocommerce/checkout-billing-address-block"]'
);
const billingAddressBlock = await editorUtils.getBlockByName(
const billingAddressBlock = await editor.getBlockByName(
'woocommerce/checkout-billing-address-block'
);
@ -688,7 +689,6 @@ test.describe( 'Merchant → Checkout', () => {
test( 'Return to cart link is visible and can be toggled', async ( {
editor,
editorUtils,
} ) => {
await editor.selectBlocks(
`${ blockSelectorInEditor } .wp-block-woocommerce-checkout-actions-block`
@ -700,7 +700,7 @@ test.describe( 'Merchant → Checkout', () => {
{ exact: true }
);
await returnToCartLinkToggle.check();
const shippingAddressBlock = await editorUtils.getBlockByName(
const shippingAddressBlock = await editor.getBlockByName(
'woocommerce/checkout-actions-block'
);

View File

@ -1,8 +1,7 @@
/**
* External dependencies
*/
import { CLASSIC_THEME_SLUG } from '@woocommerce/e2e-utils';
import { test, expect } from '@woocommerce/e2e-playwright-utils';
import { test, expect, CLASSIC_THEME_SLUG } from '@woocommerce/e2e-utils';
test.describe( 'Merchant → Checkout', () => {
test.beforeEach( async ( { requestUtils } ) => {
@ -11,17 +10,15 @@ test.describe( 'Merchant → Checkout', () => {
test.describe( 'in widget editor', () => {
test( "can't be inserted in a widget area", async ( {
editorUtils,
page,
admin,
editor,
} ) => {
await page.goto( '/wp-admin/widgets.php' );
await editorUtils.closeModalByName( 'Welcome to block Widgets' );
await editorUtils.openGlobalBlockInserter();
await editorUtils.page
await admin.visitWidgetEditor();
await editor.openGlobalBlockInserter();
await editor.page
.getByLabel( 'Search for blocks and patterns' )
.fill( 'woocommerce/checkout' );
const checkoutButton = editorUtils.page.getByRole( 'option', {
const checkoutButton = editor.page.getByRole( 'option', {
name: 'Checkout',
exact: true,
} );

View File

@ -1,9 +1,13 @@
/**
* External dependencies
*/
import { expect, test as base } from '@woocommerce/e2e-playwright-utils';
import { BlockData } from '@woocommerce/e2e-types';
import { customerFile, guestFile } from '@woocommerce/e2e-utils';
import {
expect,
test as base,
customerFile,
guestFile,
BlockData,
} from '@woocommerce/e2e-utils';
/**
* Internal dependencies
@ -243,12 +247,12 @@ test.describe( 'Shopper → Shipping and Billing Addresses', () => {
// `as string` is safe here because we know the variable is a string, it is defined above.
const blockSelectorInEditor = blockData.selectors.editor.block as string;
test.beforeEach( async ( { editor, admin, editorUtils, page } ) => {
test.beforeEach( async ( { admin, editor, page } ) => {
await admin.visitSiteEditor( {
postId: 'woocommerce/woocommerce//page-checkout',
postType: 'wp_template',
} );
await editorUtils.enterEditMode();
await editor.enterEditMode();
await editor.selectBlocks(
blockSelectorInEditor +
@ -268,7 +272,7 @@ test.describe( 'Shopper → Shipping and Billing Addresses', () => {
'div.wc-block-components-address-form__company'
)
).toBeVisible();
await editorUtils.saveSiteEditorEntities();
await editor.saveSiteEditorEntities();
} );
test( 'User can add postcodes for different countries', async ( {
@ -498,12 +502,7 @@ test.describe( 'Shopper → Checkout Form Errors (guest user)', () => {
test.describe( 'Billing Address Form', () => {
const blockSelectorInEditor = blockData.selectors.editor.block as string;
test( 'Enable company field', async ( {
page,
editor,
admin,
editorUtils,
} ) => {
test( 'Enable company field', async ( { page, admin, editor } ) => {
await admin.visitSiteEditor( {
postId: 'woocommerce/woocommerce//page-checkout',
postType: 'wp_template',
@ -526,7 +525,7 @@ test.describe( 'Billing Address Form', () => {
const companyInput = editor.canvas.getByLabel( 'Company (optional)' );
await expect( companyInput ).toBeVisible();
await editorUtils.saveSiteEditorEntities();
await editor.saveSiteEditorEntities();
} );
test.describe( 'Guest user', () => {

View File

@ -2,7 +2,7 @@
* External dependencies
*/
import { Page } from '@playwright/test';
import { expect } from '@woocommerce/e2e-playwright-utils';
import { expect } from '@woocommerce/e2e-utils';
/**
* Internal dependencies

View File

@ -1,8 +1,7 @@
/**
* External dependencies
*/
import { test as base, expect } from '@woocommerce/e2e-playwright-utils';
import { guestFile } from '@woocommerce/e2e-utils';
import { test as base, expect, guestFile } from '@woocommerce/e2e-utils';
/**
* Internal dependencies
@ -38,15 +37,15 @@ const test = base.extend< { pageObject: CheckoutPage } >( {
} );
test.describe( 'Shopper → Order Confirmation (logged in user)', () => {
test.beforeEach( async ( { admin, editorUtils, localPickupUtils } ) => {
test.beforeEach( async ( { admin, editor, localPickupUtils } ) => {
await localPickupUtils.disableLocalPickup();
await admin.visitSiteEditor( {
postId: 'woocommerce/woocommerce//order-confirmation',
postType: 'wp_template',
} );
await editorUtils.enterEditMode();
await editorUtils.transformIntoBlocks();
await editor.enterEditMode();
await editor.transformIntoBlocks();
} );
test( 'Place order', async ( {

View File

@ -1,9 +1,7 @@
/**
* External dependencies
*/
import { BlockData } from '@woocommerce/e2e-types';
import { test, expect } from '@woocommerce/e2e-playwright-utils';
import { cli } from '@woocommerce/e2e-utils';
import { test, expect, cli, BlockData } from '@woocommerce/e2e-utils';
/**
* Internal dependencies

View File

@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { expect, test } from '@woocommerce/e2e-playwright-utils';
import { expect, test } from '@woocommerce/e2e-utils';
const blockData = {
name: 'woocommerce/customer-account',
@ -47,14 +47,13 @@ test.describe( `${ blockData.name } Block`, () => {
editor,
page,
frontendUtils,
editorUtils,
} ) => {
await admin.createNewPost( { legacyCanvas: true } );
await admin.createNewPost();
await editor.insertBlock( { name: blockData.name } );
await selectTextOnlyOption( { page } );
await editorUtils.publishAndVisitPost();
await editor.publishAndVisitPost();
// We have specified the parent block name as 'main' to ensure that the
// block is found within the main content area of the page and not the hooked block in the header.
@ -76,14 +75,13 @@ test.describe( `${ blockData.name } Block`, () => {
editor,
page,
frontendUtils,
editorUtils,
} ) => {
await admin.createNewPost( { legacyCanvas: true } );
await admin.createNewPost();
await editor.insertBlock( { name: blockData.name } );
await selectIconOnlyOption( { page } );
await editorUtils.publishAndVisitPost();
await editor.publishAndVisitPost();
// We have specified the parent block name as 'main' to ensure that the
// block is found within the main content area of the page and not the hooked block in the header.
@ -105,14 +103,13 @@ test.describe( `${ blockData.name } Block`, () => {
editor,
page,
frontendUtils,
editorUtils,
} ) => {
await admin.createNewPost( { legacyCanvas: true } );
await admin.createNewPost();
await editor.insertBlock( { name: blockData.name } );
await selectIconAndTextOption( { page } );
await editorUtils.publishAndVisitPost();
await editor.publishAndVisitPost();
// We have specified the parent block name as 'main' to ensure that the
// block is found within the main content area of the page and not the hooked block in the header.

View File

@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { expect, test } from '@woocommerce/e2e-playwright-utils';
import { expect, test } from '@woocommerce/e2e-utils';
const blockData = {
slug: 'woocommerce/featured-category',
@ -9,17 +9,16 @@ const blockData = {
test.describe( `${ blockData.slug } Block`, () => {
test( 'can be inserted in Post Editor and it is visible on the frontend', async ( {
editorUtils,
editor,
admin,
frontendUtils,
} ) => {
await admin.createNewPost();
await editor.insertBlock( { name: blockData.slug } );
const blockLocator = await editorUtils.getBlockByName( blockData.slug );
const blockLocator = await editor.getBlockByName( blockData.slug );
await blockLocator.getByText( 'Music' ).click();
await blockLocator.getByText( 'Done' ).click();
await editorUtils.publishAndVisitPost();
await editor.publishAndVisitPost();
const blockLocatorFrontend = await frontendUtils.getBlockByName(
blockData.slug
);

View File

@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { expect, test } from '@woocommerce/e2e-playwright-utils';
import { expect, test } from '@woocommerce/e2e-utils';
const blockData = {
slug: 'woocommerce/featured-product',
@ -9,17 +9,16 @@ const blockData = {
test.describe( `${ blockData.slug } Block`, () => {
test( 'can be inserted in Post Editor and it is visible on the frontend', async ( {
editorUtils,
editor,
admin,
frontendUtils,
} ) => {
await admin.createNewPost();
await editor.insertBlock( { name: blockData.slug } );
const blockLocator = await editorUtils.getBlockByName( blockData.slug );
const blockLocator = await editor.getBlockByName( blockData.slug );
await blockLocator.getByText( 'Album' ).click();
await blockLocator.getByText( 'Done' ).click();
await editorUtils.publishAndVisitPost();
await editor.publishAndVisitPost();
const blockLocatorFrontend = await frontendUtils.getBlockByName(
blockData.slug
);

View File

@ -1,15 +1,16 @@
/**
* External dependencies
*/
import { test, expect } from '@woocommerce/e2e-playwright-utils';
import path from 'path';
import { TemplateCompiler, test as base, expect } from '@woocommerce/e2e-utils';
/**
* Internal dependencies
*/
import { PRODUCT_CATALOG_LINK, PRODUCT_CATALOG_TEMPLATE_ID } from './constants';
const TEMPLATE_PATH = path.join( __dirname, './active-filters.handlebars' );
const test = base.extend< { templateCompiler: TemplateCompiler } >( {
templateCompiler: async ( { requestUtils }, use ) => {
const compiler = await requestUtils.createTemplateFromFile(
'archive-product_active-filters'
);
await use( compiler );
},
} );
test.describe( 'Product Filter: Active Filters Block', () => {
test.describe( 'frontend', () => {
@ -17,17 +18,15 @@ test.describe( 'Product Filter: Active Filters Block', () => {
await requestUtils.activatePlugin(
'woocommerce-blocks-test-enable-experimental-features'
);
await requestUtils.updateTemplateContents(
PRODUCT_CATALOG_TEMPLATE_ID,
TEMPLATE_PATH,
{}
);
} );
test( 'Without any filters selected, only a wrapper block is rendered', async ( {
page,
templateCompiler,
} ) => {
await page.goto( PRODUCT_CATALOG_LINK );
await templateCompiler.compile();
await page.goto( '/shop' );
const locator = page.locator(
'.wp-block-woocommerce-product-filter'
@ -41,8 +40,11 @@ test.describe( 'Product Filter: Active Filters Block', () => {
test( 'With rating filters applied it shows the correct active filters', async ( {
page,
templateCompiler,
} ) => {
await page.goto( `${ PRODUCT_CATALOG_LINK }?rating_filter=1,2,5` );
await templateCompiler.compile();
await page.goto( `${ '/shop' }?rating_filter=1,2,5` );
await expect( page.getByText( 'Rating:' ) ).toBeVisible();
await expect( page.getByText( 'Rated 1 out of 5' ) ).toBeVisible();
@ -52,9 +54,12 @@ test.describe( 'Product Filter: Active Filters Block', () => {
test( 'With stock filters applied it shows the correct active filters', async ( {
page,
templateCompiler,
} ) => {
await templateCompiler.compile();
await page.goto(
`${ PRODUCT_CATALOG_LINK }?filter_stock_status=instock,onbackorder`
`${ '/shop' }?filter_stock_status=instock,onbackorder`
);
await expect( page.getByText( 'Stock Status:' ) ).toBeVisible();
@ -64,9 +69,12 @@ test.describe( 'Product Filter: Active Filters Block', () => {
test( 'With attribute filters applied it shows the correct active filters', async ( {
page,
templateCompiler,
} ) => {
await templateCompiler.compile();
await page.goto(
`${ PRODUCT_CATALOG_LINK }?filter_color=blue,gray&query_type_color=or`
`${ '/shop' }?filter_color=blue,gray&query_type_color=or`
);
await expect( page.getByText( 'Color:' ) ).toBeVisible();
@ -76,10 +84,11 @@ test.describe( 'Product Filter: Active Filters Block', () => {
test( 'With price filters applied it shows the correct active filters', async ( {
page,
templateCompiler,
} ) => {
await page.goto(
`${ PRODUCT_CATALOG_LINK }?min_price=17&max_price=71`
);
await templateCompiler.compile();
await page.goto( `${ '/shop' }?min_price=17&max_price=71` );
await expect( page.getByText( 'Price:' ) ).toBeVisible();
await expect(

View File

@ -1,18 +1,9 @@
/**
* External dependencies
*/
import { test, expect } from '@woocommerce/e2e-playwright-utils';
import path from 'path';
/**
* Internal dependencies
*/
import { PRODUCT_CATALOG_LINK, PRODUCT_CATALOG_TEMPLATE_ID } from './constants';
const TEMPLATE_PATH = path.join( __dirname, './attribute-filter.handlebars' );
import { TemplateCompiler, test as base, expect } from '@woocommerce/e2e-utils';
const COLOR_ATTRIBUTE_VALUES = [ 'Blue', 'Gray', 'Green', 'Red', 'Yellow' ];
const COLOR_ATTRIBUTES_WITH_COUNTS = [
'Blue (4)',
'Gray (2)',
@ -21,27 +12,32 @@ const COLOR_ATTRIBUTES_WITH_COUNTS = [
'Yellow (1)',
];
const test = base.extend< { templateCompiler: TemplateCompiler } >( {
templateCompiler: async ( { requestUtils }, use ) => {
const compiler = await requestUtils.createTemplateFromFile(
'archive-product_attribute-filter'
);
await use( compiler );
},
} );
test.describe( 'Product Filter: Attribute Block', () => {
test.describe( 'With default display style', () => {
test.beforeEach( async ( { requestUtils } ) => {
test.beforeEach( async ( { requestUtils, templateCompiler } ) => {
await requestUtils.activatePlugin(
'woocommerce-blocks-test-enable-experimental-features'
);
await requestUtils.updateTemplateContents(
PRODUCT_CATALOG_TEMPLATE_ID,
TEMPLATE_PATH,
{
await templateCompiler.compile( {
attributes: {
attributeId: 1,
},
}
);
} );
} );
test( 'clear button is not shown on initial page load', async ( {
page,
} ) => {
await page.goto( PRODUCT_CATALOG_LINK );
await page.goto( '/shop' );
const button = page.getByRole( 'button', { name: 'Clear' } );
@ -51,7 +47,7 @@ test.describe( 'Product Filter: Attribute Block', () => {
test( 'renders a checkbox list with the available attribute filters', async ( {
page,
} ) => {
await page.goto( PRODUCT_CATALOG_LINK );
await page.goto( '/shop' );
const attributes = page.locator(
'.wc-block-components-checkbox__label'
@ -69,7 +65,7 @@ test.describe( 'Product Filter: Attribute Block', () => {
test( 'filters the list of products by selecting an attribute', async ( {
page,
} ) => {
await page.goto( PRODUCT_CATALOG_LINK );
await page.goto( '/shop' );
const grayCheckbox = page.getByText( 'Gray' );
await grayCheckbox.click();
@ -85,7 +81,7 @@ test.describe( 'Product Filter: Attribute Block', () => {
test( 'clear button appears after a filter is applied', async ( {
page,
} ) => {
await page.goto( PRODUCT_CATALOG_LINK );
await page.goto( '/shop' );
const grayCheckbox = page.getByText( 'Gray' );
await grayCheckbox.click();
@ -101,7 +97,7 @@ test.describe( 'Product Filter: Attribute Block', () => {
test( 'clear button hides after deselecting all filters', async ( {
page,
} ) => {
await page.goto( PRODUCT_CATALOG_LINK );
await page.goto( '/shop' );
const grayCheckbox = page.getByText( 'Gray' );
await grayCheckbox.click();
@ -119,7 +115,7 @@ test.describe( 'Product Filter: Attribute Block', () => {
test( 'filters are cleared after clear button is clicked', async ( {
page,
} ) => {
await page.goto( PRODUCT_CATALOG_LINK );
await page.goto( '/shop' );
const grayCheckbox = page.getByText( 'Gray' );
await grayCheckbox.click();
@ -142,26 +138,22 @@ test.describe( 'Product Filter: Attribute Block', () => {
} );
test.describe( 'With show counts enabled', () => {
test.beforeEach( async ( { requestUtils } ) => {
test.beforeEach( async ( { requestUtils, templateCompiler } ) => {
await requestUtils.activatePlugin(
'woocommerce-blocks-test-enable-experimental-features'
);
await requestUtils.updateTemplateContents(
PRODUCT_CATALOG_TEMPLATE_ID,
TEMPLATE_PATH,
{
await templateCompiler.compile( {
attributes: {
attributeId: 1,
showCounts: true,
},
}
);
} );
} );
test( 'Renders checkboxes with associated product counts', async ( {
page,
} ) => {
await page.goto( PRODUCT_CATALOG_LINK );
await page.goto( '/shop' );
const attributes = page.locator(
'.wc-block-components-checkbox__label'
@ -178,26 +170,22 @@ test.describe( 'Product Filter: Attribute Block', () => {
} );
test.describe( "With display style 'dropdown'", () => {
test.beforeEach( async ( { requestUtils } ) => {
test.beforeEach( async ( { requestUtils, templateCompiler } ) => {
await requestUtils.activatePlugin(
'woocommerce-blocks-test-enable-experimental-features'
);
await requestUtils.updateTemplateContents(
PRODUCT_CATALOG_TEMPLATE_ID,
TEMPLATE_PATH,
{
await templateCompiler.compile( {
attributes: {
attributeId: 1,
displayStyle: 'dropdown',
},
}
);
} );
} );
test( 'clear button is not shown on initial page load', async ( {
page,
} ) => {
await page.goto( PRODUCT_CATALOG_LINK );
await page.goto( '/shop' );
const button = page.getByRole( 'button', { name: 'Clear' } );
@ -207,7 +195,7 @@ test.describe( 'Product Filter: Attribute Block', () => {
test( 'renders a dropdown list with the available attribute filters', async ( {
page,
} ) => {
await page.goto( PRODUCT_CATALOG_LINK );
await page.goto( '/shop' );
const dropdownLocator = page.locator(
'.wc-interactivity-dropdown'
@ -226,7 +214,7 @@ test.describe( 'Product Filter: Attribute Block', () => {
test( 'Clicking a dropdown option should filter the displayed products', async ( {
page,
} ) => {
await page.goto( PRODUCT_CATALOG_LINK );
await page.goto( '/shop' );
const dropdownLocator = page.locator(
'.wc-interactivity-dropdown'
@ -249,7 +237,7 @@ test.describe( 'Product Filter: Attribute Block', () => {
test( 'clear button appears after a filter is applied', async ( {
page,
} ) => {
await page.goto( PRODUCT_CATALOG_LINK );
await page.goto( '/shop' );
const dropdownLocator = page.locator(
'.wc-interactivity-dropdown'
@ -272,7 +260,7 @@ test.describe( 'Product Filter: Attribute Block', () => {
test( 'clear button hides after deselecting all filters', async ( {
page,
} ) => {
await page.goto( PRODUCT_CATALOG_LINK );
await page.goto( '/shop' );
const dropdownLocator = page.locator(
'.wc-interactivity-dropdown'
@ -302,7 +290,7 @@ test.describe( 'Product Filter: Attribute Block', () => {
test( 'filters are cleared after clear button is clicked', async ( {
page,
} ) => {
await page.goto( PRODUCT_CATALOG_LINK );
await page.goto( '/shop' );
const dropdownLocator = page.locator(
'.wc-interactivity-dropdown'

View File

@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { test, expect } from '@woocommerce/e2e-playwright-utils';
import { test, expect } from '@woocommerce/e2e-utils';
const filterBlocks = [
{
@ -41,10 +41,10 @@ test.describe( 'Filter blocks registration', () => {
test( 'Variations can be inserted through the inserter.', async ( {
page,
editorUtils,
editor,
} ) => {
for ( const block of filterBlocks ) {
await editorUtils.insertBlockUsingGlobalInserter( block.title );
await editor.insertBlockUsingGlobalInserter( block.title );
await expect(
page.getByLabel( `Block: ${ block.title }` )
@ -53,11 +53,11 @@ test.describe( 'Filter blocks registration', () => {
} );
test( 'Each filter block comes with a default title', async ( {
editorUtils,
editor,
page,
} ) => {
for ( const block of filterBlocks ) {
await editorUtils.insertBlockUsingGlobalInserter( block.title );
await editor.insertBlockUsingGlobalInserter( block.title );
await expect(
page

View File

@ -1,3 +0,0 @@
export const PRODUCT_CATALOG_LINK = '/shop';
export const PRODUCT_CATALOG_TEMPLATE_ID =
'woocommerce/woocommerce//archive-product';

View File

@ -1,33 +1,30 @@
/**
* External dependencies
*/
import { test, expect } from '@woocommerce/e2e-playwright-utils';
import path from 'path';
import { TemplateCompiler, test as base, expect } from '@woocommerce/e2e-utils';
/**
* Internal dependencies
*/
import { PRODUCT_CATALOG_LINK, PRODUCT_CATALOG_TEMPLATE_ID } from './constants';
const TEMPLATE_PATH = path.join( __dirname, './price-filter.handlebars' );
const test = base.extend< { templateCompiler: TemplateCompiler } >( {
templateCompiler: async ( { requestUtils }, use ) => {
const compiler = await requestUtils.createTemplateFromFile(
'archive-product_price-filter'
);
await use( compiler );
},
} );
test.describe( 'Product Filter: Price Filter Block', () => {
test.describe( 'frontend', () => {
test.beforeEach( async ( { requestUtils } ) => {
test.beforeEach( async ( { requestUtils, templateCompiler } ) => {
await requestUtils.activatePlugin(
'woocommerce-blocks-test-enable-experimental-features'
);
await requestUtils.updateTemplateContents(
PRODUCT_CATALOG_TEMPLATE_ID,
TEMPLATE_PATH,
{}
);
await templateCompiler.compile();
} );
test( 'clear button is not shown on initial page load', async ( {
page,
} ) => {
await page.goto( PRODUCT_CATALOG_LINK );
await page.goto( '/shop' );
const button = page.getByRole( 'button', { name: 'Clear' } );
@ -37,9 +34,7 @@ test.describe( 'Product Filter: Price Filter Block', () => {
test( 'With price filters applied it shows the correct price', async ( {
page,
} ) => {
await page.goto(
`${ PRODUCT_CATALOG_LINK }?min_price=20&max_price=67`
);
await page.goto( '/shop?min_price=20&max_price=67' );
// Min price input field
const leftInputContainer = page.locator(
@ -74,9 +69,7 @@ test.describe( 'Product Filter: Price Filter Block', () => {
test( 'clear button appears after a filter is applied', async ( {
page,
} ) => {
await page.goto(
`${ PRODUCT_CATALOG_LINK }?min_price=20&max_price=67`
);
await page.goto( '/shop?min_price=20&max_price=67' );
const button = page.getByRole( 'button', { name: 'Clear' } );
@ -86,13 +79,11 @@ test.describe( 'Product Filter: Price Filter Block', () => {
test( 'clear button hides after deselecting all filters', async ( {
page,
} ) => {
await page.goto(
`${ PRODUCT_CATALOG_LINK }?min_price=20&max_price=67`
);
await page.goto( '/shop?min_price=20&max_price=67' );
const defaultRange = await page
const defaultRange = ( await page
.locator( '.wp-block-woocommerce-product-filter-price' )
.getAttribute( 'data-wc-context' );
.getAttribute( 'data-wc-context' ) ) as string;
const defaultMinRange = JSON.parse( defaultRange ).minRange;
const defaultMaxRange = JSON.parse( defaultRange ).maxRange;
@ -120,19 +111,17 @@ test.describe( 'Product Filter: Price Filter Block', () => {
test( 'filters are cleared after clear button is clicked', async ( {
page,
} ) => {
await page.goto(
`${ PRODUCT_CATALOG_LINK }?min_price=20&max_price=67`
);
await page.goto( '/shop?min_price=20&max_price=67' );
const button = page.getByRole( 'button', { name: 'Clear' } );
await button.click();
await page.waitForURL( `${ PRODUCT_CATALOG_LINK }/` );
await page.waitForURL( '/shop/' );
const defaultRangePrice = await page
const defaultRangePrice = ( await page
.locator( '.wp-block-woocommerce-product-filter-price' )
.getAttribute( 'data-wc-context' );
.getAttribute( 'data-wc-context' ) ) as string;
const defaultMinRange = JSON.parse( defaultRangePrice ).minRange;
const defaultMaxRange = JSON.parse( defaultRangePrice ).maxRange;
@ -146,9 +135,7 @@ test.describe( 'Product Filter: Price Filter Block', () => {
test( 'Changes in the price input field triggers price slider updates', async ( {
page,
} ) => {
await page.goto(
`${ PRODUCT_CATALOG_LINK }?min_price=20&max_price=67`
);
await page.goto( '/shop?min_price=20&max_price=67' );
// Min price input field
const leftInputContainer = page.locator(
@ -187,9 +174,7 @@ test.describe( 'Product Filter: Price Filter Block', () => {
test( 'Price input field rejects min price higher than max price', async ( {
page,
} ) => {
await page.goto(
`${ PRODUCT_CATALOG_LINK }?min_price=20&max_price=67`
);
await page.goto( '/shop?min_price=20&max_price=67' );
// Min price input field
const minPriceInput = page
@ -211,9 +196,7 @@ test.describe( 'Product Filter: Price Filter Block', () => {
test( 'Price input field rejects max price lower than min price', async ( {
page,
} ) => {
await page.goto(
`${ PRODUCT_CATALOG_LINK }?min_price=20&max_price=67`
);
await page.goto( '/shop?min_price=20&max_price=67' );
// Max price input field
const maxPriceInput = page

View File

@ -1,37 +1,34 @@
/**
* External dependencies
*/
import { test, expect } from '@woocommerce/e2e-playwright-utils';
import path from 'path';
import { TemplateCompiler, test as base, expect } from '@woocommerce/e2e-utils';
/**
* Internal dependencies
*/
import { PRODUCT_CATALOG_LINK, PRODUCT_CATALOG_TEMPLATE_ID } from './constants';
const TEMPLATE_PATH = path.join( __dirname, './rating-filter.handlebars' );
const test = base.extend< { templateCompiler: TemplateCompiler } >( {
templateCompiler: async ( { requestUtils }, use ) => {
const compiler = await requestUtils.createTemplateFromFile(
'archive-product_rating-filter'
);
await use( compiler );
},
} );
test.describe( 'Product Filter: Rating Filter Block', () => {
test.describe( 'frontend', () => {
test.beforeEach( async ( { requestUtils } ) => {
test.beforeEach( async ( { requestUtils, templateCompiler } ) => {
await requestUtils.activatePlugin(
'woocommerce-blocks-test-enable-experimental-features'
);
await requestUtils.updateTemplateContents(
PRODUCT_CATALOG_TEMPLATE_ID,
TEMPLATE_PATH,
{
await templateCompiler.compile( {
attributes: {
attributeId: 1,
},
}
);
} );
} );
test( 'clear button is not shown on initial page load', async ( {
page,
} ) => {
await page.goto( PRODUCT_CATALOG_LINK );
await page.goto( '/shop' );
const button = page.getByRole( 'button', { name: 'Clear' } );
@ -41,7 +38,7 @@ test.describe( 'Product Filter: Rating Filter Block', () => {
test( 'clear button appears after a filter is applied', async ( {
page,
} ) => {
await page.goto( `${ PRODUCT_CATALOG_LINK }?rating_filter=1` );
await page.goto( '/shop?rating_filter=1' );
const button = page.getByRole( 'button', { name: 'Clear' } );
@ -51,7 +48,7 @@ test.describe( 'Product Filter: Rating Filter Block', () => {
test( 'clear button hides after deselecting all filters', async ( {
page,
} ) => {
await page.goto( `${ PRODUCT_CATALOG_LINK }?rating_filter=1` );
await page.goto( '/shop?rating_filter=1' );
const ratingCheckboxes = page.getByLabel(
/Checkbox: Rated \d out of 5/
@ -67,7 +64,7 @@ test.describe( 'Product Filter: Rating Filter Block', () => {
test( 'filters are cleared after clear button is clicked', async ( {
page,
} ) => {
await page.goto( `${ PRODUCT_CATALOG_LINK }?rating_filter=1` );
await page.goto( '/shop?rating_filter=1' );
const button = page.getByRole( 'button', { name: 'Clear' } );
@ -84,7 +81,7 @@ test.describe( 'Product Filter: Rating Filter Block', () => {
test( 'Renders a checkbox list with the available ratings', async ( {
page,
} ) => {
await page.goto( PRODUCT_CATALOG_LINK );
await page.goto( '/shop' );
const ratingStars = page.getByLabel( /^Rated \d out of 5/ );
await expect( ratingStars ).toHaveCount( 2 );
@ -103,7 +100,7 @@ test.describe( 'Product Filter: Rating Filter Block', () => {
test( 'Selecting a checkbox filters down the products', async ( {
page,
} ) => {
await page.goto( PRODUCT_CATALOG_LINK );
await page.goto( '/shop' );
const ratingCheckboxes = page.getByLabel(
/Checkbox: Rated \d out of 5/

View File

@ -1,33 +1,30 @@
/**
* External dependencies
*/
import { test, expect } from '@woocommerce/e2e-playwright-utils';
import path from 'path';
import { TemplateCompiler, test as base, expect } from '@woocommerce/e2e-utils';
/**
* Internal dependencies
*/
import { PRODUCT_CATALOG_LINK, PRODUCT_CATALOG_TEMPLATE_ID } from './constants';
const TEMPLATE_PATH = path.join( __dirname, './stock-status.handlebars' );
const test = base.extend< { templateCompiler: TemplateCompiler } >( {
templateCompiler: async ( { requestUtils }, use ) => {
const compiler = await requestUtils.createTemplateFromFile(
'archive-product_stock-status'
);
await use( compiler );
},
} );
test.describe( 'Product Filter: Stock Status Block', () => {
test.describe( 'With default display style', () => {
test.beforeEach( async ( { requestUtils } ) => {
test.beforeEach( async ( { requestUtils, templateCompiler } ) => {
await requestUtils.activatePlugin(
'woocommerce-blocks-test-enable-experimental-features'
);
await requestUtils.updateTemplateContents(
PRODUCT_CATALOG_TEMPLATE_ID,
TEMPLATE_PATH,
{}
);
await templateCompiler.compile();
} );
test( 'clear button is not shown on initial page load', async ( {
page,
} ) => {
await page.goto( PRODUCT_CATALOG_LINK );
await page.goto( '/shop' );
const button = page.getByRole( 'button', { name: 'Clear' } );
@ -37,7 +34,7 @@ test.describe( 'Product Filter: Stock Status Block', () => {
test( 'renders a checkbox list with the available stock statuses', async ( {
page,
} ) => {
await page.goto( PRODUCT_CATALOG_LINK );
await page.goto( '/shop' );
const stockStatuses = page.locator(
'.wc-block-components-checkbox__label'
@ -51,7 +48,7 @@ test.describe( 'Product Filter: Stock Status Block', () => {
test( 'filters the list of products by selecting a stock status', async ( {
page,
} ) => {
await page.goto( PRODUCT_CATALOG_LINK );
await page.goto( '/shop' );
const outOfStockCheckbox = page.getByText( 'Out of stock' );
await outOfStockCheckbox.click();
@ -67,7 +64,7 @@ test.describe( 'Product Filter: Stock Status Block', () => {
test( 'clear button appears after a filter is applied', async ( {
page,
} ) => {
await page.goto( PRODUCT_CATALOG_LINK );
await page.goto( '/shop' );
const outOfStockCheckbox = page.getByText( 'Out of stock' );
await outOfStockCheckbox.click();
@ -83,9 +80,7 @@ test.describe( 'Product Filter: Stock Status Block', () => {
test( 'clear button hides after deselecting all filters', async ( {
page,
} ) => {
await page.goto(
`${ PRODUCT_CATALOG_LINK }?filter_stock_status=outofstock`
);
await page.goto( '/shop?filter_stock_status=outofstock' );
const outOfStockCheckbox = page.getByText( 'Out of stock' );
await outOfStockCheckbox.click();
@ -98,9 +93,7 @@ test.describe( 'Product Filter: Stock Status Block', () => {
test( 'filters are cleared after clear button is clicked', async ( {
page,
} ) => {
await page.goto(
`${ PRODUCT_CATALOG_LINK }?filter_stock_status=outofstock`
);
await page.goto( '/shop?filter_stock_status=outofstock' );
const button = page.getByRole( 'button', { name: 'Clear' } );
@ -115,25 +108,21 @@ test.describe( 'Product Filter: Stock Status Block', () => {
} );
test.describe( 'With dropdown display style', () => {
test.beforeEach( async ( { requestUtils } ) => {
test.beforeEach( async ( { requestUtils, templateCompiler } ) => {
await requestUtils.activatePlugin(
'woocommerce-blocks-test-enable-experimental-features'
);
await requestUtils.updateTemplateContents(
PRODUCT_CATALOG_TEMPLATE_ID,
TEMPLATE_PATH,
{
await templateCompiler.compile( {
attributes: {
displayStyle: 'dropdown',
},
}
);
} );
} );
test( 'clear button is not shown on initial page load', async ( {
page,
} ) => {
await page.goto( PRODUCT_CATALOG_LINK );
await page.goto( '/shop' );
const button = page.getByRole( 'button', { name: 'Clear' } );
@ -143,7 +132,7 @@ test.describe( 'Product Filter: Stock Status Block', () => {
test( 'a dropdown is displayed with the available stock statuses', async ( {
page,
} ) => {
await page.goto( PRODUCT_CATALOG_LINK );
await page.goto( '/shop' );
const dropdownLocator = page.locator(
'.wc-interactivity-dropdown'
@ -159,7 +148,7 @@ test.describe( 'Product Filter: Stock Status Block', () => {
test( 'clear button appears after a filter is applied', async ( {
page,
} ) => {
await page.goto( PRODUCT_CATALOG_LINK );
await page.goto( '/shop' );
const dropdownLocator = page.locator(
'.wc-interactivity-dropdown'
@ -180,9 +169,7 @@ test.describe( 'Product Filter: Stock Status Block', () => {
test( 'clear button hides after deselecting all filters', async ( {
page,
} ) => {
await page.goto(
`${ PRODUCT_CATALOG_LINK }?filter_stock_status=instock`
);
await page.goto( '/shop?filter_stock_status=instock' );
const dropdownLocator = page.locator(
'.wc-interactivity-dropdown'
@ -204,9 +191,7 @@ test.describe( 'Product Filter: Stock Status Block', () => {
test( 'filters are cleared after clear button is clicked', async ( {
page,
} ) => {
await page.goto(
`${ PRODUCT_CATALOG_LINK }?filter_stock_status=instock`
);
await page.goto( '/shop?filter_stock_status=instock' );
const button = page.getByRole( 'button', { name: 'Clear' } );

View File

@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { expect, test } from '@woocommerce/e2e-playwright-utils';
import { expect, test } from '@woocommerce/e2e-utils';
const blockData = {
name: 'Hand-picked Products',
@ -10,17 +10,16 @@ const blockData = {
test.describe( `${ blockData.slug } Block`, () => {
test( 'can be inserted in Post Editor and it is visible on the frontend', async ( {
editorUtils,
editor,
admin,
frontendUtils,
} ) => {
await admin.createNewPost();
await editor.insertBlock( { name: blockData.slug } );
const blockLocator = await editorUtils.getBlockByName( blockData.slug );
const blockLocator = await editor.getBlockByName( blockData.slug );
await blockLocator.getByText( 'Album' ).click();
await blockLocator.getByText( 'Done' ).click();
await editorUtils.publishAndVisitPost();
await editor.publishAndVisitPost();
const blockLocatorFrontend = await frontendUtils.getBlockByName(
blockData.slug
);

View File

@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { test, expect } from '@woocommerce/e2e-playwright-utils';
import { test, expect } from '@woocommerce/e2e-utils';
/**
* Internal dependencies
@ -189,7 +189,6 @@ test.describe( 'Merchant → Local Pickup Settings', () => {
localPickupUtils,
admin,
editor,
editorUtils,
frontendUtils,
} ) => {
// First update the title via the site editor then check the local pickup settings.
@ -197,7 +196,7 @@ test.describe( 'Merchant → Local Pickup Settings', () => {
postId: 'woocommerce/woocommerce//page-checkout',
postType: 'wp_template',
} );
await editorUtils.enterEditMode();
await editor.enterEditMode();
const block = editor.canvas.locator(
'[data-type="woocommerce/checkout-shipping-method-block"]'
);
@ -227,7 +226,7 @@ test.describe( 'Merchant → Local Pickup Settings', () => {
postId: 'woocommerce/woocommerce//page-checkout',
postType: 'wp_template',
} );
await editorUtils.enterEditMode();
await editor.enterEditMode();
await expect(
editor.canvas.getByText( 'Edited from settings page' )

View File

@ -1,8 +1,7 @@
/**
* External dependencies
*/
import { test, expect } from '@woocommerce/e2e-playwright-utils';
import { BlockData } from '@woocommerce/e2e-types';
import { test, expect, BlockData } from '@woocommerce/e2e-utils';
const blockData: BlockData = {
name: 'Mini-Cart',
@ -19,16 +18,12 @@ const blockData: BlockData = {
test.describe( 'Merchant → Mini Cart', () => {
test.describe( 'in FSE editor', () => {
test( 'can be inserted in FSE area', async ( {
editorUtils,
editor,
admin,
} ) => {
test( 'can be inserted in FSE area', async ( { editor, admin } ) => {
await admin.visitSiteEditor( {
postId: `woocommerce/woocommerce//single-product`,
postType: 'wp_template',
} );
await editorUtils.enterEditMode();
await editor.enterEditMode();
await editor.setContent( '' );
@ -38,19 +33,19 @@ test.describe( 'Merchant → Mini Cart', () => {
).toBeVisible();
} );
test( 'can only be inserted once', async ( { editorUtils, admin } ) => {
test( 'can only be inserted once', async ( { editor, admin } ) => {
await admin.visitSiteEditor( {
postId: `woocommerce/woocommerce//single-product`,
postType: 'wp_template',
} );
await editorUtils.enterEditMode();
await editorUtils.openGlobalBlockInserter();
await editor.enterEditMode();
await editor.openGlobalBlockInserter();
await editorUtils.page
await editor.page
.getByLabel( 'Search for blocks and patterns' )
.fill( blockData.slug );
const miniCartButton = editorUtils.page.getByRole( 'option', {
const miniCartButton = editor.page.getByRole( 'option', {
name: blockData.name,
} );

View File

@ -1,9 +1,12 @@
/**
* External dependencies
*/
import { CLASSIC_THEME_SLUG } from '@woocommerce/e2e-utils';
import { expect, test } from '@woocommerce/e2e-playwright-utils';
import { BlockData } from '@woocommerce/e2e-types';
import {
expect,
test,
CLASSIC_THEME_SLUG,
BlockData,
} from '@woocommerce/e2e-utils';
const blockData: BlockData = {
name: 'Mini-Cart',
@ -21,15 +24,18 @@ test.describe( 'Merchant → Mini Cart', () => {
} );
test.describe( 'in widget editor', () => {
test( 'can be inserted in a widget area', async ( { editorUtils } ) => {
await editorUtils.openWidgetEditor();
await editorUtils.openGlobalBlockInserter();
test( 'can be inserted in a widget area', async ( {
admin,
editor,
} ) => {
await admin.visitWidgetEditor();
await editor.openGlobalBlockInserter();
await editorUtils.page
await editor.page
.getByLabel( 'Search for blocks and patterns' )
.fill( blockData.slug );
const miniCartButton = editorUtils.page.getByRole( 'option', {
const miniCartButton = editor.page.getByRole( 'option', {
name: blockData.name,
exact: true,
} );
@ -39,18 +45,22 @@ test.describe( 'Merchant → Mini Cart', () => {
await miniCartButton.click();
await expect(
await editorUtils.getBlockByName( blockData.slug )
await editor.getBlockByName( blockData.slug )
).toBeVisible();
} );
test( 'can only be inserted once', async ( { editorUtils } ) => {
await editorUtils.openWidgetEditor();
await editorUtils.openGlobalBlockInserter();
test( 'can only be inserted once', async ( {
page,
admin,
editor,
} ) => {
await admin.visitWidgetEditor();
await editor.openGlobalBlockInserter();
await editorUtils.page
await editor.page
.getByLabel( 'Search for blocks and patterns' )
.fill( blockData.slug );
const miniCartButton = editorUtils.page.getByRole( 'option', {
const miniCartButton = page.getByRole( 'option', {
name: blockData.name,
exact: true,
} );

View File

@ -1,8 +1,7 @@
/**
* External dependencies
*/
import { expect, test } from '@woocommerce/e2e-playwright-utils';
import { cli } from '@woocommerce/e2e-utils';
import { expect, test, cli } from '@woocommerce/e2e-utils';
/**
* Internal dependencies

View File

@ -1,8 +1,7 @@
/**
* External dependencies
*/
import { test, expect } from '@woocommerce/e2e-playwright-utils';
import { BlockData } from '@woocommerce/e2e-types';
import { test, expect, BlockData } from '@woocommerce/e2e-utils';
/**
* Internal dependencies

View File

@ -1,8 +1,7 @@
/**
* External dependencies
*/
import { BlockData } from '@woocommerce/e2e-types';
import { FrontendUtils } from '@woocommerce/e2e-utils';
import { FrontendUtils, BlockData } from '@woocommerce/e2e-utils';
export const blockData: BlockData = {
name: 'Mini-Cart',

View File

@ -1,8 +1,12 @@
/**
* External dependencies
*/
import { test as base, expect } from '@woocommerce/e2e-playwright-utils';
import { EditorUtils, FrontendUtils } from '@woocommerce/e2e-utils';
import {
test as base,
expect,
Editor,
FrontendUtils,
} from '@woocommerce/e2e-utils';
/**
* Internal dependencies
@ -14,14 +18,12 @@ const blockData = {
mainClass: '.wp-block-woocommerce-product-sale-badge',
selectors: {
frontend: {
productSaleBadge: '.wc-block-components-product-sale-badge',
productSaleBadgeContainer:
'.wp-block-woocommerce-product-sale-badge',
badge: '.wc-block-components-product-sale-badge',
badgeContainer: '.wp-block-woocommerce-product-sale-badge',
},
editor: {
productSaleBadge: '.wc-block-components-product-sale-badge',
productSaleBadgeContainer:
'.wp-block-woocommerce-product-sale-badge',
badge: '.wc-block-components-product-sale-badge',
badgeContainer: '.wp-block-woocommerce-product-sale-badge',
},
},
// This margin is applied via Block Styles to the product sale badge. It's necessary to take it into account when calculating the position of the badge. https://github.com/woocommerce/woocommerce-blocks/blob/445b9431ccba460f9badd41d52ed991958524e33/assets/js/blocks/product-gallery/edit.tsx/#L44-L53
@ -31,65 +33,80 @@ const blockData = {
productPageNotOnSale: '/product/album/',
};
const test = base.extend< { pageObject: ProductGalleryPage } >( {
pageObject: async ( { page, editor, frontendUtils, editorUtils }, use ) => {
const pageObject = new ProductGalleryPage( {
page,
class BlockUtils {
editor: Editor;
frontendUtils: FrontendUtils;
constructor( {
editor,
frontendUtils,
editorUtils,
} );
await use( pageObject );
},
} );
const getBoundingClientRect = async ( {
frontendUtils,
editorUtils,
isFrontend,
}: {
}: {
editor: Editor;
frontendUtils: FrontendUtils;
editorUtils: EditorUtils;
isFrontend: boolean;
} ) => {
const page = isFrontend ? frontendUtils.page : editorUtils.editor.canvas;
} ) {
this.editor = editor;
this.frontendUtils = frontendUtils;
}
async getSaleBadgeBoundingClientRect( isFrontend: boolean ): Promise< {
badge: DOMRect;
badgeContainer: DOMRect;
} > {
const page = isFrontend ? this.frontendUtils.page : this.editor.canvas;
return {
productSaleBadge: await page
badge: await page
.locator(
blockData.selectors[ isFrontend ? 'frontend' : 'editor' ]
.productSaleBadge
.badge
)
.first()
.evaluate( ( el ) => el.getBoundingClientRect() ),
productSaleBadgeContainer: await page
badgeContainer: await page
.locator(
blockData.selectors[ isFrontend ? 'frontend' : 'editor' ]
.productSaleBadgeContainer
.badgeContainer
)
.first()
.evaluate( ( el ) => el.getBoundingClientRect() ),
};
};
}
}
const test = base.extend< {
pageObject: ProductGalleryPage;
blockUtils: BlockUtils;
} >( {
pageObject: async ( { page, editor, frontendUtils }, use ) => {
await use(
new ProductGalleryPage( {
page,
editor,
frontendUtils,
} )
);
},
blockUtils: async ( { editor, frontendUtils }, use ) => {
await use( new BlockUtils( { editor, frontendUtils } ) );
},
} );
test.describe( `${ blockData.name }`, () => {
test.describe( `On the Single Product Template`, () => {
test.beforeEach( async ( { admin, editorUtils, editor } ) => {
test.beforeEach( async ( { admin, editor } ) => {
await admin.visitSiteEditor( {
postId: `woocommerce/woocommerce//${ blockData.slug }`,
postType: 'wp_template',
} );
await editorUtils.enterEditMode();
await editor.enterEditMode();
await editor.setContent( '' );
} );
test( 'should be rendered on the editor side', async ( {
editorUtils,
editor,
} ) => {
test( 'should be rendered on the editor side', async ( { editor } ) => {
await editor.insertBlock( {
name: 'woocommerce/product-gallery',
} );
const block = await editorUtils.getBlockByName( blockData.name );
const block = await editor.getBlockByName( blockData.name );
await expect( block ).toBeVisible();
} );
@ -138,12 +155,11 @@ test.describe( `${ blockData.name }`, () => {
await expect( block ).toBeHidden();
} );
test( 'should be aligned on the left', async ( {
frontendUtils,
editorUtils,
test( 'should be aligned to the left', async ( {
editor,
page,
pageObject,
blockUtils,
} ) => {
await editor.openDocumentSettingsSidebar();
await editor.insertBlock( {
@ -152,43 +168,43 @@ test.describe( `${ blockData.name }`, () => {
await pageObject.toggleFullScreenOnClickSetting( false );
const block = await editorUtils.getBlockByName( blockData.name );
const block = await editor.getBlockByName( blockData.name );
await block.click();
await editorUtils.setAlignOption( 'Align Left' );
await page.locator( "button[aria-label='Align']" ).click();
await page.getByText( 'Align Left' ).click();
const editorBoundingClientRect = await getBoundingClientRect( {
frontendUtils,
editorUtils,
isFrontend: false,
} );
await expect
.poll( async () => {
const { badge, badgeContainer } =
await blockUtils.getSaleBadgeBoundingClientRect(
false
);
expect(
editorBoundingClientRect.productSaleBadge.x - blockData.margin
).toEqual( editorBoundingClientRect.productSaleBadgeContainer.x );
return badge.x - badgeContainer.x;
} )
.toEqual( blockData.margin );
await editor.saveSiteEditorEntities();
await page.goto( blockData.productPage );
const clientBoundingClientRect = await getBoundingClientRect( {
frontendUtils,
editorUtils,
isFrontend: true,
await expect
.poll( async () => {
const { badge, badgeContainer } =
await blockUtils.getSaleBadgeBoundingClientRect( true );
return badge.x - badgeContainer.x;
} )
.toEqual( blockData.margin );
} );
expect(
clientBoundingClientRect.productSaleBadge.x - blockData.margin
).toEqual( clientBoundingClientRect.productSaleBadgeContainer.x );
} );
test( 'should be aligned on the center', async ( {
frontendUtils,
editorUtils,
test( 'should be aligned to the center', async ( {
editor,
page,
pageObject,
blockUtils,
} ) => {
await editor.openDocumentSettingsSidebar();
await editor.insertBlock( {
@ -197,47 +213,43 @@ test.describe( `${ blockData.name }`, () => {
await pageObject.toggleFullScreenOnClickSetting( false );
const block = await editorUtils.getBlockByName( blockData.name );
const block = await editor.getBlockByName( blockData.name );
await block.click();
await editorUtils.setAlignOption( 'Align Center' );
await page.locator( "button[aria-label='Align']" ).click();
await page.getByText( 'Align Center' ).click();
const editorBoundingClientRect = await getBoundingClientRect( {
frontendUtils,
editorUtils,
isFrontend: false,
} );
expect(
editorBoundingClientRect.productSaleBadge.right
).toBeLessThan(
editorBoundingClientRect.productSaleBadgeContainer.right
await expect
.poll( async () => {
const { badge, badgeContainer } =
await blockUtils.getSaleBadgeBoundingClientRect(
false
);
return badge.right < badgeContainer.right;
} )
.toBe( true );
await editor.saveSiteEditorEntities();
await page.goto( blockData.productPage );
const clientBoundingClientRect = await getBoundingClientRect( {
frontendUtils,
editorUtils,
isFrontend: true,
await expect
.poll( async () => {
const { badge, badgeContainer } =
await blockUtils.getSaleBadgeBoundingClientRect( true );
return badge.right < badgeContainer.right;
} )
.toBe( true );
} );
expect(
clientBoundingClientRect.productSaleBadge.right
).toBeLessThan(
clientBoundingClientRect.productSaleBadgeContainer.right
);
} );
test( 'should be aligned on the right by default', async ( {
frontendUtils,
editorUtils,
test( 'should be aligned to the right by default', async ( {
editor,
page,
pageObject,
blockUtils,
} ) => {
await editor.openDocumentSettingsSidebar();
await editor.insertBlock( {
@ -245,35 +257,29 @@ test.describe( `${ blockData.name }`, () => {
} );
await pageObject.toggleFullScreenOnClickSetting( false );
const editorBoundingClientRect = await getBoundingClientRect( {
frontendUtils,
editorUtils,
isFrontend: false,
} );
expect(
editorBoundingClientRect.productSaleBadge.right +
blockData.margin
).toEqual(
editorBoundingClientRect.productSaleBadgeContainer.right
await expect
.poll( async () => {
const { badge, badgeContainer } =
await blockUtils.getSaleBadgeBoundingClientRect(
false
);
return badgeContainer.right - badge.right;
} )
.toEqual( blockData.margin );
await editor.saveSiteEditorEntities();
await page.goto( blockData.productPage );
const clientBoundingClientRect = await getBoundingClientRect( {
frontendUtils,
editorUtils,
isFrontend: true,
} );
await expect
.poll( async () => {
const { badge, badgeContainer } =
await blockUtils.getSaleBadgeBoundingClientRect( true );
expect(
clientBoundingClientRect.productSaleBadge.right +
blockData.margin
).toEqual(
clientBoundingClientRect.productSaleBadgeContainer.right
);
return badgeContainer.right - badge.right;
} )
.toEqual( blockData.margin );
} );
} );
} );

View File

@ -1,8 +1,7 @@
/**
* External dependencies
*/
import { test, expect } from '@woocommerce/e2e-playwright-utils';
import type { FrontendUtils } from '@woocommerce/e2e-utils';
import { test, expect, FrontendUtils } from '@woocommerce/e2e-utils';
// Instead of testing the block individually, we test the Cart and Checkout
// templates, which make use of the block.
@ -41,7 +40,7 @@ for ( const template of templates ) {
test( `the content of the ${ template.title } page is correctly rendered in the ${ template.title } template`, async ( {
page,
admin,
editorUtils,
editor,
frontendUtils,
requestUtils,
} ) => {
@ -58,12 +57,17 @@ for ( const template of templates ) {
page.locator( template.blockClassName )
).toBeVisible();
await editorUtils.editor.insertBlock( {
await editor.insertBlock( {
name: 'core/paragraph',
attributes: { content: userText },
} );
await editorUtils.updatePost();
await page.getByRole( 'button', { name: 'Update' } ).click();
await page
.getByRole( 'button', { name: 'Dismiss this notice' } )
.filter( { hasText: 'updated' } )
.waitFor();
// Verify edits are in the template when viewed from the frontend.
await template.visitPage( { frontendUtils } );

View File

@ -1,17 +1,15 @@
/**
* External dependencies
*/
import { test, expect } from '@woocommerce/e2e-playwright-utils';
import { BASE_URL, cli } from '@woocommerce/e2e-utils';
import path from 'path';
import {
test as base,
expect,
TemplateCompiler,
BASE_URL,
cli,
} from '@woocommerce/e2e-utils';
const PRODUCT_CATALOG_LINK = '/shop';
const TEMPLATE_PATH = path.join(
__dirname,
'../shared/filters-with-product-collection.handlebars'
);
export const blockData = {
const blockData = {
slug: 'woocommerce/price-filter',
name: 'Filter by Price',
mainClass: '.wc-block-price-filter',
@ -24,6 +22,15 @@ export const blockData = {
placeholderUrl: `${ BASE_URL }/wp-content/plugins/woocommerce/assets/images/placeholder.png`,
};
const test = base.extend< { templateCompiler: TemplateCompiler } >( {
templateCompiler: async ( { requestUtils }, use ) => {
const compiler = await requestUtils.createTemplateFromFile(
'archive-product_filters-with-product-collection'
);
await use( compiler );
},
} );
test.describe( `${ blockData.name } Block - editor side`, () => {
test.beforeEach( async ( { admin, editor } ) => {
await admin.createNewPost();
@ -50,10 +57,9 @@ test.describe( `${ blockData.name } Block - editor side`, () => {
test( 'should allow changing the display style', async ( {
page,
editorUtils,
editor,
} ) => {
const priceFilterControls = await editorUtils.getBlockByName(
const priceFilterControls = await editor.getBlockByName(
'woocommerce/price-filter'
);
await editor.selectBlocks( priceFilterControls );
@ -90,10 +96,9 @@ test.describe( `${ blockData.name } Block - editor side`, () => {
test( 'should allow toggling the visibility of the filter button', async ( {
page,
editorUtils,
editor,
} ) => {
const priceFilterControls = await editorUtils.getBlockByName(
const priceFilterControls = await editor.getBlockByName(
blockData.slug
);
await editor.selectBlocks( priceFilterControls );
@ -116,7 +121,7 @@ test.describe( `${ blockData.name } Block - editor side`, () => {
test.describe( `${ blockData.name } Block - with All products Block`, () => {
test.beforeEach( async ( { admin, page, editor } ) => {
await admin.createNewPost( { legacyCanvas: true } );
await admin.createNewPost();
await editor.insertBlock( { name: 'woocommerce/all-products' } );
await editor.insertBlock( {
name: 'woocommerce/filter-wrapper',
@ -220,7 +225,7 @@ test.describe( `${ blockData.name } Block - with All products Block`, () => {
} );
} );
test.describe( `${ blockData.name } Block - with PHP classic template`, () => {
test.beforeEach( async ( { admin, page, editor, editorUtils } ) => {
test.beforeEach( async ( { admin, page, editor } ) => {
await cli(
'npm run wp-env run tests-cli -- wp option update wc_blocks_use_blockified_product_grid_block_as_template false'
);
@ -230,7 +235,7 @@ test.describe( `${ blockData.name } Block - with PHP classic template`, () => {
postType: 'wp_template',
} );
await editorUtils.enterEditMode();
await editor.enterEditMode();
await editor.insertBlock( {
name: 'woocommerce/filter-wrapper',
@ -240,7 +245,7 @@ test.describe( `${ blockData.name } Block - with PHP classic template`, () => {
},
} );
await editor.saveSiteEditorEntities();
await page.goto( `/shop` );
await page.goto( '/shop' );
} );
test( 'should show all products', async ( { frontendUtils } ) => {
@ -283,16 +288,10 @@ test.describe( `${ blockData.name } Block - with PHP classic template`, () => {
} );
test.describe( `${ blockData.name } Block - with Product Collection`, () => {
test.beforeEach( async ( { requestUtils } ) => {
await requestUtils.updateTemplateContents(
'woocommerce/woocommerce//archive-product',
TEMPLATE_PATH,
{}
);
} );
test( 'should show all products', async ( { page, templateCompiler } ) => {
await templateCompiler.compile();
test( 'should show all products', async ( { page } ) => {
await page.goto( PRODUCT_CATALOG_LINK );
await page.goto( '/shop' );
const products = page
.locator( '.wp-block-woocommerce-product-template' )
.getByRole( 'listitem' );
@ -303,8 +302,11 @@ test.describe( `${ blockData.name } Block - with Product Collection`, () => {
test( 'should show only products that match the filter', async ( {
page,
frontendUtils,
templateCompiler,
} ) => {
await page.goto( PRODUCT_CATALOG_LINK );
await templateCompiler.compile();
await page.goto( '/shop' );
const maxPriceInput = page.getByRole( 'textbox', {
name: 'Filter products by maximum price',
} );
@ -327,16 +329,18 @@ test.describe( `${ blockData.name } Block - with Product Collection`, () => {
page,
admin,
editor,
editorUtils,
templateCompiler,
} ) => {
const template = await templateCompiler.compile();
await admin.visitSiteEditor( {
postId: 'woocommerce/woocommerce//archive-product',
postType: 'wp_template',
postId: template.id,
postType: template.type,
} );
await editorUtils.enterEditMode();
await editor.enterEditMode();
const priceFilterControls = await editorUtils.getBlockByName(
const priceFilterControls = await editor.getBlockByName(
blockData.slug
);
await expect( priceFilterControls ).toBeVisible();
@ -345,7 +349,7 @@ test.describe( `${ blockData.name } Block - with Product Collection`, () => {
await page.getByText( "Show 'Apply filters' button" ).click();
await editor.saveSiteEditorEntities();
await page.goto( PRODUCT_CATALOG_LINK );
await page.goto( '/shop' );
const maxPriceInput = page.getByRole( 'textbox', {
name: 'Filter products by maximum price',

View File

@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { expect, test } from '@woocommerce/e2e-playwright-utils';
import { expect, test } from '@woocommerce/e2e-utils';
const blockData = {
name: 'Best Selling Products',
@ -10,16 +10,15 @@ const blockData = {
test.describe( `${ blockData.slug } Block`, () => {
test( 'can be inserted in Post Editor and it is visible on the frontend', async ( {
editorUtils,
editor,
admin,
frontendUtils,
} ) => {
await admin.createNewPost();
await editor.insertBlock( { name: blockData.slug } );
const blockLocator = await editorUtils.getBlockByName( blockData.slug );
const blockLocator = await editor.getBlockByName( blockData.slug );
await expect( blockLocator.getByRole( 'listitem' ) ).toHaveCount( 9 );
await editorUtils.publishAndVisitPost();
await editor.publishAndVisitPost();
const blockLocatorFrontend = await frontendUtils.getBlockByName(
blockData.slug
);

View File

@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { expect, test } from '@woocommerce/e2e-playwright-utils';
import { expect, test } from '@woocommerce/e2e-utils';
/**
* Internal dependencies

View File

@ -1,8 +1,11 @@
/**
* External dependencies
*/
import { CLASSIC_THEME_SLUG } from '@woocommerce/e2e-utils';
import { expect, test as base } from '@woocommerce/e2e-playwright-utils';
import {
expect,
test as base,
CLASSIC_THEME_SLUG,
} from '@woocommerce/e2e-utils';
/**
* Internal dependencies
@ -11,16 +14,11 @@ import { blockData } from './utils';
import ProductCollectionPage from '../product-collection/product-collection.page';
const test = base.extend< { productCollectionPage: ProductCollectionPage } >( {
productCollectionPage: async (
{ page, admin, editor, templateApiUtils, editorUtils },
use
) => {
productCollectionPage: async ( { page, admin, editor }, use ) => {
const pageObject = new ProductCollectionPage( {
page,
admin,
editor,
templateApiUtils,
editorUtils,
} );
await use( pageObject );
},

View File

@ -2,7 +2,7 @@
* External dependencies
*/
import { Page } from '@playwright/test';
import { Admin } from '@wordpress/e2e-test-utils-playwright';
import { Admin } from '@woocommerce/e2e-utils';
export const blockData = {
name: 'Product Button',

View File

@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { expect, test } from '@woocommerce/e2e-playwright-utils';
import { expect, test } from '@woocommerce/e2e-utils';
const blockData = {
name: 'Product Categories List',
@ -10,16 +10,15 @@ const blockData = {
test.describe( `${ blockData.slug } Block`, () => {
test( 'can be inserted in Post Editor and it is visible on the frontend', async ( {
editorUtils,
editor,
admin,
frontendUtils,
} ) => {
await admin.createNewPost();
await editor.insertBlock( { name: blockData.slug } );
const blockLocator = await editorUtils.getBlockByName( blockData.slug );
const blockLocator = await editor.getBlockByName( blockData.slug );
await expect( blockLocator.getByRole( 'listitem' ) ).toHaveCount( 6 );
await editorUtils.publishAndVisitPost();
await editor.publishAndVisitPost();
const blockLocatorFrontend = await frontendUtils.getBlockByName(
blockData.slug
);

View File

@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { expect, test } from '@woocommerce/e2e-playwright-utils';
import { expect, test } from '@woocommerce/e2e-utils';
const blockData = {
name: 'Products by Category',
@ -10,18 +10,17 @@ const blockData = {
test.describe( `${ blockData.slug } Block`, () => {
test( 'can be inserted in Post Editor and it is visible on the frontend', async ( {
editorUtils,
editor,
admin,
frontendUtils,
} ) => {
await admin.createNewPost();
await editor.insertBlock( { name: blockData.slug } );
const blockLocator = await editorUtils.getBlockByName( blockData.slug );
const blockLocator = await editor.getBlockByName( blockData.slug );
await blockLocator.getByText( 'Accessories' ).click();
await blockLocator.getByText( 'Done' ).click();
await expect( blockLocator.getByRole( 'listitem' ) ).toHaveCount( 5 );
await editorUtils.publishAndVisitPost();
await editor.publishAndVisitPost();
const blockLocatorFrontend = await frontendUtils.getBlockByName(
blockData.slug
);

View File

@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { test as base, expect } from '@woocommerce/e2e-playwright-utils';
import { test as base, expect } from '@woocommerce/e2e-utils';
/**
* Internal dependencies
@ -76,16 +76,11 @@ const multipleOccurrenceScenarios: Scenario[] = [
];
const test = base.extend< { pageObject: ProductCollectionPage } >( {
pageObject: async (
{ page, admin, editor, templateApiUtils, editorUtils },
use
) => {
pageObject: async ( { page, admin, editor }, use ) => {
const pageObject = new ProductCollectionPage( {
page,
admin,
editor,
templateApiUtils,
editorUtils,
} );
await use( pageObject );
},

View File

@ -1,8 +1,8 @@
/**
* External dependencies
*/
import { test as base, expect } from '@woocommerce/e2e-playwright-utils';
import type { Request } from '@playwright/test';
import { Request } from '@playwright/test';
import { test as base, expect } from '@woocommerce/e2e-utils';
/**
* Internal dependencies
@ -10,12 +10,11 @@ import type { Request } from '@playwright/test';
import ProductCollectionPage, { SELECTORS } from './product-collection.page';
const test = base.extend< { pageObject: ProductCollectionPage } >( {
pageObject: async ( { page, admin, editor, editorUtils }, use ) => {
pageObject: async ( { page, admin, editor }, use ) => {
const pageObject = new ProductCollectionPage( {
page,
admin,
editor,
editorUtils,
} );
await use( pageObject );
},
@ -881,7 +880,6 @@ test.describe( 'Product Collection', () => {
page,
admin,
editor,
editorUtils,
pageObject,
} ) => {
await admin.createNewPost();
@ -891,11 +889,11 @@ test.describe( 'Product Collection', () => {
await expect( paginations ).toHaveCount( 1 );
const siblingBlock = await editorUtils.getBlockByName(
const siblingBlock = await editor.getBlockByName(
'woocommerce/product-template'
);
await editor.selectBlocks( siblingBlock );
await editorUtils.insertBlockUsingGlobalInserter( 'Pagination' );
await editor.insertBlockUsingGlobalInserter( 'Pagination' );
await expect( paginations ).toHaveCount( 2 );
} );
@ -953,19 +951,31 @@ test.describe( 'Product Collection', () => {
};
test( 'as product in specific Single Product template', async ( {
admin,
page,
pageObject,
editorUtils,
editor,
} ) => {
const productName = 'Cap';
const productSlug = 'cap';
await admin.visitSiteEditor( { path: '/wp_template' } );
await editorUtils.openSpecificProductTemplate(
productName,
productSlug
);
await page
.getByRole( 'button', { name: 'Add New Template' } )
.click();
await page
.getByRole( 'button', { name: 'Single Item: Product' } )
.click();
await page
.getByRole( 'option', {
name: `Cap http://localhost:8889/product/cap/`,
} )
.click();
await page
.getByRole( 'button', {
name: 'Skip',
} )
.click();
await editorUtils.insertBlockUsingGlobalInserter(
await editor.insertBlockUsingGlobalInserter(
pageObject.BLOCK_NAME
);
@ -984,7 +994,7 @@ test.describe( 'Product Collection', () => {
} );
test( 'as category in Products by Category template', async ( {
admin,
editorUtils,
editor,
pageObject,
page,
} ) => {
@ -992,8 +1002,8 @@ test.describe( 'Product Collection', () => {
postId: `woocommerce/woocommerce//taxonomy-product_cat`,
postType: 'wp_template',
} );
await editorUtils.enterEditMode();
await editorUtils.insertBlockUsingGlobalInserter(
await editor.enterEditMode();
await editor.insertBlockUsingGlobalInserter(
pageObject.BLOCK_NAME
);
@ -1013,7 +1023,7 @@ test.describe( 'Product Collection', () => {
test( 'as tag in Products by Tag template', async ( {
admin,
editorUtils,
editor,
pageObject,
page,
} ) => {
@ -1021,8 +1031,8 @@ test.describe( 'Product Collection', () => {
postId: `woocommerce/woocommerce//taxonomy-product_tag`,
postType: 'wp_template',
} );
await editorUtils.enterEditMode();
await editorUtils.insertBlockUsingGlobalInserter(
await editor.enterEditMode();
await editor.insertBlockUsingGlobalInserter(
pageObject.BLOCK_NAME
);
@ -1042,12 +1052,12 @@ test.describe( 'Product Collection', () => {
test( 'as site in post', async ( {
admin,
editorUtils,
editor,
pageObject,
page,
} ) => {
await admin.createNewPost();
await editorUtils.insertBlockUsingGlobalInserter(
await editor.insertBlockUsingGlobalInserter(
pageObject.BLOCK_NAME
);

View File

@ -2,8 +2,8 @@
* External dependencies
*/
import { Locator, Page } from '@playwright/test';
import { EditorUtils } from '@woocommerce/e2e-utils';
import { expect, Editor, Admin } from '@wordpress/e2e-test-utils-playwright';
import { Editor, Admin, expect } from '@woocommerce/e2e-utils';
import { BlockRepresentation } from '@wordpress/e2e-test-utils-playwright/build-types/editor/insert-block';
/**
* Internal dependencies
@ -78,7 +78,6 @@ class ProductCollectionPage {
private page: Page;
private admin: Admin;
private editor: Editor;
private editorUtils: EditorUtils;
BLOCK_NAME = 'Product Collection';
productTemplate!: Locator;
products!: Locator;
@ -92,17 +91,14 @@ class ProductCollectionPage {
page,
admin,
editor,
editorUtils,
}: {
page: Page;
admin: Admin;
editor: Editor;
editorUtils: EditorUtils;
} ) {
this.page = page;
this.admin = admin;
this.editor = editor;
this.editorUtils = editorUtils;
}
async chooseCollectionInPost( collection?: Collections ) {
@ -165,6 +161,33 @@ class ProductCollectionPage {
await this.refreshLocators( 'frontend' );
}
async replaceBlockByBlockName( name: string, nameToInsert: string ) {
await this.page.evaluate(
( { name: _name, nameToInsert: _nameToInsert } ) => {
const blocks = window.wp.data
.select( 'core/block-editor' )
.getBlocks();
const firstMatchingBlock = blocks
.flatMap(
( {
innerBlocks,
}: {
innerBlocks: BlockRepresentation[];
} ) => innerBlocks
)
.find(
( block: BlockRepresentation ) => block.name === _name
);
const { clientId } = firstMatchingBlock;
const block = window.wp.blocks.createBlock( _nameToInsert );
window.wp.data
.dispatch( 'core/block-editor' )
.replaceBlock( clientId, block );
},
{ name, nameToInsert }
);
}
async replaceProductsWithProductCollectionInTemplate(
template: string,
collection?: Collections
@ -174,23 +197,20 @@ class ProductCollectionPage {
postType: 'wp_template',
} );
await this.editorUtils.enterEditMode();
await this.editor.enterEditMode();
await expect(
this.editor.canvas.locator( `[data-type="core/query"]` )
).toBeVisible();
await this.editorUtils.replaceBlockByBlockName(
'core/query',
this.BLOCK_SLUG
);
await this.replaceBlockByBlockName( 'core/query', this.BLOCK_SLUG );
await this.chooseCollectionInTemplate( collection );
await this.refreshLocators( 'editor' );
await this.editor.saveSiteEditorEntities();
}
async goToProductCatalogFrontend() {
await this.page.goto( `/shop` );
await this.page.goto( '/shop' );
await this.refreshLocators( 'frontend' );
}
@ -211,7 +231,7 @@ class ProductCollectionPage {
postId: template,
postType: 'wp_template',
} );
await this.editorUtils.enterEditMode();
await this.editor.enterEditMode();
await this.editor.canvas.locator( 'body' ).click();
await this.insertProductCollection();
await this.chooseCollectionInTemplate( collection );
@ -535,36 +555,31 @@ class ProductCollectionPage {
name: string;
attributes: object;
} ) {
const productTemplate = await this.editorUtils.getBlockByName(
const productTemplate = await this.editor.getBlockByName(
'woocommerce/product-template'
);
const productTemplateId =
( await productTemplate.getAttribute( 'data-block' ) ) ?? '';
await this.editor.selectBlocks( productTemplate );
await this.editorUtils.insertBlock(
block,
undefined,
productTemplateId
);
await this.editor.insertBlock( block, { clientId: productTemplateId } );
}
async insertProductCollectionInSingleProductBlock() {
await this.insertSingleProductBlock();
const siblingBlock = await this.editorUtils.getBlockByName(
const siblingBlock = await this.editor.getBlockByName(
'woocommerce/product-price'
);
const clientId =
( await siblingBlock.getAttribute( 'data-block' ) ) ?? '';
const parentClientId =
( await this.editorUtils.getBlockRootClientId( clientId ) ) ?? '';
( await this.editor.getBlockRootClientId( clientId ) ) ?? '';
await this.editor.selectBlocks( siblingBlock );
await this.editorUtils.insertBlock(
await this.editor.insertBlock(
{ name: this.BLOCK_SLUG },
undefined,
parentClientId
{ clientId: parentClientId }
);
}
@ -590,7 +605,7 @@ class ProductCollectionPage {
*/
private async insertSingleProductBlock() {
await this.editor.insertBlock( { name: 'woocommerce/single-product' } );
const singleProductBlock = await this.editorUtils.getBlockByName(
const singleProductBlock = await this.editor.getBlockByName(
'woocommerce/single-product'
);
await singleProductBlock

View File

@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { test as base, expect } from '@woocommerce/e2e-playwright-utils';
import { test as base, expect } from '@woocommerce/e2e-utils';
/**
* Internal dependencies
@ -22,19 +22,18 @@ const blockData = {
};
const test = base.extend< { pageObject: ProductFiltersPage } >( {
pageObject: async ( { page, editor, frontendUtils, editorUtils }, use ) => {
pageObject: async ( { page, editor, frontendUtils }, use ) => {
const pageObject = new ProductFiltersPage( {
page,
editor,
frontendUtils,
editorUtils,
} );
await use( pageObject );
},
} );
test.describe( `${ blockData.name }`, () => {
test.beforeEach( async ( { admin, editorUtils, requestUtils } ) => {
test.beforeEach( async ( { admin, editor, requestUtils } ) => {
await requestUtils.activatePlugin(
'woocommerce-blocks-test-enable-experimental-features'
);
@ -42,7 +41,7 @@ test.describe( `${ blockData.name }`, () => {
postId: `woocommerce/woocommerce//${ blockData.slug }`,
postType: 'wp_template',
} );
await editorUtils.enterEditMode();
await editor.enterEditMode();
} );
test( 'should be visible and contain correct inner blocks', async ( {

View File

@ -2,29 +2,25 @@
* External dependencies
*/
import { Page } from '@playwright/test';
import { EditorUtils, FrontendUtils } from '@woocommerce/e2e-utils';
import { Editor } from '@wordpress/e2e-test-utils-playwright';
import { Editor, FrontendUtils } from '@woocommerce/e2e-utils';
export class ProductFiltersPage {
editor: Editor;
page: Page;
frontendUtils: FrontendUtils;
editorUtils: EditorUtils;
constructor( {
editor,
page,
frontendUtils,
editorUtils,
}: {
editor: Editor;
page: Page;
frontendUtils: FrontendUtils;
editorUtils: EditorUtils;
} ) {
this.editor = editor;
this.page = page;
this.frontendUtils = frontendUtils;
this.editorUtils = editorUtils;
this.editor = editor;
}
async addProductFiltersBlock( { cleanContent = true } ) {
@ -45,6 +41,6 @@ export class ProductFiltersPage {
has: this.page.locator( ':visible' ),
} );
}
return this.editorUtils.getBlockByName( blockName );
return this.editor.getBlockByName( blockName );
}
}

View File

@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { test as base, expect } from '@woocommerce/e2e-playwright-utils';
import { test as base, expect } from '@woocommerce/e2e-utils';
/**
* Internal dependencies
@ -75,24 +75,23 @@ const getBoundingClientRect = async ( {
};
const test = base.extend< { pageObject: ProductGalleryPage } >( {
pageObject: async ( { page, editor, frontendUtils, editorUtils }, use ) => {
pageObject: async ( { page, editor, frontendUtils }, use ) => {
const pageObject = new ProductGalleryPage( {
page,
editor,
frontendUtils,
editorUtils,
} );
await use( pageObject );
},
} );
test.describe( `${ blockData.name }`, () => {
test.beforeEach( async ( { admin, editorUtils } ) => {
test.beforeEach( async ( { admin, editor } ) => {
await admin.visitSiteEditor( {
postId: `woocommerce/woocommerce//${ blockData.slug }`,
postType: 'wp_template',
} );
await editorUtils.enterEditMode();
await editor.enterEditMode();
} );
// eslint-disable-next-line playwright/no-skipped-test
@ -114,12 +113,11 @@ test.describe( `${ blockData.name }`, () => {
// eslint-disable-next-line playwright/no-skipped-test
test.skip( 'Renders Next/Previous Button block on the frontend side', async ( {
admin,
editorUtils,
editor,
page,
pageObject,
} ) => {
await addBlock( admin, editor, editorUtils );
await addBlock( admin, editor );
await editor.saveSiteEditorEntities();
@ -137,11 +135,10 @@ test.describe( `${ blockData.name }`, () => {
test.skip( 'Hide correctly the arrows', async ( {
page,
editor,
editorUtils,
pageObject,
admin,
} ) => {
await addBlock( admin, editor, editorUtils );
await addBlock( admin, editor );
await (
await pageObject.getNextPreviousButtonsBlock( {
page: 'editor',
@ -179,11 +176,10 @@ test.describe( `${ blockData.name }`, () => {
test.skip( 'Show button outside of the image', async ( {
page,
editor,
editorUtils,
pageObject,
} ) => {
// Currently we are adding the block under the related products block, but in the future we have to add replace the product gallery block with this block.
const parentBlock = await editorUtils.getBlockByName(
const parentBlock = await editor.getBlockByName(
'woocommerce/product-image-gallery'
);
const clientId =
@ -191,13 +187,12 @@ test.describe( `${ blockData.name }`, () => {
( await parentBlock.getAttribute( 'data-block' ) ) ?? '';
const parentClientId =
// eslint-disable-next-line playwright/no-conditional-in-test
( await editorUtils.getBlockRootClientId( clientId ) ) ?? '';
( await editor.getBlockRootClientId( clientId ) ) ?? '';
await editor.selectBlocks( parentBlock );
await editorUtils.insertBlock(
await editor.insertBlock(
{ name: 'woocommerce/product-gallery' },
undefined,
parentClientId
{ clientId: parentClientId }
);
await (
await pageObject.getNextPreviousButtonsBlock( {
@ -253,11 +248,10 @@ test.describe( `${ blockData.name }`, () => {
test.skip( 'Show button inside of the image', async ( {
page,
editor,
editorUtils,
pageObject,
} ) => {
// Currently we are adding the block under the related products block, but in the future we have to add replace the product gallery block with this block.
const parentBlock = await editorUtils.getBlockByName(
const parentBlock = await editor.getBlockByName(
'woocommerce/product-image-gallery'
);
const clientId =
@ -265,13 +259,12 @@ test.describe( `${ blockData.name }`, () => {
( await parentBlock.getAttribute( 'data-block' ) ) ?? '';
const parentClientId =
// eslint-disable-next-line playwright/no-conditional-in-test
( await editorUtils.getBlockRootClientId( clientId ) ) ?? '';
( await editor.getBlockRootClientId( clientId ) ) ?? '';
await editor.selectBlocks( parentBlock );
await editorUtils.insertBlock(
await editor.insertBlock(
{ name: 'woocommerce/product-gallery' },
undefined,
parentClientId
{ clientId: parentClientId }
);
await (
await pageObject.getNextPreviousButtonsBlock( {
@ -327,11 +320,10 @@ test.describe( `${ blockData.name }`, () => {
test.skip( 'Show buttons at the top of the image', async ( {
page,
editor,
editorUtils,
pageObject,
} ) => {
// Currently we are adding the block under the related products block, but in the future we have to add replace the product gallery block with this block.
const parentBlock = await editorUtils.getBlockByName(
const parentBlock = await editor.getBlockByName(
'woocommerce/product-image-gallery'
);
const clientId =
@ -339,13 +331,12 @@ test.describe( `${ blockData.name }`, () => {
( await parentBlock.getAttribute( 'data-block' ) ) ?? '';
const parentClientId =
// eslint-disable-next-line playwright/no-conditional-in-test
( await editorUtils.getBlockRootClientId( clientId ) ) ?? '';
( await editor.getBlockRootClientId( clientId ) ) ?? '';
await editor.selectBlocks( parentBlock );
await editorUtils.insertBlock(
await editor.insertBlock(
{ name: 'woocommerce/product-gallery' },
undefined,
parentClientId
{ clientId: parentClientId }
);
await (
await pageObject.getNextPreviousButtonsBlock( {
@ -353,7 +344,10 @@ test.describe( `${ blockData.name }`, () => {
} )
).click();
await editorUtils.setLayoutOption( 'Align Top' );
await page
.locator( "button[aria-label='Change vertical alignment']" )
.click();
await page.getByText( 'Align Top' ).click();
const block = await pageObject.getNextPreviousButtonsBlock( {
page: 'editor',
@ -381,11 +375,10 @@ test.describe( `${ blockData.name }`, () => {
test.skip( 'Show buttons at the middle of the image', async ( {
page,
editor,
editorUtils,
pageObject,
} ) => {
// Currently we are adding the block under the related products block, but in the future we have to add replace the product gallery block with this block.
const parentBlock = await editorUtils.getBlockByName(
const parentBlock = await editor.getBlockByName(
'woocommerce/product-image-gallery'
);
const clientId =
@ -393,13 +386,12 @@ test.describe( `${ blockData.name }`, () => {
( await parentBlock.getAttribute( 'data-block' ) ) ?? '';
const parentClientId =
// eslint-disable-next-line playwright/no-conditional-in-test
( await editorUtils.getBlockRootClientId( clientId ) ) ?? '';
( await editor.getBlockRootClientId( clientId ) ) ?? '';
await editor.selectBlocks( parentBlock );
await editorUtils.insertBlock(
await editor.insertBlock(
{ name: 'woocommerce/product-gallery' },
undefined,
parentClientId
{ clientId: parentClientId }
);
await (
await pageObject.getNextPreviousButtonsBlock( {
@ -407,7 +399,10 @@ test.describe( `${ blockData.name }`, () => {
} )
).click();
await editorUtils.setLayoutOption( 'Align Middle' );
await page
.locator( "button[aria-label='Change vertical alignment']" )
.click();
await page.getByText( 'Align Middle' ).click();
const block = await pageObject.getNextPreviousButtonsBlock( {
page: 'editor',
@ -432,11 +427,10 @@ test.describe( `${ blockData.name }`, () => {
test.skip( 'Show buttons at the bottom of the image by default', async ( {
page,
editor,
editorUtils,
pageObject,
} ) => {
// Currently we are adding the block under the related products block, but in the future we have to add replace the product gallery block with this block.
const parentBlock = await editorUtils.getBlockByName(
const parentBlock = await editor.getBlockByName(
'woocommerce/product-image-gallery'
);
const clientId =
@ -444,13 +438,12 @@ test.describe( `${ blockData.name }`, () => {
( await parentBlock.getAttribute( 'data-block' ) ) ?? '';
const parentClientId =
// eslint-disable-next-line playwright/no-conditional-in-test
( await editorUtils.getBlockRootClientId( clientId ) ) ?? '';
( await editor.getBlockRootClientId( clientId ) ) ?? '';
await editor.selectBlocks( parentBlock );
await editorUtils.insertBlock(
await editor.insertBlock(
{ name: 'woocommerce/product-gallery' },
undefined,
parentClientId
{ clientId: parentClientId }
);
await (
await pageObject.getNextPreviousButtonsBlock( {

View File

@ -1,19 +1,14 @@
/**
* External dependencies
*/
import { EditorUtils } from '@woocommerce/e2e-utils';
import { Admin, Editor } from '@wordpress/e2e-test-utils-playwright';
import { Admin, Editor } from '@woocommerce/e2e-utils';
export const addBlock = async (
admin: Admin,
editor: Editor,
editorUtils: EditorUtils
) => {
export const addBlock = async ( admin: Admin, editor: Editor ) => {
await admin.visitSiteEditor( {
postId: `woocommerce/woocommerce//single-product`,
postType: 'wp_template',
} );
await editorUtils.enterEditMode();
await editor.enterEditMode();
await editor.insertBlock( {
name: 'woocommerce/product-gallery',

View File

@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { test as base, expect } from '@woocommerce/e2e-playwright-utils';
import { test as base, expect } from '@woocommerce/e2e-utils';
/**
* Internal dependencies
@ -19,24 +19,23 @@ const blockData = {
};
const test = base.extend< { pageObject: ProductGalleryPage } >( {
pageObject: async ( { page, editor, frontendUtils, editorUtils }, use ) => {
pageObject: async ( { page, editor, frontendUtils }, use ) => {
const pageObject = new ProductGalleryPage( {
page,
editor,
frontendUtils,
editorUtils,
} );
await use( pageObject );
},
} );
test.describe( `${ blockData.name }`, () => {
test.beforeEach( async ( { admin, editorUtils, editor } ) => {
test.beforeEach( async ( { admin, editor } ) => {
await admin.visitSiteEditor( {
postId: `woocommerce/woocommerce//${ blockData.slug }`,
postType: 'wp_template',
} );
await editorUtils.enterEditMode();
await editor.enterEditMode();
await editor.openDocumentSettingsSidebar();
} );

View File

@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { test as base, expect } from '@woocommerce/e2e-playwright-utils';
import { test as base, expect } from '@woocommerce/e2e-utils';
/**
* Internal dependencies
@ -32,24 +32,23 @@ const blockData = {
};
const test = base.extend< { pageObject: ProductGalleryPage } >( {
pageObject: async ( { page, editor, frontendUtils, editorUtils }, use ) => {
pageObject: async ( { page, editor, frontendUtils }, use ) => {
const pageObject = new ProductGalleryPage( {
page,
editor,
frontendUtils,
editorUtils,
} );
await use( pageObject );
},
} );
test.describe( `${ blockData.name }`, () => {
test.beforeEach( async ( { admin, editorUtils, editor } ) => {
test.beforeEach( async ( { admin, editor } ) => {
await admin.visitSiteEditor( {
postId: `woocommerce/woocommerce//${ blockData.slug }`,
postType: 'wp_template',
} );
await editorUtils.enterEditMode();
await editor.enterEditMode();
await editor.openDocumentSettingsSidebar();
} );

View File

@ -1,8 +1,8 @@
/**
* External dependencies
*/
import { test as base, expect } from '@woocommerce/e2e-playwright-utils';
import { Locator, Page } from '@playwright/test';
import { test as base, expect } from '@woocommerce/e2e-utils';
/**
* Internal dependencies
@ -36,12 +36,11 @@ const changeNumberOfThumbnailsInputValue = async (
};
const test = base.extend< { pageObject: ProductGalleryPage } >( {
pageObject: async ( { page, editor, frontendUtils, editorUtils }, use ) => {
pageObject: async ( { page, editor, frontendUtils }, use ) => {
const pageObject = new ProductGalleryPage( {
page,
editor,
frontendUtils,
editorUtils,
} );
await use( pageObject );
},
@ -64,7 +63,6 @@ test.describe( `${ blockData.name }`, () => {
page,
editor,
pageObject,
editorUtils,
frontendUtils,
} ) => {
await editor.insertBlock( {
@ -80,13 +78,10 @@ test.describe( `${ blockData.name }`, () => {
// Test the default (left) position of thumbnails by cross-checking:
// - The Gallery block has the classes "is-layout-flex" and "is-nowrap".
// - The Thumbnails block has a lower index than the Large Image block.
const groupBlock = (
await editorUtils.getBlockByTypeWithParent(
'core/group',
'woocommerce/product-gallery'
)
).first();
const groupBlock = editor.canvas
.locator( '[data-type="woocommerce/product-gallery"]' )
.locator( '[data-type="core/group"]' )
.first();
const groupBlockClassAttribute = await groupBlock.getAttribute(
'class'
@ -94,7 +89,7 @@ test.describe( `${ blockData.name }`, () => {
expect( groupBlockClassAttribute ).toContain( 'is-layout-flex' );
expect( groupBlockClassAttribute ).toContain( 'is-nowrap' );
const isThumbnailsBlockEarlier = await editorUtils.isBlockEarlierThan(
const isThumbnailsBlockEarlier = await editor.isBlockEarlierThan(
groupBlock,
'woocommerce/product-gallery-thumbnails',
'core/group'
@ -158,11 +153,10 @@ test.describe( `${ blockData.name }`, () => {
test( 'Position thumbnails on the left of the large image', async ( {
page,
editor,
editorUtils,
frontendUtils,
} ) => {
// Currently we are adding the block under the legacy Product Image Gallery block, but in the future we have to add replace the product gallery block with this block.
const parentBlock = await editorUtils.getBlockByName(
const parentBlock = await editor.getBlockByName(
'woocommerce/product-image-gallery'
);
const clientId =
@ -170,17 +164,14 @@ test.describe( `${ blockData.name }`, () => {
( await parentBlock.getAttribute( 'data-block' ) ) ?? '';
const parentClientId =
// eslint-disable-next-line playwright/no-conditional-in-test
( await editorUtils.getBlockRootClientId( clientId ) ) ?? '';
( await editor.getBlockRootClientId( clientId ) ) ?? '';
await editor.selectBlocks( parentBlock );
await editorUtils.insertBlock(
await editor.insertBlock(
{ name: 'woocommerce/product-gallery' },
undefined,
parentClientId
{ clientId: parentClientId }
);
await (
await editorUtils.getBlockByName( blockData.name )
).click();
await ( await editor.getBlockByName( blockData.name ) ).click();
await editor.openDocumentSettingsSidebar();
await page
@ -189,12 +180,10 @@ test.describe( `${ blockData.name }`, () => {
)
.click();
const groupBlock = (
await editorUtils.getBlockByTypeWithParent(
'core/group',
'woocommerce/product-gallery'
)
).first();
const groupBlock = editor.canvas
.locator( '[data-type="woocommerce/product-gallery"]' )
.locator( '[data-type="core/group"]' )
.first();
const groupBlockClassAttribute = await groupBlock.getAttribute(
'class'
@ -202,8 +191,7 @@ test.describe( `${ blockData.name }`, () => {
expect( groupBlockClassAttribute ).toContain( 'is-layout-flex' );
expect( groupBlockClassAttribute ).toContain( 'is-nowrap' );
const isThumbnailsBlockEarlier =
await editorUtils.isBlockEarlierThan(
const isThumbnailsBlockEarlier = await editor.isBlockEarlierThan(
groupBlock,
'woocommerce/product-gallery-thumbnails',
'core/group'
@ -244,11 +232,10 @@ test.describe( `${ blockData.name }`, () => {
test( 'Position thumbnails on the bottom of the large image', async ( {
page,
editor,
editorUtils,
frontendUtils,
} ) => {
// Currently we are adding the block under the legacy Product Image Gallery block, but in the future we have to add replace the product gallery block with this block.
const parentBlock = await editorUtils.getBlockByName(
const parentBlock = await editor.getBlockByName(
'woocommerce/product-image-gallery'
);
const clientId =
@ -256,17 +243,14 @@ test.describe( `${ blockData.name }`, () => {
( await parentBlock.getAttribute( 'data-block' ) ) ?? '';
const parentClientId =
// eslint-disable-next-line playwright/no-conditional-in-test
( await editorUtils.getBlockRootClientId( clientId ) ) ?? '';
( await editor.getBlockRootClientId( clientId ) ) ?? '';
await editor.selectBlocks( parentBlock );
await editorUtils.insertBlock(
await editor.insertBlock(
{ name: 'woocommerce/product-gallery' },
undefined,
parentClientId
{ clientId: parentClientId }
);
await (
await editorUtils.getBlockByName( blockData.name )
).click();
await ( await editor.getBlockByName( blockData.name ) ).click();
await editor.openDocumentSettingsSidebar();
await page
@ -275,12 +259,10 @@ test.describe( `${ blockData.name }`, () => {
)
.click();
const groupBlock = (
await editorUtils.getBlockByTypeWithParent(
'core/group',
'woocommerce/product-gallery'
)
).first();
const groupBlock = editor.canvas
.locator( '[data-type="woocommerce/product-gallery"]' )
.locator( '[data-type="core/group"]' )
.first();
const groupBlockClassAttribute = await groupBlock.getAttribute(
'class'
@ -288,8 +270,7 @@ test.describe( `${ blockData.name }`, () => {
expect( groupBlockClassAttribute ).toContain( 'is-layout-flex' );
expect( groupBlockClassAttribute ).toContain( 'is-vertical' );
const isThumbnailsBlockEarlier =
await editorUtils.isBlockEarlierThan(
const isThumbnailsBlockEarlier = await editor.isBlockEarlierThan(
groupBlock,
'woocommerce/product-gallery-thumbnails',
'core/group'
@ -331,11 +312,10 @@ test.describe( `${ blockData.name }`, () => {
test( 'Position thumbnails on the right of the large image', async ( {
page,
editor,
editorUtils,
frontendUtils,
} ) => {
// Currently we are adding the block under the legacy Product Image Gallery block, but in the future we have to add replace the product gallery block with this block.
const parentBlock = await editorUtils.getBlockByName(
const parentBlock = await editor.getBlockByName(
'woocommerce/product-image-gallery'
);
const clientId =
@ -343,17 +323,14 @@ test.describe( `${ blockData.name }`, () => {
( await parentBlock.getAttribute( 'data-block' ) ) ?? '';
const parentClientId =
// eslint-disable-next-line playwright/no-conditional-in-test
( await editorUtils.getBlockRootClientId( clientId ) ) ?? '';
( await editor.getBlockRootClientId( clientId ) ) ?? '';
await editor.selectBlocks( parentBlock );
await editorUtils.insertBlock(
await editor.insertBlock(
{ name: 'woocommerce/product-gallery' },
undefined,
parentClientId
{ clientId: parentClientId }
);
await (
await editorUtils.getBlockByName( blockData.name )
).click();
await ( await editor.getBlockByName( blockData.name ) ).click();
await editor.openDocumentSettingsSidebar();
await page
@ -362,12 +339,10 @@ test.describe( `${ blockData.name }`, () => {
)
.click();
const groupBlock = (
await editorUtils.getBlockByTypeWithParent(
'core/group',
'woocommerce/product-gallery'
)
).first();
const groupBlock = editor.canvas
.locator( '[data-type="woocommerce/product-gallery"]' )
.locator( '[data-type="core/group"]' )
.first();
const groupBlockClassAttribute = await groupBlock.getAttribute(
'class'
@ -375,8 +350,7 @@ test.describe( `${ blockData.name }`, () => {
expect( groupBlockClassAttribute ).toContain( 'is-layout-flex' );
expect( groupBlockClassAttribute ).toContain( 'is-nowrap' );
const isThumbnailsBlockEarlier =
await editorUtils.isBlockEarlierThan(
const isThumbnailsBlockEarlier = await editor.isBlockEarlierThan(
groupBlock,
'woocommerce/product-gallery-thumbnails',
'core/group'

View File

@ -1,8 +1,8 @@
/**
* External dependencies
*/
import { test as base, expect } from '@woocommerce/e2e-playwright-utils';
import { Locator } from '@playwright/test';
import { test as base, expect } from '@woocommerce/e2e-utils';
/**
* Internal dependencies
@ -26,12 +26,11 @@ const blockData = {
};
const test = base.extend< { pageObject: ProductGalleryPage } >( {
pageObject: async ( { page, editor, frontendUtils, editorUtils }, use ) => {
pageObject: async ( { page, editor, frontendUtils }, use ) => {
const pageObject = new ProductGalleryPage( {
page,
editor,
frontendUtils,
editorUtils,
} );
await use( pageObject );
},
@ -520,9 +519,9 @@ test.describe( `${ blockData.name }`, () => {
test.describe( 'block availability', () => {
test( 'should be available on the Single Product Template', async ( {
page,
editorUtils,
editor,
} ) => {
await editorUtils.openGlobalBlockInserter();
await editor.openGlobalBlockInserter();
await page.getByRole( 'tab', { name: 'Blocks' } ).click();
const productGalleryBlockOption = page
.getByRole( 'listbox', { name: 'WooCommerce' } )
@ -533,15 +532,15 @@ test.describe( `${ blockData.name }`, () => {
test( 'should be available on the Product Gallery template part', async ( {
admin,
editorUtils,
editor,
page,
} ) => {
await admin.visitSiteEditor( {
postId: `woocommerce/woocommerce//product-gallery`,
postType: 'wp_template_part',
} );
await editorUtils.enterEditMode();
await editorUtils.openGlobalBlockInserter();
await editor.enterEditMode();
await editor.openGlobalBlockInserter();
await page.getByRole( 'tab', { name: 'Blocks' } ).click();
const productGalleryBlockOption = page
.getByRole( 'listbox', { name: 'WooCommerce' } )
@ -553,10 +552,10 @@ test.describe( `${ blockData.name }`, () => {
test( 'should be hidden on the post editor', async ( {
admin,
page,
editorUtils,
editor,
} ) => {
await admin.createNewPost();
await editorUtils.openGlobalBlockInserter();
await editor.openGlobalBlockInserter();
const productGalleryBlockOption = page
.getByRole( 'listbox', { name: 'WooCommerce' } )
.getByRole( 'option', { name: blockData.title } );

View File

@ -2,8 +2,7 @@
* External dependencies
*/
import { Page } from '@playwright/test';
import { EditorUtils, FrontendUtils } from '@woocommerce/e2e-utils';
import { Editor } from '@wordpress/e2e-test-utils-playwright';
import { Editor, FrontendUtils } from '@woocommerce/e2e-utils';
const selectors = {
editor: {
@ -18,22 +17,19 @@ export class ProductGalleryPage {
editor: Editor;
page: Page;
frontendUtils: FrontendUtils;
editorUtils: EditorUtils;
constructor( {
editor,
page,
frontendUtils,
editorUtils,
}: {
editor: Editor;
page: Page;
frontendUtils: FrontendUtils;
editorUtils: EditorUtils;
} ) {
this.editor = editor;
this.page = page;
this.frontendUtils = frontendUtils;
this.editorUtils = editorUtils;
this.editor = editor;
}
async addProductGalleryBlock( { cleanContent = true } ) {
@ -96,7 +92,7 @@ export class ProductGalleryPage {
has: this.page.locator( ':visible' ),
} );
}
return this.editorUtils.getBlockByName( blockName );
return this.editor.getBlockByName( blockName );
}
async getThumbnailsBlock( { page }: { page: 'frontend' | 'editor' } ) {
@ -108,7 +104,7 @@ export class ProductGalleryPage {
has: this.page.locator( ':visible' ),
} );
}
return this.editorUtils.getBlockByName( blockName );
return this.editor.getBlockByName( blockName );
}
async getNextPreviousButtonsBlock( {
@ -125,7 +121,7 @@ export class ProductGalleryPage {
has: this.page.locator( ':visible' ),
} );
}
return this.editorUtils.getBlockByName( blockName );
return this.editor.getBlockByName( blockName );
}
async getPagerBlock( { page }: { page: 'frontend' | 'editor' } ) {
@ -137,7 +133,7 @@ export class ProductGalleryPage {
has: this.page.locator( ':visible' ),
} );
}
return this.editorUtils.getBlockByName( blockName );
return this.editor.getBlockByName( blockName );
}
async getBlock( { page }: { page: 'frontend' | 'editor' } ) {
@ -149,7 +145,7 @@ export class ProductGalleryPage {
has: this.page.locator( ':visible' ),
} );
}
return this.editorUtils.getBlockByName( blockName );
return this.editor.getBlockByName( blockName );
}
async getAddToCartWithOptionsBlock( {
@ -165,6 +161,6 @@ export class ProductGalleryPage {
has: this.page.locator( ':visible' ),
} );
}
return this.editorUtils.getBlockByName( blockName );
return this.editor.getBlockByName( blockName );
}
}

View File

@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { expect, test } from '@woocommerce/e2e-playwright-utils';
import { expect, test } from '@woocommerce/e2e-utils';
const blockData = {
name: 'Newest Products',
@ -10,16 +10,15 @@ const blockData = {
test.describe( `${ blockData.slug } Block`, () => {
test( 'can be inserted in Post Editor and it is visible on the frontend', async ( {
editorUtils,
editor,
admin,
frontendUtils,
} ) => {
await admin.createNewPost();
await editor.insertBlock( { name: blockData.slug } );
const blockLocator = await editorUtils.getBlockByName( blockData.slug );
const blockLocator = await editor.getBlockByName( blockData.slug );
await expect( blockLocator.getByRole( 'listitem' ) ).toHaveCount( 9 );
await editorUtils.publishAndVisitPost();
await editor.publishAndVisitPost();
const blockLocatorFrontend = await frontendUtils.getBlockByName(
blockData.slug
);

View File

@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { expect, test } from '@woocommerce/e2e-playwright-utils';
import { expect, test } from '@woocommerce/e2e-utils';
const blockData = {
name: 'On Sale Products',
@ -10,16 +10,15 @@ const blockData = {
test.describe( `${ blockData.slug } Block`, () => {
test( 'can be inserted in Post Editor and it is visible on the frontend', async ( {
editorUtils,
editor,
admin,
frontendUtils,
} ) => {
await admin.createNewPost();
await editor.insertBlock( { name: blockData.slug } );
const blockLocator = await editorUtils.getBlockByName( blockData.slug );
const blockLocator = await editor.getBlockByName( blockData.slug );
await expect( blockLocator.getByRole( 'listitem' ) ).toHaveCount( 6 );
await editorUtils.publishAndVisitPost();
await editor.publishAndVisitPost();
const blockLocatorFrontend = await frontendUtils.getBlockByName(
blockData.slug
);

View File

@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { expect, test } from '@woocommerce/e2e-playwright-utils';
import { expect, test } from '@woocommerce/e2e-utils';
const blockData = {
name: 'Product Results Count',
@ -25,7 +25,6 @@ test.describe( `${ blockData.slug } Block`, () => {
test( 'block can be inserted in the Site Editor', async ( {
admin,
requestUtils,
editorUtils,
editor,
} ) => {
const template = await requestUtils.createTemplate( 'wp_template', {
@ -46,7 +45,7 @@ test.describe( `${ blockData.slug } Block`, () => {
name: blockData.slug,
} );
const block = await editorUtils.getBlockByName( blockData.slug );
const block = await editor.getBlockByName( blockData.slug );
await expect( block ).toHaveText( 'Showing 1-X of X results' );
} );

View File

@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { expect, test } from '@woocommerce/e2e-playwright-utils';
import { expect, test } from '@woocommerce/e2e-utils';
const blockData = {
name: 'Products by Tag',
@ -10,18 +10,17 @@ const blockData = {
test.describe( `${ blockData.slug } Block`, () => {
test( 'can be inserted in Post Editor and it is visible on the frontend', async ( {
editorUtils,
editor,
admin,
frontendUtils,
} ) => {
await admin.createNewPost();
await editor.insertBlock( { name: blockData.slug } );
const blockLocator = await editorUtils.getBlockByName( blockData.slug );
const blockLocator = await editor.getBlockByName( blockData.slug );
await blockLocator.getByText( 'Recommended' ).click();
await blockLocator.getByText( 'Done' ).click();
await expect( blockLocator.getByRole( 'listitem' ) ).toHaveCount( 2 );
await editorUtils.publishAndVisitPost();
await editor.publishAndVisitPost();
const blockLocatorFrontend = await frontendUtils.getBlockByName(
blockData.slug
);

View File

@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { expect, test } from '@woocommerce/e2e-playwright-utils';
import { expect, test } from '@woocommerce/e2e-utils';
const blockData = {
name: 'Top Rated Products',
@ -10,16 +10,15 @@ const blockData = {
test.describe( `${ blockData.slug } Block`, () => {
test( 'can be inserted in Post Editor and it is visible on the frontend', async ( {
editorUtils,
editor,
admin,
frontendUtils,
} ) => {
await admin.createNewPost();
await editor.insertBlock( { name: blockData.slug } );
const blockLocator = await editorUtils.getBlockByName( blockData.slug );
const blockLocator = await editor.getBlockByName( blockData.slug );
await expect( blockLocator.getByRole( 'listitem' ) ).toHaveCount( 9 );
await editorUtils.publishAndVisitPost();
await editor.publishAndVisitPost();
const blockLocatorFrontend = await frontendUtils.getBlockByName(
blockData.slug
);

View File

@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { expect, test } from '@woocommerce/e2e-playwright-utils';
import { expect, test } from '@woocommerce/e2e-utils';
const blockData = {
name: 'Products by Attribute',
@ -10,18 +10,17 @@ const blockData = {
test.describe( `${ blockData.slug } Block`, () => {
test( 'can be inserted in Post Editor and it is visible on the frontend', async ( {
editorUtils,
editor,
admin,
frontendUtils,
} ) => {
await admin.createNewPost();
await editor.insertBlock( { name: blockData.slug } );
const blockLocator = await editorUtils.getBlockByName( blockData.slug );
const blockLocator = await editor.getBlockByName( blockData.slug );
await blockLocator.getByText( 'Color' ).click();
await blockLocator.getByText( 'Done' ).click();
await expect( blockLocator.getByRole( 'listitem' ) ).toHaveCount( 9 );
await editorUtils.publishAndVisitPost();
await editor.publishAndVisitPost();
const blockLocatorFrontend = await frontendUtils.getBlockByName(
blockData.slug
);

View File

@ -1,8 +1,7 @@
/**
* External dependencies
*/
import { BlockData } from '@woocommerce/e2e-types';
import { test, expect } from '@woocommerce/e2e-playwright-utils';
import { test, expect, BlockData } from '@woocommerce/e2e-utils';
/**
* Internal dependencies
@ -14,6 +13,7 @@ import {
const blockData: BlockData = {
name: 'core/query',
slug: '',
mainClass: '.wc-block-price-filter',
selectors: {
frontend: {},
@ -58,7 +58,6 @@ const templates = {
test.describe( `${ blockData.name } Block `, () => {
test( 'when Inherit Query from template is enabled all the settings that customize the query should be hidden', async ( {
admin,
editorUtils,
editor,
page,
} ) => {
@ -69,7 +68,7 @@ test.describe( `${ blockData.name } Block `, () => {
await editor.canvas.locator( 'body' ).click();
const block = await editorUtils.getBlockByName( blockData.name );
const block = await editor.getBlockByName( blockData.name );
await editor.selectBlocks( block );
await editor.openDocumentSettingsSidebar();
@ -86,7 +85,6 @@ test.describe( `${ blockData.name } Block `, () => {
} );
test( 'when Inherit Query from template is disabled all the settings that customize the query should be visble', async ( {
admin,
editorUtils,
editor,
page,
} ) => {
@ -97,7 +95,7 @@ test.describe( `${ blockData.name } Block `, () => {
await editor.canvas.locator( 'body' ).click();
const block = await editorUtils.getBlockByName( blockData.name );
const block = await editor.getBlockByName( blockData.name );
await editor.selectBlocks( block );
await editor.openDocumentSettingsSidebar();
@ -127,7 +125,6 @@ for ( const {
admin,
editor,
page,
editorUtils,
} ) => {
await admin.visitSiteEditor( {
postId: `woocommerce/woocommerce//${ slug }`,
@ -135,17 +132,16 @@ for ( const {
} );
await editor.canvas.locator( 'body' ).click();
const block = await editorUtils.getBlockByName( blockData.name );
const block = await editor.getBlockByName( blockData.name );
// eslint-disable-next-line playwright/no-conditional-in-test
const clientId = ( await block.getAttribute( 'data-block' ) ) ?? '';
const parentClientId =
// eslint-disable-next-line playwright/no-conditional-in-test
( await editorUtils.getBlockRootClientId( clientId ) ) ?? '';
( await editor.getBlockRootClientId( clientId ) ) ?? '';
await editor.selectBlocks( block );
await editorUtils.insertBlock(
await editor.insertBlock(
{ name: legacyBlockName },
undefined,
parentClientId
{ clientId: parentClientId }
);
await editor.saveSiteEditorEntities();

View File

@ -1,15 +1,12 @@
/**
* External dependencies
*/
import { test, expect } from '@woocommerce/e2e-playwright-utils';
import { cli } from '@woocommerce/e2e-utils';
import path from 'path';
const PRODUCT_CATALOG_LINK = '/shop';
const TEMPLATE_PATH = path.join(
__dirname,
'../shared/filters-with-product-collection.handlebars'
);
import {
test as base,
expect,
cli,
TemplateCompiler,
} from '@woocommerce/e2e-utils';
const blockData = {
name: 'Filter by Rating',
@ -17,6 +14,15 @@ const blockData = {
urlSearchParamWhenFilterIsApplied: 'rating_filter=1',
};
const test = base.extend< { templateCompiler: TemplateCompiler } >( {
templateCompiler: async ( { requestUtils }, use ) => {
const compiler = await requestUtils.createTemplateFromFile(
'archive-product_filters-with-product-collection'
);
await use( compiler );
},
} );
test.describe( `${ blockData.name } Block`, () => {
test.beforeEach( async ( { admin, editor } ) => {
await admin.createNewPost();
@ -43,10 +49,9 @@ test.describe( `${ blockData.name } Block`, () => {
test( 'should allow changing the display style', async ( {
page,
editorUtils,
editor,
} ) => {
const stockFilter = await editorUtils.getBlockByName( blockData.slug );
const stockFilter = await editor.getBlockByName( blockData.slug );
await editor.selectBlocks( stockFilter );
await expect(
@ -70,10 +75,9 @@ test.describe( `${ blockData.name } Block`, () => {
test( 'should allow toggling the visibility of the filter button', async ( {
page,
editorUtils,
editor,
} ) => {
const priceFilterControls = await editorUtils.getBlockByName(
const priceFilterControls = await editor.getBlockByName(
blockData.slug
);
await editor.selectBlocks( priceFilterControls );
@ -95,7 +99,7 @@ test.describe( `${ blockData.name } Block`, () => {
} );
test.describe( `${ blockData.name } Block - with PHP classic template`, () => {
test.beforeEach( async ( { admin, page, editor, editorUtils } ) => {
test.beforeEach( async ( { admin, page, editor } ) => {
await cli(
'npm run wp-env run tests-cli -- wp option update wc_blocks_use_blockified_product_grid_block_as_template false'
);
@ -105,7 +109,7 @@ test.describe( `${ blockData.name } Block - with PHP classic template`, () => {
postType: 'wp_template',
} );
await editorUtils.enterEditMode();
await editor.enterEditMode();
await editor.insertBlock( {
name: 'woocommerce/filter-wrapper',
@ -115,8 +119,10 @@ test.describe( `${ blockData.name } Block - with PHP classic template`, () => {
},
} );
await page.keyboard.press( 'Escape' );
await editor.saveSiteEditorEntities();
await page.goto( `/shop` );
await page.goto( '/shop' );
} );
test( 'should show all products', async ( { frontendUtils, page } ) => {
@ -160,16 +166,10 @@ test.describe( `${ blockData.name } Block - with PHP classic template`, () => {
} );
test.describe( `${ blockData.name } Block - with Product Collection`, () => {
test.beforeEach( async ( { requestUtils } ) => {
await requestUtils.updateTemplateContents(
'woocommerce/woocommerce//archive-product',
TEMPLATE_PATH,
{}
);
} );
test( 'should show all products', async ( { page, templateCompiler } ) => {
await templateCompiler.compile();
test( 'should show all products', async ( { page } ) => {
await page.goto( PRODUCT_CATALOG_LINK );
await page.goto( '/shop' );
const products = page
.locator( '.wp-block-woocommerce-product-template' )
.getByRole( 'listitem' );
@ -179,8 +179,11 @@ test.describe( `${ blockData.name } Block - with Product Collection`, () => {
test( 'should show only products that match the filter', async ( {
page,
templateCompiler,
} ) => {
await page.goto( PRODUCT_CATALOG_LINK );
await templateCompiler.compile();
await page.goto( '/shop' );
await page
.getByRole( 'checkbox', { name: 'Rated 1 out of 5' } )
.click();
@ -200,16 +203,18 @@ test.describe( `${ blockData.name } Block - with Product Collection`, () => {
page,
admin,
editor,
editorUtils,
templateCompiler,
} ) => {
const template = await templateCompiler.compile();
await admin.visitSiteEditor( {
postId: 'woocommerce/woocommerce//archive-product',
postType: 'wp_template',
postId: template.id,
postType: template.type,
} );
await editorUtils.enterEditMode();
await editor.enterEditMode();
const ratingFilterControls = await editorUtils.getBlockByName(
const ratingFilterControls = await editor.getBlockByName(
'woocommerce/rating-filter'
);
await expect( ratingFilterControls ).toBeVisible();
@ -218,7 +223,7 @@ test.describe( `${ blockData.name } Block - with Product Collection`, () => {
await page.getByText( "Show 'Apply filters' button" ).click();
await editor.saveSiteEditorEntities();
await page.goto( PRODUCT_CATALOG_LINK );
await page.goto( '/shop' );
await page
.getByRole( 'checkbox', { name: 'Rated 1 out of 5' } )

View File

@ -1,8 +1,7 @@
/**
* External dependencies
*/
import { BlockData } from '@woocommerce/e2e-types';
import { test, expect } from '@woocommerce/e2e-playwright-utils';
import { test, expect, BlockData } from '@woocommerce/e2e-utils';
const blockData: BlockData = {
name: 'Related Products',
@ -28,13 +27,12 @@ test.describe( `${ blockData.name } Block`, () => {
test( "can't be added in the Post Editor - Product Catalog Template", async ( {
admin,
editor,
editorUtils,
} ) => {
await admin.visitSiteEditor( {
postId: `woocommerce/woocommerce//archive-product`,
postType: 'wp_template',
} );
await editorUtils.enterEditMode();
await editor.enterEditMode();
await editor.setContent( '' );
@ -45,25 +43,24 @@ test.describe( `${ blockData.name } Block`, () => {
}
await expect(
await editorUtils.getBlockByName( blockData.slug )
await editor.getBlockByName( blockData.slug )
).toBeHidden();
} );
test( 'can be added in the Post Editor - Single Product Template', async ( {
admin,
editor,
editorUtils,
} ) => {
await admin.visitSiteEditor( {
postId: `woocommerce/woocommerce//single-product`,
postType: 'wp_template',
} );
await editorUtils.enterEditMode();
await editor.enterEditMode();
await editor.setContent( '' );
await editor.insertBlock( { name: blockData.slug } );
await expect(
await editorUtils.getBlockByName( blockData.slug )
await editor.getBlockByName( blockData.slug )
).toBeVisible();
} );
} );

View File

@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { expect, test } from '@woocommerce/e2e-playwright-utils';
import { expect, test } from '@woocommerce/e2e-utils';
/**
* Internal dependencies
@ -28,7 +28,7 @@ test.describe( `${ BLOCK_NAME } Block`, () => {
test( 'block can be inserted and it successfully renders a review in the editor and the frontend', async ( {
page,
editorUtils,
editor,
} ) => {
const categoryCheckbox = page.getByLabel( 'Clothing' );
await categoryCheckbox.check();
@ -40,7 +40,7 @@ test.describe( `${ BLOCK_NAME } Block`, () => {
page.getByText( hoodieReviews[ 0 ].review )
).toBeVisible();
await editorUtils.publishAndVisitPost();
await editor.publishAndVisitPost();
await expect(
page.getByText( hoodieReviews[ 0 ].review )
@ -50,9 +50,9 @@ test.describe( `${ BLOCK_NAME } Block`, () => {
test( 'sorts by most recent review by default and can sort by highest rating', async ( {
page,
frontendUtils,
editorUtils,
editor,
} ) => {
await editorUtils.publishAndVisitPost();
await editor.publishAndVisitPost();
const block = await frontendUtils.getBlockByName( BLOCK_NAME );
@ -71,9 +71,9 @@ test.describe( `${ BLOCK_NAME } Block`, () => {
test( 'can sort by lowest rating', async ( {
page,
frontendUtils,
editorUtils,
editor,
} ) => {
await editorUtils.publishAndVisitPost();
await editor.publishAndVisitPost();
const block = await frontendUtils.getBlockByName( BLOCK_NAME );

View File

@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { expect, test } from '@woocommerce/e2e-playwright-utils';
import { expect, test } from '@woocommerce/e2e-utils';
/**
* Internal dependencies
@ -28,7 +28,7 @@ test.describe( `${ BLOCK_NAME } Block`, () => {
test( 'block can be inserted and it successfully renders a review in the editor and the frontend', async ( {
page,
editorUtils,
editor,
} ) => {
const productCheckbox = page.getByLabel( 'Hoodie, has 2 reviews' );
await productCheckbox.check();
@ -41,7 +41,7 @@ test.describe( `${ BLOCK_NAME } Block`, () => {
page.getByText( hoodieReviews[ 0 ].review )
).toBeVisible();
await editorUtils.publishAndVisitPost();
await editor.publishAndVisitPost();
await expect(
page.getByText( hoodieReviews[ 0 ].review )
@ -51,9 +51,9 @@ test.describe( `${ BLOCK_NAME } Block`, () => {
test( 'sorts by most recent by default and can sort by highest rating', async ( {
page,
frontendUtils,
editorUtils,
editor,
} ) => {
await editorUtils.publishAndVisitPost();
await editor.publishAndVisitPost();
const block = await frontendUtils.getBlockByName( BLOCK_NAME );
const reviews = block.locator(
@ -71,9 +71,9 @@ test.describe( `${ BLOCK_NAME } Block`, () => {
test( 'can sort by lowest rating', async ( {
page,
frontendUtils,
editorUtils,
editor,
} ) => {
await editorUtils.publishAndVisitPost();
await editor.publishAndVisitPost();
const block = await frontendUtils.getBlockByName( BLOCK_NAME );
const reviews = block.locator(

View File

@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { expect, test } from '@woocommerce/e2e-playwright-utils';
import { expect, test } from '@woocommerce/e2e-utils';
/**
* Internal dependencies
@ -28,7 +28,6 @@ test.describe( `${ blockData.slug } Block`, () => {
test( 'block can be inserted in the Site Editor', async ( {
admin,
requestUtils,
editorUtils,
editor,
} ) => {
const template = await requestUtils.createTemplate( 'wp_template', {
@ -50,7 +49,7 @@ test.describe( `${ blockData.slug } Block`, () => {
name: blockData.slug,
} );
const block = await editorUtils.getBlockByName( blockData.slug );
const block = await editor.getBlockByName( blockData.slug );
await expect( block ).toHaveText(
/This block lists description, attributes and reviews for a single product./

View File

@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { test, expect } from '@woocommerce/e2e-playwright-utils';
import { test, expect } from '@woocommerce/e2e-utils';
/**
* Internal dependencies

View File

@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { test, expect } from '@woocommerce/e2e-playwright-utils';
import { test, expect } from '@woocommerce/e2e-utils';
const products = [
{

View File

@ -1,15 +1,12 @@
/**
* External dependencies
*/
import { test, expect } from '@woocommerce/e2e-playwright-utils';
import { cli } from '@woocommerce/e2e-utils';
import path from 'path';
const PRODUCT_CATALOG_LINK = '/shop';
const TEMPLATE_PATH = path.join(
__dirname,
'../shared/filters-with-product-collection.handlebars'
);
import {
test as base,
expect,
TemplateCompiler,
cli,
} from '@woocommerce/e2e-utils';
export const blockData = {
name: 'Filter by Stock',
@ -17,6 +14,15 @@ export const blockData = {
urlSearchParamWhenFilterIsApplied: 'filter_stock_status=outofstock',
};
const test = base.extend< { templateCompiler: TemplateCompiler } >( {
templateCompiler: async ( { requestUtils }, use ) => {
const compiler = await requestUtils.createTemplateFromFile(
'archive-product_filters-with-product-collection'
);
await use( compiler );
},
} );
test.describe( `${ blockData.name } Block`, () => {
test.beforeEach( async ( { admin, editor } ) => {
await admin.createNewPost();
@ -44,10 +50,9 @@ test.describe( `${ blockData.name } Block`, () => {
test( 'should allow changing the display style', async ( {
page,
editorUtils,
editor,
} ) => {
const stockFilter = await editorUtils.getBlockByName( blockData.slug );
const stockFilter = await editor.getBlockByName( blockData.slug );
await editor.selectBlocks( stockFilter );
await expect(
@ -81,10 +86,9 @@ test.describe( `${ blockData.name } Block`, () => {
test( 'should allow toggling the visibility of the filter button', async ( {
page,
editorUtils,
editor,
} ) => {
const priceFilterControls = await editorUtils.getBlockByName(
const priceFilterControls = await editor.getBlockByName(
blockData.slug
);
await editor.selectBlocks( priceFilterControls );
@ -114,14 +118,9 @@ test.describe( `${ blockData.name } Block - with PHP classic template`, () => {
await admin.visitSiteEditor( {
postId: 'woocommerce/woocommerce//archive-product',
postType: 'wp_template',
canvas: 'edit',
} );
await editor.canvas
.locator(
'.wp-block-woocommerce-classic-template__placeholder-image'
)
.waitFor();
await editor.enterEditMode();
await editor.insertBlock( {
name: 'woocommerce/filter-wrapper',
@ -131,7 +130,7 @@ test.describe( `${ blockData.name } Block - with PHP classic template`, () => {
},
} );
await editor.saveSiteEditorEntities();
await page.goto( `/shop` );
await page.goto( '/shop' );
} );
test( 'should show all products', async ( { frontendUtils } ) => {
@ -175,16 +174,10 @@ test.describe( `${ blockData.name } Block - with PHP classic template`, () => {
} );
test.describe( `${ blockData.name } Block - with Product Collection`, () => {
test.beforeEach( async ( { requestUtils } ) => {
await requestUtils.updateTemplateContents(
'woocommerce/woocommerce//archive-product',
TEMPLATE_PATH,
{}
);
} );
test( 'should show all products', async ( { page, templateCompiler } ) => {
await templateCompiler.compile();
test( 'should show all products', async ( { page } ) => {
await page.goto( PRODUCT_CATALOG_LINK );
await page.goto( '/shop' );
const products = page
.locator( '.wp-block-woocommerce-product-template' )
.getByRole( 'listitem' );
@ -194,8 +187,11 @@ test.describe( `${ blockData.name } Block - with Product Collection`, () => {
test( 'should show only products that match the filter', async ( {
page,
templateCompiler,
} ) => {
await page.goto( PRODUCT_CATALOG_LINK );
await templateCompiler.compile();
await page.goto( '/shop' );
await page.getByText( 'Out of Stock' ).click();
await expect( page ).toHaveURL(
@ -213,15 +209,17 @@ test.describe( `${ blockData.name } Block - with Product Collection`, () => {
page,
admin,
editor,
editorUtils,
templateCompiler,
} ) => {
await admin.visitSiteEditor( {
postId: 'woocommerce/woocommerce//archive-product',
postType: 'wp_template',
} );
const template = await templateCompiler.compile();
await editorUtils.enterEditMode();
const stockFilterControls = await editorUtils.getBlockByName(
await admin.visitSiteEditor( {
postId: template.id,
postType: template.type,
} );
await editor.enterEditMode();
const stockFilterControls = await editor.getBlockByName(
blockData.slug
);
await expect( stockFilterControls ).toBeVisible();
@ -229,7 +227,7 @@ test.describe( `${ blockData.name } Block - with Product Collection`, () => {
await editor.openDocumentSettingsSidebar();
await page.getByText( "Show 'Apply filters' button" ).click();
await editor.saveSiteEditorEntities();
await page.goto( PRODUCT_CATALOG_LINK );
await page.goto( '/shop' );
await page.getByText( 'Out of Stock' ).click();
await page.getByRole( 'button', { name: 'Apply' } ).click();

View File

@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { expect, test } from '@woocommerce/e2e-playwright-utils';
import { expect, test } from '@woocommerce/e2e-utils';
/**
* Internal dependencies
@ -14,15 +14,15 @@ const blockData = {
test.describe( `${ blockData.slug } Block`, () => {
test( 'should be visible on the Product Catalog template', async ( {
editorUtils,
editor,
admin,
} ) => {
await admin.visitSiteEditor( {
postId: 'woocommerce/woocommerce//archive-product',
postType: 'wp_template',
} );
await editorUtils.enterEditMode();
const block = await editorUtils.getBlockByName( blockData.slug );
await editor.enterEditMode();
const block = await editor.getBlockByName( blockData.slug );
await expect( block ).toBeVisible();
await expect( block ).toHaveText(
'Notices added by WooCommerce or extensions will show up here.'

View File

@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { test, expect } from '@woocommerce/e2e-playwright-utils';
import { test, expect } from '@woocommerce/e2e-utils';
const permalink = '/cart';
const templatePath = 'woocommerce/woocommerce//page-cart';
@ -11,13 +11,12 @@ test.describe( 'Test the cart template', () => {
test( 'Template can be opened in the site editor', async ( {
admin,
editor,
editorUtils,
} ) => {
await admin.visitSiteEditor( {
postId: templatePath,
postType: templateType,
} );
await editorUtils.enterEditMode();
await editor.enterEditMode();
await expect(
editor.canvas.getByLabel( 'Block: Title' )
).toBeVisible();
@ -27,13 +26,12 @@ test.describe( 'Test the cart template', () => {
admin,
editor,
page,
editorUtils,
} ) => {
await admin.visitSiteEditor( { path: '/page' } );
await editor.page
.getByRole( 'button', { name: 'Cart', exact: true } )
.click();
await editorUtils.enterEditMode();
await editor.enterEditMode();
await expect(
editor.canvas.locator( 'h1:has-text("Cart")' ).first()
@ -60,14 +58,13 @@ test.describe( 'Test the cart template', () => {
test.describe( 'Test editing the cart template', () => {
test( 'Merchant can transform shortcode block into blocks', async ( {
admin,
editorUtils,
editor,
} ) => {
await admin.visitSiteEditor( {
postId: templatePath,
postType: templateType,
} );
await editorUtils.enterEditMode();
await editor.enterEditMode();
await editor.setContent(
'<!-- wp:woocommerce/classic-shortcode {"shortcode":"cart"} /-->'
);

View File

@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { test, expect } from '@woocommerce/e2e-playwright-utils';
import { test, expect } from '@woocommerce/e2e-utils';
const permalink = '/checkout';
const templatePath = 'woocommerce/woocommerce//page-checkout';
@ -11,13 +11,12 @@ test.describe( 'Test the checkout template', () => {
test( 'Template can be opened in the site editor', async ( {
admin,
editor,
editorUtils,
} ) => {
await admin.visitSiteEditor( {
postId: templatePath,
postType: templateType,
} );
await editorUtils.enterEditMode();
await editor.enterEditMode();
await expect(
editor.canvas.getByRole( 'button', {
name: 'Place Order · <price/>',
@ -29,7 +28,6 @@ test.describe( 'Test the checkout template', () => {
admin,
editor,
page,
editorUtils,
} ) => {
await admin.visitSiteEditor( {
postId: templatePath,
@ -39,7 +37,7 @@ test.describe( 'Test the checkout template', () => {
await editor.page
.getByRole( 'button', { name: 'Checkout', exact: true } )
.click();
await editorUtils.enterEditMode();
await editor.enterEditMode();
await expect(
editor.canvas.getByRole( 'button', {
@ -78,14 +76,13 @@ test.describe( 'Test the checkout template', () => {
test.describe( 'Test editing the checkout template', () => {
test( 'Merchant can transform shortcode block into blocks', async ( {
admin,
editorUtils,
editor,
} ) => {
await admin.visitSiteEditor( {
postId: templatePath,
postType: templateType,
} );
await editorUtils.enterEditMode();
await editor.enterEditMode();
await editor.setContent(
'<!-- wp:woocommerce/classic-shortcode {"shortcode":"checkout"} /-->'
);

Some files were not shown because too many files have changed in this diff Show More