From 9e697cdf0ad85bcfbfa1ab1c12e9176fae76d446 Mon Sep 17 00:00:00 2001 From: Gan Eng Chin Date: Tue, 27 Sep 2022 22:25:48 +0800 Subject: [PATCH] Add tests for UI Revamp on Marketing page (#34840) --- .../CollapsibleCard/CollapsibleCard.test.tsx | 41 +++++ .../LearnMarketing/LearnMarketing.test.tsx | 146 ++++++++++++++++++ .../LearnMarketing/LearnMarketing.tsx | 27 +--- .../LearnMarketing/PlaceholderPostTile.tsx | 5 +- .../LearnMarketing/useBlogPosts.ts | 26 ++++ .../feature-34732-marketing-page-tests | 4 + .../tests/admin-marketing/overview.spec.js | 55 +++++++ 7 files changed, 283 insertions(+), 21 deletions(-) create mode 100644 plugins/woocommerce-admin/client/marketing/components/CollapsibleCard/CollapsibleCard.test.tsx create mode 100644 plugins/woocommerce-admin/client/marketing/overview-multichannel/LearnMarketing/LearnMarketing.test.tsx create mode 100644 plugins/woocommerce-admin/client/marketing/overview-multichannel/LearnMarketing/useBlogPosts.ts create mode 100644 plugins/woocommerce/changelog/feature-34732-marketing-page-tests create mode 100644 plugins/woocommerce/tests/e2e-pw/tests/admin-marketing/overview.spec.js diff --git a/plugins/woocommerce-admin/client/marketing/components/CollapsibleCard/CollapsibleCard.test.tsx b/plugins/woocommerce-admin/client/marketing/components/CollapsibleCard/CollapsibleCard.test.tsx new file mode 100644 index 00000000000..d320c659064 --- /dev/null +++ b/plugins/woocommerce-admin/client/marketing/components/CollapsibleCard/CollapsibleCard.test.tsx @@ -0,0 +1,41 @@ +/** + * External dependencies + */ +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; + +/** + * Internal dependencies + */ +import { CollapsibleCard } from './CollapsibleCard'; + +const header = 'Card header'; +const body = 'Card body'; + +describe( 'CollapsibleCard component', () => { + it( 'should render a card that can be expanded or collapsed when the card header is clicked', async () => { + render( { body } ); + + // Card is expanded by default. + expect( screen.queryByText( header ) ).toBeInTheDocument(); + expect( screen.queryByText( body ) ).toBeInTheDocument(); + + // Click on card header to collapsed the card. + await userEvent.click( screen.getByText( header ) ); + + // Card body should not be there. + expect( screen.queryByText( body ) ).not.toBeInTheDocument(); + } ); + + it( 'should render a card that is collapsed by default when `initialCollapsed` is set', async () => { + render( + + { body } + + ); + + // Card is collapsed by default. + expect( screen.queryByText( header ) ).toBeInTheDocument(); + expect( screen.queryByText( body ) ).not.toBeInTheDocument(); + } ); +} ); diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/LearnMarketing/LearnMarketing.test.tsx b/plugins/woocommerce-admin/client/marketing/overview-multichannel/LearnMarketing/LearnMarketing.test.tsx new file mode 100644 index 00000000000..fac63a1f58c --- /dev/null +++ b/plugins/woocommerce-admin/client/marketing/overview-multichannel/LearnMarketing/LearnMarketing.test.tsx @@ -0,0 +1,146 @@ +/** + * External dependencies + */ +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; + +/** + * Internal dependencies + */ +import { useBlogPosts } from './useBlogPosts'; +import { LearnMarketing } from './LearnMarketing'; + +jest.mock( './useBlogPosts', () => ( { + useBlogPosts: jest.fn(), +} ) ); + +describe( 'LearnMarketing component', () => { + it( 'should render placeholders when loading is in progress', async () => { + ( useBlogPosts as jest.Mock ).mockReturnValue( { + isLoading: true, + error: undefined, + posts: [], + } ); + render( ); + + // Click on expand button to expand the card. + await userEvent.click( + screen.getByRole( 'button', { name: 'Expand' } ) + ); + + // should render three elements with the "progressbar" role: + // two from the PlaceholderPostTile, and one in the card footer. + expect( screen.getAllByRole( 'progressbar' ) ).toHaveLength( 3 ); + } ); + + it( 'should render an error message when there is an error', async () => { + ( useBlogPosts as jest.Mock ).mockReturnValue( { + isLoading: false, + error: new Error(), + posts: [], + } ); + render( ); + + // Click on expand button to expand the card. + await userEvent.click( + screen.getByRole( 'button', { name: 'Expand' } ) + ); + + expect( + screen.getByText( "Oops, our posts aren't loading right now" ) + ).toBeInTheDocument(); + } ); + + it( 'should render "No posts yet" when loading is done and there are no posts', async () => { + ( useBlogPosts as jest.Mock ).mockReturnValue( { + isLoading: false, + error: undefined, + posts: [], + } ); + render( ); + + // Click on expand button to expand the card. + await userEvent.click( + screen.getByRole( 'button', { name: 'Expand' } ) + ); + + expect( screen.getByText( 'No posts yet' ) ).toBeInTheDocument(); + } ); + + it( 'should render two posts in one page with pagination when loading is done and there are posts', async () => { + ( useBlogPosts as jest.Mock ).mockReturnValue( { + isLoading: false, + error: undefined, + posts: [ + { + title: 'Grow Your Store with an Omnichannel Presence', + date: '2022-09-21T19:46:40', + link: 'https://woocommerce.com/posts/grow-store-omnichannel-ecommerce/', + author_name: 'Kathryn Marr', + author_avatar: + 'https://secure.gravatar.com/avatar/431b87d722d366103cc5d9b26c66c665?s=96&d=mm&r=g', + image: 'https://woocommerce.com/wp-content/uploads/2022/09/blog-fb-Omnichannel@2x.jpg?resize=650,340&crop=1', + }, + { + title: 'What is Affiliate Marketing and How to Use it to Make More Money Online', + date: '2022-08-30T22:03:54', + link: 'https://woocommerce.com/posts/what-is-affliate-marketing/', + author_name: 'Kathryn Marr', + author_avatar: + 'https://secure.gravatar.com/avatar/431b87d722d366103cc5d9b26c66c665?s=96&d=mm&r=g', + image: 'https://woocommerce.com/wp-content/uploads/2022/08/blog-fb-Affiliate@2x.jpg?resize=650,340&crop=1', + }, + { + title: 'Ten Customer Retention Strategies to Boost Revenue for eCommerce Stores', + date: '2022-06-22T17:58:12', + link: 'https://woocommerce.com/posts/10-ecommerce-customer-retention-strategies-boost-revenue/', + author_name: 'Craig Cohen', + author_avatar: + 'https://secure.gravatar.com/avatar/66c306ae543fb47f594ef9b9cdb88d93?s=96&d=mm&r=g', + }, + { + title: 'TikTok Marketing: A Guide for WooCommerce Stores', + date: '2022-05-25T14:03:00', + link: 'https://woocommerce.com/posts/tiktok-marketing-a-guide-for-woocommerce-stores/', + author_name: 'Elina Vilk', + author_avatar: + 'https://secure.gravatar.com/avatar/fc7aedb0e531795eeffa3654ce203a8e?s=96&d=mm&r=g', + image: 'https://woocommerce.com/wp-content/uploads/2022/05/Facebook-Post-1200x630@2x3.jpg?resize=650,340&crop=1', + }, + ], + } ); + render( ); + + // Click on expand button to expand the card. + await userEvent.click( + screen.getByRole( 'button', { name: 'Expand' } ) + ); + + // Assert that the first and second post title are in the page. + expect( + screen.getByText( 'Grow Your Store with an Omnichannel Presence' ) + ).toBeInTheDocument(); + expect( + screen.getByText( + 'What is Affiliate Marketing and How to Use it to Make More Money Online' + ) + ).toBeInTheDocument(); + + // Click on the next page button in card footer. + await userEvent.click( + screen.getByRole( 'button', { name: 'Next Page' } ) + ); + + // Assert that the third and fourth post title are in the page. + expect( + screen.getByText( + 'Ten Customer Retention Strategies to Boost Revenue for eCommerce Stores' + ) + ).toBeInTheDocument(); + expect( + screen.getByText( + 'TikTok Marketing: A Guide for WooCommerce Stores' + ) + ).toBeInTheDocument(); + } ); +} ); diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/LearnMarketing/LearnMarketing.tsx b/plugins/woocommerce-admin/client/marketing/overview-multichannel/LearnMarketing/LearnMarketing.tsx index c4039db48c6..25e348c8273 100644 --- a/plugins/woocommerce-admin/client/marketing/overview-multichannel/LearnMarketing/LearnMarketing.tsx +++ b/plugins/woocommerce-admin/client/marketing/overview-multichannel/LearnMarketing/LearnMarketing.tsx @@ -3,17 +3,15 @@ */ import { useState } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; -import { useSelect } from '@wordpress/data'; import { Pagination, EmptyContent } from '@woocommerce/components'; /** * Internal dependencies */ import { CollapsibleCard, ReadBlogMessage } from '~/marketing/components'; -import { STORE_KEY } from '~/marketing/data/constants'; import { PlaceholderPostTile } from './PlaceholderPostTile'; import { PostTile } from './PostTile'; -import { Post } from './types'; +import { useBlogPosts } from './useBlogPosts'; import './LearnMarketing.scss'; const BLOG_POST_CATEGORY = 'marketing'; @@ -21,21 +19,7 @@ const PER_PAGE = 2; export const LearnMarketing = () => { const [ page, setPage ] = useState( 1 ); - const { isLoading, error, posts } = useSelect( - ( select ) => { - const { getBlogPosts, getBlogPostsError, isResolving } = - select( STORE_KEY ); - - return { - posts: getBlogPosts( BLOG_POST_CATEGORY ), - isLoading: isResolving( 'getBlogPosts', [ - BLOG_POST_CATEGORY, - ] ), - error: getBlogPostsError( BLOG_POST_CATEGORY ), - }; - }, - [ BLOG_POST_CATEGORY ] - ); + const { isLoading, error, posts } = useBlogPosts( BLOG_POST_CATEGORY ); /** * Renders card footer. @@ -47,7 +31,10 @@ export const LearnMarketing = () => { const renderFooter = () => { if ( isLoading ) { return ( -
+
); } @@ -111,7 +98,7 @@ export const LearnMarketing = () => { return posts .slice( ( page - 1 ) * PER_PAGE, page * PER_PAGE ) - .map( ( post: Post, index: number ) => { + .map( ( post, index ) => { return ; } ); }; diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/LearnMarketing/PlaceholderPostTile.tsx b/plugins/woocommerce-admin/client/marketing/overview-multichannel/LearnMarketing/PlaceholderPostTile.tsx index 49adbee5e78..6c9c76d2486 100644 --- a/plugins/woocommerce-admin/client/marketing/overview-multichannel/LearnMarketing/PlaceholderPostTile.tsx +++ b/plugins/woocommerce-admin/client/marketing/overview-multichannel/LearnMarketing/PlaceholderPostTile.tsx @@ -1,6 +1,9 @@ export const PlaceholderPostTile = () => { return ( -
+
diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/LearnMarketing/useBlogPosts.ts b/plugins/woocommerce-admin/client/marketing/overview-multichannel/LearnMarketing/useBlogPosts.ts new file mode 100644 index 00000000000..0dce4c4893a --- /dev/null +++ b/plugins/woocommerce-admin/client/marketing/overview-multichannel/LearnMarketing/useBlogPosts.ts @@ -0,0 +1,26 @@ +/** + * External dependencies + */ +import { useSelect } from '@wordpress/data'; + +/** + * Internal dependencies + */ +import { STORE_KEY } from '~/marketing/data/constants'; +import { Post } from './types'; + +export const useBlogPosts = ( category: string ) => { + return useSelect( + ( select ) => { + const { getBlogPosts, getBlogPostsError, isResolving } = + select( STORE_KEY ); + + return { + isLoading: isResolving( 'getBlogPosts', [ category ] ), + error: getBlogPostsError( category ), + posts: getBlogPosts< Post[] >( category ), + }; + }, + [ category ] + ); +}; diff --git a/plugins/woocommerce/changelog/feature-34732-marketing-page-tests b/plugins/woocommerce/changelog/feature-34732-marketing-page-tests new file mode 100644 index 00000000000..1d56e933b3f --- /dev/null +++ b/plugins/woocommerce/changelog/feature-34732-marketing-page-tests @@ -0,0 +1,4 @@ +Significance: minor +Type: dev + +Add tests for UI Revamp on Marketing Page. diff --git a/plugins/woocommerce/tests/e2e-pw/tests/admin-marketing/overview.spec.js b/plugins/woocommerce/tests/e2e-pw/tests/admin-marketing/overview.spec.js new file mode 100644 index 00000000000..5de02a455b0 --- /dev/null +++ b/plugins/woocommerce/tests/e2e-pw/tests/admin-marketing/overview.spec.js @@ -0,0 +1,55 @@ +const { test, expect } = require( '@playwright/test' ); + +test.describe( 'Marketing page', () => { + test.use( { storageState: process.env.ADMINSTATE } ); + + test( 'A user can disable the Multichannel Marketing feature in WC Settings and view the Marketing > Overview page without it crashing', async ( { + page, + } ) => { + // Go to WC Settings > Advanced > Features page. + await page.goto( + 'wp-admin/admin.php?page=wc-settings&tab=advanced§ion=features' + ); + + // Disable multichannel marketing experience by unchecking the checkbox and clicking on "Save changes" button. + await page + .locator( + '"Enables the new WooCommerce Multichannel Marketing experience in the Marketing page"' + ) + .uncheck(); + await page.locator( '"Save changes"' ).click(); + + // Go to the Marketing page. + await page.goto( 'wp-admin/admin.php?page=wc-admin&path=%2Fmarketing' ); + + // Users should see the knowledge base card. + await expect( + page.locator( '"WooCommerce knowledge base"' ) + ).toBeVisible(); + } ); + + test( 'A user can enable the Multichannel Marketing feature in WC Settings and view the Marketing > Overview page without it crashing', async ( { + page, + } ) => { + // Go to WC Settings > Advanced > Features page. + await page.goto( + 'wp-admin/admin.php?page=wc-settings&tab=advanced§ion=features' + ); + + // Enable multichannel marketing experience by checking the checkbox and clicking on "Save changes" button. + await page + .locator( + '"Enables the new WooCommerce Multichannel Marketing experience in the Marketing page"' + ) + .check(); + await page.locator( '"Save changes"' ).click(); + + // Go to the Marketing page. + await page.goto( 'wp-admin/admin.php?page=wc-admin&path=%2Fmarketing' ); + + // Users should see the "Learn about marketing a store" card. + await expect( + page.locator( '"Learn about marketing a store"' ) + ).toBeVisible(); + } ); +} );