Merge pull request #31114 from woocommerce/fix/30867

move coupon delete, add tax classes, rates to withRestApi
This commit is contained in:
Greg 2021-11-10 10:49:26 -07:00 committed by GitHub
commit 008e4f19c4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 114 additions and 163 deletions

View File

@ -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,
};

View File

@ -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 );
}
});
});

View File

@ -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
});
}

View File

@ -51,7 +51,7 @@ const updateCustomerBilling = async () => {
search: 'Jane',
role: 'all',
} );
if ( ! customers.data | ! customers.data.length ) {
if ( ! customers.data || ! customers.data.length ) {
return;
}

View File

@ -5,8 +5,11 @@
- `utils.waitForTimeout( delay )` pause processing for `delay` milliseconds
- `AdminEdit` class with utility functions for the respective edit screens
- Update `shopper.addToCartFromShopPage()` and `.removeFromCart()` to accept product Id or Title
- Added `deleteAllProductAttributes()`, `deleteAllProductCategories()`, and `deleteAllProductTags()` to clean up meta data added when products are imported
- Added `withRestApi.createProductCategory()` that creates a product category and returns the ID
- `deleteAllProductAttributes()`, `deleteAllProductCategories()`, and `deleteAllProductTags()` to clean up meta data added when products are imported
- `withRestApi.createProductCategory()` that creates a product category and returns the ID
- `withRestApi.deleteCoupon()` that deletes a single coupon
- `withRestApi.addTaxClasses()` that adds an array of tax classes if they do not exist
- `withRestApi.addTaxRates()` that adds an array of tax rates if they do not exist
# 0.1.6

View File

@ -142,22 +142,25 @@ Please note: if you're using a non-SSL environment (such as a Docker container f
| Function | Parameters | Description |
|----------|------------|-------------|
| `resetOnboarding` | | Reset onboarding settings |
| `deleteAllCoupons` | | Permanently delete all coupons |
| `deleteAllProducts` | | Permanently delete all products |
| `deleteAllShippingZones` | | Permanently delete all shipping zones except the default |
| `deleteAllShippingClasses` | Permanently delete all shipping classes |
| `deleteCustomerByEmail` | `emailAddress` | Delete customer user account. Posts are reassigned to user ID 1 |
| `resetSettingsGroupToDefault` | `settingsGroup` | Reset settings in settings group to default except `select` fields |
| `batchCreateOrders` | `orders` | Create a batch of orders using the "Batch Create Order" API endpoint |
| `addTaxClasses` | `taxClasses` | Add an array of tax classes if they do not exist |
| `addTaxRates` | `taxRates` | Add an array of tax rates if they do not exist |
| `createProductCategory` | `categoryName` | Create a product category with the provided name |
| `deleteAllCoupons` | | Permanently delete all coupons |
| `deleteAllOrders` | | Permanently delete all orders |
| `deleteAllProductAttributes` | | Permanently delete all product attributes |
| `deleteAllProductCategories` | | Permanently delete all product categories |
| `deleteAllProducts` | | Permanently delete all products |
| `deleteAllProductTags` | | Permanently delete all product tags |
| `deleteAllShippingClasses` | Permanently delete all shipping classes |
| `deleteAllShippingZones` | | Permanently delete all shipping zones except the default |
| `deleteCoupon` | `couponId` | Permanently delete a coupon |
| `deleteCustomerByEmail` | `emailAddress` | Delete customer user account. Posts are reassigned to user ID 1 |
| `getSystemEnvironment` | | Get the current environment from the WooCommerce system status API. |
| `resetOnboarding` | | Reset onboarding settings |
| `resetSettingsGroupToDefault` | `settingsGroup` | Reset settings in settings group to default except `select` fields |
| `updateSettingOption` | `settingsGroup`, `settingID`, `payload` | Update a settings group |
| `updatePaymentGateway`| `paymentGatewayId`, `payload` | Update a payment gateway |
| `getSystemEnvironment` | | Get the current environment from the WooCommerce system status API. |
| `deleteAllProductAttributes` | | Permanently delete all product attributes. |
| `deleteAllProductCategories` | | Permanently delete all product categories. |
| `deleteAllProductTags` | | Permanently delete all product tags. |
| `createProductCategory` | `categoryName` | Create a product category with the provided name. |
### Classes

View File

@ -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;
} ;

View File

@ -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 {<Array<Object>>} taxClasses Array of tax class objects.
* @returns {Promise<void>}
*/
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 {<Array<Object>>} taxRates Array of tax rate objects.
* @returns {Promise<void>}
*/
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.
*