Add tests for UI Revamp on Marketing page (#34840)
This commit is contained in:
parent
c31f8b0aa5
commit
9e697cdf0a
|
@ -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( <CollapsibleCard header={ header }>{ body }</CollapsibleCard> );
|
||||||
|
|
||||||
|
// 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(
|
||||||
|
<CollapsibleCard initialCollapsed header={ header }>
|
||||||
|
{ body }
|
||||||
|
</CollapsibleCard>
|
||||||
|
);
|
||||||
|
|
||||||
|
// Card is collapsed by default.
|
||||||
|
expect( screen.queryByText( header ) ).toBeInTheDocument();
|
||||||
|
expect( screen.queryByText( body ) ).not.toBeInTheDocument();
|
||||||
|
} );
|
||||||
|
} );
|
|
@ -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( <LearnMarketing /> );
|
||||||
|
|
||||||
|
// 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( <LearnMarketing /> );
|
||||||
|
|
||||||
|
// 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( <LearnMarketing /> );
|
||||||
|
|
||||||
|
// 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( <LearnMarketing /> );
|
||||||
|
|
||||||
|
// 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();
|
||||||
|
} );
|
||||||
|
} );
|
|
@ -3,17 +3,15 @@
|
||||||
*/
|
*/
|
||||||
import { useState } from '@wordpress/element';
|
import { useState } from '@wordpress/element';
|
||||||
import { __ } from '@wordpress/i18n';
|
import { __ } from '@wordpress/i18n';
|
||||||
import { useSelect } from '@wordpress/data';
|
|
||||||
import { Pagination, EmptyContent } from '@woocommerce/components';
|
import { Pagination, EmptyContent } from '@woocommerce/components';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal dependencies
|
* Internal dependencies
|
||||||
*/
|
*/
|
||||||
import { CollapsibleCard, ReadBlogMessage } from '~/marketing/components';
|
import { CollapsibleCard, ReadBlogMessage } from '~/marketing/components';
|
||||||
import { STORE_KEY } from '~/marketing/data/constants';
|
|
||||||
import { PlaceholderPostTile } from './PlaceholderPostTile';
|
import { PlaceholderPostTile } from './PlaceholderPostTile';
|
||||||
import { PostTile } from './PostTile';
|
import { PostTile } from './PostTile';
|
||||||
import { Post } from './types';
|
import { useBlogPosts } from './useBlogPosts';
|
||||||
import './LearnMarketing.scss';
|
import './LearnMarketing.scss';
|
||||||
|
|
||||||
const BLOG_POST_CATEGORY = 'marketing';
|
const BLOG_POST_CATEGORY = 'marketing';
|
||||||
|
@ -21,21 +19,7 @@ const PER_PAGE = 2;
|
||||||
|
|
||||||
export const LearnMarketing = () => {
|
export const LearnMarketing = () => {
|
||||||
const [ page, setPage ] = useState( 1 );
|
const [ page, setPage ] = useState( 1 );
|
||||||
const { isLoading, error, posts } = useSelect(
|
const { isLoading, error, posts } = useBlogPosts( BLOG_POST_CATEGORY );
|
||||||
( 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 ]
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders card footer.
|
* Renders card footer.
|
||||||
|
@ -47,7 +31,10 @@ export const LearnMarketing = () => {
|
||||||
const renderFooter = () => {
|
const renderFooter = () => {
|
||||||
if ( isLoading ) {
|
if ( isLoading ) {
|
||||||
return (
|
return (
|
||||||
<div className="woocommerce-marketing-learn-marketing-card__footer--placeholder" />
|
<div
|
||||||
|
role="progressbar"
|
||||||
|
className="woocommerce-marketing-learn-marketing-card__footer--placeholder"
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,7 +98,7 @@ export const LearnMarketing = () => {
|
||||||
|
|
||||||
return posts
|
return posts
|
||||||
.slice( ( page - 1 ) * PER_PAGE, page * PER_PAGE )
|
.slice( ( page - 1 ) * PER_PAGE, page * PER_PAGE )
|
||||||
.map( ( post: Post, index: number ) => {
|
.map( ( post, index ) => {
|
||||||
return <PostTile key={ index } post={ post } />;
|
return <PostTile key={ index } post={ post } />;
|
||||||
} );
|
} );
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
export const PlaceholderPostTile = () => {
|
export const PlaceholderPostTile = () => {
|
||||||
return (
|
return (
|
||||||
<div className="woocommerce-marketing-learn-marketing-card__post">
|
<div
|
||||||
|
role="progressbar"
|
||||||
|
className="woocommerce-marketing-learn-marketing-card__post"
|
||||||
|
>
|
||||||
<div className="woocommerce-marketing-learn-marketing-card__post-img woocommerce-marketing-learn-marketing-card__post-img--placeholder" />
|
<div className="woocommerce-marketing-learn-marketing-card__post-img woocommerce-marketing-learn-marketing-card__post-img--placeholder" />
|
||||||
<div className="woocommerce-marketing-learn-marketing-card__post-title woocommerce-marketing-learn-marketing-card__post-title--placeholder" />
|
<div className="woocommerce-marketing-learn-marketing-card__post-title woocommerce-marketing-learn-marketing-card__post-title--placeholder" />
|
||||||
<div className="woocommerce-marketing-learn-marketing-card__post-description woocommerce-marketing-learn-marketing-card__post-description--placeholder" />
|
<div className="woocommerce-marketing-learn-marketing-card__post-description woocommerce-marketing-learn-marketing-card__post-description--placeholder" />
|
||||||
|
|
|
@ -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 ]
|
||||||
|
);
|
||||||
|
};
|
|
@ -0,0 +1,4 @@
|
||||||
|
Significance: minor
|
||||||
|
Type: dev
|
||||||
|
|
||||||
|
Add tests for UI Revamp on Marketing Page.
|
|
@ -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();
|
||||||
|
} );
|
||||||
|
} );
|
Loading…
Reference in New Issue