Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

E2E tests: Dashboard - Edit Free Listings #2080

Merged
merged 25 commits into from
Aug 31, 2023
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
68d76b3
Add filter to override DB options
jorgemd24 Aug 29, 2023
edbd0cd
Add action to simulate GLA onboarded
jorgemd24 Aug 29, 2023
251de35
Add Mock Requests Utility class
jorgemd24 Aug 29, 2023
acd00aa
Create Dashboard Page
jorgemd24 Aug 29, 2023
280b8f8
Add edit free-listings page
jorgemd24 Aug 29, 2023
f76fb1d
Add edit free listings test
jorgemd24 Aug 29, 2023
551b385
Rename onboarded function and move the method to mock requests class
jorgemd24 Aug 29, 2023
d722ba4
Remove unnecessary spaces
jorgemd24 Aug 29, 2023
0a84f51
Fix phpcs
jorgemd24 Aug 29, 2023
9c5010d
Fix js linting
jorgemd24 Aug 29, 2023
82fdb76
Merge branch 'develop' into dev/dashboard-e2e-tests
jorgemd24 Aug 30, 2023
d3b3448
Add endpoints to simulate onboarded merchant
jorgemd24 Aug 30, 2023
0664818
Remove filter to simulate options values
jorgemd24 Aug 30, 2023
d520d8b
Use the test API to simulate onboarded merchant
jorgemd24 Aug 30, 2023
c5942d6
Add onBoarded functions
jorgemd24 Aug 30, 2023
a19a8a8
Remove old mockOnboarded method as we will use the test API to simula…
jorgemd24 Aug 30, 2023
d68f4d7
Set the number of workers to 1
jorgemd24 Aug 30, 2023
4b4f063
Adding missing awaits
jorgemd24 Aug 30, 2023
62f6270
Fix js lint
jorgemd24 Aug 30, 2023
097f2fb
Fix misspelling targetAudienceRequest
jorgemd24 Aug 31, 2023
e68a11e
Mock saving settings sync request
jorgemd24 Aug 31, 2023
819250b
Move EditFreeListings page in beforeAll
jorgemd24 Aug 31, 2023
5a9c0e2
Test the snackbar message after the settings have been saved
jorgemd24 Aug 31, 2023
3e7fbdb
Reorder imports
jorgemd24 Aug 31, 2023
d0c9172
Add missing return JSDOC
jorgemd24 Aug 31, 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
2 changes: 1 addition & 1 deletion src/Options/Options.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public function get( string $name, $default = null ) {

if ( ! array_key_exists( $name, $this->options ) ) {
$value = get_option( $this->prefix_name( $name ), $default );
$this->options[ $name ] = $this->maybe_cast_value( $name, $value );
$this->options[ $name ] = apply_filters( "woocommerce_gla_options_get_{$name}", $this->maybe_cast_value( $name, $value ) );
}

return $this->raw_value( $this->options[ $name ] );
Expand Down
29 changes: 29 additions & 0 deletions tests/e2e/bin/test-data.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,35 @@ function register_routes() {
);
}

add_action(
'plugins_loaded',
function () {
if ( isset( $_GET['gla-e2e-onboarded'] ) ) {
add_filter(
'woocommerce_gla_options_get_' . OptionsInterface::REDIRECT_TO_ONBOARDING,
function ( $value ) {
return 'no';
}
);

add_filter(
'woocommerce_gla_options_get_' . OptionsInterface::MC_SETUP_COMPLETED_AT,
function ( $value ) {
return 1693215209;
}
);

add_filter(
'woocommerce_gla_options_get_' . OptionsInterface::GOOGLE_CONNECTED,
function ( $value ) {
return true;
}
);
}
}
);


/**
* Set the Ads Conversion Action to test values.
*/
Expand Down
91 changes: 91 additions & 0 deletions tests/e2e/specs/dashboard/edit-free-listings.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/**
* External dependencies
*/
import { test, expect } from '@playwright/test';
/**
* Internal dependencies
*/
import DashboardPage from '../../utils/pages/dashboard.js';
import EditFreeListingsPage from '../../utils/pages/edit-free-listings.js';

test.use( { storageState: process.env.ADMINSTATE } );

test.describe.configure( { mode: 'serial' } );

