Skip to content
This repository has been archived by the owner on Feb 23, 2024. It is now read-only.

E2E: Product Query: Popular filters presets #7749

Merged
merged 48 commits into from
Jan 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
42b9c13
wip: start working on popular filters
dinhtungdu Nov 22, 2022
3b8d03e
test default preset
dinhtungdu Nov 22, 2022
608aa8a
Merge branch 'trunk' into tests/popular-filters
dinhtungdu Nov 24, 2022
6645dfa
Merge branch 'trunk' into tests/popular-filters
dinhtungdu Nov 24, 2022
262f2ee
test file clean up
dinhtungdu Nov 25, 2022
2646666
test products displayed in editor preview and block front end
dinhtungdu Nov 25, 2022
f71c166
give editor time to update after resetting content
dinhtungdu Dec 2, 2022
0029728
restore the test name
dinhtungdu Dec 5, 2022
34a7a6e
Merge branch 'trunk' into fix/flaky-test-interact-with-form-token-field
dinhtungdu Dec 5, 2022
1b1b260
try: fixing flaky test by waiting for suggestion items
dinhtungdu Dec 5, 2022
09ceb7e
Merge branch 'trunk' into fix/flaky-test-interact-with-form-token-field
dinhtungdu Dec 5, 2022
2e9799d
use block.name when possible
dinhtungdu Dec 5, 2022
a0c2716
Merge branch 'trunk' into fix/flaky-test-interact-with-form-token-field
dinhtungdu Dec 5, 2022
eb48d53
update atomic tests to reflect changes introduced in #7815
dinhtungdu Dec 5, 2022
c96efbc
wait for elements before assertion
dinhtungdu Dec 6, 2022
8a65139
Merge branch 'trunk' into fix/flaky-test-interact-with-form-token-field
dinhtungdu Dec 6, 2022
34c21ad
update rating test as the default template removed rating block
dinhtungdu Dec 6, 2022
90b9f8e
fix rating test
dinhtungdu Dec 6, 2022
ef76d5a
fix advanced filters flaky test
dinhtungdu Dec 6, 2022
b72e1ae
Merge branch 'trunk' into fix/flaky-test-interact-with-form-token-field
dinhtungdu Dec 6, 2022
2f353d4
Merge branch 'trunk' into fix/flaky-test-interact-with-form-token-field
dinhtungdu Dec 7, 2022
3ba8e28
migrate improvements from #7719
dinhtungdu Dec 12, 2022
2cb26e7
Merge branch 'trunk' into fix/flaky-test-interact-with-form-token-field
dinhtungdu Dec 12, 2022
ba03443
ensure the setting is applied in the editor before saving and checkin…
dinhtungdu Dec 12, 2022
c548d57
Merge branch 'trunk' into fix/flaky-test-interact-with-form-token-field
dinhtungdu Dec 12, 2022
a0918ee
Merge branch 'trunk' into fix/flaky-test-interact-with-form-token-field
dinhtungdu Dec 21, 2022
58f3741
Merge branch 'fix/flaky-test-interact-with-form-token-field' into tes…
dinhtungdu Dec 21, 2022
ce275b8
import const and utilities from common.ts
dinhtungdu Dec 21, 2022
c926aa8
test sorted by title preset
dinhtungdu Dec 21, 2022
5724c57
extract common logic to utilites, Newest preset test
dinhtungdu Dec 22, 2022
5622f56
best selling and top rated test
dinhtungdu Dec 22, 2022
909cc7a
Merge branch 'trunk' into tests/popular-filters
dinhtungdu Dec 22, 2022
66dafac
replace openBlockEditorSettings by ensureSidebarOpened
dinhtungdu Dec 23, 2022
1f02fb1
fix flakiness of setting preset
dinhtungdu Dec 23, 2022
277bd68
fix: shorter and faster way to reset the product query page
dinhtungdu Dec 24, 2022
cf8fb22
Merge branch 'trunk' into tests/popular-filters
dinhtungdu Dec 29, 2022
7259f2d
try: not using beforeEeach
dinhtungdu Dec 29, 2022
fdbdd39
Revert "try: not using beforeEeach"
dinhtungdu Dec 29, 2022
4832a0c
try: timeout
dinhtungdu Dec 29, 2022
748d48b
use timeout after selecting the preset, giving the editor time to update
dinhtungdu Dec 30, 2022
53960ec
verify the popular filter selection
dinhtungdu Dec 30, 2022
1c79015
Merge branch 'trunk' into tests/popular-filters
dinhtungdu Dec 30, 2022
3638cd2
Merge branch 'trunk' into tests/popular-filters
dinhtungdu Dec 30, 2022
e60cf03
use jest.each to avoid duplicated code
dinhtungdu Jan 3, 2023
f8ee1ab
Use ensureSidebarOpened from @wordpress/e2e-test-utils
dinhtungdu Jan 3, 2023
691cfb9
move utilities for popular filter tests specifically to the test file.
dinhtungdu Jan 3, 2023
8afad60
more explicit tests for on sale and stock status
dinhtungdu Jan 3, 2023
12121b5
test default state once
dinhtungdu Jan 3, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions tests/e2e/config/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,5 @@ module.exports = {
'utils',
],
transformIgnorePatterns: [ 'node_modules/(?!(woocommerce)/)' ],
testMatch: [ '**/?(*.)+(spec|test).[jt]s?(x)' ],
};

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"title":"Products (Beta) Block","pageContent":"<!-- wp:query {\"queryId\":1,\"query\":{\"perPage\":9,\"pages\":0,\"offset\":0,\"postType\":\"product\",\"order\":\"asc\",\"orderBy\":\"title\",\"author\":\"\",\"search\":\"\",\"exclude\":[],\"sticky\":\"\",\"inherit\":false,\"__woocommerceAttributes\":[],\"__woocommerceStockStatus\":[\"instock\",\"outofstock\",\"onbackorder\"]},\"displayLayout\":{\"type\":\"flex\",\"columns\":3},\"namespace\":\"woocommerce/product-query\"} --><div class=\"wp-block-query\"><!-- wp:post-template --><!-- wp:woocommerce/product-image {\"isDescendentOfQueryLoop\":true} /--><!-- wp:post-title {\"textAlign\":\"center\",\"level\":3,\"fontSize\":\"medium\",\"__woocommerceNamespace\":\"woocommerce/product-query/product-title\"} /--><!-- wp:woocommerce/product-price {\"isDescendentOfQueryLoop\":true,\"textAlign\":\"center\",\"fontSize\":\"small\"} /--><!-- wp:woocommerce/product-button {\"isDescendentOfQueryLoop\":true,\"textAlign\":\"center\",\"fontSize\":\"small\"} /--><!-- /wp:post-template --><!-- wp:query-pagination {\"layout\":{\"type\":\"flex\",\"justifyContent\":\"center\"}} --><!-- wp:query-pagination-previous /--><!-- wp:query-pagination-numbers /--><!-- wp:query-pagination-next /--><!-- /wp:query-pagination --><!-- wp:query-no-results --><!-- wp:paragraph {\"placeholder\":\"Add text or blocks that will display when a query returns no results.\"} --><p></p><!-- /wp:paragraph --><!-- /wp:query-no-results --></div><!-- /wp:query -->"}
156 changes: 156 additions & 0 deletions tests/e2e/specs/backend/product-query/advanced-filters.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
/**
* External dependencies
*/
import {
saveOrPublish,
selectBlockByName,
findToolsPanelWithTitle,
getFixtureProductsData,
shopper,
getToggleIdByLabel,
} from '@woocommerce/blocks-test-utils';
import { ElementHandle } from 'puppeteer';
import { setCheckbox } from '@woocommerce/e2e-utils';
import { ensureSidebarOpened, canvas } from '@wordpress/e2e-test-utils';

