This commit is contained in:
parent
1784b525df
commit
1761da37cd
|
@ -0,0 +1,38 @@
|
|||
name: Report Flaky Tests
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: ['E2E tests']
|
||||
types:
|
||||
- completed
|
||||
|
||||
jobs:
|
||||
report-to-issues:
|
||||
name: Report to GitHub issues
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event.workflow_run.conclusion == 'success' }}
|
||||
steps:
|
||||
# Checkout defaults to using the branch which triggered the event, which
|
||||
# isn't necessarily `trunk` (e.g. in the case of a merge).
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
repository: WordPress/gutenberg
|
||||
ref: trunk
|
||||
|
||||
- name: Use desired version of NodeJS
|
||||
uses: actions/setup-node@5b52f097d36d4b0b2f94ed6de710023fbb8b2236 # v3.1.0
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: npm
|
||||
|
||||
- name: Npm install and build
|
||||
# TODO: We don't have to build the entire project, just the action itself.
|
||||
run: |
|
||||
npm ci
|
||||
npm run build:packages
|
||||
- name: Report flaky tests
|
||||
uses: ./packages/report-flaky-tests
|
||||
with:
|
||||
repo-token: '${{ secrets.GITHUB_TOKEN }}'
|
||||
label: 'type: flaky test'
|
||||
artifact-name-prefix: flaky-tests-report
|
|
@ -7,6 +7,10 @@ on:
|
|||
|
||||
jobs:
|
||||
JSE2EWithGutenberg:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
part: [1, 2, 3, 4, 5]
|
||||
name: JavaScript E2E Tests (WP latest with Gutenberg plugin)
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
@ -62,19 +66,32 @@ jobs:
|
|||
WOOCOMMERCE_BLOCKS_PHASE: 3
|
||||
GUTENBERG_EDITOR_CONTEXT: 'gutenberg'
|
||||
run: |
|
||||
chmod -R 767 ./ #needed for permissions issues
|
||||
node ./bin/wp-env-with-gutenberg.js
|
||||
npm run wp-env start
|
||||
npm run wp-env clean all
|
||||
npm run test:e2e
|
||||
npm run wp-env:config && npx cross-env NODE_CONFIG_DIR=tests/e2e/config wp-scripts test-e2e --config tests/e2e/config/jest.config.js --listTests > ~/.jest-e2e-tests
|
||||
npx cross-env JEST_PUPPETEER_CONFIG=tests/e2e/config/jest-puppeteer.config.js cross-env NODE_CONFIG_DIR=tests/e2e/config wp-scripts test-e2e --config tests/e2e/config/jest.config.js --runInBand --runTestsByPath $( awk 'NR % 5 == ${{ matrix.part }} - 1' < ~/.jest-e2e-tests )
|
||||
|
||||
- name: Upload artifacts on failure
|
||||
if: ${{ failure() }}
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: e2e-with-gutenberg-test-report
|
||||
name: e2e-with-gutenberg-test-report-${{matrix.part}}
|
||||
path: reports/e2e
|
||||
|
||||
- name: Archive flaky tests report
|
||||
uses: actions/upload-artifact@e448a9b857ee2131e752b06002bf0e093c65e571 # v2.2.2
|
||||
if: always()
|
||||
with:
|
||||
name: flaky-tests-report-${{ matrix.part }}
|
||||
path: flaky-tests
|
||||
if-no-files-found: ignore
|
||||
|
||||
JSE2ETests:
|
||||
name: JavaScript E2E Tests (latest)
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
part: [1, 2, 3, 4, 5]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
@ -131,12 +148,20 @@ jobs:
|
|||
WOOCOMMERCE_BLOCKS_PHASE: 3
|
||||
run: |
|
||||
npm run wp-env start
|
||||
npm run wp-env clean all
|
||||
npm run test:e2e
|
||||
npm run wp-env:config && npx cross-env NODE_CONFIG_DIR=tests/e2e/config wp-scripts test-e2e --config tests/e2e/config/jest.config.js --listTests > ~/.jest-e2e-tests
|
||||
npx cross-env JEST_PUPPETEER_CONFIG=tests/e2e/config/jest-puppeteer.config.js cross-env NODE_CONFIG_DIR=tests/e2e/config wp-scripts test-e2e --config tests/e2e/config/jest.config.js --runInBand --runTestsByPath $( awk 'NR % 5 == ${{ matrix.part }} - 1' < ~/.jest-e2e-tests )
|
||||
|
||||
- name: Upload artifacts on failure
|
||||
if: ${{ failure() }}
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: e2e-test-report
|
||||
name: e2e-test-report-${{matrix.part}}
|
||||
path: reports/e2e
|
||||
|
||||
- name: Archive flaky tests report
|
||||
uses: actions/upload-artifact@e448a9b857ee2131e752b06002bf0e093c65e571 # v2.2.2
|
||||
if: always()
|
||||
with:
|
||||
name: flaky-tests-report-${{ matrix.part }}
|
||||
path: flaky-tests
|
||||
if-no-files-found: ignore
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -68,8 +68,8 @@
|
|||
"test": "wp-scripts test-unit-js --config tests/js/jest.config.json",
|
||||
"test:debug": "ndb .",
|
||||
"test:e2e": "npm run wp-env:config && cross-env JEST_PUPPETEER_CONFIG=tests/e2e/config/jest-puppeteer.config.js NODE_CONFIG_DIR=tests/e2e/config wp-scripts test-e2e --config tests/e2e/config/jest.config.js",
|
||||
"test:e2e-dev": "npm run wp-env:config && cross-env JEST_PUPPETEER_CONFIG=tests/e2e/config/jest-puppeteer.config.js NODE_CONFIG_DIR=tests/e2e/config wp-scripts test-e2e --config tests/e2e/config/jest.config.js --puppeteer-interactive",
|
||||
"test:e2e-dev-watch": "npm run wp-env:config && cross-env JEST_PUPPETEER_CONFIG=tests/e2e/config/jest-puppeteer.config.js NODE_CONFIG_DIR=tests/e2e/config wp-scripts test-e2e --config tests/e2e/config/jest.config.js --watch --puppeteer-interactive",
|
||||
"test:e2e-dev": "npm run wp-env:config && cross-env JEST_PUPPETEER_CONFIG=tests/e2e/config/jest-puppeteer.config-dev.js NODE_CONFIG_DIR=tests/e2e/config wp-scripts test-e2e --config tests/e2e/config/jest.config.js",
|
||||
"test:e2e-dev-watch": "npm run wp-env:config && cross-env JEST_PUPPETEER_CONFIG=tests/e2e/config/jest-puppeteer.config-dev.js NODE_CONFIG_DIR=tests/e2e/config wp-scripts test-e2e --config tests/e2e/config/jest.config.js --watch",
|
||||
"test:e2e:update": "npm run wp-env:config && cross-env JEST_PUPPETEER_CONFIG=tests/e2e/config/jest-puppeteer.config.js NODE_CONFIG_DIR=tests/e2e/config wp-scripts test-e2e --config tests/e2e/config/jest.config.js --updateSnapshot",
|
||||
"test:help": "wp-scripts test-unit-js --help",
|
||||
"test:performance": "npm run wp-env:config && cross-env NODE_CONFIG_DIR=tests/e2e/config wp-scripts test-e2e --config tests/e2e/config/jest.performance.config.js -- performance",
|
||||
|
@ -133,8 +133,8 @@
|
|||
"@wordpress/data-controls": "2.2.7",
|
||||
"@wordpress/dependency-extraction-webpack-plugin": "3.2.1",
|
||||
"@wordpress/dom": "3.2.7",
|
||||
"@wordpress/e2e-test-utils": "7.4.0",
|
||||
"@wordpress/e2e-tests": "4.3.0",
|
||||
"@wordpress/e2e-test-utils": "7.8.0",
|
||||
"@wordpress/e2e-tests": "4.6.0",
|
||||
"@wordpress/element": "4.0.4",
|
||||
"@wordpress/env": "4.5.0",
|
||||
"@wordpress/html-entities": "3.2.3",
|
||||
|
@ -164,7 +164,7 @@
|
|||
"eslint-plugin-import": "2.25.4",
|
||||
"eslint-plugin-woocommerce": "file:bin/eslint-plugin-woocommerce",
|
||||
"eslint-plugin-you-dont-need-lodash-underscore": "6.12.0",
|
||||
"expect-puppeteer": "6.0.2",
|
||||
"expect-puppeteer": "6.1.0",
|
||||
"follow-redirects": "1.14.9",
|
||||
"fs-extra": "9.1.0",
|
||||
"gh-pages": "3.2.3",
|
||||
|
@ -189,7 +189,7 @@
|
|||
"prettier": "npm:wp-prettier@2.6.2",
|
||||
"progress-bar-webpack-plugin": "2.1.0",
|
||||
"promptly": "3.2.0",
|
||||
"puppeteer": "13.7.0",
|
||||
"puppeteer": "15.2.0",
|
||||
"react-docgen": "5.4.0",
|
||||
"react-test-renderer": "17.0.2",
|
||||
"request-promise": "4.2.6",
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
const config = require( './jest-puppeteer.config' );
|
||||
|
||||
module.exports = {
|
||||
...config,
|
||||
launch: {
|
||||
...config.launch,
|
||||
headless: false,
|
||||
},
|
||||
};
|
|
@ -1,3 +1,7 @@
|
|||
module.exports = {
|
||||
exitOnPageError: false,
|
||||
launch: {
|
||||
ignoreDefaultArgs: [ '--disable-extensions' ],
|
||||
args: [ '--no-sandbox', '--disable-dev-shm-usage' ],
|
||||
},
|
||||
};
|
||||
|
|
|
@ -3,7 +3,6 @@ module.exports = {
|
|||
rootDir: '../../../',
|
||||
// Automatically clear mock calls and instances between every test
|
||||
clearMocks: true,
|
||||
|
||||
moduleNameMapper: {
|
||||
'@woocommerce/blocks-test-utils': '<rootDir>/tests/utils',
|
||||
},
|
||||
|
@ -14,7 +13,8 @@ module.exports = {
|
|||
'jest-html-reporters',
|
||||
{ publicPath: './reports/e2e', filename: 'index.html' },
|
||||
],
|
||||
],
|
||||
process.env.CI && '@wordpress/e2e-tests/config/flaky-tests-reporter.js',
|
||||
].filter( Boolean ),
|
||||
|
||||
testEnvironment: '<rootDir>/tests/e2e/config/environment.js',
|
||||
testRunner: 'jest-circus/runner',
|
||||
|
@ -30,7 +30,6 @@ module.exports = {
|
|||
'<rootDir>/tests/e2e/config/jest.setup.js',
|
||||
'expect-puppeteer',
|
||||
],
|
||||
|
||||
testPathIgnorePatterns: [ '<rootDir>/tests/e2e/specs/performance' ],
|
||||
transformIgnorePatterns: [ 'node_modules/(?!(woocommerce)/)' ],
|
||||
};
|
||||
|
|
|
@ -11,12 +11,20 @@ import {
|
|||
visitAdminPage,
|
||||
} from '@wordpress/e2e-test-utils';
|
||||
import { setDefaultOptions } from 'expect-puppeteer';
|
||||
import { get } from 'lodash';
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { DEFAULT_TIMEOUT } from '../utils';
|
||||
// Set the default test timeout.
|
||||
jest.setTimeout( 120000 );
|
||||
// Retry failed tests at most 2 times in CI.
|
||||
// This enables `flaky-tests-reporter` and `report-flaky-tests` GitHub action
|
||||
// to mark test as flaky and automatically create a tracking issue about it.
|
||||
if ( process.env.CI ) {
|
||||
jest.retryTimes( 2 );
|
||||
}
|
||||
|
||||
setDefaultOptions( { timeout: DEFAULT_TIMEOUT } );
|
||||
|
||||
/**
|
||||
|
@ -110,12 +118,33 @@ function observeConsoleLogging() {
|
|||
if ( ! OBSERVED_CONSOLE_MESSAGE_TYPES.hasOwnProperty( type ) ) {
|
||||
return;
|
||||
}
|
||||
const text = message.text();
|
||||
|
||||
let text = message.text();
|
||||
|
||||
// An exception is made for _blanket_ deprecation warnings: Those
|
||||
// which log regardless of whether a deprecated feature is in use.
|
||||
if ( text.includes( 'This is a global warning' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// A chrome advisory warning about SameSite cookies is informational
|
||||
// about future changes, tracked separately for improvement in core.
|
||||
//
|
||||
// See: https://core.trac.wordpress.org/ticket/37000
|
||||
// See: https://www.chromestatus.com/feature/5088147346030592
|
||||
// See: https://www.chromestatus.com/feature/5633521622188032
|
||||
if (
|
||||
text.includes( 'A cookie associated with a cross-site resource' )
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Viewing posts on the front end can result in this error, which
|
||||
// has nothing to do with Gutenberg.
|
||||
if ( text.includes( 'net::ERR_UNKNOWN_URL_SCHEME' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Network errors are ignored only if we are intentionally testing
|
||||
// offline mode.
|
||||
if (
|
||||
|
@ -124,10 +153,44 @@ function observeConsoleLogging() {
|
|||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
// As of WordPress 5.3.2 in Chrome 79, navigating to the block editor
|
||||
// (Posts > Add New) will display a console warning about
|
||||
// non - unique IDs.
|
||||
// See: https://core.trac.wordpress.org/ticket/23165
|
||||
if ( text.includes( 'elements with non-unique id #_wpnonce' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Ignore all JQMIGRATE (jQuery migrate) deprecation warnings.
|
||||
if ( text.includes( 'JQMIGRATE' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
const logFunction = OBSERVED_CONSOLE_MESSAGE_TYPES[ type ];
|
||||
// Disable reason: We intentionally bubble up console error messages
|
||||
// for debugging reasons. If you need to test explicitly the logging,
|
||||
// use @wordpress/jest-console
|
||||
|
||||
// As of Puppeteer 1.6.1, `message.text()` wrongly returns an object of
|
||||
// type JSHandle for error logging, instead of the expected string.
|
||||
//
|
||||
// See: https://github.com/GoogleChrome/puppeteer/issues/3397
|
||||
//
|
||||
// The recommendation there to asynchronously resolve the error value
|
||||
// upon a console event may be prone to a race condition with the test
|
||||
// completion, leaving a possibility of an error not being surfaced
|
||||
// correctly. Instead, the logic here synchronously inspects the
|
||||
// internal object shape of the JSHandle to find the error text. If it
|
||||
// cannot be found, the default text value is used instead.
|
||||
text = get(
|
||||
message.args(),
|
||||
[ 0, '_remoteObject', 'description' ],
|
||||
text
|
||||
);
|
||||
|
||||
// Disable reason: We intentionally bubble up the console message
|
||||
// which, unless the test explicitly anticipates the logging via
|
||||
// @wordpress/jest-console matchers, will cause the intended test
|
||||
// failure.
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console[ logFunction ]( text );
|
||||
} );
|
||||
|
@ -142,6 +205,9 @@ beforeAll( async () => {
|
|||
observeConsoleLogging();
|
||||
await setupBrowser();
|
||||
await importSampleProducts();
|
||||
await page.emulateMediaFeatures( [
|
||||
{ name: 'prefers-reduced-motion', value: 'reduce' },
|
||||
] );
|
||||
} );
|
||||
|
||||
afterEach( async () => {
|
||||
|
|
|
@ -49,6 +49,7 @@ module.exports = async ( globalConfig ) => {
|
|||
enablePaymentGateways(),
|
||||
setupPageSettings(),
|
||||
] ).catch( console.log );
|
||||
|
||||
const [ taxes, coupons, categories, tags, shippingZones, attributes ] =
|
||||
results;
|
||||
// Create products after categories.
|
||||
|
|
|
@ -14,7 +14,7 @@ exports[`Store Editing Templates Product Search Results block template should co
|
|||
"<!-- wp:template-part {\\"slug\\":\\"header\\",\\"theme\\":\\"emptytheme\\",\\"tagName\\":\\"header\\"} /-->
|
||||
|
||||
<!-- wp:group {\\"layout\\":{\\"inherit\\":true}} -->
|
||||
<div class=\\"wp-block-group\\"><!-- wp:woocommerce/legacy-template {\\"template\\":\\"archive-product\\"} /--></div>
|
||||
<div class=\\"wp-block-group\\"><!-- wp:woocommerce/legacy-template {\\"template\\":\\"product-search-results\\"} /--></div>
|
||||
<!-- /wp:group -->
|
||||
|
||||
<!-- wp:template-part {\\"slug\\":\\"footer\\",\\"theme\\":\\"emptytheme\\",\\"tagName\\":\\"footer\\"} /-->"
|
||||
|
|
|
@ -92,6 +92,14 @@ const BLOCK_DATA = {
|
|||
},
|
||||
name: 'woocommerce/legacy-template',
|
||||
},
|
||||
'product-search-results': {
|
||||
attributes: {
|
||||
title: 'WooCommerce Product Search Results Block',
|
||||
template: 'product-search-results',
|
||||
placeholder: 'archive-product',
|
||||
},
|
||||
name: 'woocommerce/legacy-template',
|
||||
},
|
||||
};
|
||||
|
||||
const SELECTORS = {
|
||||
|
@ -515,7 +523,7 @@ describe( 'Store Editing Templates', () => {
|
|||
);
|
||||
|
||||
expect( classicBlock.attributes.template ).toBe(
|
||||
BLOCK_DATA[ 'archive-product' ].attributes.template
|
||||
BLOCK_DATA[ 'product-search-results' ].attributes.template
|
||||
);
|
||||
expect( await getCurrentSiteEditorContent() ).toMatchSnapshot();
|
||||
} );
|
||||
|
|
|
@ -53,7 +53,7 @@ const block = {
|
|||
|
||||
const FILTER_STOCK_STATUS_TITLE = 'Stock Status';
|
||||
const FILTER_STOCK_STATUS_PROPERTY = 'In stock';
|
||||
const FILTER_CAPACITY_TITLE = 'Capacity';
|
||||
const FILTER_CAPACITY_TITLE = 'Capacity:';
|
||||
const FILTER_CAPACITY_PROPERTY = '128gb';
|
||||
|
||||
const { selectors } = block;
|
||||
|
@ -68,10 +68,25 @@ const insertBlocks = async () => {
|
|||
const configurateFilterProductsByAttributeBlock = async (
|
||||
pageOrCanvas: Page | Frame
|
||||
) => {
|
||||
await pageOrCanvas.click( selectors.editor.firstAttributeInTheList );
|
||||
await pageOrCanvas.$eval(
|
||||
selectors.editor.firstAttributeInTheList,
|
||||
( el ) => ( el as HTMLElement ).click()
|
||||
);
|
||||
await pageOrCanvas.click( selectors.editor.doneButton );
|
||||
};
|
||||
|
||||
const getActiveFilterTypeText = () =>
|
||||
page.$eval(
|
||||
selectors.frontend.activeFilterType,
|
||||
( el ) => ( el as HTMLElement ).innerText
|
||||
);
|
||||
|
||||
const getActiveFilterNameText = () =>
|
||||
page.$eval(
|
||||
selectors.frontend.activeFilterName,
|
||||
( el ) => ( el as HTMLElement ).childNodes[ 0 ].textContent
|
||||
);
|
||||
|
||||
describe( 'Shopper → Active Filters Block', () => {
|
||||
describe( 'With All Products block', () => {
|
||||
beforeAll( async () => {
|
||||
|
@ -115,11 +130,10 @@ describe( 'Shopper → Active Filters Block', () => {
|
|||
text: FILTER_CAPACITY_PROPERTY,
|
||||
} );
|
||||
|
||||
await expect( page ).toMatchElement(
|
||||
selectors.frontend.activeFilterType,
|
||||
{
|
||||
text: FILTER_CAPACITY_TITLE,
|
||||
}
|
||||
const activeFilterType = await getActiveFilterTypeText();
|
||||
|
||||
expect( activeFilterType ).toBe(
|
||||
FILTER_CAPACITY_TITLE.toUpperCase()
|
||||
);
|
||||
|
||||
await waitForAllProductsBlockLoaded();
|
||||
|
@ -130,12 +144,9 @@ describe( 'Shopper → Active Filters Block', () => {
|
|||
|
||||
await expect( page ).toMatch( FILTER_STOCK_STATUS_TITLE );
|
||||
|
||||
await expect( page ).toMatchElement(
|
||||
selectors.frontend.activeFilterName,
|
||||
{
|
||||
text: FILTER_STOCK_STATUS_PROPERTY,
|
||||
}
|
||||
);
|
||||
const activeFilterNameText = await getActiveFilterNameText();
|
||||
|
||||
expect( activeFilterNameText ).toBe( FILTER_STOCK_STATUS_PROPERTY );
|
||||
|
||||
await waitForAllProductsBlockLoaded();
|
||||
|
||||
|
@ -189,13 +200,6 @@ describe( 'Shopper → Active Filters Block', () => {
|
|||
text: FILTER_CAPACITY_PROPERTY,
|
||||
} );
|
||||
|
||||
await expect( page ).toMatchElement(
|
||||
selectors.frontend.removeAllFiltersButton,
|
||||
{
|
||||
text: 'Clear All',
|
||||
}
|
||||
);
|
||||
|
||||
await page.click( selectors.frontend.removeAllFiltersButton );
|
||||
|
||||
await waitForAllProductsBlockLoaded();
|
||||
|
@ -252,13 +256,11 @@ describe( 'Shopper → Active Filters Block', () => {
|
|||
|
||||
await page.waitForSelector( block.class );
|
||||
|
||||
await expect( page ).toMatchElement(
|
||||
selectors.frontend.activeFilterType,
|
||||
{
|
||||
text: FILTER_CAPACITY_TITLE,
|
||||
}
|
||||
);
|
||||
const activeFilterType = await getActiveFilterTypeText();
|
||||
|
||||
expect( activeFilterType ).toBe(
|
||||
FILTER_CAPACITY_TITLE.toUpperCase()
|
||||
);
|
||||
await page.waitForSelector( selectors.frontend.stockFilterBlock );
|
||||
|
||||
await expect( page ).toClick( 'label', {
|
||||
|
@ -269,19 +271,8 @@ describe( 'Shopper → Active Filters Block', () => {
|
|||
|
||||
await page.waitForSelector( block.class );
|
||||
|
||||
await expect( page ).toMatchElement(
|
||||
selectors.frontend.activeFilterType,
|
||||
{
|
||||
text: 'Stock Status',
|
||||
}
|
||||
);
|
||||
|
||||
await expect( page ).toMatchElement(
|
||||
selectors.frontend.activeFilterName,
|
||||
{
|
||||
text: FILTER_STOCK_STATUS_PROPERTY,
|
||||
}
|
||||
);
|
||||
const activeFilterNameText = await getActiveFilterNameText();
|
||||
expect( activeFilterNameText ).toBe( FILTER_STOCK_STATUS_PROPERTY );
|
||||
|
||||
const products = await page.$$(
|
||||
selectors.frontend.classicProductsList
|
||||
|
@ -314,13 +305,6 @@ describe( 'Shopper → Active Filters Block', () => {
|
|||
|
||||
await page.waitForSelector( block.class );
|
||||
|
||||
await expect( page ).toMatchElement(
|
||||
selectors.frontend.activeFilterType,
|
||||
{
|
||||
text: FILTER_CAPACITY_TITLE,
|
||||
}
|
||||
);
|
||||
|
||||
await clickLink( selectors.frontend.removeFilterButton );
|
||||
|
||||
const products = await page.$$(
|
||||
|
@ -347,13 +331,6 @@ describe( 'Shopper → Active Filters Block', () => {
|
|||
|
||||
await page.waitForSelector( block.class );
|
||||
|
||||
await expect( page ).toMatchElement(
|
||||
selectors.frontend.removeAllFiltersButton,
|
||||
{
|
||||
text: 'Clear All',
|
||||
}
|
||||
);
|
||||
|
||||
await clickLink( selectors.frontend.removeAllFiltersButton );
|
||||
|
||||
const products = await page.$$(
|
||||
|
|
|
@ -6,10 +6,7 @@ import {
|
|||
selectBlockByName,
|
||||
saveOrPublish,
|
||||
} from '@woocommerce/blocks-test-utils';
|
||||
import {
|
||||
setCheckbox,
|
||||
openDocumentSettingsSidebar,
|
||||
} from '@woocommerce/e2e-utils';
|
||||
import { setCheckbox } from '@woocommerce/e2e-utils';
|
||||
import { visitAdminPage } from '@wordpress/e2e-test-utils';
|
||||
|
||||
/**
|
||||
|
@ -17,6 +14,7 @@ import { visitAdminPage } from '@wordpress/e2e-test-utils';
|
|||
*/
|
||||
import { shopper, merchant, clickLink } from '../../../../utils';
|
||||
import { SIMPLE_PHYSICAL_PRODUCT_NAME } from '.../../../../utils/constants';
|
||||
import { openBlockEditorSettings } from '../../../utils';
|
||||
|
||||
const block = {
|
||||
name: 'Checkout',
|
||||
|
@ -44,11 +42,11 @@ describe( 'Shopper → Checkout → Account', () => {
|
|||
await setCheckbox( '#woocommerce_enable_guest_checkout' );
|
||||
await clickLink( 'button[name="save"]' );
|
||||
await visitBlockPage( `${ block.name } Block` );
|
||||
await openDocumentSettingsSidebar();
|
||||
await selectBlockByName( block.slug );
|
||||
await selectBlockByName(
|
||||
'woocommerce/checkout-contact-information-block'
|
||||
);
|
||||
await openBlockEditorSettings( { isFSEEditor: false } );
|
||||
//Enable shoppers to sign up at checkout option.
|
||||
// eslint-disable-next-line jest/no-standalone-expect
|
||||
await expect( page ).toClick( 'label', {
|
||||
|
|
|
@ -21,10 +21,15 @@ describe( 'Shopper → Cart', () => {
|
|||
it( 'User can view empty cart message', async () => {
|
||||
await shopper.block.goToCart();
|
||||
|
||||
await page.waitForSelector( '.wc-block-cart__empty-cart__title' );
|
||||
|
||||
// Verify cart is empty'
|
||||
await expect( page ).toMatchElement( 'h2', {
|
||||
text: 'Your cart is currently empty!',
|
||||
} );
|
||||
await expect( page ).toMatchElement(
|
||||
'.wc-block-cart__empty-cart__title',
|
||||
{
|
||||
text: 'Your cart is currently empty!',
|
||||
}
|
||||
);
|
||||
} );
|
||||
|
||||
it( 'User can remove a product from cart', async () => {
|
||||
|
|
|
@ -146,9 +146,7 @@ describe( `${ block.name } Block`, () => {
|
|||
expect( isRefreshed ).not.toBeCalled();
|
||||
|
||||
await Promise.all( [
|
||||
page.waitForNavigation( {
|
||||
waitUntil: 'networkidle0',
|
||||
} ),
|
||||
page.waitForNavigation(),
|
||||
page.click( selectors.frontend.filter ),
|
||||
] );
|
||||
|
||||
|
@ -173,7 +171,7 @@ describe( `${ block.name } Block`, () => {
|
|||
} );
|
||||
|
||||
await selectBlockByName( block.slug );
|
||||
await openBlockEditorSettings();
|
||||
await openBlockEditorSettings( { isFSEEditor: true } );
|
||||
const [ filterButtonToggle ] = await page.$x(
|
||||
block.selectors.editor.filterButtonToggle
|
||||
);
|
||||
|
|
|
@ -52,13 +52,12 @@ const goToShopPage = () =>
|
|||
const setMaxPrice = async () => {
|
||||
await page.waitForSelector( selectors.frontend.priceMaxAmount );
|
||||
await page.focus( selectors.frontend.priceMaxAmount );
|
||||
await page.click( selectors.frontend.priceMaxAmount, {
|
||||
clickCount: 3,
|
||||
} );
|
||||
await page.keyboard.type( '1.99' );
|
||||
await page.$eval( selectors.frontend.priceMaxAmount, ( el ) =>
|
||||
( el as HTMLElement ).blur()
|
||||
await page.$eval(
|
||||
selectors.frontend.priceMaxAmount,
|
||||
( el ) => ( ( el as HTMLInputElement ).value = '' )
|
||||
);
|
||||
await page.keyboard.type( '1.99' );
|
||||
await page.keyboard.press( 'Tab' );
|
||||
};
|
||||
|
||||
describe( `${ block.name } Block`, () => {
|
||||
|
@ -91,7 +90,6 @@ describe( `${ block.name } Block`, () => {
|
|||
const isRefreshed = jest.fn( () => void 0 );
|
||||
page.on( 'load', isRefreshed );
|
||||
await setMaxPrice();
|
||||
await page.waitForNetworkIdle();
|
||||
await waitForAllProductsBlockLoaded();
|
||||
|
||||
await page.waitForSelector( selectors.frontend.productsList );
|
||||
|
@ -121,6 +119,10 @@ describe( `${ block.name } Block`, () => {
|
|||
await goToShopPage();
|
||||
} );
|
||||
|
||||
beforeEach( async () => {
|
||||
await goToShopPage();
|
||||
} );
|
||||
|
||||
afterAll( async () => {
|
||||
await deleteAllTemplates( 'wp_template' );
|
||||
await deleteAllTemplates( 'wp_template_part' );
|
||||
|
@ -145,12 +147,7 @@ describe( `${ block.name } Block`, () => {
|
|||
await expect( page ).toMatch( block.foundProduct );
|
||||
expect( isRefreshed ).not.toBeCalled();
|
||||
|
||||
await Promise.all( [
|
||||
setMaxPrice(),
|
||||
page.waitForNavigation( {
|
||||
waitUntil: 'networkidle0',
|
||||
} ),
|
||||
] );
|
||||
await Promise.all( [ page.waitForNavigation(), setMaxPrice() ] );
|
||||
|
||||
await page.waitForSelector(
|
||||
selectors.frontend.classicProductsList
|
||||
|
@ -177,7 +174,7 @@ describe( `${ block.name } Block`, () => {
|
|||
} );
|
||||
|
||||
await selectBlockByName( block.slug );
|
||||
await openBlockEditorSettings();
|
||||
await openBlockEditorSettings( { isFSEEditor: true } );
|
||||
await page.waitForXPath(
|
||||
block.selectors.editor.filterButtonToggle
|
||||
);
|
||||
|
|
|
@ -34,7 +34,7 @@ const block = {
|
|||
frontend: {
|
||||
productsList: '.wc-block-grid__products > li',
|
||||
classicProductsList: '.products.columns-3 > li',
|
||||
filter: 'label[for=outofstock]',
|
||||
filter: 'input[id=outofstock]',
|
||||
submitButton: '.wc-block-components-filter-submit-button',
|
||||
},
|
||||
},
|
||||
|
@ -104,6 +104,10 @@ describe( `${ block.name } Block`, () => {
|
|||
await goToShopPage();
|
||||
} );
|
||||
|
||||
beforeEach( async () => {
|
||||
await goToShopPage();
|
||||
} );
|
||||
|
||||
afterAll( async () => {
|
||||
await deleteAllTemplates( 'wp_template' );
|
||||
await deleteAllTemplates( 'wp_template_part' );
|
||||
|
@ -126,8 +130,13 @@ describe( `${ block.name } Block`, () => {
|
|||
} );
|
||||
|
||||
expect( isRefreshed ).not.toBeCalled();
|
||||
await page.click( selectors.frontend.filter );
|
||||
await page.waitForNetworkIdle();
|
||||
|
||||
await page.waitForSelector( selectors.frontend.filter );
|
||||
|
||||
await Promise.all( [
|
||||
page.waitForNavigation(),
|
||||
page.click( selectors.frontend.filter ),
|
||||
] );
|
||||
|
||||
const products = await page.$$(
|
||||
selectors.frontend.classicProductsList
|
||||
|
@ -150,10 +159,11 @@ describe( `${ block.name } Block`, () => {
|
|||
|
||||
await waitForCanvas();
|
||||
await selectBlockByName( block.slug );
|
||||
await openBlockEditorSettings();
|
||||
await openBlockEditorSettings( { isFSEEditor: true } );
|
||||
await page.waitForXPath(
|
||||
block.selectors.editor.filterButtonToggle
|
||||
);
|
||||
|
||||
const [ filterButtonToggle ] = await page.$x(
|
||||
selectors.editor.filterButtonToggle
|
||||
);
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
import { Coupon, HTTPClientFactory } from '@woocommerce/api';
|
||||
import config from 'config';
|
||||
import {
|
||||
activateTheme,
|
||||
disableSiteEditorWelcomeGuide,
|
||||
openGlobalBlockInserter,
|
||||
switchUserToAdmin,
|
||||
|
@ -19,8 +18,9 @@ import fs from 'fs';
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { elementExists, getElementData, getTextContent } from './page-utils';
|
||||
import { elementExists, getTextContent } from './page-utils';
|
||||
import { PERFORMANCE_REPORT_FILENAME } from '../utils/constants';
|
||||
import { cli } from '../utils';
|
||||
|
||||
/**
|
||||
* @typedef {import('@types/puppeteer').ElementHandle} ElementHandle
|
||||
|
@ -64,7 +64,7 @@ const SELECTORS = {
|
|||
savePrompt: '.entities-saved-states__text-prompt',
|
||||
},
|
||||
allProductsBlock: {
|
||||
productsList: '.wc-block-grid__products > li.is-loading',
|
||||
productsList: '.wc-block-grid__products > li > div:not(.is-loading)',
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -134,6 +134,9 @@ export const closeModalIfExists = async () => {
|
|||
};
|
||||
|
||||
export const openWidgetsEditorBlockInserter = async () => {
|
||||
await page.waitForSelector(
|
||||
'.edit-widgets-header [aria-label="Add block"],.edit-widgets-header [aria-label="Toggle block inserter"]'
|
||||
);
|
||||
await page.click(
|
||||
'.edit-widgets-header [aria-label="Add block"],.edit-widgets-header [aria-label="Toggle block inserter"]'
|
||||
);
|
||||
|
@ -247,10 +250,6 @@ export async function saveTemplate() {
|
|||
await page.waitForSelector( savePrompt );
|
||||
await page.click( confirmSave );
|
||||
await page.waitForSelector( `${ saveButton }[aria-disabled="true"]` );
|
||||
await page.waitForResponse( ( res ) => {
|
||||
// Will match both templates and template_parts endpoints.
|
||||
return res.url().includes( '/wp/v2/template' );
|
||||
} );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -329,22 +328,18 @@ export async function filterCurrentBlocks( predicate ) {
|
|||
* @param {string} themeSlug The theme the test suite should use
|
||||
*/
|
||||
export function useTheme( themeSlug ) {
|
||||
let previousTheme;
|
||||
|
||||
beforeAll( async () => {
|
||||
await switchUserToAdmin();
|
||||
await visitAdminPage( 'themes.php' );
|
||||
|
||||
previousTheme = await getElementData(
|
||||
SELECTORS.themesPage.currentTheme,
|
||||
'slug'
|
||||
await cli(
|
||||
`npm run wp-env run tests-cli wp theme activate ${ themeSlug }`
|
||||
);
|
||||
|
||||
await activateTheme( themeSlug );
|
||||
await switchUserToAdmin();
|
||||
} );
|
||||
|
||||
afterAll( async () => {
|
||||
await activateTheme( previousTheme );
|
||||
await cli(
|
||||
`npm run wp-env run tests-cli wp theme activate storefront`
|
||||
);
|
||||
await switchUserToAdmin();
|
||||
} );
|
||||
}
|
||||
|
||||
|
@ -436,27 +431,30 @@ export const createCoupon = async ( coupon ) => {
|
|||
|
||||
/**
|
||||
* Open the block editor settings menu.
|
||||
*
|
||||
* @param {Object} [root0]
|
||||
* @param {boolean} [root0.isFSEEditor] Amount to be applied. Defaults to 5.
|
||||
*/
|
||||
export const openBlockEditorSettings = async () => {
|
||||
const buttonSelector =
|
||||
'.edit-site-header__actions button[aria-label="Settings"]';
|
||||
|
||||
const isSideBarAlreadyOpened = await page.$(
|
||||
'.interface-interface-skeleton__sidebar'
|
||||
);
|
||||
export const openBlockEditorSettings = async ( { isFSEEditor = false } ) => {
|
||||
const buttonSelector = isFSEEditor
|
||||
? '.edit-site-header__actions button[aria-label="Settings"]'
|
||||
: '.edit-post-header__settings button[aria-label="Settings"]';
|
||||
|
||||
const isPressed = `${ buttonSelector }.is-pressed`;
|
||||
|
||||
const isSideBarAlreadyOpened = await page.$( isPressed );
|
||||
|
||||
if ( isSideBarAlreadyOpened === null ) {
|
||||
await page.click( buttonSelector );
|
||||
// @ts-ignore
|
||||
await page.$eval( buttonSelector, ( el ) => el.click() );
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Wait for all Products Block is loaded completely: when the skeleton disappears, and the products are visible.
|
||||
* Wait for all Products Block is loaded completely: when the skeleton disappears, and the products are visible
|
||||
*/
|
||||
export const waitForAllProductsBlockLoaded = async () => {
|
||||
await page.waitForSelector( SELECTORS.allProductsBlock.productsList, {
|
||||
hidden: true,
|
||||
} );
|
||||
|
||||
await page.waitForNetworkIdle();
|
||||
await page.waitForSelector( SELECTORS.allProductsBlock.productsList );
|
||||
await page.waitForTimeout( 5000 );
|
||||
};
|
||||
|
|
|
@ -34,10 +34,6 @@ export const shopper = {
|
|||
await page.goto( url, {
|
||||
waitUntil: 'networkidle0',
|
||||
} );
|
||||
|
||||
await expect( page ).toMatchElement( 'h1', {
|
||||
text: blockName,
|
||||
} );
|
||||
},
|
||||
|
||||
goToCart: async () => {
|
||||
|
@ -212,6 +208,7 @@ export const shopper = {
|
|||
|
||||
// prettier-ignore
|
||||
fillBillingDetails: async ( customerBillingDetails ) => {
|
||||
await page.waitForSelector("#billing-fields");
|
||||
const companyInputField = await page.$( '#billing-company' );
|
||||
|
||||
if ( companyInputField ) {
|
||||
|
@ -474,4 +471,23 @@ export const shopper = {
|
|||
page.click( 'button[name="login"]' ),
|
||||
] );
|
||||
},
|
||||
|
||||
addToCartFromShopPage: async ( productIdOrTitle ) => {
|
||||
if ( Number.isInteger( productIdOrTitle ) ) {
|
||||
const addToCart = `a[data-product_id="${ productIdOrTitle }"]`;
|
||||
await page.click( addToCart );
|
||||
await expect( page ).toMatchElement( addToCart + '.added' );
|
||||
} else {
|
||||
const addToCartXPath =
|
||||
`//li[contains(@class, "type-product") and a/h2[contains(text(), "${ productIdOrTitle }")]]` +
|
||||
'//a[contains(@class, "add_to_cart_button") and contains(@class, "ajax_add_to_cart")';
|
||||
|
||||
const [ addToCartButton ] = await page.$x( addToCartXPath + ']' );
|
||||
await addToCartButton.click();
|
||||
|
||||
await page.waitForXPath(
|
||||
addToCartXPath + ' and contains(@class, "added")]'
|
||||
);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
|
@ -22,7 +22,9 @@ import { clickLink } from '.';
|
|||
* @param {string} link the page or post you want to visit.
|
||||
*/
|
||||
async function visitPage( link ) {
|
||||
await page.goto( link );
|
||||
await page.goto( link, {
|
||||
waitUntil: 'load',
|
||||
} );
|
||||
await page.waitForSelector( '.edit-post-layout' );
|
||||
const isWelcomeGuideActive = await page.evaluate( () =>
|
||||
wp.data.select( 'core/edit-post' ).isFeatureActive( 'welcomeGuide' )
|
||||
|
|
Loading…
Reference in New Issue