/**
* @type {import('../../utils/pages/dashboard.js').default} dashboardPage
*/
let dashboardPage = null;

/**
* @type {import('../../utils/pages/edit-free-listings.js').default} editFreeListingsPage
*/
let editFreeListingsPage = null;

/**
* @type {import('@playwright/test').Page} page
*/
let page = null;

test.describe( 'Edit Free Listings', () => {
test.beforeAll( async ( { browser } ) => {
page = await browser.newPage();
dashboardPage = new DashboardPage( page );
await dashboardPage.mockOnboarded();
await dashboardPage.mockRequests();
await dashboardPage.goto();
} );

test.afterAll( async () => {
await page.close();
} );

test( 'Dashboard page contains Free Listings', async () => {
await expect( dashboardPage.freeListingRow ).toContainText(
'Free listings'
);

await expect( dashboardPage.editFreeListingButton ).toBeEnabled();
} );

test( 'Edit Free Listings should show modal', async () => {
await dashboardPage.clickEditFreeListings();

await page.waitForLoadState( 'domcontentloaded' );

const continueToEditButton = await dashboardPage.getContinueToEditButton();

Check failure on line 56 in tests/e2e/specs/dashboard/edit-free-listings.test.js

View workflow job for this annotation

GitHub Actions / Lint JavaScript

[prettier/prettier] Replace `·` with `⏎↹↹↹`
const dontEditButton = await dashboardPage.getDontEditButton();
await expect( continueToEditButton ).toBeEnabled();
await expect( dontEditButton ).toBeEnabled();
} );

test( 'Continue to edit Free listings', async () => {
await dashboardPage.clickContinueToEditButton();
await page.waitForLoadState( 'domcontentloaded' );
} );

test( 'Check recommended shipping settings', async () => {
editFreeListingsPage = new EditFreeListingsPage( page );
Copy link
Member

Choose a reason for hiding this comment

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

While the test is configured to run serial, I think it'd still be better to move this line to beforeAll() like dashboardPage.

await editFreeListingsPage.checkRecommendShippingSettings();
await editFreeListingsPage.fillCountriesShippingTimeInput( '5' );
await editFreeListingsPage.checkDestinationBasedTaxRates();
const saveChangesButton = await editFreeListingsPage.getSaveChangesButton();

Check failure on line 72 in tests/e2e/specs/dashboard/edit-free-listings.test.js

View workflow job for this annotation

GitHub Actions / Lint JavaScript

[prettier/prettier] Replace `·` with `⏎↹↹↹`
await expect( saveChangesButton ).toBeEnabled();
} );

test( 'Save changes', async () => {
const awaitForRequests = editFreeListingsPage.registerSavingRequests();
await editFreeListingsPage.clickSaveChanges();
const requests = await awaitForRequests;
const settingsResponse = await (
await requests[ 0 ].response()
).json();

expect( settingsResponse.status ).toBe( 'success' );
expect( settingsResponse.message ).toBe(
'Merchant Center Settings successfully updated.'
);
expect( settingsResponse.data.shipping_time ).toBe( 'flat' );
expect( settingsResponse.data.tax_rate ).toBe( 'destination' );
} );
} );
98 changes: 98 additions & 0 deletions tests/e2e/utils/mock-requests.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/**
* Mock Requests
*
* This class is used to mock requests to the server.
*/
export default class MockRequests {
/**
* @param {import('@playwright/test').Page} page
*/
constructor( page ) {
this.page = page;
}

/**
* Add the parameter gla-e2e-onboarded to the request to simulate the onboarded state; otherwise, it will redirect to the onboarding page.
*
* @return {Promise<void>}
*/
async mockOnboarded() {
await this.page.route( /\/admin.php\b/, ( route ) => {
const url = `${ route.request().url() }&gla-e2e-onboarded=true`;
route.continue( { url } );
} );
}

/**
* Fulfill a request with a payload.
*
* @param {RegExp|string} url The url to fulfill.
* @param {Object} payload The payload to send.
* @return {Promise<void>}
*/
async fulfillRequest( url, payload ) {
await this.page.route( url, ( route ) =>
route.fulfill( {
content: 'application/json',
headers: { 'Access-Control-Allow-Origin': '*' },
body: JSON.stringify( payload ),
} )
);
}

/**
* Fulfill the MC Report Program request.
*
* @param {Object} payload
* @return {Promise<void>}
*/
async fulfillMCReportProgram( payload ) {
await this.fulfillRequest(
/\/wc\/gla\/mc\/reports\/programs\b/,
payload
);
}

/**
* Fulfill the Target Audience request.
*
* @param {Object} payload
* @return {Promise<void>}
*/
async fulfillTargetAudience( payload ) {
await this.fulfillRequest(
/\/wc\/gla\/mc\/target_audience\b/,
payload
);
}

/**
* Fulfill the JetPack Connection request.
*
* @param {Object} payload
* @return {Promise<void>}
*/
async fulfillJetPackConnection( payload ) {
await this.fulfillRequest( /\/wc\/gla\/jetpack\/connected\b/, payload );
}

/**
* Fulfill the Google Connection request.
*
* @param {Object} payload
* @return {Promise<void>}
*/
async fulfillGoogleConnection( payload ) {
await this.fulfillRequest( /\/wc\/gla\/google\/connected\b/, payload );
}

/**
* Fulfill the Ads Connection request.
*
* @param {Object} payload
* @return {Promise<void>}
*/
async fulfillAdsConnection( payload ) {
await this.fulfillRequest( /\/wc\/gla\/ads\/connection\b/, payload );
}
}
131 changes: 131 additions & 0 deletions tests/e2e/utils/pages/dashboard.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
/**
* Internal dependencies
*/
import MockRequests from '../mock-requests';