/**
* Internal dependencies
*/
import { GUTENBERG_EDITOR_CONTEXT, describeOrSkip } from '../../../utils';
import {
block,
SELECTORS,
resetProductQueryBlockPage,
toggleAdvancedFilter,
getPreviewProducts,
getFrontEndProducts,
clearSelectedTokens,
selectToken,
} from './common';

describeOrSkip( GUTENBERG_EDITOR_CONTEXT === 'gutenberg' )(
`${ block.name } > Advanced Filters`,
() => {
let $productFiltersPanel: ElementHandle< Node >;
const defaultCount = getFixtureProductsData().length;
const saleCount = getFixtureProductsData( 'sale_price' ).length;
const outOfStockCount = getFixtureProductsData( 'stock_status' ).filter(
( status: string ) => status === 'outofstock'
).length;

beforeEach( async () => {
/**
* Reset the block page before each test to ensure the block is
* inserted in a known state. This is also needed to ensure each
* test can be run individually.
*/
await resetProductQueryBlockPage();
await ensureSidebarOpened();
await selectBlockByName( block.slug );
$productFiltersPanel = await findToolsPanelWithTitle(
'Advanced Filters'
);
} );

/**
* Reset the content of Product Query Block page after this test suite
* to avoid breaking other tests.
*/
afterAll( async () => {
await resetProductQueryBlockPage();
} );

it( 'Editor preview shows all products by default', async () => {
expect( await getPreviewProducts() ).toHaveLength( defaultCount );
} );

it( 'On the front end, blocks shows all products by default', async () => {
expect( await getPreviewProducts() ).toHaveLength( defaultCount );
} );

describe( 'Sale Status', () => {
it( 'Sale status is disabled by default', async () => {
await expect( $productFiltersPanel ).not.toMatch(
'Show only products on sale'
);
} );

it( 'Can add and remove Sale Status filter', async () => {
await toggleAdvancedFilter( 'Sale status' );
await expect( $productFiltersPanel ).toMatch(
'Show only products on sale'
);
await toggleAdvancedFilter( 'Sale status' );
await expect( $productFiltersPanel ).not.toMatch(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about reusing more code here by extracting common/duplicated lines into utility functions to make the tests easier to read and maintain?

Copy link
Member Author

@dinhtungdu dinhtungdu Jan 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you suggest something here? At the moment, I don't have a good idea to refactor this further.

From the test code I can see the test perform these step:

  1. Toggle the Sale status filter.
  2. Verify the panel contains the option label.
  3. Toggle the Sale status filter again.
  4. verify the panel doesn't contain the option label anymore.

I'm curious about what you read from the test. If we can do anything to increase the readability, I'm all in.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking something along these lines (for the editor preview test, for example):

const toggleSaleStatusFilter = async () => {
	await toggleAdvancedFilter( 'Sale status' );
	await setCheckbox( await getToggleIdByLabel( 'Show only products on sale' ) );
};

const removeSaleStatusFilter = async () => {
	await toggleAdvancedFilter( 'Sale status' );
	await unsetCheckbox( await getToggleIdByLabel( 'Show only products on sale' ) );
};

But that is super minor/a nit! The tests are now structured nicely, a-ok to keep them as-is :)

'Show only products on sale'
);
} );

it( 'Enable Sale Status > Editor preview shows only on sale products', async () => {
await toggleAdvancedFilter( 'Sale status' );
await setCheckbox(
await getToggleIdByLabel( 'Show only products on sale' )
);
expect( await getPreviewProducts() ).toHaveLength( saleCount );
} );

it( 'Enable Sale Status > On the front end, block shows only on sale products', async () => {
await toggleAdvancedFilter( 'Sale status' );
await setCheckbox(
await getToggleIdByLabel( 'Show only products on sale' )
);
await canvas().waitForSelector( SELECTORS.productsGrid );
await saveOrPublish();
await shopper.block.goToBlockPage( block.name );
expect( await getFrontEndProducts() ).toHaveLength( saleCount );
} );
} );

describe( 'Stock Status', () => {
it( 'Stock status is enabled by default', async () => {
await expect( $productFiltersPanel ).toMatchElement(
SELECTORS.formTokenField.label,
{ text: 'Stock status' }
);
} );

it( 'Can add and remove Stock Status filter', async () => {
await toggleAdvancedFilter( 'Stock status' );
await expect( $productFiltersPanel ).not.toMatchElement(
SELECTORS.formTokenField.label,
{ text: 'Stock status' }
);
await toggleAdvancedFilter( 'Stock status' );
await expect( $productFiltersPanel ).toMatchElement(
SELECTORS.formTokenField.label,
{ text: 'Stock status' }
);
} );

it( 'All statuses are enabled by default', async () => {
await expect( $productFiltersPanel ).toMatch( 'In stock' );
await expect( $productFiltersPanel ).toMatch( 'Out of stock' );
await expect( $productFiltersPanel ).toMatch( 'On backorder' );
Comment on lines +131 to +133
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a big deal, but should this also be perhaps related to the fixture data?

We could have a loop on something like getFixtureProductsData( 'stock_statii' ) and make it more future proof?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Fixture doesn't have any information about all available statuses right now, we need to hard-code it if we want to get stock statuses from it.
  • In the future, if WC Core changes the default stock statuses, we will need to update the fixture as well. To me, updating this test or updating the fixture is similar. Test should be updated as the WC and WC Blocks update.
  • I checked WooCommerce REST API to see if there is any endpoint returning available stock status, but sadly there is none.
  • We can centeralize the reference for available stock status options, but it should be a utility or a constants, not in the fixture data.

} );

it( 'Set Stock status to Out of stock > Editor preview shows only out-of-stock products', async () => {
await clearSelectedTokens( $productFiltersPanel );
await selectToken( 'Stock status', 'Out of stock' );
expect( await getPreviewProducts() ).toHaveLength(
outOfStockCount
);
} );

it( 'Set Stock status to Out of stock > On the front end, block shows only out-of-stock products', async () => {
await clearSelectedTokens( $productFiltersPanel );
await selectToken( 'Stock status', 'Out of stock' );
await canvas().waitForSelector( SELECTORS.productsGrid );
await saveOrPublish();
await shopper.block.goToBlockPage( block.name );
expect( await getFrontEndProducts() ).toHaveLength(
outOfStockCount
);
} );
} );
}
);
Loading