diff --git a/packages/js/e2e-core-tests/specs/keep/onboarding-tasklist.test.js b/packages/js/e2e-core-tests/specs/keep/onboarding-tasklist.test.js deleted file mode 100644 index 47aeecb715f..00000000000 --- a/packages/js/e2e-core-tests/specs/keep/onboarding-tasklist.test.js +++ /dev/null @@ -1,83 +0,0 @@ -/* eslint-disable jest/no-export, jest/no-disabled-tests */ - -/** - * Internal dependencies - */ -const { - merchant, - completeOnboardingWizard, - withRestApi, - addShippingZoneAndMethod, - IS_RETEST_MODE, -} = require( '@woocommerce/e2e-utils' ); - -/** - * External dependencies - */ -const config = require( 'config' ); -const { - it, - describe, -} = require( '@jest/globals' ); - -const shippingZoneNameUS = config.get( 'addresses.customer.shipping.country' ); - -const runOnboardingFlowTest = () => { - describe('Store owner can go through store Onboarding', () => { - if ( IS_RETEST_MODE ) { - it('can reset onboarding to default settings', async () => { - await withRestApi.resetOnboarding(); - }); - - it('can reset shipping zones to default settings', async () => { - await withRestApi.deleteAllShippingZones(); - }); - - it('can reset to default settings', async () => { - await withRestApi.resetSettingsGroupToDefault('general'); - await withRestApi.resetSettingsGroupToDefault('products'); - await withRestApi.resetSettingsGroupToDefault('tax'); - }); - } - - it('can start and complete onboarding when visiting the site for the first time.', async () => { - await completeOnboardingWizard(); - }); - }); -}; - -const runTaskListTest = () => { - describe('Store owner can go through setup Task List', () => { - it('can setup shipping', async () => { - await page.evaluate(() => { - document.querySelector('.woocommerce-list__item-title').scrollIntoView(); - }); - // Query for all tasks on the list - const taskListItems = await page.$$('.woocommerce-list__item-title'); - expect(taskListItems.length).toBeInRange( 5, 6 ); - - // Work around for https://github.com/woocommerce/woocommerce-admin/issues/6761 - if ( taskListItems.length == 6 ) { - // Click on "Set up shipping" task to move to the next step - const [ setupTaskListItem ] = await page.$x( '//div[contains(text(),"Set up shipping")]' ); - await setupTaskListItem.click(); - - // Wait for "Proceed" button to become active - await page.waitForSelector('button.is-primary:not(:disabled)'); - await page.waitFor(3000); - - // Click on "Proceed" button to save shipping settings - await page.click('button.is-primary'); - await page.waitFor(3000); - } else { - await merchant.openNewShipping(); - await addShippingZoneAndMethod(shippingZoneNameUS); - } - }); - }); -}; - -module.exports = { - runOnboardingFlowTest, - runTaskListTest, -}; diff --git a/packages/js/e2e-core-tests/specs/merchant/wp-admin-coupon-new.test.js b/packages/js/e2e-core-tests/specs/merchant/wp-admin-coupon-new.test.js index cccd3d8aa39..87921c63ce2 100644 --- a/packages/js/e2e-core-tests/specs/merchant/wp-admin-coupon-new.test.js +++ b/packages/js/e2e-core-tests/specs/merchant/wp-admin-coupon-new.test.js @@ -5,9 +5,8 @@ const { merchant, clickTab, AdminEdit, - factories, + withRestApi, } = require( '@woocommerce/e2e-utils' ); -const { Coupon } = require( '@woocommerce/api' ); /** * External dependencies @@ -50,8 +49,7 @@ const runCreateCouponTest = () => { // Delete the coupon const couponId = await adminEdit.getId(); if ( couponId ) { - const repository = Coupon.restRepository( factories.api.withDefaultPermalinks ); - await repository.delete( couponId ); + await withRestApi.deleteCoupon( couponId ); } }); }); diff --git a/packages/js/e2e-core-tests/specs/merchant/wp-admin-order-new.test.js b/packages/js/e2e-core-tests/specs/merchant/wp-admin-order-new.test.js index 176b11cb768..3dd15e2d758 100644 --- a/packages/js/e2e-core-tests/specs/merchant/wp-admin-order-new.test.js +++ b/packages/js/e2e-core-tests/specs/merchant/wp-admin-order-new.test.js @@ -4,9 +4,10 @@ const { merchant, uiUnblocked, + withRestApi, AdminEdit, -} = require('@woocommerce/e2e-utils'); -const config = require('config'); +} = require( '@woocommerce/e2e-utils' ); +const config = require( 'config' ); const { HTTPClientFactory, VariableProduct, @@ -14,22 +15,34 @@ const { SimpleProduct, ProductVariation, ExternalProduct -} = require('@woocommerce/api'); +} = require( '@woocommerce/api' ); + +const taxClasses = [ + { + name: 'Tax Class Simple', + }, + { + name: 'Tax Class Variable', + }, + { + name: 'Tax Class External', + }, +]; const taxRates = [ { name: 'Tax Rate Simple', - rate: '10', + rate: '10.0000', class: 'tax-class-simple' }, { name: 'Tax Rate Variable', - rate: '20', + rate: '20.0000', class: 'tax-class-variable' }, { name: 'Tax Rate External', - rate: '30', + rate: '30.0000', class: 'tax-class-external' } ]; @@ -43,60 +56,22 @@ const initProducts = async () => { const httpClient = HTTPClientFactory.build(apiUrl) .withBasicAuth(adminUsername, adminPassword) .create(); - const taxClassesPath = '/wc/v3/taxes/classes'; - const taxClasses = [ - { - name: 'Tax Class Simple', - slug: 'tax-class-simple-698962' - }, - { - name: 'Tax Class Variable', - slug: 'tax-class-variable-790238' - }, - { - name: 'Tax Class External', - slug: 'tax-class-external-991321' - } - ]; - // Enable taxes in settings - const enableTaxes = async () => { - const path = '/wc/v3/settings/general/woocommerce_calc_taxes'; - const data = { - value: 'yes' - }; - await httpClient.put(path, data); - }; - await enableTaxes(); - - // Initialize tax classes - const initTaxClasses = async () => { - for (const classToBeAdded of taxClasses) { - await httpClient.post(taxClassesPath, classToBeAdded); - } - }; - await initTaxClasses(); - - // Initialize tax rates - const initTaxRates = async () => { - const path = '/wc/v3/taxes'; - - for (const rateToBeAdded of taxRates) { - await httpClient.post(path, rateToBeAdded); - } - }; - await initTaxRates(); + await withRestApi.updateSettingOption( 'general', 'woocommerce_calc_taxes', { value: 'yes' } ); + await withRestApi.addTaxClasses( taxClasses ); + await withRestApi.addTaxRates( taxRates ); // Initialization functions per product type const initSimpleProduct = async () => { - const repo = SimpleProduct.restRepository(httpClient); + const repo = SimpleProduct.restRepository( httpClient ); const simpleProduct = { name: 'Simple Product 273722', regularPrice: '100', taxClass: 'Tax Class Simple' }; - return await repo.create(simpleProduct); + return await repo.create( simpleProduct ); }; + const initVariableProduct = async () => { const variations = [ { @@ -264,12 +239,12 @@ const runCreateOrderTest = () => { } // Verify that the names of each tax class were shown - for (const { name } of taxRates) { + for (const taxRate of taxRates) { await expect(page).toMatchElement('th.line_tax', { - text: name + text: taxRate.name }); await expect(page).toMatchElement('.wc-order-totals td.label', { - text: name + text: taxRate.name }); } diff --git a/packages/js/e2e-utils/src/components.js b/packages/js/e2e-utils/src/components.js index 1349be25edd..21767d578c2 100644 --- a/packages/js/e2e-utils/src/components.js +++ b/packages/js/e2e-utils/src/components.js @@ -190,13 +190,13 @@ const completeOnboardingWizard = async () => { /** * Create simple product. * - * @param productTitle - Defaults to Simple Product. Customizable title. - * @param productPrice - Defaults to $9.99. Customizable pricing. + * @param productTitle Defaults to Simple Product. Customizable title. + * @param productPrice Defaults to $9.99. Customizable pricing. */ const createSimpleProduct = async ( productTitle = simpleProductName, productPrice = simpleProductPrice ) => { const product = await factories.products.simple.create( { name: productTitle, - regularPrice: productPrice + regularPrice: productPrice, } ); return product.id; } ; diff --git a/packages/js/e2e-utils/src/flows/with-rest-api.js b/packages/js/e2e-utils/src/flows/with-rest-api.js index 49b496d273c..10509afa4ce 100644 --- a/packages/js/e2e-utils/src/flows/with-rest-api.js +++ b/packages/js/e2e-utils/src/flows/with-rest-api.js @@ -4,12 +4,14 @@ import {Coupon, Setting, SimpleProduct, Order} from '@woocommerce/api'; const client = factories.api.withDefaultPermalinks; const onboardingProfileEndpoint = '/wc-admin/onboarding/profile'; -const shippingZoneEndpoint = '/wc/v3/shipping/zones'; -const shippingClassesEndpoint = '/wc/v3/products/shipping_classes'; -const userEndpoint = '/wp/v2/users'; -const systemStatusEndpoint = '/wc/v3/system_status'; const productsEndpoint = '/wc/v3/products'; const productCategoriesEndpoint = '/wc/v3/products/categories'; +const shippingClassesEndpoint = '/wc/v3/products/shipping_classes'; +const shippingZoneEndpoint = '/wc/v3/shipping/zones'; +const systemStatusEndpoint = '/wc/v3/system_status'; +const taxClassesEndpoint = '/wc/v3/taxes/classes'; +const taxRatesEndpoint = '/wc/v3/taxes'; +const userEndpoint = '/wp/v2/users'; /** * Utility function to delete all merchant created data store objects. @@ -42,6 +44,16 @@ const deleteAllRepositoryObjects = async ( repository, defaultObjectId = null, s } }; +/** + * Utility to flatten a tax rate. + * + * @param {object} taxRate Tax rate to be flattened. + * @return {string} + */ +const flattenTaxRate = ( taxRate ) => { + return taxRate.rate + '/' + taxRate.class + '/' + taxRate.name; +} + /** * Utility functions that use the REST API to process the requested function. */ @@ -77,6 +89,16 @@ export const withRestApi = { const repository = Coupon.restRepository( client ); await deleteAllRepositoryObjects( repository ); }, + /** + * Use api package to delete a coupon. + * + * @param {number} couponId Coupon ID. + * @return {Promise} Promise resolving once coupon has been deleted. + */ + deleteCoupon: async ( couponId ) => { + const repository = Coupon.restRepository( client ); + await repository.delete( couponId ); + }, /** * Use api package to delete products. * @@ -331,13 +353,46 @@ export const withRestApi = { * * @param orders Array of orders to be created */ - batchCreateOrders: async (orders) => { + batchCreateOrders: async ( orders ) => { const path = '/wc/v3/orders/batch'; const payload = { create: orders }; const response = await client.post(path, payload); expect( response.status ).toEqual(200); }, + /** + * Add tax classes. + * + * @param {>} taxClasses Array of tax class objects. + * @returns {Promise} + */ + addTaxClasses: async ( taxClasses ) => { + // Only add tax classes which don't already exist. + const existingTaxClasses = await client.get( taxClassesEndpoint ); + const existingTaxNames = existingTaxClasses.data.map( taxClass => taxClass.name ); + const newTaxClasses = taxClasses.filter( taxClass => ! existingTaxNames.includes( taxClass.name ) ); + + for ( const taxClass of newTaxClasses ) { + await client.post( taxClassesEndpoint, taxClass ); + } + }, + /** + * Add tax rates. + * + * @param {>} taxRates Array of tax rate objects. + * @returns {Promise} + */ + addTaxRates: async ( taxRates ) => { + // Only add rates which don't already exist + const existingTaxRates = await client.get( taxRatesEndpoint ); + const existingRates = existingTaxRates.data.map( taxRate => flattenTaxRate( taxRate ) ); + + for ( const taxRate of taxRates ) { + if ( ! existingRates.includes( flattenTaxRate( taxRate ) ) ) { + await client.post( taxRatesEndpoint, taxRate ); + } + } + }, /** * Get the current environment from the WooCommerce system status API. *