/**
* Dashboard page object class.
*/
export default class DashboardPage extends MockRequests {
/**
* @param {import('@playwright/test').Page} page
*/
constructor( page ) {
super( page );
this.page = page;
this.freeListingRow = this.page.locator(
'.gla-all-programs-table-card table tr:nth-child(2)'
);
this.editFreeListingButton = this.freeListingRow.getByRole( 'button', {
name: 'Edit',
} );
}

/**
* Close the current page.
*
* @return {Promise<void>}
*/
async closePage() {
await this.page.close();
}

/**
* Mock all requests related to external accounts such as Merchant Center, Google, etc.
*/
async mockRequests() {
// Mock Reports Programs
this.fulfillMCReportProgram( {
jorgemd24 marked this conversation as resolved.
Show resolved Hide resolved
free_listings: null,
products: null,
intervals: null,
totals: {
clicks: 0,
impressions: 0,
},
next_page: null,
} );

this.fulfillTargetAudience( {
location: 'selected',
countries: [ 'US' ],
locale: 'en_US',
language: 'English',
} );

this.fulfillJetPackConnection( {
active: 'yes',
owner: 'yes',
displayName: 'John',
email: '[email protected]',
} );

this.fulfillGoogleConnection( {
active: 'yes',
email: '[email protected]',
scope: [],
} );

this.fulfillAdsConnection( {
id: 0,
currency: null,
symbol: '$',
status: 'disconnected',
} );
}

/**
* Go to the dashboard page.
*
* @return {Promise<void>}
*/
async goto() {
await this.page.goto(
'/wp-admin/admin.php?page=wc-admin&path=%2Fgoogle%2Fdashboard',
{ waitUntil: 'domcontentloaded' }
);
}

/**
* Click the edit free listings button.
*
* @return {Promise<void>}
*/
async clickEditFreeListings() {
await this.editFreeListingButton.click();
}

/**
* Get the continue to edit button from the modal.
*
* @return {Promise<import('@playwright/test').Locator>} Get the continue to edit button from the modal.
*/
async getContinueToEditButton() {
return this.page.getByRole( 'button', {
name: 'Continue to edit',
exact: true,
} );
}

/**
* Get the don't edit button from the modal.
*
* @return {Promise<import('@playwright/test').Locator>} Get the don't edit button from the modal.
*/
async getDontEditButton() {
return this.page.getByRole( 'button', {
name: "Don't edit",
exact: true,
} );
}

/**
* Click the continue to edit button from the modal.
*
* @return {Promise<void>}
*/
async clickContinueToEditButton() {
const continueToEditButton = await this.getContinueToEditButton();
await continueToEditButton.click();
}
}
Loading
Loading