E2E: fix flakiness in `analytics-overview.spec.js` (#39308)
This commit is contained in:
commit
e5b26f0b7d
|
@ -0,0 +1,4 @@
|
||||||
|
Significance: patch
|
||||||
|
Type: dev
|
||||||
|
|
||||||
|
Fix flaky E2E tests in analytics-overview.spec.js.
|
|
@ -1,199 +1,286 @@
|
||||||
const { test, expect } = require( '@playwright/test' );
|
const { test, expect, Page, Locator } = require( '@playwright/test' );
|
||||||
|
const { admin } = require( '../../test-data/data' );
|
||||||
|
|
||||||
|
const EXPECTED_SECTION_HEADERS = [ 'Performance', 'Charts', 'Leaderboards' ];
|
||||||
|
|
||||||
|
let /**
|
||||||
|
* @type {number}
|
||||||
|
*/
|
||||||
|
userId,
|
||||||
|
/**
|
||||||
|
* @type {Locator}
|
||||||
|
*/
|
||||||
|
headings_sections,
|
||||||
|
/**
|
||||||
|
* @type {Locator}
|
||||||
|
*/
|
||||||
|
heading_performance,
|
||||||
|
/**
|
||||||
|
* @type {Locator}
|
||||||
|
*/
|
||||||
|
buttons_ellipsis,
|
||||||
|
/**
|
||||||
|
* @type {Locator}
|
||||||
|
*/ menuitem_moveUp,
|
||||||
|
/**
|
||||||
|
* @type {Locator}
|
||||||
|
*/ menuitem_moveDown,
|
||||||
|
/**
|
||||||
|
* @type {Page}
|
||||||
|
*/
|
||||||
|
page;
|
||||||
|
|
||||||
|
const basicAuth = () => {
|
||||||
|
const base64String = Buffer.from(
|
||||||
|
`${ admin.username }:${ admin.password }`
|
||||||
|
).toString( 'base64' );
|
||||||
|
|
||||||
|
return `Basic ${ base64String }`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const hidePerformanceSection = async () => {
|
||||||
|
const response =
|
||||||
|
await test.step( `Send POST request to hide Performance section`, async () => {
|
||||||
|
const request = page.request;
|
||||||
|
const url = `/wp-json/wp/v2/users/${ userId }`;
|
||||||
|
const params = { _locale: 'user' };
|
||||||
|
const dashboard_sections = JSON.stringify( [
|
||||||
|
{ key: 'store-performance', isVisible: false },
|
||||||
|
] );
|
||||||
|
const headers = {
|
||||||
|
Authorization: basicAuth(),
|
||||||
|
cookie: '',
|
||||||
|
};
|
||||||
|
const data = {
|
||||||
|
id: userId,
|
||||||
|
woocommerce_meta: {
|
||||||
|
dashboard_sections,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const response = await request.post( url, {
|
||||||
|
data,
|
||||||
|
params,
|
||||||
|
headers,
|
||||||
|
} );
|
||||||
|
|
||||||
|
return response;
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( `Assert response status is OK`, async () => {
|
||||||
|
expect( response.ok() ).toBeTruthy();
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( `Inspect the response payload to verify that Performance section was successfully hidden`, async () => {
|
||||||
|
const { woocommerce_meta } = await response.json();
|
||||||
|
const { dashboard_sections } = woocommerce_meta;
|
||||||
|
const sections = JSON.parse( dashboard_sections );
|
||||||
|
const performanceSection = sections.find(
|
||||||
|
( { key } ) => key === 'store-performance'
|
||||||
|
);
|
||||||
|
expect( performanceSection.isVisible ).toBeFalsy();
|
||||||
|
} );
|
||||||
|
};
|
||||||
|
|
||||||
|
const resetSections = async () => {
|
||||||
|
const response =
|
||||||
|
await test.step( `Send POST request to reset all sections`, async () => {
|
||||||
|
const request = page.request;
|
||||||
|
const url = `/wp-json/wp/v2/users/${ userId }`;
|
||||||
|
const params = { _locale: 'user' };
|
||||||
|
const headers = {
|
||||||
|
Authorization: basicAuth(),
|
||||||
|
cookie: '',
|
||||||
|
};
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
id: userId,
|
||||||
|
woocommerce_meta: {
|
||||||
|
dashboard_sections: '',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const response = await request.post( url, {
|
||||||
|
data,
|
||||||
|
params,
|
||||||
|
headers,
|
||||||
|
} );
|
||||||
|
|
||||||
|
return response;
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( `Assert response status is OK`, async () => {
|
||||||
|
expect( response.ok() ).toBeTruthy();
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( `Verify that sections were reset`, async () => {
|
||||||
|
const { woocommerce_meta } = await response.json();
|
||||||
|
const { dashboard_sections } = woocommerce_meta;
|
||||||
|
|
||||||
|
expect( dashboard_sections ).toHaveLength( 0 );
|
||||||
|
} );
|
||||||
|
};
|
||||||
|
|
||||||
test.describe( 'Analytics pages', () => {
|
test.describe( 'Analytics pages', () => {
|
||||||
test.use( { storageState: process.env.ADMINSTATE } );
|
test.use( { storageState: process.env.ADMINSTATE } );
|
||||||
|
|
||||||
test.afterEach( async ( { page } ) => {
|
test.beforeAll( async ( { browser } ) => {
|
||||||
// do some cleanup after each test to make sure things are where they should be
|
page = await browser.newPage();
|
||||||
await page.goto(
|
|
||||||
'wp-admin/admin.php?page=wc-admin&path=%2Fanalytics%2Foverview'
|
|
||||||
);
|
|
||||||
|
|
||||||
// Grab all of the section headings
|
await test.step( `Send GET request to get the current user id`, async () => {
|
||||||
const sections = await page
|
const request = page.request;
|
||||||
.locator( 'h2.woocommerce-section-header__title' )
|
const response = await request.get( '/wp-json/wp/v2/users' );
|
||||||
.count();
|
const responseJson = await response.json();
|
||||||
if ( sections < 3 ) {
|
const { id } = responseJson.find(
|
||||||
// performance section is hidden
|
( { slug } ) => slug === admin.username
|
||||||
await page
|
|
||||||
.locator( '//button[@title="Add more sections"]' )
|
|
||||||
.click();
|
|
||||||
await page
|
|
||||||
.locator( '//button[@title="Add Performance section"]' )
|
|
||||||
.click();
|
|
||||||
await expect(
|
|
||||||
page.locator( 'h2:has-text("Performance")' )
|
|
||||||
).toBeVisible();
|
|
||||||
await page.waitForLoadState( 'networkidle' );
|
|
||||||
}
|
|
||||||
const lastSection = await page
|
|
||||||
.locator( 'h2.woocommerce-section-header__title >> nth=2' )
|
|
||||||
.textContent();
|
|
||||||
if ( lastSection === 'Performance' ) {
|
|
||||||
// sections are in the wrong order
|
|
||||||
await page
|
|
||||||
.locator(
|
|
||||||
'//button[@title="Choose which analytics to display and the section name"]'
|
|
||||||
)
|
|
||||||
.click();
|
|
||||||
await page.locator( 'text=Move up' ).click();
|
|
||||||
await page
|
|
||||||
.locator(
|
|
||||||
'//button[@title="Choose which analytics to display and the section name"]'
|
|
||||||
)
|
|
||||||
.click();
|
|
||||||
await page.locator( 'text=Move up' ).click();
|
|
||||||
|
|
||||||
// wait for the changes to be saved
|
|
||||||
await page.waitForResponse(
|
|
||||||
( response ) =>
|
|
||||||
response.url().includes( '/users/' ) &&
|
|
||||||
response.status() === 200
|
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
userId = id;
|
||||||
|
} );
|
||||||
|
|
||||||
|
await resetSections();
|
||||||
|
|
||||||
|
await test.step( `Initialize locators`, async () => {
|
||||||
|
const pattern = new RegExp( EXPECTED_SECTION_HEADERS.join( '|' ) );
|
||||||
|
|
||||||
|
headings_sections = page.getByRole( 'heading', {
|
||||||
|
name: pattern,
|
||||||
|
} );
|
||||||
|
|
||||||
|
heading_performance = page.getByRole( 'heading', {
|
||||||
|
name: 'Performance',
|
||||||
|
} );
|
||||||
|
|
||||||
|
buttons_ellipsis = page.getByRole( 'button', {
|
||||||
|
name: 'Choose which',
|
||||||
|
} );
|
||||||
|
|
||||||
|
menuitem_moveUp = page.getByRole( 'menuitem', {
|
||||||
|
name: 'Move up',
|
||||||
|
} );
|
||||||
|
|
||||||
|
menuitem_moveDown = page.getByRole( 'menuitem', {
|
||||||
|
name: 'Move down',
|
||||||
|
} );
|
||||||
|
} );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
test( 'a user should see 3 sections by default - Performance, Charts, and Leaderboards', async ( {
|
test.beforeEach( async () => {
|
||||||
page,
|
await test.step( `Go to Analytics > Overview`, async () => {
|
||||||
} ) => {
|
await page.goto(
|
||||||
// Create an array of the sections we're expecting to find.
|
'wp-admin/admin.php?page=wc-admin&path=%2Fanalytics%2Foverview'
|
||||||
const arrExpectedSections = [ 'Charts', 'Leaderboards', 'Performance' ];
|
);
|
||||||
await page.goto(
|
} );
|
||||||
'wp-admin/admin.php?page=wc-admin&path=%2Fanalytics%2Foverview'
|
} );
|
||||||
);
|
|
||||||
|
|
||||||
for ( const expectedSection of arrExpectedSections ) {
|
test.afterEach( async () => {
|
||||||
|
await resetSections();
|
||||||
|
} );
|
||||||
|
|
||||||
|
test.afterAll( async () => {
|
||||||
|
await page.close();
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'a user should see 3 sections by default - Performance, Charts, and Leaderboards', async () => {
|
||||||
|
for ( const expectedSection of EXPECTED_SECTION_HEADERS ) {
|
||||||
await test.step( `Assert that the "${ expectedSection }" section is visible`, async () => {
|
await test.step( `Assert that the "${ expectedSection }" section is visible`, async () => {
|
||||||
await expect(
|
await expect(
|
||||||
page.locator( 'h2.woocommerce-section-header__title', {
|
headings_sections.filter( { hasText: expectedSection } )
|
||||||
hasText: expectedSection,
|
|
||||||
} )
|
|
||||||
).toBeVisible();
|
).toBeVisible();
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
|
|
||||||
test.describe( 'moving sections', () => {
|
test.describe( 'moving sections', () => {
|
||||||
test.use( { storageState: process.env.ADMINSTATE } );
|
test( 'should not display move up for the top, or move down for the bottom section', async () => {
|
||||||
|
await test.step( `Check the top section`, async () => {
|
||||||
|
await buttons_ellipsis.first().click();
|
||||||
|
await expect( menuitem_moveUp ).not.toBeVisible();
|
||||||
|
await expect( menuitem_moveDown ).toBeVisible();
|
||||||
|
await page.keyboard.press( 'Escape' );
|
||||||
|
} );
|
||||||
|
|
||||||
test( 'should not display move up for the top, or move down for the bottom section', async ( {
|
await test.step( `Check the bottom section`, async () => {
|
||||||
page,
|
await buttons_ellipsis.last().click();
|
||||||
} ) => {
|
await expect( menuitem_moveDown ).not.toBeVisible();
|
||||||
await page.goto(
|
await expect( menuitem_moveUp ).toBeVisible();
|
||||||
'wp-admin/admin.php?page=wc-admin&path=%2Fanalytics%2Foverview'
|
await page.keyboard.press( 'Escape' );
|
||||||
);
|
} );
|
||||||
// check the top section
|
|
||||||
await page
|
|
||||||
.locator( 'button.woocommerce-ellipsis-menu__toggle' )
|
|
||||||
.first()
|
|
||||||
.click();
|
|
||||||
await expect( page.locator( 'text=Move up' ) ).not.toBeVisible();
|
|
||||||
await expect( page.locator( 'text=Move down' ) ).toBeVisible();
|
|
||||||
await page.keyboard.press( 'Escape' );
|
|
||||||
|
|
||||||
// check the bottom section
|
|
||||||
await page
|
|
||||||
.locator( 'button.woocommerce-ellipsis-menu__toggle' )
|
|
||||||
.last()
|
|
||||||
.click();
|
|
||||||
await expect( page.locator( 'text=Move down' ) ).not.toBeVisible();
|
|
||||||
await expect( page.locator( 'text=Move up' ) ).toBeVisible();
|
|
||||||
await page.keyboard.press( 'Escape' );
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
test( 'should allow a user to move a section down', async ( {
|
test( 'should allow a user to move a section down', async () => {
|
||||||
page,
|
const firstSection = await headings_sections.first().innerText();
|
||||||
} ) => {
|
const secondSection = await headings_sections.nth( 1 ).innerText();
|
||||||
await page.goto(
|
|
||||||
'wp-admin/admin.php?page=wc-admin&path=%2Fanalytics%2Foverview'
|
|
||||||
);
|
|
||||||
const firstSection = await page
|
|
||||||
.locator( 'h2.woocommerce-section-header__title >> nth=0' )
|
|
||||||
.innerText();
|
|
||||||
const secondSection = await page
|
|
||||||
.locator( 'h2.woocommerce-section-header__title >> nth=1' )
|
|
||||||
.innerText();
|
|
||||||
|
|
||||||
await page
|
await test.step( `Move first section down`, async () => {
|
||||||
.locator(
|
await buttons_ellipsis.first().click();
|
||||||
'button.components-button.woocommerce-ellipsis-menu__toggle >> nth=0'
|
await menuitem_moveDown.click();
|
||||||
)
|
} );
|
||||||
.click();
|
|
||||||
await page.locator( 'text=Move down' ).click();
|
|
||||||
|
|
||||||
// second section becomes first section, first becomes second
|
await test.step( `Expect the second section to become first, and first becomes second.`, async () => {
|
||||||
await expect(
|
await expect( headings_sections.first() ).toHaveText(
|
||||||
page.locator( 'h2.woocommerce-section-header__title >> nth=0' )
|
secondSection
|
||||||
).toHaveText( secondSection );
|
);
|
||||||
await expect(
|
|
||||||
page.locator( 'h2.woocommerce-section-header__title >> nth=1' )
|
await expect( headings_sections.nth( 1 ) ).toHaveText(
|
||||||
).toHaveText( firstSection );
|
firstSection
|
||||||
|
);
|
||||||
|
} );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
test( 'should allow a user to move a section up', async ( {
|
test( 'should allow a user to move a section up', async () => {
|
||||||
page,
|
const firstSection = await headings_sections.first().innerText();
|
||||||
} ) => {
|
const secondSection = await headings_sections.nth( 1 ).innerText();
|
||||||
await page.goto(
|
|
||||||
'wp-admin/admin.php?page=wc-admin&path=%2Fanalytics%2Foverview'
|
|
||||||
);
|
|
||||||
const firstSection = await page
|
|
||||||
.locator( 'h2.woocommerce-section-header__title >> nth=0' )
|
|
||||||
.innerText();
|
|
||||||
const secondSection = await page
|
|
||||||
.locator( 'h2.woocommerce-section-header__title >> nth=1' )
|
|
||||||
.innerText();
|
|
||||||
|
|
||||||
await page
|
await test.step( `Move second section up`, async () => {
|
||||||
.locator(
|
await buttons_ellipsis.nth( 1 ).click();
|
||||||
'button.components-button.woocommerce-ellipsis-menu__toggle >> nth=1'
|
await menuitem_moveUp.click();
|
||||||
)
|
} );
|
||||||
.click();
|
|
||||||
await page.locator( 'text=Move up' ).click();
|
|
||||||
|
|
||||||
// second section becomes first section, first becomes second
|
await test.step( `Expect second section becomes first section, first becomes second`, async () => {
|
||||||
await expect(
|
await expect( headings_sections.first() ).toHaveText(
|
||||||
page.locator( 'h2.woocommerce-section-header__title >> nth=0' )
|
secondSection
|
||||||
).toHaveText( secondSection );
|
);
|
||||||
await expect(
|
await expect( headings_sections.nth( 1 ) ).toHaveText(
|
||||||
page.locator( 'h2.woocommerce-section-header__title >> nth=1' )
|
firstSection
|
||||||
).toHaveText( firstSection );
|
);
|
||||||
|
} );
|
||||||
} );
|
} );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
test( 'should allow a user to remove a section', async ( { page } ) => {
|
test( 'should allow a user to remove a section', async () => {
|
||||||
await page.goto(
|
await test.step( `Remove the Performance section`, async () => {
|
||||||
'wp-admin/admin.php?page=wc-admin&path=%2Fanalytics%2Foverview'
|
await page
|
||||||
);
|
.getByRole( 'button', {
|
||||||
// clicks the first button to the right of the Performance heading
|
name: 'Choose which analytics to display and the section name',
|
||||||
await page
|
} )
|
||||||
.locator( 'button:right-of(:text("Performance")) >> nth=0' )
|
.click();
|
||||||
.click();
|
await page
|
||||||
await page.locator( 'text=Remove section' ).click();
|
.getByRole( 'menuitem', { name: 'Remove section' } )
|
||||||
// Grab all of the section headings
|
.click();
|
||||||
await page.waitForLoadState( 'networkidle' );
|
await page.waitForResponse(
|
||||||
const sections = page.locator( 'h2.woocommerce-section-header__title' );
|
( response ) =>
|
||||||
await expect( sections ).toHaveCount( 2 );
|
response.url().includes( '/users' ) && response.ok()
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
|
||||||
|
await test.step( `Expect the Performance section to be hidden`, async () => {
|
||||||
|
await expect( headings_sections ).toHaveCount( 2 );
|
||||||
|
await expect( heading_performance ).not.toBeVisible();
|
||||||
|
} );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
test( 'should allow a user to add a section back in', async ( {
|
test( 'should allow a user to add a section back in', async () => {
|
||||||
page,
|
await hidePerformanceSection( page );
|
||||||
} ) => {
|
await page.reload();
|
||||||
await page.goto(
|
|
||||||
'wp-admin/admin.php?page=wc-admin&path=%2Fanalytics%2Foverview'
|
|
||||||
);
|
|
||||||
// button only shows when not all sections visible, so remove a section
|
|
||||||
await page
|
|
||||||
.locator( 'button:right-of(:text("Performance")) >> nth=0' )
|
|
||||||
.click();
|
|
||||||
await page.locator( 'text=Remove section' ).click();
|
|
||||||
|
|
||||||
// add section
|
await test.step( `Add the Performance section back in.`, async () => {
|
||||||
await page.locator( '//button[@title="Add more sections"]' ).click();
|
await page.getByTitle( 'Add more sections' ).click();
|
||||||
await page
|
await page.getByTitle( 'Add Performance section' ).click();
|
||||||
.locator( '//button[@title="Add Performance section"]' )
|
} );
|
||||||
.click();
|
|
||||||
await expect(
|
await test.step( `Expect the Performance section to be added back.`, async () => {
|
||||||
page.locator( 'h2.woocommerce-section-header__title >> nth=2' )
|
await expect( heading_performance ).toBeVisible();
|
||||||
).toContainText( 'Performance' );
|
} );
|
||||||
} );
|
} );
|
||||||
} );
|
} );
|
||||||
|
|
Loading…
Reference in New Issue