Standardize linting: e2e js packages (#32794)
This commit is contained in:
parent
4915c389ef
commit
489ebf2cc6
|
@ -0,0 +1,3 @@
|
|||
module.exports = {
|
||||
extends: [ 'plugin:@woocommerce/eslint-plugin/recommended' ],
|
||||
};
|
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: dev
|
||||
|
||||
Standardize linting: Ensure e2e packages are lintable
|
|
@ -1,4 +1,4 @@
|
|||
const { customerBilling, customerShipping } = require('./shared');
|
||||
const { customerBilling, customerShipping } = require( './shared' );
|
||||
|
||||
/**
|
||||
* A basic order.
|
||||
|
@ -53,10 +53,10 @@ const couponLines = {
|
|||
/**
|
||||
* Builds an example order request.
|
||||
*
|
||||
* @returns {Object} Sample Order payload.
|
||||
* @return {Object} Sample Order payload.
|
||||
*/
|
||||
const getOrderExample = () => {
|
||||
let orderExample = {
|
||||
const orderExample = {
|
||||
id: 0,
|
||||
payment_method: 'cod',
|
||||
payment_method_title: 'Cash on Delivery',
|
||||
|
@ -73,7 +73,7 @@ const getOrderExample = () => {
|
|||
coupon_lines: [ couponLines ],
|
||||
};
|
||||
return orderExample;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
order,
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -3,12 +3,12 @@
|
|||
*
|
||||
* Note that by default the update endpoint is limited to 100 objects to be created, updated, or deleted.
|
||||
*
|
||||
* @param {string} action Batch action. Must be one of: create, update, or delete.
|
||||
* @param {Array} resources A list of resource objects. For the delete action, this will be a list of IDs.
|
||||
* @param {Object} payload The batch payload object. Defaults to an empty object.
|
||||
* @returns {Object} The payload to send to the batch endpoint.
|
||||
* @param {string} action Batch action. Must be one of: create, update, or delete.
|
||||
* @param {Array} resources A list of resource objects. For the delete action, this will be a list of IDs.
|
||||
* @param {Object} payload The batch payload object. Defaults to an empty object.
|
||||
* @return {Object} The payload to send to the batch endpoint.
|
||||
*/
|
||||
const batch = ( action, resources = [], payload = {} ) => {
|
||||
const batch = ( action, resources = [], payload = {} ) => {
|
||||
if ( ! [ 'create', 'update', 'delete' ].includes( action ) ) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ const errorResponse = {
|
|||
code: '',
|
||||
message: '',
|
||||
data: {
|
||||
status: 400
|
||||
status: 400,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
const { customerBilling, customerShipping } = require('./customer');
|
||||
const {
|
||||
batch,
|
||||
getBatchPayloadExample
|
||||
} = require('./batch-update');
|
||||
const { errorResponse } = require('./error-response');
|
||||
const { customerBilling, customerShipping } = require( './customer' );
|
||||
const { batch, getBatchPayloadExample } = require( './batch-update' );
|
||||
const { errorResponse } = require( './error-response' );
|
||||
|
||||
module.exports = {
|
||||
customerBilling,
|
||||
|
|
|
@ -6,7 +6,9 @@
|
|||
* - `flat_rate`
|
||||
* - `local_pickup`
|
||||
*
|
||||
* @returns shipping method object that can serve as a request payload for adding a shipping method to a shipping zone.
|
||||
* @param methodId
|
||||
* @param cost
|
||||
* @return shipping method object that can serve as a request payload for adding a shipping method to a shipping zone.
|
||||
*/
|
||||
const getShippingMethodExample = ( methodId, cost ) => {
|
||||
const shippingMethodExample = {
|
||||
|
@ -15,7 +17,7 @@ const getShippingMethodExample = ( methodId, cost ) => {
|
|||
|
||||
if ( cost !== undefined ) {
|
||||
shippingMethodExample.settings = {
|
||||
cost: cost,
|
||||
cost,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ const shippingZone = {
|
|||
/**
|
||||
* Constructs a default shipping zone object.
|
||||
*
|
||||
* @returns default shipping zone
|
||||
* @return default shipping zone
|
||||
*/
|
||||
const getShippingZoneExample = () => {
|
||||
return shippingZone;
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
const { getRequest, postRequest, putRequest, deleteRequest } = require('../utils/request');
|
||||
const { coupon, shared } = require('../data');
|
||||
const {
|
||||
getRequest,
|
||||
postRequest,
|
||||
putRequest,
|
||||
deleteRequest,
|
||||
} = require( '../utils/request' );
|
||||
const { coupon, shared } = require( '../data' );
|
||||
|
||||
/**
|
||||
* WooCommerce Coupon endpoints.
|
||||
|
@ -17,14 +22,15 @@ const couponsApi = {
|
|||
path: 'coupons',
|
||||
responseCode: 201,
|
||||
payload: coupon,
|
||||
coupon: async ( couponDetails ) => postRequest( 'coupons', couponDetails ),
|
||||
coupon: async ( couponDetails ) =>
|
||||
postRequest( 'coupons', couponDetails ),
|
||||
},
|
||||
retrieve: {
|
||||
name: 'Retrieve a coupon',
|
||||
method: 'GET',
|
||||
path: 'coupons/<id>',
|
||||
responseCode: 200,
|
||||
coupon: async ( couponId ) => getRequest( `coupons/${couponId}` ),
|
||||
coupon: async ( couponId ) => getRequest( `coupons/${ couponId }` ),
|
||||
},
|
||||
listAll: {
|
||||
name: 'List all coupons',
|
||||
|
@ -39,7 +45,8 @@ const couponsApi = {
|
|||
path: 'coupons/<id>',
|
||||
responseCode: 200,
|
||||
payload: coupon,
|
||||
coupon: async ( couponId, couponDetails ) => putRequest( `coupons/${couponId}`, couponDetails ),
|
||||
coupon: async ( couponId, couponDetails ) =>
|
||||
putRequest( `coupons/${ couponId }`, couponDetails ),
|
||||
},
|
||||
delete: {
|
||||
name: 'Delete a coupon',
|
||||
|
@ -47,9 +54,10 @@ const couponsApi = {
|
|||
path: 'coupons/<id>',
|
||||
responseCode: 200,
|
||||
payload: {
|
||||
force: false
|
||||
force: false,
|
||||
},
|
||||
coupon: async ( couponId, deletePermanently ) => deleteRequest( `coupons/${couponId}`, deletePermanently ),
|
||||
coupon: async ( couponId, deletePermanently ) =>
|
||||
deleteRequest( `coupons/${ couponId }`, deletePermanently ),
|
||||
},
|
||||
batch: {
|
||||
name: 'Batch update coupons',
|
||||
|
@ -57,8 +65,9 @@ const couponsApi = {
|
|||
path: 'coupons/batch',
|
||||
responseCode: 200,
|
||||
payload: shared.getBatchPayloadExample( coupon ),
|
||||
coupons: async ( batchUpdatePayload ) => postRequest( `coupons/batch`, batchUpdatePayload ),
|
||||
coupons: async ( batchUpdatePayload ) =>
|
||||
postRequest( `coupons/batch`, batchUpdatePayload ),
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = { couponsApi };
|
||||
module.exports = { couponsApi };
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
const { getRequest, postRequest, putRequest, deleteRequest } = require('../utils/request');
|
||||
const {
|
||||
getRequest,
|
||||
postRequest,
|
||||
putRequest,
|
||||
deleteRequest,
|
||||
} = require( '../utils/request' );
|
||||
|
||||
/**
|
||||
* WooCommerce Products endpoints.
|
||||
|
@ -15,28 +20,31 @@ const productsApi = {
|
|||
method: 'POST',
|
||||
path: 'products',
|
||||
responseCode: 201,
|
||||
product: async ( productDetails ) => postRequest( 'products', productDetails ),
|
||||
product: async ( productDetails ) =>
|
||||
postRequest( 'products', productDetails ),
|
||||
},
|
||||
retrieve: {
|
||||
name: 'Retrieve a product',
|
||||
method: 'GET',
|
||||
path: 'products/<id>',
|
||||
responseCode: 200,
|
||||
product: async ( productId ) => getRequest( `products/${productId}` ),
|
||||
product: async ( productId ) => getRequest( `products/${ productId }` ),
|
||||
},
|
||||
listAll: {
|
||||
name: 'List all products',
|
||||
method: 'GET',
|
||||
path: 'products',
|
||||
responseCode: 200,
|
||||
products: async ( productsQuery = {} ) => getRequest( 'products', productsQuery ),
|
||||
products: async ( productsQuery = {} ) =>
|
||||
getRequest( 'products', productsQuery ),
|
||||
},
|
||||
update: {
|
||||
name: 'Update a product',
|
||||
method: 'PUT',
|
||||
path: 'products/<id>',
|
||||
responseCode: 200,
|
||||
product: async ( productId, productDetails ) => putRequest( `products/${productId}`, productDetails ),
|
||||
product: async ( productId, productDetails ) =>
|
||||
putRequest( `products/${ productId }`, productDetails ),
|
||||
},
|
||||
delete: {
|
||||
name: 'Delete a product',
|
||||
|
@ -44,16 +52,18 @@ const productsApi = {
|
|||
path: 'products/<id>',
|
||||
responseCode: 200,
|
||||
payload: {
|
||||
force: false
|
||||
force: false,
|
||||
},
|
||||
product: async ( productId, deletePermanently ) => deleteRequest( `products/${productId}`, deletePermanently ),
|
||||
product: async ( productId, deletePermanently ) =>
|
||||
deleteRequest( `products/${ productId }`, deletePermanently ),
|
||||
},
|
||||
batch: {
|
||||
name: 'Batch update products',
|
||||
method: 'POST',
|
||||
path: 'products/batch',
|
||||
responseCode: 200,
|
||||
products: async ( batchUpdatePayload ) => postRequest( `products/batch`, batchUpdatePayload ),
|
||||
products: async ( batchUpdatePayload ) =>
|
||||
postRequest( `products/batch`, batchUpdatePayload ),
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -55,5 +55,5 @@ const refundsApi = {
|
|||
};
|
||||
|
||||
module.exports = {
|
||||
refundsApi: refundsApi,
|
||||
refundsApi,
|
||||
};
|
||||
|
|
|
@ -9,7 +9,9 @@
|
|||
"test:api": "jest --group=api",
|
||||
"test:hello": "jest --group=hello",
|
||||
"make:collection": "node utils/api-collection/build-collection.js",
|
||||
"report": "allure generate --clean && allure serve"
|
||||
"report": "allure generate --clean && allure serve",
|
||||
"lint": "eslint data endpoints tests utils --ext=js,ts,tsx",
|
||||
"lint:fix": "eslint data endpoints tests utils --ext=js,ts,tsx --fix"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -29,6 +31,10 @@
|
|||
"postman-collection": "^4.1.0",
|
||||
"supertest": "^6.1.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@woocommerce/eslint-plugin": "workspace:*",
|
||||
"eslint": "^8.12.0"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const { getRequest } = require('../../utils/request');
|
||||
const { getRequest } = require( '../../utils/request' );
|
||||
|
||||
/**
|
||||
* Tests to verify connection to the API.
|
||||
|
@ -6,16 +6,14 @@ const { getRequest } = require('../../utils/request');
|
|||
* @group hello
|
||||
*
|
||||
*/
|
||||
describe('Test API connectivity', () => {
|
||||
|
||||
it('can access a non-authenticated endpoint', async () => {
|
||||
describe( 'Test API connectivity', () => {
|
||||
it( 'can access a non-authenticated endpoint', async () => {
|
||||
const result = await getRequest( '' );
|
||||
expect( result.statusCode ).toEqual( 200 );
|
||||
});
|
||||
} );
|
||||
|
||||
it('can access an authenticated endpoint', async () => {
|
||||
it( 'can access an authenticated endpoint', async () => {
|
||||
const result = await getRequest( 'system_status' );
|
||||
expect( result.statusCode ).toEqual( 200 );
|
||||
});
|
||||
|
||||
});
|
||||
} );
|
||||
} );
|
||||
|
|
|
@ -341,39 +341,36 @@ describe( 'Orders API tests', () => {
|
|||
};
|
||||
|
||||
const verifyOrderPrecision = ( order, dp ) => {
|
||||
expectPrecisionToMatch( order[ 'discount_total' ], dp );
|
||||
expectPrecisionToMatch( order[ 'discount_tax' ], dp );
|
||||
expectPrecisionToMatch( order[ 'shipping_total' ], dp );
|
||||
expectPrecisionToMatch( order[ 'shipping_tax' ], dp );
|
||||
expectPrecisionToMatch( order[ 'cart_tax' ], dp );
|
||||
expectPrecisionToMatch( order[ 'total' ], dp );
|
||||
expectPrecisionToMatch( order[ 'total_tax' ], dp );
|
||||
expectPrecisionToMatch( order.discount_total, dp );
|
||||
expectPrecisionToMatch( order.discount_tax, dp );
|
||||
expectPrecisionToMatch( order.shipping_total, dp );
|
||||
expectPrecisionToMatch( order.shipping_tax, dp );
|
||||
expectPrecisionToMatch( order.cart_tax, dp );
|
||||
expectPrecisionToMatch( order.total, dp );
|
||||
expectPrecisionToMatch( order.total_tax, dp );
|
||||
|
||||
order[ 'line_items' ].forEach( ( lineItem ) => {
|
||||
expectPrecisionToMatch( lineItem[ 'total' ], dp );
|
||||
expectPrecisionToMatch( lineItem[ 'total_tax' ], dp );
|
||||
order.line_items.forEach( ( lineItem ) => {
|
||||
expectPrecisionToMatch( lineItem.total, dp );
|
||||
expectPrecisionToMatch( lineItem.total_tax, dp );
|
||||
} );
|
||||
|
||||
order[ 'tax_lines' ].forEach( ( taxLine ) => {
|
||||
expectPrecisionToMatch( taxLine[ 'tax_total' ], dp );
|
||||
expectPrecisionToMatch(
|
||||
taxLine[ 'shipping_tax_total' ],
|
||||
dp
|
||||
);
|
||||
order.tax_lines.forEach( ( taxLine ) => {
|
||||
expectPrecisionToMatch( taxLine.tax_total, dp );
|
||||
expectPrecisionToMatch( taxLine.shipping_tax_total, dp );
|
||||
} );
|
||||
|
||||
order[ 'shipping_lines' ].forEach( ( shippingLine ) => {
|
||||
expectPrecisionToMatch( shippingLine[ 'total' ], dp );
|
||||
expectPrecisionToMatch( shippingLine[ 'total_tax' ], dp );
|
||||
order.shipping_lines.forEach( ( shippingLine ) => {
|
||||
expectPrecisionToMatch( shippingLine.total, dp );
|
||||
expectPrecisionToMatch( shippingLine.total_tax, dp );
|
||||
} );
|
||||
|
||||
order[ 'fee_lines' ].forEach( ( feeLine ) => {
|
||||
expectPrecisionToMatch( feeLine[ 'total' ], dp );
|
||||
expectPrecisionToMatch( feeLine[ 'total_tax' ], dp );
|
||||
order.fee_lines.forEach( ( feeLine ) => {
|
||||
expectPrecisionToMatch( feeLine.total, dp );
|
||||
expectPrecisionToMatch( feeLine.total_tax, dp );
|
||||
} );
|
||||
|
||||
order[ 'refunds' ].forEach( ( refund ) => {
|
||||
expectPrecisionToMatch( refund[ 'total' ], dp );
|
||||
order.refunds.forEach( ( refund ) => {
|
||||
expectPrecisionToMatch( refund.total, dp );
|
||||
} );
|
||||
};
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,12 +1,7 @@
|
|||
const fs = require('fs');
|
||||
const { Collection, ItemGroup, Item } = require('postman-collection');
|
||||
require('dotenv').config();
|
||||
const {
|
||||
BASE_URL,
|
||||
USER_KEY,
|
||||
USER_SECRET,
|
||||
USE_INDEX_PERMALINKS
|
||||
} = process.env;
|
||||
const fs = require( 'fs' );
|
||||
const { Collection, ItemGroup, Item } = require( 'postman-collection' );
|
||||
require( 'dotenv' ).config();
|
||||
const { BASE_URL, USER_KEY, USER_SECRET, USE_INDEX_PERMALINKS } = process.env;
|
||||
|
||||
/**
|
||||
* Build a Postman collection using the API testing objects.
|
||||
|
@ -17,10 +12,10 @@ const {
|
|||
|
||||
// Set up our empty collection
|
||||
if ( typeof USER_KEY === 'undefined' ) {
|
||||
console.log('No USER_KEY was defined.');
|
||||
console.log( 'No USER_KEY was defined.' );
|
||||
}
|
||||
if ( typeof USER_SECRET === 'undefined' ) {
|
||||
console.log('No USER_SECRET was defined.');
|
||||
console.log( 'No USER_SECRET was defined.' );
|
||||
}
|
||||
|
||||
const postmanCollection = new Collection( {
|
||||
|
@ -30,74 +25,72 @@ const postmanCollection = new Collection( {
|
|||
{
|
||||
key: 'username',
|
||||
value: USER_KEY,
|
||||
type: 'string'
|
||||
type: 'string',
|
||||
},
|
||||
{
|
||||
key: 'password',
|
||||
value: USER_SECRET,
|
||||
type: 'string'
|
||||
type: 'string',
|
||||
},
|
||||
]
|
||||
],
|
||||
},
|
||||
info: {
|
||||
name: 'WooCommerce API - v3'
|
||||
name: 'WooCommerce API - v3',
|
||||
},
|
||||
} );
|
||||
|
||||
// Get the API url
|
||||
if ( typeof BASE_URL === 'undefined' ) {
|
||||
console.log('No BASE_URL was defined.');
|
||||
console.log( 'No BASE_URL was defined.' );
|
||||
}
|
||||
|
||||
// Update the API path if the `USE_INDEX_PERMALINKS` flag is set
|
||||
const useIndexPermalinks = ( USE_INDEX_PERMALINKS === 'true' );
|
||||
let apiPath = `${BASE_URL}/?rest_route=/wc/v3`;
|
||||
const useIndexPermalinks = USE_INDEX_PERMALINKS === 'true';
|
||||
let apiPath = `${ BASE_URL }/?rest_route=/wc/v3`;
|
||||
if ( useIndexPermalinks ) {
|
||||
apiPath = `${BASE_URL}/wp-json/wc/v3`;
|
||||
apiPath = `${ BASE_URL }/wp-json/wc/v3`;
|
||||
}
|
||||
// Set this here for use in `request.js`
|
||||
global.API_PATH = `${apiPath}/`;
|
||||
global.API_PATH = `${ apiPath }/`;
|
||||
|
||||
// Add the API path has a collection variable
|
||||
postmanCollection.variables.add({
|
||||
postmanCollection.variables.add( {
|
||||
id: 'apiBaseUrl',
|
||||
value: apiPath,
|
||||
type: 'string',
|
||||
});
|
||||
} );
|
||||
|
||||
// Get the API request data
|
||||
const resources = require('../../endpoints');
|
||||
const resources = require( '../../endpoints' );
|
||||
resourceKeys = Object.keys( resources );
|
||||
|
||||
// Add the requests to folders in the collection
|
||||
for ( const key in resources ) {
|
||||
|
||||
const folder = new ItemGroup( {
|
||||
name: resources[key].name,
|
||||
items: []
|
||||
name: resources[ key ].name,
|
||||
items: [],
|
||||
} );
|
||||
|
||||
for ( const endpoint in resources[key] ) {
|
||||
|
||||
let api = resources[key][endpoint];
|
||||
for ( const endpoint in resources[ key ] ) {
|
||||
const api = resources[ key ][ endpoint ];
|
||||
|
||||
// If there is no name defined, continue
|
||||
if ( !api.name ) {
|
||||
if ( ! api.name ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const request = new Item( {
|
||||
name: api.name,
|
||||
request: {
|
||||
url: `{{apiBaseUrl}}/${api.path}`,
|
||||
method: api.method,
|
||||
body: {
|
||||
mode: 'raw',
|
||||
raw: JSON.stringify( api.payload ),
|
||||
options: {
|
||||
raw: { language: 'json' }
|
||||
}
|
||||
},
|
||||
url: `{{apiBaseUrl}}/${ api.path }`,
|
||||
method: api.method,
|
||||
body: {
|
||||
mode: 'raw',
|
||||
raw: JSON.stringify( api.payload ),
|
||||
options: {
|
||||
raw: { language: 'json' },
|
||||
},
|
||||
},
|
||||
},
|
||||
} );
|
||||
folder.items.add( request );
|
||||
|
@ -110,9 +103,13 @@ for ( const key in resources ) {
|
|||
const collectionJSON = postmanCollection.toJSON();
|
||||
|
||||
// Create a colleciton.json file. It can be imported to postman
|
||||
fs.writeFile('./collection.json', JSON.stringify( collectionJSON ), ( err ) => {
|
||||
if ( err ) {
|
||||
console.log( err );
|
||||
fs.writeFile(
|
||||
'./collection.json',
|
||||
JSON.stringify( collectionJSON ),
|
||||
( err ) => {
|
||||
if ( err ) {
|
||||
console.log( err );
|
||||
}
|
||||
console.log( 'File saved!' );
|
||||
}
|
||||
console.log('File saved!');
|
||||
});
|
||||
);
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
require('dotenv').config();
|
||||
require( 'dotenv' ).config();
|
||||
const { USER_KEY, USER_SECRET } = process.env;
|
||||
const request = require('supertest')( API_PATH );
|
||||
const request = require( 'supertest' )( API_PATH );
|
||||
|
||||
/**
|
||||
* Make a GET request.
|
||||
*
|
||||
* @param {string} requestPath The path of the request.
|
||||
* @param {object} queryString Optional. An object of one or more `key: value` query string parameters.
|
||||
* @returns {Response}
|
||||
* @param {Object} queryString Optional. An object of one or more `key: value` query string parameters.
|
||||
* @return {Response}
|
||||
*/
|
||||
const getRequest = async ( requestPath, queryString = {} ) => {
|
||||
const response = await request
|
||||
|
@ -22,8 +22,8 @@ const getRequest = async ( requestPath, queryString = {} ) => {
|
|||
* Make a POST request.
|
||||
*
|
||||
* @param {string} requestPath The path of the request.
|
||||
* @param {object} requestBody The body of the request to submit.
|
||||
* @returns {Response}
|
||||
* @param {Object} requestBody The body of the request to submit.
|
||||
* @return {Response}
|
||||
*/
|
||||
const postRequest = async ( requestPath, requestBody ) => {
|
||||
const response = await request
|
||||
|
@ -38,8 +38,8 @@ const postRequest = async ( requestPath, requestBody ) => {
|
|||
* Make a PUT request.
|
||||
*
|
||||
* @param {string} requestPath The path of the request.
|
||||
* @param {object} requestBody The body of the request to submit.
|
||||
* @returns {Request}
|
||||
* @param {Object} requestBody The body of the request to submit.
|
||||
* @return {Request}
|
||||
*/
|
||||
const putRequest = async ( requestPath, requestBody ) => {
|
||||
const response = await request
|
||||
|
@ -53,12 +53,12 @@ const putRequest = async ( requestPath, requestBody ) => {
|
|||
/**
|
||||
* Make a DELETE request, optionally deleting the resource permanently.
|
||||
*
|
||||
* @param {string} requestPath The path of the request.
|
||||
* @param {string} requestPath The path of the request.
|
||||
* @param {boolean} deletePermanently Flag to permanently delete the resource.
|
||||
* @returns {Response}
|
||||
* @return {Response}
|
||||
*/
|
||||
const deleteRequest = async ( requestPath, deletePermanently = false ) => {
|
||||
const requestBody = deletePermanently ? { force: true } : {}
|
||||
const requestBody = deletePermanently ? { force: true } : {};
|
||||
const response = await request
|
||||
.delete( requestPath )
|
||||
.set( 'Accept', 'application/json' )
|
||||
|
@ -67,4 +67,4 @@ const deleteRequest = async ( requestPath, deletePermanently = false ) => {
|
|||
return response;
|
||||
};
|
||||
|
||||
module.exports = { getRequest, postRequest, putRequest, deleteRequest }
|
||||
module.exports = { getRequest, postRequest, putRequest, deleteRequest };
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
module.exports = {
|
||||
extends: [ 'plugin:@woocommerce/eslint-plugin/recommended' ],
|
||||
root: true,
|
||||
};
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: dev
|
||||
|
||||
Standardize linting: Ensure e2e packages are lintable
|
|
@ -1,26 +1,37 @@
|
|||
{
|
||||
"name": "@woocommerce/e2e-builds",
|
||||
"version": "0.1.0",
|
||||
"description": "Utility build files for e2e packages",
|
||||
"private": "true",
|
||||
"main": "build.js",
|
||||
"bin": {
|
||||
"e2e-builds": "./build.js"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/woocommerce/woocommerce.git"
|
||||
},
|
||||
"license": "GPL-3.0+",
|
||||
"bugs": {
|
||||
"url": "https://github.com/woocommerce/woocommerce/issues"
|
||||
},
|
||||
"homepage": "https://github.com/woocommerce/woocommerce#readme",
|
||||
"devDependencies": {
|
||||
"@babel/core": "7.12.9",
|
||||
"chalk": "^4.1.2",
|
||||
"glob": "^7.2.0",
|
||||
"mkdirp": "^1.0.4",
|
||||
"lodash": "^4.17.21"
|
||||
"name": "@woocommerce/e2e-builds",
|
||||
"version": "0.1.0",
|
||||
"description": "Utility build files for e2e packages",
|
||||
"private": "true",
|
||||
"main": "build.js",
|
||||
"bin": {
|
||||
"e2e-builds": "./build.js"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/woocommerce/woocommerce.git"
|
||||
},
|
||||
"license": "GPL-3.0+",
|
||||
"bugs": {
|
||||
"url": "https://github.com/woocommerce/woocommerce/issues"
|
||||
},
|
||||
"homepage": "https://github.com/woocommerce/woocommerce#readme",
|
||||
"scripts": {
|
||||
"lint": "eslint build.js",
|
||||
"lint:fix": "eslint build.js --fix"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "7.12.9",
|
||||
"@woocommerce/eslint-plugin": "workspace:*",
|
||||
"chalk": "^4.1.2",
|
||||
"eslint": "^8.12.0",
|
||||
"glob": "^7.2.0",
|
||||
"mkdirp": "^1.0.4",
|
||||
"lodash": "^4.17.21"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.(t|j)s?(x)": [
|
||||
"pnpm lint:fix"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
module.exports = {
|
||||
extends: [ 'plugin:@woocommerce/eslint-plugin/recommended' ],
|
||||
};
|
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: dev
|
||||
|
||||
Standardize linting: Ensure e2e packages are lintable
|
|
@ -24,18 +24,20 @@
|
|||
"config": "3.3.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/cli": "7.12.8",
|
||||
"@babel/core": "7.12.9",
|
||||
"@babel/plugin-proposal-async-generator-functions": "^7.16.4",
|
||||
"@babel/plugin-proposal-object-rest-spread": "^7.16.0",
|
||||
"@babel/plugin-transform-react-jsx": "^7.16.0",
|
||||
"@babel/plugin-transform-runtime": "^7.16.4",
|
||||
"@babel/polyfill": "7.12.1",
|
||||
"@babel/preset-env": "7.12.7",
|
||||
"@woocommerce/e2e-builds": "workspace:*",
|
||||
"@wordpress/babel-plugin-import-jsx-pragma": "1.1.3",
|
||||
"@wordpress/babel-preset-default": "3.0.2",
|
||||
"@wordpress/browserslist-config": "^4.1.0"
|
||||
"@babel/cli": "7.12.8",
|
||||
"@babel/core": "7.12.9",
|
||||
"@babel/plugin-proposal-async-generator-functions": "^7.16.4",
|
||||
"@babel/plugin-proposal-object-rest-spread": "^7.16.0",
|
||||
"@babel/plugin-transform-react-jsx": "^7.16.0",
|
||||
"@babel/plugin-transform-runtime": "^7.16.4",
|
||||
"@babel/polyfill": "7.12.1",
|
||||
"@babel/preset-env": "7.12.7",
|
||||
"@woocommerce/e2e-builds": "workspace:*",
|
||||
"@woocommerce/eslint-plugin": "workspace:*",
|
||||
"@wordpress/babel-plugin-import-jsx-pragma": "1.1.3",
|
||||
"@wordpress/babel-preset-default": "3.0.2",
|
||||
"@wordpress/browserslist-config": "^4.1.0",
|
||||
"eslint": "^8.12.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@woocommerce/api": "^0.2.0",
|
||||
|
@ -46,14 +48,16 @@
|
|||
},
|
||||
"scripts": {
|
||||
"postinstall": "composer install",
|
||||
"prepack": "pnpm run build",
|
||||
"prepare": "pnpm run build",
|
||||
"clean": "rm -rf ./build ./build-module",
|
||||
"compile": "e2e-builds",
|
||||
"build": "./bin/build.sh && pnpm run clean && pnpm run compile"
|
||||
"build": "./bin/build.sh && pnpm run clean && pnpm run compile",
|
||||
"lint": "eslint src --ext=js,ts,tsx",
|
||||
"lint:fix": "eslint src --ext=js,ts,tsx --fix"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.(t|j)s?(x)": [
|
||||
"eslint --fix"
|
||||
"pnpm lint:fix"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,35 +6,35 @@ const { merchant } = require( '@woocommerce/e2e-utils' );
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
const {
|
||||
it,
|
||||
describe,
|
||||
beforeAll,
|
||||
} = require( '@jest/globals' );
|
||||
const { it, describe, beforeAll } = require( '@jest/globals' );
|
||||
import deprecated from '@wordpress/deprecated';
|
||||
|
||||
const runActivationTest = () => {
|
||||
describe('Store owner can login and make sure WooCommerce is activated', () => {
|
||||
beforeAll(async () => {
|
||||
describe( 'Store owner can login and make sure WooCommerce is activated', () => {
|
||||
beforeAll( async () => {
|
||||
await merchant.login();
|
||||
});
|
||||
} );
|
||||
|
||||
it('can make sure WooCommerce is activated. If not, activate it', async () => {
|
||||
it( 'can make sure WooCommerce is activated. If not, activate it', async () => {
|
||||
deprecated( 'runActivationTest', {
|
||||
alternative: '@woocommerce/admin-e2e-tests `testAdminBasicSetup()`',
|
||||
});
|
||||
alternative:
|
||||
'@woocommerce/admin-e2e-tests `testAdminBasicSetup()`',
|
||||
} );
|
||||
|
||||
const slug = 'woocommerce';
|
||||
await merchant.openPlugins();
|
||||
const disableLink = await page.$(`tr[data-slug="${slug}"] .deactivate a`);
|
||||
if (disableLink) {
|
||||
const disableLink = await page.$(
|
||||
`tr[data-slug="${ slug }"] .deactivate a`
|
||||
);
|
||||
if ( disableLink ) {
|
||||
return;
|
||||
}
|
||||
await page.click(`tr[data-slug="${slug}"] .activate a`);
|
||||
await page.waitForSelector(`tr[data-slug="${slug}"] .deactivate a`);
|
||||
});
|
||||
|
||||
});
|
||||
await page.click( `tr[data-slug="${ slug }"] .activate a` );
|
||||
await page.waitForSelector(
|
||||
`tr[data-slug="${ slug }"] .deactivate a`
|
||||
);
|
||||
} );
|
||||
} );
|
||||
};
|
||||
|
||||
module.exports = runActivationTest;
|
||||
|
|
|
@ -14,84 +14,91 @@ const {
|
|||
*/
|
||||
const config = require( 'config' );
|
||||
import deprecated from '@wordpress/deprecated';
|
||||
const {
|
||||
it,
|
||||
describe,
|
||||
} = require( '@jest/globals' );
|
||||
const { it, describe } = require( '@jest/globals' );
|
||||
|
||||
const shippingZoneNameUS = config.get( 'addresses.customer.shipping.country' );
|
||||
|
||||
const runOnboardingFlowTest = () => {
|
||||
describe('Store owner can go through store Onboarding', () => {
|
||||
beforeAll(async () => {
|
||||
describe( 'Store owner can go through store Onboarding', () => {
|
||||
beforeAll( async () => {
|
||||
await merchant.login();
|
||||
});
|
||||
} );
|
||||
|
||||
if ( IS_RETEST_MODE ) {
|
||||
it('can reset onboarding to default settings', async () => {
|
||||
it( 'can reset onboarding to default settings', async () => {
|
||||
await withRestApi.resetOnboarding();
|
||||
});
|
||||
} );
|
||||
|
||||
it('can reset shipping zones to default settings', async () => {
|
||||
it( 'can reset shipping zones to default settings', async () => {
|
||||
await withRestApi.deleteAllShippingZones();
|
||||
});
|
||||
} );
|
||||
|
||||
it('can reset shipping classes', async () => {
|
||||
it( 'can reset shipping classes', async () => {
|
||||
await withRestApi.deleteAllShippingClasses();
|
||||
})
|
||||
} );
|
||||
|
||||
it('can reset to default settings', async () => {
|
||||
await withRestApi.resetSettingsGroupToDefault('general');
|
||||
await withRestApi.resetSettingsGroupToDefault('products');
|
||||
await withRestApi.resetSettingsGroupToDefault('tax');
|
||||
});
|
||||
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 () => {
|
||||
it( 'can start and complete onboarding when visiting the site for the first time.', async () => {
|
||||
deprecated( 'runOnboardingFlowTest', {
|
||||
alternative: '@woocommerce/admin-e2e-tests `testAdminOnboardingWizard()`',
|
||||
});
|
||||
alternative:
|
||||
'@woocommerce/admin-e2e-tests `testAdminOnboardingWizard()`',
|
||||
} );
|
||||
await completeOnboardingWizard();
|
||||
});
|
||||
});
|
||||
} );
|
||||
} );
|
||||
};
|
||||
|
||||
const runTaskListTest = () => {
|
||||
describe('Store owner can go through setup Task List', () => {
|
||||
beforeAll(async () => {
|
||||
describe( 'Store owner can go through setup Task List', () => {
|
||||
beforeAll( async () => {
|
||||
await merchant.login();
|
||||
});
|
||||
} );
|
||||
|
||||
it('can setup shipping', async () => {
|
||||
it( 'can setup shipping', async () => {
|
||||
deprecated( 'runTaskListTest', {
|
||||
alternative: '@woocommerce/admin-e2e-tests `testAdminHomescreenTasklist()`',
|
||||
});
|
||||
await page.evaluate(() => {
|
||||
document.querySelector('.woocommerce-list__item-title').scrollIntoView();
|
||||
});
|
||||
alternative:
|
||||
'@woocommerce/admin-e2e-tests `testAdminHomescreenTasklist()`',
|
||||
} );
|
||||
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 );
|
||||
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")]' );
|
||||
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);
|
||||
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);
|
||||
await page.click( 'button.is-primary' );
|
||||
await page.waitFor( 3000 );
|
||||
} else {
|
||||
await merchant.openNewShipping();
|
||||
await addShippingZoneAndMethod(shippingZoneNameUS);
|
||||
await addShippingZoneAndMethod( shippingZoneNameUS );
|
||||
}
|
||||
});
|
||||
});
|
||||
} );
|
||||
} );
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
|
|
|
@ -2,10 +2,7 @@
|
|||
* External dependencies
|
||||
*/
|
||||
const { HTTPClientFactory } = require( '@woocommerce/api' );
|
||||
const {
|
||||
it,
|
||||
describe,
|
||||
} = require( '@jest/globals' );
|
||||
const { it, describe } = require( '@jest/globals' );
|
||||
import deprecated from '@wordpress/deprecated';
|
||||
|
||||
/**
|
||||
|
@ -17,64 +14,85 @@ const {
|
|||
setCheckbox,
|
||||
settingsPageSaveChanges,
|
||||
verifyCheckboxIsSet,
|
||||
verifyValueOfInputField
|
||||
verifyValueOfInputField,
|
||||
} = require( '@woocommerce/e2e-utils' );
|
||||
|
||||
const {
|
||||
getTestConfig,
|
||||
waitAndClick
|
||||
waitAndClick,
|
||||
} = require( '@woocommerce/e2e-environment' );
|
||||
|
||||
const runInitialStoreSettingsTest = () => {
|
||||
describe('Store owner can finish initial store setup', () => {
|
||||
beforeAll(async () => {
|
||||
describe( 'Store owner can finish initial store setup', () => {
|
||||
beforeAll( async () => {
|
||||
await merchant.login();
|
||||
});
|
||||
} );
|
||||
|
||||
it('can enable tax rates and calculations', async () => {
|
||||
it( 'can enable tax rates and calculations', async () => {
|
||||
deprecated( 'runInitialStoreSettingsTest', {
|
||||
alternative: '@woocommerce/admin-e2e-tests `testAdminBasicSetup()`',
|
||||
});
|
||||
alternative:
|
||||
'@woocommerce/admin-e2e-tests `testAdminBasicSetup()`',
|
||||
} );
|
||||
// Go to general settings page
|
||||
await merchant.openSettings('general');
|
||||
await merchant.openSettings( 'general' );
|
||||
|
||||
// Make sure the general tab is active
|
||||
await expect(page).toMatchElement('a.nav-tab-active', {text: 'General'});
|
||||
await expect( page ).toMatchElement( 'a.nav-tab-active', {
|
||||
text: 'General',
|
||||
} );
|
||||
|
||||
// Enable tax rates and calculations
|
||||
await setCheckbox('#woocommerce_calc_taxes');
|
||||
await setCheckbox( '#woocommerce_calc_taxes' );
|
||||
|
||||
await settingsPageSaveChanges();
|
||||
|
||||
// Verify that settings have been saved
|
||||
await Promise.all([
|
||||
expect(page).toMatchElement('#message', {text: 'Your settings have been saved.'}),
|
||||
verifyCheckboxIsSet('#woocommerce_calc_taxes'),
|
||||
]);
|
||||
});
|
||||
await Promise.all( [
|
||||
expect( page ).toMatchElement( '#message', {
|
||||
text: 'Your settings have been saved.',
|
||||
} ),
|
||||
verifyCheckboxIsSet( '#woocommerce_calc_taxes' ),
|
||||
] );
|
||||
} );
|
||||
|
||||
it('can configure permalink settings', async () => {
|
||||
it( 'can configure permalink settings', async () => {
|
||||
// Go to Permalink Settings page
|
||||
await merchant.openPermalinkSettings();
|
||||
|
||||
// Select "Post name" option in common settings section
|
||||
await page.click('input[value="/%postname%/"]', {text: ' Post name'});
|
||||
await page.click( 'input[value="/%postname%/"]', {
|
||||
text: ' Post name',
|
||||
} );
|
||||
|
||||
// Select "Custom base" in product permalinks section
|
||||
await waitAndClick( page, '#woocommerce_custom_selection' );
|
||||
|
||||
// Fill custom base slug to use
|
||||
await expect(page).toFill('#woocommerce_permalink_structure', '/product/');
|
||||
await expect( page ).toFill(
|
||||
'#woocommerce_permalink_structure',
|
||||
'/product/'
|
||||
);
|
||||
|
||||
await permalinkSettingsPageSaveChanges();
|
||||
|
||||
// Verify that settings have been saved
|
||||
await Promise.all([
|
||||
expect(page).toMatchElement('#setting-error-settings_updated', {text: 'Permalink structure updated.'}),
|
||||
verifyValueOfInputField('#permalink_structure', '/%postname%/'),
|
||||
verifyValueOfInputField('#woocommerce_permalink_structure', '/product/'),
|
||||
]);
|
||||
});
|
||||
await Promise.all( [
|
||||
expect( page ).toMatchElement(
|
||||
'#setting-error-settings_updated',
|
||||
{
|
||||
text: 'Permalink structure updated.',
|
||||
}
|
||||
),
|
||||
verifyValueOfInputField(
|
||||
'#permalink_structure',
|
||||
'/%postname%/'
|
||||
),
|
||||
verifyValueOfInputField(
|
||||
'#woocommerce_permalink_structure',
|
||||
'/product/'
|
||||
),
|
||||
] );
|
||||
} );
|
||||
|
||||
it( 'can use api with pretty permalinks', async () => {
|
||||
const testConfig = getTestConfig();
|
||||
|
@ -86,8 +104,8 @@ const runInitialStoreSettingsTest = () => {
|
|||
|
||||
const response = await client.get( '/wc/v3/products' );
|
||||
expect( response.status ).toBe( 200 );
|
||||
});
|
||||
});
|
||||
} );
|
||||
} );
|
||||
};
|
||||
|
||||
module.exports = runInitialStoreSettingsTest;
|
||||
|
|
|
@ -2,59 +2,64 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
const { HTTPClientFactory, VariableProduct, ProductVariation } = require( '@woocommerce/api' );
|
||||
const {
|
||||
HTTPClientFactory,
|
||||
VariableProduct,
|
||||
ProductVariation,
|
||||
} = require( '@woocommerce/api' );
|
||||
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
const config = require( 'config' );
|
||||
const {
|
||||
it,
|
||||
describe,
|
||||
beforeAll,
|
||||
} = require( '@jest/globals' );
|
||||
const { it, describe, beforeAll } = require( '@jest/globals' );
|
||||
|
||||
/**
|
||||
* Create a variable product and retrieve via the API.
|
||||
*/
|
||||
const runVariableProductAPITest = () => {
|
||||
describe('REST API > Variable Product', () => {
|
||||
describe( 'REST API > Variable Product', () => {
|
||||
let client;
|
||||
let defaultVariableProduct;
|
||||
let defaultVariations;
|
||||
let baseVariableProduct;
|
||||
let product;
|
||||
let variations = [];
|
||||
const variations = [];
|
||||
let productRepository;
|
||||
let variationRepository;
|
||||
|
||||
beforeAll(async () => {
|
||||
defaultVariableProduct = config.get('products.variable');
|
||||
defaultVariations = config.get('products.variations');
|
||||
const admin = config.get('users.admin');
|
||||
const url = config.get('url');
|
||||
beforeAll( async () => {
|
||||
defaultVariableProduct = config.get( 'products.variable' );
|
||||
defaultVariations = config.get( 'products.variations' );
|
||||
const admin = config.get( 'users.admin' );
|
||||
const url = config.get( 'url' );
|
||||
|
||||
client = HTTPClientFactory.build(url)
|
||||
.withBasicAuth(admin.username, admin.password)
|
||||
client = HTTPClientFactory.build( url )
|
||||
.withBasicAuth( admin.username, admin.password )
|
||||
.withIndexPermalinks()
|
||||
.create();
|
||||
});
|
||||
} );
|
||||
|
||||
it('can create a variable product', async () => {
|
||||
productRepository = VariableProduct.restRepository(client);
|
||||
it( 'can create a variable product', async () => {
|
||||
productRepository = VariableProduct.restRepository( client );
|
||||
|
||||
// Check properties of product in the create product response.
|
||||
product = await productRepository.create(defaultVariableProduct);
|
||||
expect(product).toEqual(expect.objectContaining(defaultVariableProduct));
|
||||
});
|
||||
product = await productRepository.create( defaultVariableProduct );
|
||||
expect( product ).toEqual(
|
||||
expect.objectContaining( defaultVariableProduct )
|
||||
);
|
||||
} );
|
||||
|
||||
it('can add variations', async () => {
|
||||
variationRepository = ProductVariation.restRepository(client);
|
||||
for (let v = 0; v < defaultVariations.length; v++) {
|
||||
const variation = await variationRepository.create(product.id, defaultVariations[v]);
|
||||
it( 'can add variations', async () => {
|
||||
variationRepository = ProductVariation.restRepository( client );
|
||||
for ( let v = 0; v < defaultVariations.length; v++ ) {
|
||||
const variation = await variationRepository.create(
|
||||
product.id,
|
||||
defaultVariations[ v ]
|
||||
);
|
||||
// Test that variation id is a number.
|
||||
expect(variation.id).toBeGreaterThan(0);
|
||||
variations.push(variation.id);
|
||||
expect( variation.id ).toBeGreaterThan( 0 );
|
||||
variations.push( variation.id );
|
||||
}
|
||||
|
||||
baseVariableProduct = {
|
||||
|
@ -62,31 +67,36 @@ const runVariableProductAPITest = () => {
|
|||
...defaultVariableProduct,
|
||||
variations,
|
||||
};
|
||||
});
|
||||
} );
|
||||
|
||||
it('can retrieve a transformed variable product', async () => {
|
||||
it( 'can retrieve a transformed variable product', async () => {
|
||||
// Read product via the repository.
|
||||
const transformed = await productRepository.read(product.id);
|
||||
expect(transformed).toEqual(expect.objectContaining(baseVariableProduct));
|
||||
});
|
||||
const transformed = await productRepository.read( product.id );
|
||||
expect( transformed ).toEqual(
|
||||
expect.objectContaining( baseVariableProduct )
|
||||
);
|
||||
} );
|
||||
|
||||
it('can retrieve transformed product variations', async () => {
|
||||
it( 'can retrieve transformed product variations', async () => {
|
||||
// Read variations via the repository.
|
||||
const transformed = await variationRepository.list(product.id);
|
||||
expect(transformed).toHaveLength(defaultVariations.length);
|
||||
});
|
||||
const transformed = await variationRepository.list( product.id );
|
||||
expect( transformed ).toHaveLength( defaultVariations.length );
|
||||
} );
|
||||
|
||||
it('can delete a variation', async () => {
|
||||
it( 'can delete a variation', async () => {
|
||||
const variationId = baseVariableProduct.variations.pop();
|
||||
const status = variationRepository.delete(product.id, variationId);
|
||||
expect(status).toBeTruthy();
|
||||
});
|
||||
const status = variationRepository.delete(
|
||||
product.id,
|
||||
variationId
|
||||
);
|
||||
expect( status ).toBeTruthy();
|
||||
} );
|
||||
|
||||
it('can delete a variable product', async () => {
|
||||
const status = productRepository.delete(product.id);
|
||||
expect(status).toBeTruthy();
|
||||
});
|
||||
});
|
||||
}
|
||||
it( 'can delete a variable product', async () => {
|
||||
const status = productRepository.delete( product.id );
|
||||
expect( status ).toBeTruthy();
|
||||
} );
|
||||
} );
|
||||
};
|
||||
|
||||
module.exports = runVariableProductAPITest;
|
||||
|
|
|
@ -5,14 +5,17 @@
|
|||
|
||||
// Setup and onboarding tests
|
||||
const runActivationTest = require( './activate-and-setup/activate.test' );
|
||||
const { runOnboardingFlowTest, runTaskListTest } = require( './activate-and-setup/onboarding-tasklist.test' );
|
||||
const {
|
||||
runOnboardingFlowTest,
|
||||
runTaskListTest,
|
||||
} = require( './activate-and-setup/onboarding-tasklist.test' );
|
||||
const runInitialStoreSettingsTest = require( './activate-and-setup/setup.test' );
|
||||
|
||||
// Shopper tests
|
||||
const runProductBrowseSearchSortTest = require( './shopper/front-end-product-browse-search-sort.test' );
|
||||
const runCartApplyCouponsTest = require( './shopper/front-end-cart-coupons.test');
|
||||
const runCartApplyCouponsTest = require( './shopper/front-end-cart-coupons.test' );
|
||||
const runCartPageTest = require( './shopper/front-end-cart.test' );
|
||||
const runCheckoutApplyCouponsTest = require( './shopper/front-end-checkout-coupons.test');
|
||||
const runCheckoutApplyCouponsTest = require( './shopper/front-end-checkout-coupons.test' );
|
||||
const runCheckoutPageTest = require( './shopper/front-end-checkout.test' );
|
||||
const runMyAccountPageTest = require( './shopper/front-end-my-account.test' );
|
||||
const runMyAccountPayOrderTest = require( './shopper/front-end-my-account-pay-order.test' );
|
||||
|
@ -26,12 +29,15 @@ const runCartRedirectionTest = require( './shopper/front-end-cart-redirection.te
|
|||
const runOrderEmailReceivingTest = require( './shopper/front-end-order-email-receiving.test' );
|
||||
|
||||
// Merchant tests
|
||||
const runAddNewShippingZoneTest = require ( './merchant/wp-admin-settings-shipping-zones.test' );
|
||||
const runAddShippingClassesTest = require('./merchant/wp-admin-settings-shipping-classes.test')
|
||||
const runAddNewShippingZoneTest = require( './merchant/wp-admin-settings-shipping-zones.test' );
|
||||
const runAddShippingClassesTest = require( './merchant/wp-admin-settings-shipping-classes.test' );
|
||||
const runCreateCouponTest = require( './merchant/wp-admin-coupon-new.test' );
|
||||
const runCreateOrderTest = require( './merchant/wp-admin-order-new.test' );
|
||||
const runEditOrderTest = require( './merchant/wp-admin-order-edit.test' );
|
||||
const { runAddSimpleProductTest, runAddVariableProductTest } = require( './merchant/wp-admin-product-new.test' );
|
||||
const {
|
||||
runAddSimpleProductTest,
|
||||
runAddVariableProductTest,
|
||||
} = require( './merchant/wp-admin-product-new.test' );
|
||||
const runUpdateGeneralSettingsTest = require( './merchant/wp-admin-settings-general.test' );
|
||||
const runProductSettingsTest = require( './merchant/wp-admin-settings-product.test' );
|
||||
const runTaxSettingsTest = require( './merchant/wp-admin-settings-tax.test' );
|
||||
|
@ -105,7 +111,7 @@ const runMerchantTests = () => {
|
|||
runAnalyticsPageLoadsTest();
|
||||
runInitiateWccomConnectionTest();
|
||||
runAdminPageLoadTests();
|
||||
}
|
||||
};
|
||||
|
||||
const runApiTests = () => {
|
||||
runExternalProductAPITest();
|
||||
|
@ -114,7 +120,7 @@ const runApiTests = () => {
|
|||
runCouponApiTest();
|
||||
runOrderApiTest();
|
||||
runTelemetryAPITest();
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
runActivationTest,
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
const {
|
||||
const {
|
||||
merchant,
|
||||
waitForSelectorWithoutThrow,
|
||||
} = require( '@woocommerce/e2e-utils' );
|
||||
|
@ -10,67 +10,67 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
const {
|
||||
it,
|
||||
describe,
|
||||
beforeAll,
|
||||
} = require( '@jest/globals' );
|
||||
const { it, describe, beforeAll } = require( '@jest/globals' );
|
||||
import deprecated from '@wordpress/deprecated';
|
||||
|
||||
/**
|
||||
* Quick check for page title and no data message.
|
||||
*
|
||||
* @param pageTitle Page title in H1.
|
||||
* @param element Defaults to '.d3-chart__empty-message'
|
||||
* @param elementText Defaults to 'No data for the selected date range'
|
||||
* @param pageTitle Page title in H1.
|
||||
* @param element Defaults to '.d3-chart__empty-message'
|
||||
* @param elementText Defaults to 'No data for the selected date range'
|
||||
*/
|
||||
const checkHeadingAndElement = async (
|
||||
pageTitle, element = '.d3-chart__empty-message', elementText = 'No data for the selected date range') => {
|
||||
await expect(page).toMatchElement('h1', {text: pageTitle});
|
||||
pageTitle,
|
||||
element = '.d3-chart__empty-message',
|
||||
elementText = 'No data for the selected date range'
|
||||
) => {
|
||||
await expect( page ).toMatchElement( 'h1', { text: pageTitle } );
|
||||
|
||||
// Depending on order of tests the chart may not be empty.
|
||||
const found = await waitForSelectorWithoutThrow( element );
|
||||
if ( found ) {
|
||||
await expect(page).toMatchElement(element, {text: elementText});
|
||||
await expect( page ).toMatchElement( element, { text: elementText } );
|
||||
} else {
|
||||
await expect(page).toMatchElement( '.woocommerce-chart' );
|
||||
await expect( page ).toMatchElement( '.woocommerce-chart' );
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// Analytics pages that we'll test against
|
||||
// Analytics pages that we'll test against
|
||||
const pages = [
|
||||
['Overview'],
|
||||
['Products'],
|
||||
['Revenue'],
|
||||
['Orders'],
|
||||
['Variations'],
|
||||
['Categories'],
|
||||
['Coupons'],
|
||||
['Taxes'],
|
||||
['Downloads'],
|
||||
['Stock', '.components-button > span', 'Product / Variation'],
|
||||
['Settings', 'h2', 'Analytics Settings']
|
||||
[ 'Overview' ],
|
||||
[ 'Products' ],
|
||||
[ 'Revenue' ],
|
||||
[ 'Orders' ],
|
||||
[ 'Variations' ],
|
||||
[ 'Categories' ],
|
||||
[ 'Coupons' ],
|
||||
[ 'Taxes' ],
|
||||
[ 'Downloads' ],
|
||||
[ 'Stock', '.components-button > span', 'Product / Variation' ],
|
||||
[ 'Settings', 'h2', 'Analytics Settings' ],
|
||||
];
|
||||
|
||||
const runAnalyticsPageLoadsTest = () => {
|
||||
describe('Analytics > Opening Top Level Pages', () => {
|
||||
beforeAll(async () => {
|
||||
describe( 'Analytics > Opening Top Level Pages', () => {
|
||||
beforeAll( async () => {
|
||||
await merchant.login();
|
||||
});
|
||||
} );
|
||||
|
||||
deprecated( 'runAnalyticsPageLoadsTest', {
|
||||
alternative: '@woocommerce/admin-e2e-tests `testAdminAnalyticsPages()`',
|
||||
});
|
||||
alternative:
|
||||
'@woocommerce/admin-e2e-tests `testAdminAnalyticsPages()`',
|
||||
} );
|
||||
|
||||
it.each(pages)(
|
||||
it.each( pages )(
|
||||
'can see %s page properly',
|
||||
async (pageTitle, element, elementText) => {
|
||||
async ( pageTitle, element, elementText ) => {
|
||||
// Go to the desired page and verify it
|
||||
await merchant.openAnalyticsPage(pageTitle.toLowerCase());
|
||||
await checkHeadingAndElement(pageTitle, element, elementText);
|
||||
await merchant.openAnalyticsPage( pageTitle.toLowerCase() );
|
||||
await checkHeadingAndElement( pageTitle, element, elementText );
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
} );
|
||||
};
|
||||
|
||||
module.exports = runAnalyticsPageLoadsTest;
|
||||
|
|
|
@ -11,48 +11,53 @@ const {
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
const {
|
||||
it,
|
||||
describe,
|
||||
beforeAll,
|
||||
} = require( '@jest/globals' );
|
||||
const { it, describe, beforeAll } = require( '@jest/globals' );
|
||||
|
||||
const runCreateCouponTest = () => {
|
||||
describe('Add New Coupon Page', () => {
|
||||
beforeAll(async () => {
|
||||
describe( 'Add New Coupon Page', () => {
|
||||
beforeAll( async () => {
|
||||
await merchant.login();
|
||||
});
|
||||
} );
|
||||
|
||||
it('can create new coupon', async () => {
|
||||
it( 'can create new coupon', async () => {
|
||||
// Go to "add coupon" page
|
||||
await merchant.openNewCoupon();
|
||||
|
||||
// Make sure we're on the add coupon page
|
||||
await expect(page.title()).resolves.toMatch('Add new coupon');
|
||||
await expect( page.title() ).resolves.toMatch( 'Add new coupon' );
|
||||
|
||||
// Fill in coupon code and description
|
||||
await expect(page).toFill('#title', 'code-' + new Date().getTime().toString());
|
||||
await expect(page).toFill('#woocommerce-coupon-description', 'test coupon');
|
||||
await expect( page ).toFill(
|
||||
'#title',
|
||||
'code-' + new Date().getTime().toString()
|
||||
);
|
||||
await expect( page ).toFill(
|
||||
'#woocommerce-coupon-description',
|
||||
'test coupon'
|
||||
);
|
||||
|
||||
// Set general coupon data
|
||||
await clickTab('General');
|
||||
await expect(page).toSelect('#discount_type', 'Fixed cart discount');
|
||||
await expect(page).toFill('#coupon_amount', '100');
|
||||
await clickTab( 'General' );
|
||||
await expect( page ).toSelect(
|
||||
'#discount_type',
|
||||
'Fixed cart discount'
|
||||
);
|
||||
await expect( page ).toFill( '#coupon_amount', '100' );
|
||||
|
||||
// Publish coupon, verify that it was published.
|
||||
const adminEdit = new AdminEdit();
|
||||
await adminEdit.verifyPublish(
|
||||
'#publish',
|
||||
'.notice',
|
||||
'Coupon updated.',
|
||||
'Coupon updated.'
|
||||
);
|
||||
// Delete the coupon
|
||||
const couponId = await adminEdit.getId();
|
||||
if ( couponId ) {
|
||||
await withRestApi.deleteCoupon( couponId );
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
} );
|
||||
} );
|
||||
};
|
||||
|
||||
module.exports = runCreateCouponTest;
|
||||
|
|
|
@ -1,46 +1,44 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
const {
|
||||
merchant,
|
||||
} = require( '@woocommerce/e2e-utils' );
|
||||
const { merchant } = require( '@woocommerce/e2e-utils' );
|
||||
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
const {
|
||||
it,
|
||||
describe,
|
||||
beforeAll,
|
||||
} = require( '@jest/globals' );
|
||||
const { it, describe, beforeAll } = require( '@jest/globals' );
|
||||
|
||||
const runInitiateWccomConnectionTest = () => {
|
||||
describe('Merchant > Initiate WCCOM Connection', () => {
|
||||
beforeAll(async () => {
|
||||
describe( 'Merchant > Initiate WCCOM Connection', () => {
|
||||
beforeAll( async () => {
|
||||
await merchant.login();
|
||||
});
|
||||
} );
|
||||
|
||||
it.skip('can initiate WCCOM connection', async () => {
|
||||
it.skip( 'can initiate WCCOM connection', async () => {
|
||||
await merchant.openExtensions();
|
||||
|
||||
// Click on a tab to choose WooCommerce Subscriptions extension
|
||||
await Promise.all( [
|
||||
expect( page ).toClick( 'a.nav-tab', { text: "WooCommerce.com Subscriptions" } ),
|
||||
expect( page ).toClick( 'a.nav-tab', {
|
||||
text: 'WooCommerce.com Subscriptions',
|
||||
} ),
|
||||
page.waitForNavigation( { waitUntil: 'networkidle0' } ),
|
||||
] );
|
||||
|
||||
// Click on Connect button to initiate a WCCOM connection
|
||||
await Promise.all([
|
||||
expect(page).toClick('.button-helper-connect'),
|
||||
page.waitForNavigation({waitUntil: 'networkidle0'}),
|
||||
]);
|
||||
await Promise.all( [
|
||||
expect( page ).toClick( '.button-helper-connect' ),
|
||||
page.waitForNavigation( { waitUntil: 'networkidle0' } ),
|
||||
] );
|
||||
|
||||
// Verify that you see a login page for connecting WCCOM account
|
||||
await expect(page).toMatchElement('div.login');
|
||||
await expect(page).toMatchElement('input#usernameOrEmail');
|
||||
await expect(page).toMatchElement('button.button', {text: "Continue"});
|
||||
});
|
||||
});
|
||||
}
|
||||
await expect( page ).toMatchElement( 'div.login' );
|
||||
await expect( page ).toMatchElement( 'input#usernameOrEmail' );
|
||||
await expect( page ).toMatchElement( 'button.button', {
|
||||
text: 'Continue',
|
||||
} );
|
||||
} );
|
||||
} );
|
||||
};
|
||||
|
||||
module.exports = runInitiateWccomConnectionTest;
|
||||
|
|
|
@ -12,55 +12,79 @@ const {
|
|||
} = require( '@woocommerce/e2e-utils' );
|
||||
|
||||
const config = require( 'config' );
|
||||
const simpleProductPrice = config.has('products.simple.price') ? config.get('products.simple.price') : '9.99';
|
||||
const discountedPrice = simpleProductPrice - 5.00;
|
||||
const simpleProductPrice = config.has( 'products.simple.price' )
|
||||
? config.get( 'products.simple.price' )
|
||||
: '9.99';
|
||||
const discountedPrice = simpleProductPrice - 5.0;
|
||||
|
||||
const couponDialogMessage = 'Enter a coupon code to apply. Discounts are applied to line totals, before taxes.';
|
||||
const couponDialogMessage =
|
||||
'Enter a coupon code to apply. Discounts are applied to line totals, before taxes.';
|
||||
|
||||
let couponCode;
|
||||
let orderId;
|
||||
let productId;
|
||||
|
||||
const runOrderApplyCouponTest = () => {
|
||||
describe('WooCommerce Orders > Apply coupon', () => {
|
||||
beforeAll(async () => {
|
||||
describe( 'WooCommerce Orders > Apply coupon', () => {
|
||||
beforeAll( async () => {
|
||||
productId = await createSimpleProduct();
|
||||
couponCode = await createCoupon();
|
||||
orderId = await createOrder( { productId, status: 'pending' } );
|
||||
|
||||
await merchant.login();
|
||||
await merchant.goToOrder( orderId );
|
||||
await page.removeAllListeners('dialog');
|
||||
await page.removeAllListeners( 'dialog' );
|
||||
|
||||
// Make sure the simple product price is greater than the coupon amount
|
||||
await expect(Number(simpleProductPrice)).toBeGreaterThan(5.00);
|
||||
await expect( Number( simpleProductPrice ) ).toBeGreaterThan( 5.0 );
|
||||
} );
|
||||
|
||||
it('can apply a coupon', async () => {
|
||||
await page.waitForSelector('button.add-coupon');
|
||||
const couponDialog = await expect(page).toDisplayDialog(async () => {
|
||||
await evalAndClick('button.add-coupon');
|
||||
});
|
||||
expect(couponDialog.message()).toMatch(couponDialogMessage);
|
||||
it( 'can apply a coupon', async () => {
|
||||
await page.waitForSelector( 'button.add-coupon' );
|
||||
const couponDialog = await expect( page ).toDisplayDialog(
|
||||
async () => {
|
||||
await evalAndClick( 'button.add-coupon' );
|
||||
}
|
||||
);
|
||||
expect( couponDialog.message() ).toMatch( couponDialogMessage );
|
||||
|
||||
// Accept the dialog with the coupon code
|
||||
await couponDialog.accept(couponCode);
|
||||
await couponDialog.accept( couponCode );
|
||||
await uiUnblocked();
|
||||
|
||||
// Verify the coupon list is showing
|
||||
await page.waitForSelector('.wc-used-coupons');
|
||||
await expect(page).toMatchElement('.wc_coupon_list', { text: 'Coupon(s)' });
|
||||
await expect(page).toMatchElement('.wc_coupon_list li.code.editable', { text: couponCode.toLowerCase() });
|
||||
await page.waitForSelector( '.wc-used-coupons' );
|
||||
await expect( page ).toMatchElement( '.wc_coupon_list', {
|
||||
text: 'Coupon(s)',
|
||||
} );
|
||||
await expect( page ).toMatchElement(
|
||||
'.wc_coupon_list li.code.editable',
|
||||
{
|
||||
text: couponCode.toLowerCase(),
|
||||
}
|
||||
);
|
||||
|
||||
// Check that the coupon has been applied
|
||||
await expect(page).toMatchElement('.wc-order-item-discount', { text: '5.00' });
|
||||
await expect(page).toMatchElement('.line_cost > .view > .woocommerce-Price-amount', { text: discountedPrice });
|
||||
});
|
||||
await expect( page ).toMatchElement( '.wc-order-item-discount', {
|
||||
text: '5.00',
|
||||
} );
|
||||
await expect(
|
||||
page
|
||||
).toMatchElement(
|
||||
'.line_cost > .view > .woocommerce-Price-amount',
|
||||
{ text: discountedPrice }
|
||||
);
|
||||
} );
|
||||
|
||||
it('can remove a coupon', async () => {
|
||||
it( 'can remove a coupon', async () => {
|
||||
// Make sure we have a coupon on the page to use
|
||||
await page.waitForSelector('.wc-used-coupons');
|
||||
await expect(page).toMatchElement('.wc_coupon_list li.code.editable', { text: couponCode.toLowerCase() });
|
||||
await page.waitForSelector( '.wc-used-coupons' );
|
||||
await expect( page ).toMatchElement(
|
||||
'.wc_coupon_list li.code.editable',
|
||||
{
|
||||
text: couponCode.toLowerCase(),
|
||||
}
|
||||
);
|
||||
await evalAndClick( 'a.remove-coupon' );
|
||||
|
||||
await uiUnblocked();
|
||||
|
@ -68,16 +92,32 @@ const runOrderApplyCouponTest = () => {
|
|||
await utils.waitForTimeout( 2000 ); // to avoid flakyness
|
||||
|
||||
// Verify the coupon pricing has been removed
|
||||
await expect(page).not.toMatchElement('.wc_coupon_list li.code.editable', { text: couponCode.toLowerCase() });
|
||||
await expect(page).not.toMatchElement('.wc-order-item-discount', { text: '5.00' });
|
||||
await expect(page).not.toMatchElement('.line-cost .view .woocommerce-Price-amount', { text: discountedPrice });
|
||||
await expect( page ).not.toMatchElement(
|
||||
'.wc_coupon_list li.code.editable',
|
||||
{
|
||||
text: couponCode.toLowerCase(),
|
||||
}
|
||||
);
|
||||
await expect( page ).not.toMatchElement(
|
||||
'.wc-order-item-discount',
|
||||
{ text: '5.00' }
|
||||
);
|
||||
await expect(
|
||||
page
|
||||
).not.toMatchElement(
|
||||
'.line-cost .view .woocommerce-Price-amount',
|
||||
{ text: discountedPrice }
|
||||
);
|
||||
|
||||
// Verify the original price is the order total
|
||||
await expect(page).toMatchElement('.line_cost > .view > .woocommerce-Price-amount', { text: simpleProductPrice });
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
await expect(
|
||||
page
|
||||
).toMatchElement(
|
||||
'.line_cost > .view > .woocommerce-Price-amount',
|
||||
{ text: simpleProductPrice }
|
||||
);
|
||||
} );
|
||||
} );
|
||||
};
|
||||
|
||||
module.exports = runOrderApplyCouponTest;
|
||||
|
|
|
@ -3,72 +3,99 @@ const { createSimpleProduct } = require( '@woocommerce/e2e-utils' );
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
const {
|
||||
merchant,
|
||||
createOrder,
|
||||
} = require( '@woocommerce/e2e-utils' );
|
||||
const { merchant, createOrder } = require( '@woocommerce/e2e-utils' );
|
||||
|
||||
// TODO create a function for the logic below getConfigSimpleProduct(), see: https://github.com/woocommerce/woocommerce/issues/29072
|
||||
const config = require( 'config' );
|
||||
const simpleProductName = config.get( 'products.simple.name' );
|
||||
const simpleProductPrice = config.has( 'products.simple.price' ) ? config.get( 'products.simple.price' ) : '9.99';
|
||||
const simpleProductPrice = config.has( 'products.simple.price' )
|
||||
? config.get( 'products.simple.price' )
|
||||
: '9.99';
|
||||
|
||||
const runMerchantOrdersCustomerPaymentPage = () => {
|
||||
let orderId;
|
||||
let productId;
|
||||
|
||||
describe('WooCommerce Merchant Flow: Orders > Customer Payment Page', () => {
|
||||
beforeAll(async () => {
|
||||
describe( 'WooCommerce Merchant Flow: Orders > Customer Payment Page', () => {
|
||||
beforeAll( async () => {
|
||||
productId = await createSimpleProduct();
|
||||
orderId = await createOrder( { productId } );
|
||||
await merchant.login();
|
||||
});
|
||||
} );
|
||||
|
||||
it('should show the customer payment page link on a pending payment order', async () => {
|
||||
it( 'should show the customer payment page link on a pending payment order', async () => {
|
||||
await merchant.goToOrder( orderId );
|
||||
|
||||
// Verify the order is still pending payment
|
||||
await expect( page ).toMatchElement( '#order_status', { text: 'Pending payment' } );
|
||||
await expect( page ).toMatchElement( '#order_status', {
|
||||
text: 'Pending payment',
|
||||
} );
|
||||
|
||||
// Verify the customer payment page link is displayed
|
||||
await expect(page).toMatchElement( 'label[for=order_status] > a' , { text: 'Customer payment page →' });
|
||||
});
|
||||
await expect( page ).toMatchElement(
|
||||
'label[for=order_status] > a',
|
||||
{ text: 'Customer payment page →' }
|
||||
);
|
||||
} );
|
||||
|
||||
|
||||
it('should load the customer payment page', async () => {
|
||||
it( 'should load the customer payment page', async () => {
|
||||
// Verify the customer payment page link is displayed
|
||||
await expect(page).toMatchElement( 'label[for=order_status] > a' , { text: 'Customer payment page →' });
|
||||
await expect( page ).toMatchElement(
|
||||
'label[for=order_status] > a',
|
||||
{ text: 'Customer payment page →' }
|
||||
);
|
||||
|
||||
// Visit the page
|
||||
await Promise.all([
|
||||
expect(page).toClick( 'label[for=order_status] > a' ),
|
||||
await Promise.all( [
|
||||
expect( page ).toClick( 'label[for=order_status] > a' ),
|
||||
page.waitForNavigation( { waitUntil: 'networkidle0' } ),
|
||||
]);
|
||||
] );
|
||||
|
||||
// Verify we landed on the customer payment page
|
||||
await expect(page).toMatchElement( 'h1.entry-title' , { text: 'Pay for order' });
|
||||
await expect(page).toMatchElement( 'td.product-name' , { text: simpleProductName });
|
||||
await expect(page).toMatchElement( 'span.woocommerce-Price-amount.amount' , { text: simpleProductPrice });
|
||||
});
|
||||
await expect( page ).toMatchElement( 'h1.entry-title', {
|
||||
text: 'Pay for order',
|
||||
} );
|
||||
await expect( page ).toMatchElement( 'td.product-name', {
|
||||
text: simpleProductName,
|
||||
} );
|
||||
await expect( page ).toMatchElement(
|
||||
'span.woocommerce-Price-amount.amount',
|
||||
{
|
||||
text: simpleProductPrice,
|
||||
}
|
||||
);
|
||||
} );
|
||||
|
||||
it('can pay for the order through the customer payment page', async () => {
|
||||
it( 'can pay for the order through the customer payment page', async () => {
|
||||
// Make sure we're still on the customer payment page
|
||||
await expect(page).toMatchElement( 'h1.entry-title' , { text: 'Pay for order' });
|
||||
await expect( page ).toMatchElement( 'h1.entry-title', {
|
||||
text: 'Pay for order',
|
||||
} );
|
||||
|
||||
// Pay for the order
|
||||
await Promise.all([
|
||||
expect(page).toClick( '#place_order'),
|
||||
await Promise.all( [
|
||||
expect( page ).toClick( '#place_order' ),
|
||||
page.waitForNavigation( { waitUntil: 'networkidle0' } ),
|
||||
]);
|
||||
] );
|
||||
|
||||
// Verify we landed on the order received page
|
||||
await expect(page).toMatchElement( 'h1.entry-title', { text: 'Order received' });
|
||||
await expect(page).toMatchElement( 'li.woocommerce-order-overview__order.order' , { text: orderId.toString() });
|
||||
await expect(page).toMatchElement( 'span.woocommerce-Price-amount.amount' , { text: simpleProductPrice });
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
await expect( page ).toMatchElement( 'h1.entry-title', {
|
||||
text: 'Order received',
|
||||
} );
|
||||
await expect( page ).toMatchElement(
|
||||
'li.woocommerce-order-overview__order.order',
|
||||
{
|
||||
text: orderId.toString(),
|
||||
}
|
||||
);
|
||||
await expect( page ).toMatchElement(
|
||||
'span.woocommerce-Price-amount.amount',
|
||||
{
|
||||
text: simpleProductPrice,
|
||||
}
|
||||
);
|
||||
} );
|
||||
} );
|
||||
};
|
||||
|
||||
module.exports = runMerchantOrdersCustomerPaymentPage;
|
||||
|
|
|
@ -15,63 +15,71 @@ let orderId;
|
|||
|
||||
const orderStatus = {
|
||||
processing: 'processing',
|
||||
completed: 'completed'
|
||||
completed: 'completed',
|
||||
};
|
||||
|
||||
const runEditOrderTest = () => {
|
||||
describe('WooCommerce Orders > Edit order', () => {
|
||||
beforeAll(async () => {
|
||||
describe( 'WooCommerce Orders > Edit order', () => {
|
||||
beforeAll( async () => {
|
||||
orderId = await createOrder( { status: orderStatus.processing } );
|
||||
await merchant.login();
|
||||
});
|
||||
} );
|
||||
|
||||
afterAll( async () => {
|
||||
await withRestApi.deleteOrder( orderId );
|
||||
});
|
||||
} );
|
||||
|
||||
it('can view single order', async () => {
|
||||
it( 'can view single order', async () => {
|
||||
// Go to "orders" page
|
||||
await merchant.openAllOrdersView();
|
||||
|
||||
// Make sure we're on the orders page
|
||||
await expect(page.title()).resolves.toMatch('Orders');
|
||||
await expect( page.title() ).resolves.toMatch( 'Orders' );
|
||||
|
||||
//Open order we created
|
||||
await merchant.goToOrder(orderId);
|
||||
await merchant.goToOrder( orderId );
|
||||
|
||||
// Make sure we're on the order details page
|
||||
await expect(page.title()).resolves.toMatch('Edit order');
|
||||
});
|
||||
await expect( page.title() ).resolves.toMatch( 'Edit order' );
|
||||
} );
|
||||
|
||||
it('can update order status', async () => {
|
||||
it( 'can update order status', async () => {
|
||||
//Open order we created
|
||||
await merchant.goToOrder(orderId);
|
||||
await merchant.goToOrder( orderId );
|
||||
|
||||
// Make sure we're still on the order details page
|
||||
await expect(page.title()).resolves.toMatch('Edit order');
|
||||
await expect( page.title() ).resolves.toMatch( 'Edit order' );
|
||||
|
||||
// Update order status to `Completed`
|
||||
await merchant.updateOrderStatus(orderId, 'Completed');
|
||||
await merchant.updateOrderStatus( orderId, 'Completed' );
|
||||
|
||||
// Verify order status changed note added
|
||||
await expect( page ).toMatchElement( '#select2-order_status-container', { text: 'Completed' } );
|
||||
await expect( page ).toMatchElement(
|
||||
'#select2-order_status-container',
|
||||
{
|
||||
text: 'Completed',
|
||||
}
|
||||
);
|
||||
await expect( page ).toMatchElement(
|
||||
'#woocommerce-order-notes .note_content',
|
||||
{
|
||||
text: 'Order status changed from Processing to Completed.',
|
||||
}
|
||||
);
|
||||
});
|
||||
} );
|
||||
|
||||
it('can update order details', async () => {
|
||||
it( 'can update order details', async () => {
|
||||
//Open order we created
|
||||
await merchant.goToOrder(orderId);
|
||||
await merchant.goToOrder( orderId );
|
||||
|
||||
// Make sure we're still on the order details page
|
||||
await expect(page.title()).resolves.toMatch('Edit order');
|
||||
await expect( page.title() ).resolves.toMatch( 'Edit order' );
|
||||
|
||||
// Update order details
|
||||
await expect(page).toFill('input[name=order_date]', '2018-12-14');
|
||||
await expect( page ).toFill(
|
||||
'input[name=order_date]',
|
||||
'2018-12-14'
|
||||
);
|
||||
|
||||
// Wait for auto save
|
||||
await utils.waitForTimeout( 2000 );
|
||||
|
@ -80,10 +88,15 @@ const runEditOrderTest = () => {
|
|||
await orderPageSaveChanges();
|
||||
|
||||
// Verify
|
||||
await expect( page ).toMatchElement( '#message', { text: 'Order updated.' } );
|
||||
await verifyValueOfInputField( 'input[name=order_date]' , '2018-12-14' );
|
||||
});
|
||||
});
|
||||
await expect( page ).toMatchElement( '#message', {
|
||||
text: 'Order updated.',
|
||||
} );
|
||||
await verifyValueOfInputField(
|
||||
'input[name=order_date]',
|
||||
'2018-12-14'
|
||||
);
|
||||
} );
|
||||
} );
|
||||
|
||||
describe( 'WooCommerce Orders > Edit order > Downloadable product permissions', () => {
|
||||
const productName = 'TDP 001';
|
||||
|
@ -97,12 +110,12 @@ const runEditOrderTest = () => {
|
|||
await merchant.login();
|
||||
} );
|
||||
|
||||
beforeEach(async () => {
|
||||
beforeEach( async () => {
|
||||
productId = await createSimpleDownloadableProduct( productName );
|
||||
orderId = await createOrder( {
|
||||
productId,
|
||||
customerBilling ,
|
||||
status: orderStatus.processing
|
||||
customerBilling,
|
||||
status: orderStatus.processing,
|
||||
} );
|
||||
} );
|
||||
|
||||
|
@ -115,7 +128,7 @@ const runEditOrderTest = () => {
|
|||
// Create order without product
|
||||
const newOrderId = await createOrder( {
|
||||
customerBilling,
|
||||
status: orderStatus.processing
|
||||
status: orderStatus.processing,
|
||||
} );
|
||||
|
||||
// Open order we created
|
||||
|
@ -125,7 +138,7 @@ const runEditOrderTest = () => {
|
|||
await merchant.addDownloadableProductPermission( productName );
|
||||
|
||||
// Verify new downloadable product permission details
|
||||
await merchant.verifyDownloadableProductPermission( productName )
|
||||
await merchant.verifyDownloadableProductPermission( productName );
|
||||
|
||||
// Remove order
|
||||
await withRestApi.deleteOrder( newOrderId );
|
||||
|
@ -134,7 +147,9 @@ const runEditOrderTest = () => {
|
|||
it( 'can add downloadable product permissions to order with product', async () => {
|
||||
// Create new downloadable product
|
||||
const newProductName = 'TDP 002';
|
||||
const newProductId = await createSimpleDownloadableProduct( newProductName );
|
||||
const newProductId = await createSimpleDownloadableProduct(
|
||||
newProductName
|
||||
);
|
||||
|
||||
// Open order we created
|
||||
await merchant.goToOrder( orderId );
|
||||
|
@ -143,7 +158,9 @@ const runEditOrderTest = () => {
|
|||
await merchant.addDownloadableProductPermission( newProductName );
|
||||
|
||||
// Verify new downloadable product permission details
|
||||
await merchant.verifyDownloadableProductPermission( newProductName )
|
||||
await merchant.verifyDownloadableProductPermission(
|
||||
newProductName
|
||||
);
|
||||
|
||||
// Remove product
|
||||
await withRestApi.deleteProduct( newProductId );
|
||||
|
@ -180,21 +197,28 @@ const runEditOrderTest = () => {
|
|||
await merchant.revokeDownloadableProductPermission( productName );
|
||||
|
||||
// Verify
|
||||
await expect( page ).not.toMatchElement( 'div.order_download_permissions', {
|
||||
text: productName
|
||||
} );
|
||||
await expect( page ).not.toMatchElement(
|
||||
'div.order_download_permissions',
|
||||
{
|
||||
text: productName,
|
||||
}
|
||||
);
|
||||
} );
|
||||
|
||||
it( 'should not allow downloading a product if download attempts are exceeded', async () => {
|
||||
// Define expected download error reason
|
||||
const expectedReason = 'Sorry, you have reached your download limit for this file';
|
||||
const expectedReason =
|
||||
'Sorry, you have reached your download limit for this file';
|
||||
|
||||
// Create order with product without any available download attempt
|
||||
const newProductId = await createSimpleDownloadableProduct( productName, 0 );
|
||||
const newProductId = await createSimpleDownloadableProduct(
|
||||
productName,
|
||||
0
|
||||
);
|
||||
const newOrderId = await createOrder( {
|
||||
productId: newProductId,
|
||||
customerBilling,
|
||||
status: orderStatus.processing
|
||||
status: orderStatus.processing,
|
||||
} );
|
||||
|
||||
// Open order we created
|
||||
|
@ -204,7 +228,10 @@ const runEditOrderTest = () => {
|
|||
const downloadPage = await merchant.openDownloadLink();
|
||||
|
||||
// Verify file download cannot start
|
||||
await merchant.verifyCannotDownloadFromBecause( downloadPage, expectedReason );
|
||||
await merchant.verifyCannotDownloadFromBecause(
|
||||
downloadPage,
|
||||
expectedReason
|
||||
);
|
||||
|
||||
// Remove data
|
||||
await withRestApi.deleteOrder( newOrderId );
|
||||
|
@ -220,15 +247,21 @@ const runEditOrderTest = () => {
|
|||
|
||||
// Update permission so that the expiration date has already passed
|
||||
// Note: Seems this operation can't be performed through the API
|
||||
await merchant.updateDownloadableProductPermission( productName, '2018-12-14' );
|
||||
await merchant.updateDownloadableProductPermission(
|
||||
productName,
|
||||
'2018-12-14'
|
||||
);
|
||||
|
||||
// Open download page
|
||||
const downloadPage = await merchant.openDownloadLink();
|
||||
|
||||
// Verify file download cannot start
|
||||
await merchant.verifyCannotDownloadFromBecause( downloadPage, expectedReason );
|
||||
await merchant.verifyCannotDownloadFromBecause(
|
||||
downloadPage,
|
||||
expectedReason
|
||||
);
|
||||
} );
|
||||
} );
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = runEditOrderTest;
|
||||
|
|
|
@ -11,14 +11,15 @@ const {
|
|||
|
||||
const config = require( 'config' );
|
||||
const customerEmail = config.get( 'addresses.customer.billing.email' );
|
||||
const adminEmail = config.has( 'users.admin.email' ) ? config.get( 'users.admin.email' ) : 'admin@woocommercecoree2etestsuite.com';
|
||||
const adminEmail = config.has( 'users.admin.email' )
|
||||
? config.get( 'users.admin.email' )
|
||||
: 'admin@woocommercecoree2etestsuite.com';
|
||||
const storeName = 'WooCommerce Core E2E Test Suite';
|
||||
|
||||
let orderId;
|
||||
|
||||
const runMerchantOrderEmailsTest = () => {
|
||||
|
||||
describe('Merchant > Order Action emails received', () => {
|
||||
describe( 'Merchant > Order Action emails received', () => {
|
||||
beforeAll( async () => {
|
||||
await merchant.login();
|
||||
|
||||
|
@ -29,7 +30,9 @@ const runMerchantOrderEmailsTest = () => {
|
|||
|
||||
await Promise.all( [
|
||||
// Select the billing email address field and add the customer billing email from the config
|
||||
await page.click( 'div.order_data_column:nth-child(2) > h3:nth-child(1) > a:nth-child(1)' ),
|
||||
await page.click(
|
||||
'div.order_data_column:nth-child(2) > h3:nth-child(1) > a:nth-child(1)'
|
||||
),
|
||||
await expect( page ).toFill( '#_billing_email', customerEmail ),
|
||||
await clickUpdateOrder( 'Order updated.' ),
|
||||
] );
|
||||
|
@ -41,31 +44,42 @@ const runMerchantOrderEmailsTest = () => {
|
|||
} );
|
||||
|
||||
// New order emails are sent automatically when we create the simple order above, so let's verify we get these emails
|
||||
it('can receive new order email', async () => {
|
||||
it( 'can receive new order email', async () => {
|
||||
await merchant.openEmailLog();
|
||||
await expect( page ).toMatchElement( '.column-receiver', { text: adminEmail } );
|
||||
await expect( page ).toMatchElement( '.column-subject', { text: `[${storeName}]: New order #${orderId}` } );
|
||||
await expect( page ).toMatchElement( '.column-receiver', {
|
||||
text: adminEmail,
|
||||
} );
|
||||
await expect( page ).toMatchElement( '.column-subject', {
|
||||
text: `[${ storeName }]: New order #${ orderId }`,
|
||||
} );
|
||||
} );
|
||||
|
||||
it('can resend new order notification', async () => {
|
||||
it( 'can resend new order notification', async () => {
|
||||
await merchant.goToOrder( orderId );
|
||||
await selectOrderAction( 'send_order_details_admin' );
|
||||
|
||||
await merchant.openEmailLog();
|
||||
await expect( page ).toMatchElement( '.column-receiver', { text: adminEmail } );
|
||||
await expect( page ).toMatchElement( '.column-subject', { text: `[${storeName}]: New order #${orderId}` } );
|
||||
await expect( page ).toMatchElement( '.column-receiver', {
|
||||
text: adminEmail,
|
||||
} );
|
||||
await expect( page ).toMatchElement( '.column-subject', {
|
||||
text: `[${ storeName }]: New order #${ orderId }`,
|
||||
} );
|
||||
} );
|
||||
|
||||
it('can email invoice/order details to customer', async () => {
|
||||
it( 'can email invoice/order details to customer', async () => {
|
||||
await merchant.goToOrder( orderId );
|
||||
await selectOrderAction( 'send_order_details' );
|
||||
|
||||
await merchant.openEmailLog();
|
||||
await expect( page ).toMatchElement( '.column-receiver', { text: customerEmail } );
|
||||
await expect( page ).toMatchElement( '.column-subject', { text: `Invoice for order #${orderId} on ${storeName}` } );
|
||||
await expect( page ).toMatchElement( '.column-receiver', {
|
||||
text: customerEmail,
|
||||
} );
|
||||
await expect( page ).toMatchElement( '.column-subject', {
|
||||
text: `Invoice for order #${ orderId } on ${ storeName }`,
|
||||
} );
|
||||
} );
|
||||
|
||||
} );
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = runMerchantOrderEmailsTest;
|
||||
|
|
|
@ -14,7 +14,7 @@ const {
|
|||
GroupedProduct,
|
||||
SimpleProduct,
|
||||
ProductVariation,
|
||||
ExternalProduct
|
||||
ExternalProduct,
|
||||
} = require( '@woocommerce/api' );
|
||||
|
||||
const taxClasses = [
|
||||
|
@ -33,31 +33,35 @@ const taxRates = [
|
|||
{
|
||||
name: 'Tax Rate Simple',
|
||||
rate: '10.0000',
|
||||
class: 'tax-class-simple'
|
||||
class: 'tax-class-simple',
|
||||
},
|
||||
{
|
||||
name: 'Tax Rate Variable',
|
||||
rate: '20.0000',
|
||||
class: 'tax-class-variable'
|
||||
class: 'tax-class-variable',
|
||||
},
|
||||
{
|
||||
name: 'Tax Rate External',
|
||||
rate: '30.0000',
|
||||
class: 'tax-class-external'
|
||||
}
|
||||
class: 'tax-class-external',
|
||||
},
|
||||
];
|
||||
|
||||
const taxTotals = ['$10.00', '$40.00', '$240.00'];
|
||||
const taxTotals = [ '$10.00', '$40.00', '$240.00' ];
|
||||
|
||||
const initProducts = async () => {
|
||||
const apiUrl = config.get('url');
|
||||
const adminUsername = config.get('users.admin.username');
|
||||
const adminPassword = config.get('users.admin.password');
|
||||
const httpClient = HTTPClientFactory.build(apiUrl)
|
||||
.withBasicAuth(adminUsername, adminPassword)
|
||||
const apiUrl = config.get( 'url' );
|
||||
const adminUsername = config.get( 'users.admin.username' );
|
||||
const adminPassword = config.get( 'users.admin.password' );
|
||||
const httpClient = HTTPClientFactory.build( apiUrl )
|
||||
.withBasicAuth( adminUsername, adminPassword )
|
||||
.create();
|
||||
|
||||
await withRestApi.updateSettingOption( 'general', 'woocommerce_calc_taxes', { value: 'yes' } );
|
||||
await withRestApi.updateSettingOption(
|
||||
'general',
|
||||
'woocommerce_calc_taxes',
|
||||
{ value: 'yes' }
|
||||
);
|
||||
await withRestApi.addTaxClasses( taxClasses );
|
||||
await withRestApi.addTaxRates( taxRates );
|
||||
|
||||
|
@ -67,7 +71,7 @@ const initProducts = async () => {
|
|||
const simpleProduct = {
|
||||
name: 'Simple Product 273722',
|
||||
regularPrice: '100',
|
||||
taxClass: 'Tax Class Simple'
|
||||
taxClass: 'Tax Class Simple',
|
||||
};
|
||||
return await repo.create( simpleProduct );
|
||||
};
|
||||
|
@ -79,65 +83,65 @@ const initProducts = async () => {
|
|||
attributes: [
|
||||
{
|
||||
name: 'Size',
|
||||
option: 'Small'
|
||||
option: 'Small',
|
||||
},
|
||||
{
|
||||
name: 'Colour',
|
||||
option: 'Yellow'
|
||||
}
|
||||
option: 'Yellow',
|
||||
},
|
||||
],
|
||||
taxClass: 'Tax Class Variable'
|
||||
taxClass: 'Tax Class Variable',
|
||||
},
|
||||
{
|
||||
regularPrice: '300',
|
||||
attributes: [
|
||||
{
|
||||
name: 'Size',
|
||||
option: 'Medium'
|
||||
option: 'Medium',
|
||||
},
|
||||
{
|
||||
name: 'Colour',
|
||||
option: 'Magenta'
|
||||
}
|
||||
option: 'Magenta',
|
||||
},
|
||||
],
|
||||
taxClass: 'Tax Class Variable'
|
||||
}
|
||||
taxClass: 'Tax Class Variable',
|
||||
},
|
||||
];
|
||||
const variableProductData = {
|
||||
name: 'Variable Product 024611',
|
||||
type: 'variable',
|
||||
taxClass: 'Tax Class Variable'
|
||||
taxClass: 'Tax Class Variable',
|
||||
};
|
||||
|
||||
const variationRepo = ProductVariation.restRepository(httpClient);
|
||||
const productRepo = VariableProduct.restRepository(httpClient);
|
||||
const variableProduct = await productRepo.create(variableProductData);
|
||||
for (const v of variations) {
|
||||
await variationRepo.create(variableProduct.id, v);
|
||||
const variationRepo = ProductVariation.restRepository( httpClient );
|
||||
const productRepo = VariableProduct.restRepository( httpClient );
|
||||
const variableProduct = await productRepo.create( variableProductData );
|
||||
for ( const v of variations ) {
|
||||
await variationRepo.create( variableProduct.id, v );
|
||||
}
|
||||
|
||||
return variableProduct;
|
||||
};
|
||||
const initGroupedProduct = async () => {
|
||||
const groupedRepo = GroupedProduct.restRepository(httpClient);
|
||||
const defaultGroupedData = config.get('products.grouped');
|
||||
const groupedRepo = GroupedProduct.restRepository( httpClient );
|
||||
const defaultGroupedData = config.get( 'products.grouped' );
|
||||
const groupedProductData = {
|
||||
...defaultGroupedData,
|
||||
name: 'Grouped Product 858012'
|
||||
name: 'Grouped Product 858012',
|
||||
};
|
||||
|
||||
return await groupedRepo.create(groupedProductData);
|
||||
return await groupedRepo.create( groupedProductData );
|
||||
};
|
||||
const initExternalProduct = async () => {
|
||||
const repo = ExternalProduct.restRepository(httpClient);
|
||||
const defaultProps = config.get('products.external');
|
||||
const repo = ExternalProduct.restRepository( httpClient );
|
||||
const defaultProps = config.get( 'products.external' );
|
||||
const props = {
|
||||
...defaultProps,
|
||||
name: 'External product 786794',
|
||||
regularPrice: '800',
|
||||
taxClass: 'Tax Class External'
|
||||
taxClass: 'Tax Class External',
|
||||
};
|
||||
return await repo.create(props);
|
||||
return await repo.create( props );
|
||||
};
|
||||
|
||||
// Create a product for each product type
|
||||
|
@ -146,66 +150,78 @@ const initProducts = async () => {
|
|||
const groupedProduct = await initGroupedProduct();
|
||||
const externalProduct = await initExternalProduct();
|
||||
|
||||
return [simpleProduct, variableProduct, groupedProduct, externalProduct];
|
||||
return [ simpleProduct, variableProduct, groupedProduct, externalProduct ];
|
||||
};
|
||||
|
||||
let products;
|
||||
|
||||
const runCreateOrderTest = () => {
|
||||
describe('WooCommerce Orders > Add new order', () => {
|
||||
beforeAll(async () => {
|
||||
describe( 'WooCommerce Orders > Add new order', () => {
|
||||
beforeAll( async () => {
|
||||
// Initialize products for each product type
|
||||
products = await initProducts();
|
||||
|
||||
// Login
|
||||
await merchant.login();
|
||||
});
|
||||
} );
|
||||
|
||||
it('can create new order', async () => {
|
||||
it( 'can create new order', async () => {
|
||||
// Go to "add order" page
|
||||
await merchant.openNewOrder();
|
||||
|
||||
// Make sure we're on the add order page
|
||||
await expect(page.title()).resolves.toMatch('Add new order');
|
||||
await expect( page.title() ).resolves.toMatch( 'Add new order' );
|
||||
|
||||
// Set order data
|
||||
await expect(page).toSelect('#order_status', 'Processing');
|
||||
await expect(page).toFill('input[name=order_date]', '2018-12-13');
|
||||
await expect(page).toFill('input[name=order_date_hour]', '18');
|
||||
await expect(page).toFill('input[name=order_date_minute]', '55');
|
||||
await expect( page ).toSelect( '#order_status', 'Processing' );
|
||||
await expect( page ).toFill(
|
||||
'input[name=order_date]',
|
||||
'2018-12-13'
|
||||
);
|
||||
await expect( page ).toFill( 'input[name=order_date_hour]', '18' );
|
||||
await expect( page ).toFill(
|
||||
'input[name=order_date_minute]',
|
||||
'55'
|
||||
);
|
||||
|
||||
// Create order, verify that it was created. Trash order, verify that it was trashed.
|
||||
const orderEdit = new AdminEdit();
|
||||
await orderEdit.verifyPublish(
|
||||
'.order_actions li .save_order',
|
||||
'#message',
|
||||
'Order updated.',
|
||||
'Order updated.'
|
||||
);
|
||||
|
||||
await expect( page ).toMatchElement( '#select2-order_status-container', { text: 'Processing' } );
|
||||
await expect( page ).toMatchElement(
|
||||
'#select2-order_status-container',
|
||||
{
|
||||
text: 'Processing',
|
||||
}
|
||||
);
|
||||
await expect( page ).toMatchElement(
|
||||
'#woocommerce-order-notes .note_content',
|
||||
{
|
||||
text: 'Order status changed from Pending payment to Processing.',
|
||||
text:
|
||||
'Order status changed from Pending payment to Processing.',
|
||||
}
|
||||
);
|
||||
});
|
||||
} );
|
||||
|
||||
it('can create new complex order with multiple product types & tax classes', async () => {
|
||||
it( 'can create new complex order with multiple product types & tax classes', async () => {
|
||||
// Go to "add order" page
|
||||
await merchant.openNewOrder();
|
||||
|
||||
// Open modal window for adding line items
|
||||
await expect(page).toClick('button.add-line-item');
|
||||
await expect(page).toClick('button.add-order-item');
|
||||
await page.waitForSelector('.wc-backbone-modal-header');
|
||||
await expect( page ).toClick( 'button.add-line-item' );
|
||||
await expect( page ).toClick( 'button.add-order-item' );
|
||||
await page.waitForSelector( '.wc-backbone-modal-header' );
|
||||
|
||||
// Search for each product to add, then verify that they are saved
|
||||
for (const { name } of products) {
|
||||
await expect(page).toClick(
|
||||
for ( const { name } of products ) {
|
||||
await expect( page ).toClick(
|
||||
'.wc-backbone-modal-content tr:last-child .select2-selection__arrow'
|
||||
);
|
||||
await expect(page).toFill(
|
||||
await expect( page ).toFill(
|
||||
'#wc-backbone-modal-dialog + .select2-container .select2-search__field',
|
||||
name
|
||||
);
|
||||
|
@ -213,52 +229,60 @@ const runCreateOrderTest = () => {
|
|||
'li[data-selected]'
|
||||
);
|
||||
await firstResult.click();
|
||||
await expect(page).toMatchElement(
|
||||
await expect( page ).toMatchElement(
|
||||
'.wc-backbone-modal-content tr:nth-last-child(2) .wc-product-search option',
|
||||
name
|
||||
);
|
||||
}
|
||||
|
||||
// Save the line items
|
||||
await expect(page).toClick('.wc-backbone-modal-content #btn-ok');
|
||||
await expect( page ).toClick(
|
||||
'.wc-backbone-modal-content #btn-ok'
|
||||
);
|
||||
await uiUnblocked();
|
||||
|
||||
// Recalculate taxes
|
||||
await expect(page).toDisplayDialog(async () => {
|
||||
await expect(page).toClick('.calculate-action');
|
||||
});
|
||||
await page.waitForSelector('th.line_tax');
|
||||
await expect( page ).toDisplayDialog( async () => {
|
||||
await expect( page ).toClick( '.calculate-action' );
|
||||
} );
|
||||
await page.waitForSelector( 'th.line_tax' );
|
||||
|
||||
// Save the order and verify line items
|
||||
await expect(page).toClick('button.save_order');
|
||||
await expect( page ).toClick( 'button.save_order' );
|
||||
await page.waitForNavigation();
|
||||
for (const { name } of products) {
|
||||
await expect(page).toMatchElement('.wc-order-item-name', {
|
||||
text: name
|
||||
});
|
||||
for ( const { name } of products ) {
|
||||
await expect( page ).toMatchElement( '.wc-order-item-name', {
|
||||
text: name,
|
||||
} );
|
||||
}
|
||||
|
||||
// Verify that the names of each tax class were shown
|
||||
for (const taxRate of taxRates) {
|
||||
await expect(page).toMatchElement('th.line_tax', {
|
||||
text: taxRate.name
|
||||
});
|
||||
await expect(page).toMatchElement('.wc-order-totals td.label', {
|
||||
text: taxRate.name
|
||||
});
|
||||
for ( const taxRate of taxRates ) {
|
||||
await expect( page ).toMatchElement( 'th.line_tax', {
|
||||
text: taxRate.name,
|
||||
} );
|
||||
await expect( page ).toMatchElement(
|
||||
'.wc-order-totals td.label',
|
||||
{
|
||||
text: taxRate.name,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Verify tax amounts
|
||||
for (const amount of taxTotals) {
|
||||
await expect(page).toMatchElement('td.line_tax', {
|
||||
text: amount
|
||||
});
|
||||
await expect(page).toMatchElement('.wc-order-totals td.total', {
|
||||
text: amount
|
||||
});
|
||||
for ( const amount of taxTotals ) {
|
||||
await expect( page ).toMatchElement( 'td.line_tax', {
|
||||
text: amount,
|
||||
} );
|
||||
await expect( page ).toMatchElement(
|
||||
'.wc-order-totals td.total',
|
||||
{
|
||||
text: amount,
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
} );
|
||||
} );
|
||||
};
|
||||
|
||||
module.exports = runCreateOrderTest;
|
||||
|
|
|
@ -18,7 +18,7 @@ const {
|
|||
*
|
||||
* @param {string} buttonSelector
|
||||
* @param {string} resultSelector
|
||||
* @returns {Promise<void>}
|
||||
* @return {Promise<void>}
|
||||
*/
|
||||
const clickAndWaitForSelector = async ( buttonSelector, resultSelector ) => {
|
||||
await evalAndClick( buttonSelector );
|
||||
|
|
|
@ -12,84 +12,121 @@ const {
|
|||
} = require( '@woocommerce/e2e-utils' );
|
||||
|
||||
const config = require( 'config' );
|
||||
const simpleProductPrice = config.has('products.simple.price') ? config.get('products.simple.price') : '9.99';
|
||||
const simpleProductPrice = config.has( 'products.simple.price' )
|
||||
? config.get( 'products.simple.price' )
|
||||
: '9.99';
|
||||
|
||||
const runRefundOrderTest = () => {
|
||||
describe('WooCommerce Orders > Refund an order', () => {
|
||||
describe( 'WooCommerce Orders > Refund an order', () => {
|
||||
let productId;
|
||||
let orderId;
|
||||
let currencySymbol;
|
||||
|
||||
beforeAll(async () => {
|
||||
beforeAll( async () => {
|
||||
productId = await createSimpleProduct();
|
||||
orderId = await createOrder( {
|
||||
productId,
|
||||
status: 'completed'
|
||||
status: 'completed',
|
||||
} );
|
||||
|
||||
await merchant.login();
|
||||
await merchant.goToOrder( orderId );
|
||||
|
||||
// Get the currency symbol for the store's selected currency
|
||||
await page.waitForSelector('.woocommerce-Price-currencySymbol');
|
||||
let currencyElement = await page.$('.woocommerce-Price-currencySymbol');
|
||||
currencySymbol = await page.evaluate(el => el.textContent, currencyElement);
|
||||
});
|
||||
await page.waitForSelector( '.woocommerce-Price-currencySymbol' );
|
||||
const currencyElement = await page.$(
|
||||
'.woocommerce-Price-currencySymbol'
|
||||
);
|
||||
currencySymbol = await page.evaluate(
|
||||
( el ) => el.textContent,
|
||||
currencyElement
|
||||
);
|
||||
} );
|
||||
|
||||
it('can issue a refund by quantity', async () => {
|
||||
it( 'can issue a refund by quantity', async () => {
|
||||
// Click the Refund button
|
||||
await expect(page).toClick('button.refund-items');
|
||||
await expect( page ).toClick( 'button.refund-items' );
|
||||
|
||||
// Verify the refund section shows
|
||||
await page.waitForSelector('div.wc-order-refund-items', { visible: true });
|
||||
await verifyCheckboxIsSet('#restock_refunded_items');
|
||||
await page.waitForSelector( 'div.wc-order-refund-items', {
|
||||
visible: true,
|
||||
} );
|
||||
await verifyCheckboxIsSet( '#restock_refunded_items' );
|
||||
|
||||
// Initiate a refund
|
||||
await expect(page).toFill('.refund_order_item_qty', '1');
|
||||
await expect(page).toFill('#refund_reason', 'No longer wanted');
|
||||
await expect( page ).toFill( '.refund_order_item_qty', '1' );
|
||||
await expect( page ).toFill( '#refund_reason', 'No longer wanted' );
|
||||
|
||||
await Promise.all([
|
||||
verifyValueOfInputField('.refund_line_total', simpleProductPrice),
|
||||
verifyValueOfInputField('#refund_amount', simpleProductPrice),
|
||||
expect(page).toMatchElement('.do-manual-refund', { text: `Refund ${currencySymbol + simpleProductPrice} manually` }),
|
||||
]);
|
||||
await Promise.all( [
|
||||
verifyValueOfInputField(
|
||||
'.refund_line_total',
|
||||
simpleProductPrice
|
||||
),
|
||||
verifyValueOfInputField( '#refund_amount', simpleProductPrice ),
|
||||
expect( page ).toMatchElement( '.do-manual-refund', {
|
||||
text: `Refund ${
|
||||
currencySymbol + simpleProductPrice
|
||||
} manually`,
|
||||
} ),
|
||||
] );
|
||||
|
||||
await clickAndWaitForSelector( '.do-manual-refund', '.quantity .refunded' );
|
||||
await clickAndWaitForSelector(
|
||||
'.do-manual-refund',
|
||||
'.quantity .refunded'
|
||||
);
|
||||
await uiUnblocked();
|
||||
|
||||
await Promise.all([
|
||||
await Promise.all( [
|
||||
// Verify the product line item shows the refunded quantity and amount
|
||||
expect(page).toMatchElement('.quantity .refunded', { text: '-1' }),
|
||||
expect(page).toMatchElement('.line_cost .refunded', { text: `-${currencySymbol + simpleProductPrice}` }),
|
||||
expect( page ).toMatchElement( '.quantity .refunded', {
|
||||
text: '-1',
|
||||
} ),
|
||||
expect( page ).toMatchElement( '.line_cost .refunded', {
|
||||
text: `-${ currencySymbol + simpleProductPrice }`,
|
||||
} ),
|
||||
|
||||
// Verify the refund shows in the list with the amount
|
||||
expect(page).toMatchElement('.refund .description', { text: 'No longer wanted' }),
|
||||
expect(page).toMatchElement('.refund > .line_cost', { text: `-${currencySymbol + simpleProductPrice}` }),
|
||||
expect( page ).toMatchElement( '.refund .description', {
|
||||
text: 'No longer wanted',
|
||||
} ),
|
||||
expect( page ).toMatchElement( '.refund > .line_cost', {
|
||||
text: `-${ currencySymbol + simpleProductPrice }`,
|
||||
} ),
|
||||
|
||||
// Verify system note was added
|
||||
expect(page).toMatchElement('.system-note', { text: 'Order status changed from Completed to Refunded.' }),
|
||||
]);
|
||||
});
|
||||
expect( page ).toMatchElement( '.system-note', {
|
||||
text: 'Order status changed from Completed to Refunded.',
|
||||
} ),
|
||||
] );
|
||||
} );
|
||||
|
||||
it('can delete an issued refund', async () => {
|
||||
it( 'can delete an issued refund', async () => {
|
||||
await clickAndWaitForSelector( 'a.delete_refund', '.refund-items' );
|
||||
await uiUnblocked();
|
||||
|
||||
await Promise.all([
|
||||
await Promise.all( [
|
||||
// Verify the refunded row item is no longer showing
|
||||
expect(page).not.toMatchElement('tr.refund', { visible: true }),
|
||||
expect( page ).not.toMatchElement( 'tr.refund', {
|
||||
visible: true,
|
||||
} ),
|
||||
// Verify the product line item doesn't show the refunded quantity and amount
|
||||
expect(page).not.toMatchElement('.quantity .refunded', { text: '-1' }),
|
||||
expect(page).not.toMatchElement('.line_cost .refunded', { text: `-${currencySymbol + simpleProductPrice}` }),
|
||||
expect( page ).not.toMatchElement( '.quantity .refunded', {
|
||||
text: '-1',
|
||||
} ),
|
||||
expect( page ).not.toMatchElement( '.line_cost .refunded', {
|
||||
text: `-${ currencySymbol + simpleProductPrice }`,
|
||||
} ),
|
||||
|
||||
// Verify the refund shows in the list with the amount
|
||||
expect(page).not.toMatchElement('.refund .description', { text: 'No longer wanted' }),
|
||||
expect(page).not.toMatchElement('.refund > .line_cost', { text: `-${currencySymbol + simpleProductPrice}` }),
|
||||
]);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
expect( page ).not.toMatchElement( '.refund .description', {
|
||||
text: 'No longer wanted',
|
||||
} ),
|
||||
expect( page ).not.toMatchElement( '.refund > .line_cost', {
|
||||
text: `-${ currencySymbol + simpleProductPrice }`,
|
||||
} ),
|
||||
] );
|
||||
} );
|
||||
} );
|
||||
};
|
||||
|
||||
module.exports = runRefundOrderTest;
|
||||
|
|
|
@ -42,7 +42,7 @@ const customerShipping = {
|
|||
/**
|
||||
* Set the billing fields for the customer account for this test suite.
|
||||
*
|
||||
* @returns {Promise<number>}
|
||||
* @return {Promise<number>}
|
||||
*/
|
||||
const updateCustomerBilling = async () => {
|
||||
const client = factories.api.withDefaultPermalinks;
|
||||
|
@ -55,7 +55,7 @@ const updateCustomerBilling = async () => {
|
|||
return;
|
||||
}
|
||||
|
||||
const customerId = customers.data[0].id;
|
||||
const customerId = customers.data[ 0 ].id;
|
||||
const customerData = {
|
||||
id: customerId,
|
||||
billing: customerBilling,
|
||||
|
@ -69,65 +69,65 @@ const updateCustomerBilling = async () => {
|
|||
* Data table to be fed into `it.each()`.
|
||||
*/
|
||||
const queries = [
|
||||
[customerBilling.first_name, 'billing first name'],
|
||||
[customerBilling.last_name, 'billing last name'],
|
||||
[customerBilling.company, 'billing company name'],
|
||||
[customerBilling.address_1, 'billing first address'],
|
||||
[customerBilling.address_2, 'billing second address'],
|
||||
[customerBilling.city, 'billing city name'],
|
||||
[customerBilling.postcode, 'billing post code'],
|
||||
[customerBilling.email, 'billing email'],
|
||||
[customerBilling.phone, 'billing phone'],
|
||||
[customerBilling.state, 'billing state'],
|
||||
[customerShipping.first_name, 'shipping first name'],
|
||||
[customerShipping.last_name, 'shipping last name'],
|
||||
[customerShipping.address_1, 'shipping first address'],
|
||||
[customerShipping.address_2, 'shipping second address'],
|
||||
[customerShipping.city, 'shipping city name'],
|
||||
[customerShipping.postcode, 'shipping post code'],
|
||||
[itemName, 'shipping item name']
|
||||
[ customerBilling.first_name, 'billing first name' ],
|
||||
[ customerBilling.last_name, 'billing last name' ],
|
||||
[ customerBilling.company, 'billing company name' ],
|
||||
[ customerBilling.address_1, 'billing first address' ],
|
||||
[ customerBilling.address_2, 'billing second address' ],
|
||||
[ customerBilling.city, 'billing city name' ],
|
||||
[ customerBilling.postcode, 'billing post code' ],
|
||||
[ customerBilling.email, 'billing email' ],
|
||||
[ customerBilling.phone, 'billing phone' ],
|
||||
[ customerBilling.state, 'billing state' ],
|
||||
[ customerShipping.first_name, 'shipping first name' ],
|
||||
[ customerShipping.last_name, 'shipping last name' ],
|
||||
[ customerShipping.address_1, 'shipping first address' ],
|
||||
[ customerShipping.address_2, 'shipping second address' ],
|
||||
[ customerShipping.city, 'shipping city name' ],
|
||||
[ customerShipping.postcode, 'shipping post code' ],
|
||||
[ itemName, 'shipping item name' ],
|
||||
];
|
||||
|
||||
const runOrderSearchingTest = () => {
|
||||
describe('WooCommerce Orders > Search orders', () => {
|
||||
describe( 'WooCommerce Orders > Search orders', () => {
|
||||
let productId;
|
||||
let orderId;
|
||||
let customerId;
|
||||
|
||||
beforeAll( async () => {
|
||||
productId = await createSimpleProduct('Wanted Product');
|
||||
productId = await createSimpleProduct( 'Wanted Product' );
|
||||
customerId = await updateCustomerBilling();
|
||||
orderId = await createOrder({
|
||||
orderId = await createOrder( {
|
||||
customerId,
|
||||
productId,
|
||||
customerBilling,
|
||||
customerShipping,
|
||||
});
|
||||
} );
|
||||
|
||||
// Login and open All Orders view
|
||||
await merchant.login();
|
||||
await merchant.openAllOrdersView();
|
||||
});
|
||||
} );
|
||||
|
||||
it('can search for order by order id', async () => {
|
||||
it( 'can search for order by order id', async () => {
|
||||
// Convert the order ID to string so we can search on it
|
||||
await searchForOrder(orderId.toString(), orderId, searchString);
|
||||
});
|
||||
await searchForOrder( orderId.toString(), orderId, searchString );
|
||||
} );
|
||||
|
||||
it.each(queries)(
|
||||
it.each( queries )(
|
||||
'can search for order containing "%s" as the %s',
|
||||
async (value) => {
|
||||
await searchForOrder(value, orderId, searchString);
|
||||
async ( value ) => {
|
||||
await searchForOrder( value, orderId, searchString );
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* shipping state is abbreviated. This test passes if billing and shipping state are the same
|
||||
*/
|
||||
it.skip('can search for order by shipping state name', async () => {
|
||||
await searchForOrder('New York', orderId, searchString);
|
||||
})
|
||||
});
|
||||
it.skip( 'can search for order by shipping state name', async () => {
|
||||
await searchForOrder( 'New York', orderId, searchString );
|
||||
} );
|
||||
} );
|
||||
};
|
||||
|
||||
module.exports = runOrderSearchingTest;
|
||||
|
|
|
@ -12,13 +12,13 @@ const statusColumnTextSelector = 'mark.order-status > span';
|
|||
|
||||
// Define order statuses to filter against
|
||||
const orderStatus = [
|
||||
['Pending payment', 'wc-pending'],
|
||||
['Processing', 'wc-processing'],
|
||||
['On hold', 'wc-on-hold'],
|
||||
['Completed', 'wc-completed'],
|
||||
['Cancelled', 'wc-cancelled'],
|
||||
['Refunded', 'wc-refunded'],
|
||||
['Failed', 'wc-failed'],
|
||||
[ 'Pending payment', 'wc-pending' ],
|
||||
[ 'Processing', 'wc-processing' ],
|
||||
[ 'On hold', 'wc-on-hold' ],
|
||||
[ 'Completed', 'wc-completed' ],
|
||||
[ 'Cancelled', 'wc-cancelled' ],
|
||||
[ 'Refunded', 'wc-refunded' ],
|
||||
[ 'Failed', 'wc-failed' ],
|
||||
];
|
||||
const defaultOrder = {
|
||||
payment_method: 'cod',
|
||||
|
@ -26,21 +26,21 @@ const defaultOrder = {
|
|||
first_name: 'John',
|
||||
last_name: 'Doe',
|
||||
email: 'john.doe@example.com',
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
const runOrderStatusFiltersTest = () => {
|
||||
describe('WooCommerce Orders > Filter Orders by Status', () => {
|
||||
beforeAll(async () => {
|
||||
describe( 'WooCommerce Orders > Filter Orders by Status', () => {
|
||||
beforeAll( async () => {
|
||||
// First, let's create some orders we can filter against
|
||||
const orders = orderStatus.map((entryPair) => {
|
||||
const statusName = entryPair[1].replace('wc-', '');
|
||||
const orders = orderStatus.map( ( entryPair ) => {
|
||||
const statusName = entryPair[ 1 ].replace( 'wc-', '' );
|
||||
|
||||
return {
|
||||
...defaultOrder,
|
||||
status: statusName,
|
||||
};
|
||||
});
|
||||
} );
|
||||
|
||||
// Create the orders using the API
|
||||
await withRestApi.batchCreateOrders( orders, false );
|
||||
|
@ -48,42 +48,53 @@ const runOrderStatusFiltersTest = () => {
|
|||
// Next, let's login and navigate to the Orders page
|
||||
await merchant.login();
|
||||
await merchant.openAllOrdersView();
|
||||
});
|
||||
} );
|
||||
|
||||
afterAll( async () => {
|
||||
// Make sure we're on the all orders view and cleanup the orders we created
|
||||
await merchant.openAllOrdersView();
|
||||
await moveAllItemsToTrash();
|
||||
});
|
||||
} );
|
||||
|
||||
it.each(orderStatus)('should filter by %s', async (statusText, statusClassName) => {
|
||||
// Identify which statuses should be shown or hidden
|
||||
const shownStatus = { text: statusText };
|
||||
const hiddenStatuses = orderStatus
|
||||
.filter((pair) => !pair.includes(statusText))
|
||||
.map(([statusText]) => {
|
||||
return { text: statusText };
|
||||
});
|
||||
it.each( orderStatus )(
|
||||
'should filter by %s',
|
||||
async ( statusText, statusClassName ) => {
|
||||
// Identify which statuses should be shown or hidden
|
||||
const shownStatus = { text: statusText };
|
||||
const hiddenStatuses = orderStatus
|
||||
.filter( ( pair ) => ! pair.includes( statusText ) )
|
||||
.map( ( [ statusText ] ) => {
|
||||
return { text: statusText };
|
||||
} );
|
||||
|
||||
// Click the status filter and verify that only the matching order is shown
|
||||
await clickFilter('.' + statusClassName);
|
||||
await expect(page).toMatchElement(statusColumnTextSelector, shownStatus);
|
||||
// Click the status filter and verify that only the matching order is shown
|
||||
await clickFilter( '.' + statusClassName );
|
||||
await expect( page ).toMatchElement(
|
||||
statusColumnTextSelector,
|
||||
shownStatus
|
||||
);
|
||||
|
||||
// Verify other statuses don't show
|
||||
for (const hiddenStatus of hiddenStatuses) {
|
||||
await expect(page).not.toMatchElement(statusColumnTextSelector, hiddenStatus);
|
||||
// Verify other statuses don't show
|
||||
for ( const hiddenStatus of hiddenStatuses ) {
|
||||
await expect( page ).not.toMatchElement(
|
||||
statusColumnTextSelector,
|
||||
hiddenStatus
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
);
|
||||
|
||||
it('should filter by All', async () => {
|
||||
it( 'should filter by All', async () => {
|
||||
// Make sure all the order statuses that were created show in this list
|
||||
await clickFilter('.all');
|
||||
await clickFilter( '.all' );
|
||||
|
||||
for (const [statusText] of orderStatus) {
|
||||
await expect(page).toMatchElement(statusColumnTextSelector, { text: statusText });
|
||||
for ( const [ statusText ] of orderStatus ) {
|
||||
await expect( page ).toMatchElement( statusColumnTextSelector, {
|
||||
text: statusText,
|
||||
} );
|
||||
}
|
||||
});
|
||||
});
|
||||
} );
|
||||
} );
|
||||
};
|
||||
|
||||
module.exports = runOrderStatusFiltersTest;
|
||||
|
|
|
@ -11,7 +11,7 @@ const { it, describe, beforeAll } = require( '@jest/globals' );
|
|||
|
||||
const runPageLoadTest = () => {
|
||||
describe.each( MENUS )(
|
||||
' %s > Opening Top Level Pages',
|
||||
'%s > Opening Top Level Pages',
|
||||
( menuTitle, menuElement, subMenus ) => {
|
||||
beforeAll( async () => {
|
||||
await merchant.login();
|
||||
|
@ -34,9 +34,11 @@ const runPageLoadTest = () => {
|
|||
|
||||
// Click sub-menu item and wait for the page to finish loading
|
||||
if ( subMenuElement.length ) {
|
||||
await Promise.all([
|
||||
await Promise.all( [
|
||||
page.click( subMenuElement ),
|
||||
page.waitForNavigation( { waitUntil: 'networkidle0' } ),
|
||||
page.waitForNavigation( {
|
||||
waitUntil: 'networkidle0',
|
||||
} ),
|
||||
] );
|
||||
}
|
||||
|
||||
|
|
|
@ -18,37 +18,43 @@ const { it, describe, beforeAll } = require( '@jest/globals' );
|
|||
let productId;
|
||||
|
||||
const runProductEditDetailsTest = () => {
|
||||
describe('Products > Edit Product', () => {
|
||||
beforeAll(async () => {
|
||||
describe( 'Products > Edit Product', () => {
|
||||
beforeAll( async () => {
|
||||
productId = await createSimpleProduct();
|
||||
await merchant.login();
|
||||
});
|
||||
} );
|
||||
|
||||
it('can edit a product and save the changes', async () => {
|
||||
await merchant.goToProduct(productId);
|
||||
it( 'can edit a product and save the changes', async () => {
|
||||
await merchant.goToProduct( productId );
|
||||
|
||||
// Clear the input fields first, then add the new values
|
||||
await expect(page).toFill('#title', '');
|
||||
await expect(page).toFill('#_regular_price', '');
|
||||
await expect( page ).toFill( '#title', '' );
|
||||
await expect( page ).toFill( '#_regular_price', '' );
|
||||
|
||||
await expect(page).toFill('#title', 'Awesome product');
|
||||
await expect( page ).toFill( '#title', 'Awesome product' );
|
||||
|
||||
// Switch to text mode to work around the iframe
|
||||
await expect(page).toClick('#content-html');
|
||||
await expect(page).toFill('.wp-editor-area', 'This product is pretty awesome.');
|
||||
await expect( page ).toClick( '#content-html' );
|
||||
await expect( page ).toFill(
|
||||
'.wp-editor-area',
|
||||
'This product is pretty awesome.'
|
||||
);
|
||||
|
||||
await expect(page).toFill('#_regular_price', '100.05');
|
||||
await expect( page ).toFill( '#_regular_price', '100.05' );
|
||||
|
||||
// Save the changes
|
||||
await verifyAndPublish('Product updated.');
|
||||
await verifyAndPublish( 'Product updated.' );
|
||||
await uiUnblocked();
|
||||
|
||||
// Verify the changes saved
|
||||
await expect(page).toMatchElement('#title', 'Awesome product');
|
||||
await expect(page).toMatchElement('.wp-editor-area', 'This product is pretty awesome.');
|
||||
await expect(page).toMatchElement('#_regular_price', '100.05');
|
||||
});
|
||||
});
|
||||
}
|
||||
await expect( page ).toMatchElement( '#title', 'Awesome product' );
|
||||
await expect( page ).toMatchElement(
|
||||
'.wp-editor-area',
|
||||
'This product is pretty awesome.'
|
||||
);
|
||||
await expect( page ).toMatchElement( '#_regular_price', '100.05' );
|
||||
} );
|
||||
} );
|
||||
};
|
||||
|
||||
module.exports = runProductEditDetailsTest;
|
||||
|
|
|
@ -104,13 +104,13 @@ const runImportProductsTest = () => {
|
|||
await merchant.openImportProducts();
|
||||
} );
|
||||
|
||||
afterAll(async () => {
|
||||
afterAll( async () => {
|
||||
// Delete imported products
|
||||
await withRestApi.deleteAllProducts();
|
||||
await withRestApi.deleteAllProductAttributes( false );
|
||||
await withRestApi.deleteAllProductCategories( false );
|
||||
await withRestApi.deleteAllProductTags( false );
|
||||
});
|
||||
} );
|
||||
|
||||
it( 'should show error message if you go without providing CSV file', async () => {
|
||||
// Verify the error message if you go without providing CSV file
|
||||
|
|
|
@ -13,22 +13,19 @@ const {
|
|||
waitForSelector,
|
||||
waitForSelectorWithoutThrow,
|
||||
} = require( '@woocommerce/e2e-utils' );
|
||||
const {
|
||||
waitAndClick,
|
||||
} = require( '@woocommerce/e2e-environment' );
|
||||
const { waitAndClick } = require( '@woocommerce/e2e-environment' );
|
||||
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
const {
|
||||
it,
|
||||
describe,
|
||||
} = require( '@jest/globals' );
|
||||
const { it, describe } = require( '@jest/globals' );
|
||||
const config = require( 'config' );
|
||||
|
||||
const VirtualProductName = 'Virtual Product Name';
|
||||
const NonVirtualProductName = 'Non-Virtual Product Name';
|
||||
const simpleProductPrice = config.has('products.simple.price') ? config.get('products.simple.price') : '9.99';
|
||||
const simpleProductPrice = config.has( 'products.simple.price' )
|
||||
? config.get( 'products.simple.price' )
|
||||
: '9.99';
|
||||
const defaultAttributes = [ 'val2', 'val1', 'val2' ];
|
||||
|
||||
const openNewProductAndVerify = async () => {
|
||||
|
@ -36,13 +33,13 @@ const openNewProductAndVerify = async () => {
|
|||
await merchant.openNewProduct();
|
||||
|
||||
// Make sure we're on the add product page
|
||||
await expect(page.title()).resolves.toMatch('Add new product');
|
||||
}
|
||||
await expect( page.title() ).resolves.toMatch( 'Add new product' );
|
||||
};
|
||||
|
||||
/**
|
||||
* Select a variation action from the actions menu.
|
||||
*
|
||||
* @param action item you selected from the variation actions menu
|
||||
* @param action item you selected from the variation actions menu
|
||||
*/
|
||||
const selectVariationAction = async ( action ) => {
|
||||
await waitForSelector( page, 'select.variation_actions:not(:disabled)' );
|
||||
|
@ -67,9 +64,8 @@ const expandVariations = async () => {
|
|||
};
|
||||
|
||||
const runAddSimpleProductTest = () => {
|
||||
describe('Add New Simple Product Page', () => {
|
||||
it('can create simple virtual product and add it to the cart', async () => {
|
||||
|
||||
describe( 'Add New Simple Product Page', () => {
|
||||
it( 'can create simple virtual product and add it to the cart', async () => {
|
||||
// @todo: remove this once https://github.com/woocommerce/woocommerce/issues/31337 has been addressed
|
||||
await setBrowserViewport( {
|
||||
width: 970,
|
||||
|
@ -80,30 +76,35 @@ const runAddSimpleProductTest = () => {
|
|||
await openNewProductAndVerify();
|
||||
|
||||
// Set product data and publish the product
|
||||
await expect(page).toFill('#title', VirtualProductName);
|
||||
await expect(page).toClick('#_virtual');
|
||||
await clickTab('General');
|
||||
await expect(page).toFill('#_regular_price', simpleProductPrice);
|
||||
await expect( page ).toFill( '#title', VirtualProductName );
|
||||
await expect( page ).toClick( '#_virtual' );
|
||||
await clickTab( 'General' );
|
||||
await expect( page ).toFill(
|
||||
'#_regular_price',
|
||||
simpleProductPrice
|
||||
);
|
||||
await verifyAndPublish();
|
||||
|
||||
await merchant.logout();
|
||||
});
|
||||
} );
|
||||
|
||||
it('can have a shopper add the simple virtual product to the cart', async () => {
|
||||
it( 'can have a shopper add the simple virtual product to the cart', async () => {
|
||||
// See product in the shop and add it to the cart
|
||||
await shopper.goToShop();
|
||||
await shopper.addToCartFromShopPage(VirtualProductName);
|
||||
await shopper.addToCartFromShopPage( VirtualProductName );
|
||||
await shopper.goToCart();
|
||||
await shopper.productIsInCart(VirtualProductName);
|
||||
await shopper.productIsInCart( VirtualProductName );
|
||||
|
||||
// Assert that the page does not contain shipping calculation button
|
||||
await expect(page).not.toMatchElement('a.shipping-calculator-button');
|
||||
await expect( page ).not.toMatchElement(
|
||||
'a.shipping-calculator-button'
|
||||
);
|
||||
|
||||
// Remove product from cart
|
||||
await shopper.removeFromCart(VirtualProductName);
|
||||
});
|
||||
await shopper.removeFromCart( VirtualProductName );
|
||||
} );
|
||||
|
||||
it('can create simple non-virtual product and add it to the cart', async () => {
|
||||
it( 'can create simple non-virtual product and add it to the cart', async () => {
|
||||
// @todo: remove this once https://github.com/woocommerce/woocommerce/issues/31337 has been addressed
|
||||
await setBrowserViewport( {
|
||||
width: 960,
|
||||
|
@ -114,74 +115,104 @@ const runAddSimpleProductTest = () => {
|
|||
await openNewProductAndVerify();
|
||||
|
||||
// Set product data and publish the product
|
||||
await expect(page).toFill('#title', NonVirtualProductName);
|
||||
await clickTab('General');
|
||||
await expect(page).toFill('#_regular_price', simpleProductPrice);
|
||||
await expect( page ).toFill( '#title', NonVirtualProductName );
|
||||
await clickTab( 'General' );
|
||||
await expect( page ).toFill(
|
||||
'#_regular_price',
|
||||
simpleProductPrice
|
||||
);
|
||||
await verifyAndPublish();
|
||||
|
||||
await merchant.logout();
|
||||
});
|
||||
} );
|
||||
|
||||
it('can have a shopper add the simple non-virtual product to the cart', async () => {
|
||||
it( 'can have a shopper add the simple non-virtual product to the cart', async () => {
|
||||
// See product in the shop and add it to the cart
|
||||
await shopper.goToShop();
|
||||
|
||||
await page.reload({ waitUntil: ['networkidle0', 'domcontentloaded'] });
|
||||
await page.reload( {
|
||||
waitUntil: [ 'networkidle0', 'domcontentloaded' ],
|
||||
} );
|
||||
|
||||
await shopper.addToCartFromShopPage(NonVirtualProductName);
|
||||
await shopper.addToCartFromShopPage( NonVirtualProductName );
|
||||
await shopper.goToCart();
|
||||
await shopper.productIsInCart(NonVirtualProductName);
|
||||
await shopper.productIsInCart( NonVirtualProductName );
|
||||
|
||||
// Assert that the page does contain shipping calculation button
|
||||
await page.waitForSelector('a.shipping-calculator-button');
|
||||
await expect(page).toMatchElement('a.shipping-calculator-button');
|
||||
await page.waitForSelector( 'a.shipping-calculator-button' );
|
||||
await expect( page ).toMatchElement(
|
||||
'a.shipping-calculator-button'
|
||||
);
|
||||
|
||||
// Remove product from cart
|
||||
await shopper.removeFromCart(NonVirtualProductName);
|
||||
});
|
||||
});
|
||||
await shopper.removeFromCart( NonVirtualProductName );
|
||||
} );
|
||||
} );
|
||||
};
|
||||
|
||||
const runAddVariableProductTest = () => {
|
||||
describe('Add New Variable Product Page', () => {
|
||||
it('can create product with variations', async () => {
|
||||
describe( 'Add New Variable Product Page', () => {
|
||||
it( 'can create product with variations', async () => {
|
||||
await merchant.login();
|
||||
await openNewProductAndVerify();
|
||||
|
||||
// Set product data
|
||||
await expect(page).toFill('#title', 'Variable Product with Three Variations');
|
||||
await expect(page).toSelect('#product-type', 'Variable product');
|
||||
});
|
||||
|
||||
it('can create set variable product attributes', async () => {
|
||||
await expect( page ).toFill(
|
||||
'#title',
|
||||
'Variable Product with Three Variations'
|
||||
);
|
||||
await expect( page ).toSelect(
|
||||
'#product-type',
|
||||
'Variable product'
|
||||
);
|
||||
} );
|
||||
|
||||
it( 'can create set variable product attributes', async () => {
|
||||
// Create attributes for variations
|
||||
await waitAndClick( page, '.attribute_tab a' );
|
||||
await expect( page ).toSelect( 'select[name="attribute_taxonomy"]', 'Custom product attribute' );
|
||||
await expect( page ).toSelect(
|
||||
'select[name="attribute_taxonomy"]',
|
||||
'Custom product attribute'
|
||||
);
|
||||
|
||||
for ( let i = 0; i < 3; i++ ) {
|
||||
await expect(page).toClick( 'button.add_attribute', {text: 'Add'} );
|
||||
await expect( page ).toClick( 'button.add_attribute', {
|
||||
text: 'Add',
|
||||
} );
|
||||
// Wait for attribute form to load
|
||||
await uiUnblocked();
|
||||
|
||||
await page.focus(`input[name="attribute_names[${i}]"]`);
|
||||
await expect(page).toFill(`input[name="attribute_names[${i}]"]`, 'attr #' + (i + 1));
|
||||
await expect(page).toFill(`textarea[name="attribute_values[${i}]"]`, 'val1 | val2');
|
||||
await waitAndClick( page, `input[name="attribute_variation[${i}]"]`);
|
||||
await page.focus( `input[name="attribute_names[${ i }]"]` );
|
||||
await expect( page ).toFill(
|
||||
`input[name="attribute_names[${ i }]"]`,
|
||||
'attr #' + ( i + 1 )
|
||||
);
|
||||
await expect( page ).toFill(
|
||||
`textarea[name="attribute_values[${ i }]"]`,
|
||||
'val1 | val2'
|
||||
);
|
||||
await waitAndClick(
|
||||
page,
|
||||
`input[name="attribute_variation[${ i }]"]`
|
||||
);
|
||||
}
|
||||
|
||||
await expect(page).toClick( 'button', {text: 'Save attributes'});
|
||||
await expect( page ).toClick( 'button', {
|
||||
text: 'Save attributes',
|
||||
} );
|
||||
|
||||
// Wait for attribute form to save (triggers 2 UI blocks)
|
||||
await uiUnblocked();
|
||||
await uiUnblocked();
|
||||
});
|
||||
} );
|
||||
|
||||
it('can create variations from all attributes', async () => {
|
||||
it( 'can create variations from all attributes', async () => {
|
||||
// Create variations from attributes
|
||||
await waitForSelector( page, '.variations_tab' );
|
||||
await waitAndClick( page, '.variations_tab a' );
|
||||
await selectVariationAction('Create variations from all attributes');
|
||||
await selectVariationAction(
|
||||
'Create variations from all attributes'
|
||||
);
|
||||
|
||||
// headless: false doesn't require this
|
||||
const firstDialog = await expect( page ).toDisplayDialog(
|
||||
|
@ -190,24 +221,22 @@ const runAddVariableProductTest = () => {
|
|||
}
|
||||
);
|
||||
|
||||
await expect(firstDialog.message()).toMatch('Are you sure you want to link all variations?');
|
||||
await expect( firstDialog.message() ).toMatch(
|
||||
'Are you sure you want to link all variations?'
|
||||
);
|
||||
|
||||
// Set some variation data
|
||||
await uiUnblocked();
|
||||
await uiUnblocked();
|
||||
});
|
||||
} );
|
||||
|
||||
it('can add variation attributes', async () => {
|
||||
it( 'can add variation attributes', async () => {
|
||||
await waitAndClick( page, '.variations_tab a' );
|
||||
await uiUnblocked();
|
||||
await waitForSelector(
|
||||
page,
|
||||
'select[name="attribute_attr-1[0]"]',
|
||||
{
|
||||
visible: true,
|
||||
timeout: 5000
|
||||
}
|
||||
);
|
||||
await waitForSelector( page, 'select[name="attribute_attr-1[0]"]', {
|
||||
visible: true,
|
||||
timeout: 5000,
|
||||
} );
|
||||
|
||||
// Verify that variations were created
|
||||
for ( let index = 0; index < 8; index++ ) {
|
||||
|
@ -215,34 +244,67 @@ const runAddVariableProductTest = () => {
|
|||
const val2 = { text: 'val2' };
|
||||
|
||||
// odd / even
|
||||
let attr3 = !! ( index % 2 );
|
||||
const attr3 = !! ( index % 2 );
|
||||
// 0-1,4-5 / 2-3,6-7
|
||||
let attr2 = ( index % 4 ) > 1;
|
||||
const attr2 = index % 4 > 1;
|
||||
// 0-3 / 4-7
|
||||
let attr1 = ( index > 3 );
|
||||
const attr1 = index > 3;
|
||||
|
||||
await expect( page ).toMatchElement( `select[name="attribute_attr-1[${index}]"]`, attr1 ? val2 : val1 );
|
||||
await expect( page ).toMatchElement( `select[name="attribute_attr-2[${index}]"]`, attr2 ? val2 : val1 );
|
||||
await expect( page ).toMatchElement( `select[name="attribute_attr-3[${index}]"]`, attr3 ? val2 : val1 );
|
||||
await expect( page ).toMatchElement(
|
||||
`select[name="attribute_attr-1[${ index }]"]`,
|
||||
attr1 ? val2 : val1
|
||||
);
|
||||
await expect( page ).toMatchElement(
|
||||
`select[name="attribute_attr-2[${ index }]"]`,
|
||||
attr2 ? val2 : val1
|
||||
);
|
||||
await expect( page ).toMatchElement(
|
||||
`select[name="attribute_attr-3[${ index }]"]`,
|
||||
attr3 ? val2 : val1
|
||||
);
|
||||
}
|
||||
|
||||
await expandVariations();
|
||||
await waitForSelectorWithoutThrow( 'input[name="variable_is_virtual[0]"]', 5 );
|
||||
await setCheckbox('input[name="variable_is_virtual[0]"]');
|
||||
await expect(page).toFill('input[name="variable_regular_price[0]"]', '9.99');
|
||||
await waitForSelectorWithoutThrow(
|
||||
'input[name="variable_is_virtual[0]"]',
|
||||
5
|
||||
);
|
||||
await setCheckbox( 'input[name="variable_is_virtual[0]"]' );
|
||||
await expect( page ).toFill(
|
||||
'input[name="variable_regular_price[0]"]',
|
||||
'9.99'
|
||||
);
|
||||
|
||||
await setCheckbox('input[name="variable_is_virtual[1]"]');
|
||||
await expect(page).toFill('input[name="variable_regular_price[1]"]', '11.99');
|
||||
await setCheckbox( 'input[name="variable_is_virtual[1]"]' );
|
||||
await expect( page ).toFill(
|
||||
'input[name="variable_regular_price[1]"]',
|
||||
'11.99'
|
||||
);
|
||||
|
||||
await setCheckbox('input[name="variable_manage_stock[2]"]');
|
||||
await expect(page).toFill('input[name="variable_regular_price[2]"]', '20');
|
||||
await expect(page).toFill('input[name="variable_weight[2]"]', '200');
|
||||
await expect(page).toFill('input[name="variable_length[2]"]', '10');
|
||||
await expect(page).toFill('input[name="variable_width[2]"]', '20');
|
||||
await expect(page).toFill('input[name="variable_height[2]"]', '15');
|
||||
await setCheckbox( 'input[name="variable_manage_stock[2]"]' );
|
||||
await expect( page ).toFill(
|
||||
'input[name="variable_regular_price[2]"]',
|
||||
'20'
|
||||
);
|
||||
await expect( page ).toFill(
|
||||
'input[name="variable_weight[2]"]',
|
||||
'200'
|
||||
);
|
||||
await expect( page ).toFill(
|
||||
'input[name="variable_length[2]"]',
|
||||
'10'
|
||||
);
|
||||
await expect( page ).toFill(
|
||||
'input[name="variable_width[2]"]',
|
||||
'20'
|
||||
);
|
||||
await expect( page ).toFill(
|
||||
'input[name="variable_height[2]"]',
|
||||
'15'
|
||||
);
|
||||
|
||||
await saveChanges();
|
||||
});
|
||||
} );
|
||||
|
||||
it( 'can bulk-edit variations', async () => {
|
||||
// Verify that all 'Downloadable' checkboxes are UNCHECKED.
|
||||
|
@ -258,7 +320,7 @@ const runAddVariableProductTest = () => {
|
|||
}
|
||||
|
||||
// Perform the 'Toggle "Downloadable"' bulk action
|
||||
await selectVariationAction('Toggle "Downloadable"');
|
||||
await selectVariationAction( 'Toggle "Downloadable"' );
|
||||
|
||||
await clickGoButton();
|
||||
await uiUnblocked();
|
||||
|
@ -407,7 +469,7 @@ const runAddVariableProductTest = () => {
|
|||
const variationsCount = await page.$$( '.woocommerce_variation' );
|
||||
expect( variationsCount ).toHaveLength( 0 );
|
||||
} );
|
||||
});
|
||||
} );
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
|
|
|
@ -3,76 +3,88 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
const {
|
||||
merchant,
|
||||
createSimpleProduct
|
||||
} = require( '@woocommerce/e2e-utils' );
|
||||
const { merchant, createSimpleProduct } = require( '@woocommerce/e2e-utils' );
|
||||
|
||||
const config = require( 'config' );
|
||||
const simpleProductName = config.get( 'products.simple.name' );
|
||||
const simpleProductPrice = config.has('products.simple.price') ? config.get('products.simple.price') : '9.99';
|
||||
const simpleProductPrice = config.has( 'products.simple.price' )
|
||||
? config.get( 'products.simple.price' )
|
||||
: '9.99';
|
||||
|
||||
const runProductSearchTest = () => {
|
||||
describe('Products > Search and View a product', () => {
|
||||
beforeAll(async () => {
|
||||
describe( 'Products > Search and View a product', () => {
|
||||
beforeAll( async () => {
|
||||
await createSimpleProduct();
|
||||
|
||||
// Make sure the simple product name is greater than 1 to do a search
|
||||
await expect(simpleProductName.length).toBeGreaterThan(1);
|
||||
await expect( simpleProductName.length ).toBeGreaterThan( 1 );
|
||||
|
||||
await merchant.login();
|
||||
});
|
||||
} );
|
||||
|
||||
beforeEach(async () => {
|
||||
beforeEach( async () => {
|
||||
await merchant.openAllProductsView();
|
||||
});
|
||||
} );
|
||||
|
||||
it('can do a partial search for a product', async () => {
|
||||
it( 'can do a partial search for a product', async () => {
|
||||
// Create partial search string
|
||||
let searchString = simpleProductName.substring(0, (simpleProductName.length / 2));
|
||||
await expect(page).toFill('#post-search-input', searchString);
|
||||
const searchString = simpleProductName.substring(
|
||||
0,
|
||||
simpleProductName.length / 2
|
||||
);
|
||||
await expect( page ).toFill( '#post-search-input', searchString );
|
||||
|
||||
// Click search and wait for the page to finish loading
|
||||
await Promise.all( [
|
||||
page.click( '#search-submit' ),
|
||||
page.waitForNavigation( { waitUntil: 'networkidle0' } ),
|
||||
]);
|
||||
] );
|
||||
|
||||
// Verify we are getting the results back in the list
|
||||
await expect(page).toMatchElement('.row-title', { text: simpleProductName });
|
||||
});
|
||||
await expect( page ).toMatchElement( '.row-title', {
|
||||
text: simpleProductName,
|
||||
} );
|
||||
} );
|
||||
|
||||
it('can view a product\'s details after search', async () => {
|
||||
await expect(page).toFill('#post-search-input', simpleProductName);
|
||||
it( "can view a product's details after search", async () => {
|
||||
await expect( page ).toFill(
|
||||
'#post-search-input',
|
||||
simpleProductName
|
||||
);
|
||||
|
||||
await Promise.all( [
|
||||
page.click( '#search-submit' ),
|
||||
page.waitForNavigation( { waitUntil: 'networkidle0' } ),
|
||||
]);
|
||||
] );
|
||||
|
||||
// Click to view the product and wait for the page to finish loading
|
||||
await Promise.all( [
|
||||
expect(page).toClick('.row-title', simpleProductName),
|
||||
expect( page ).toClick( '.row-title', simpleProductName ),
|
||||
page.waitForNavigation( { waitUntil: 'networkidle0' } ),
|
||||
]);
|
||||
] );
|
||||
|
||||
await expect(page).toMatchElement('#title', simpleProductName);
|
||||
await expect(page).toMatchElement('#_regular_price', simpleProductPrice);
|
||||
});
|
||||
await expect( page ).toMatchElement( '#title', simpleProductName );
|
||||
await expect( page ).toMatchElement(
|
||||
'#_regular_price',
|
||||
simpleProductPrice
|
||||
);
|
||||
} );
|
||||
|
||||
it('returns no results for non-existent product search', async () => {
|
||||
await expect(page).toFill('#post-search-input', 'abcd1234');
|
||||
it( 'returns no results for non-existent product search', async () => {
|
||||
await expect( page ).toFill( '#post-search-input', 'abcd1234' );
|
||||
|
||||
// Click search and wait for the page to finish loading
|
||||
await Promise.all( [
|
||||
page.click( '#search-submit' ),
|
||||
page.waitForNavigation( { waitUntil: 'networkidle0' } ),
|
||||
]);
|
||||
] );
|
||||
|
||||
// Verify we are getting the results back in the list
|
||||
await expect(page).toMatchElement('.no-items', { text: 'No products found' });
|
||||
});
|
||||
});
|
||||
}
|
||||
await expect( page ).toMatchElement( '.no-items', {
|
||||
text: 'No products found',
|
||||
} );
|
||||
} );
|
||||
} );
|
||||
};
|
||||
|
||||
module.exports = runProductSearchTest;
|
||||
|
|
|
@ -11,74 +11,126 @@ const {
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
const {
|
||||
it,
|
||||
describe,
|
||||
beforeAll,
|
||||
} = require( '@jest/globals' );
|
||||
const { it, describe, beforeAll } = require( '@jest/globals' );
|
||||
|
||||
const runUpdateGeneralSettingsTest = () => {
|
||||
describe('WooCommerce General Settings', () => {
|
||||
beforeAll(async () => {
|
||||
describe( 'WooCommerce General Settings', () => {
|
||||
beforeAll( async () => {
|
||||
await merchant.login();
|
||||
});
|
||||
} );
|
||||
|
||||
it('can update settings', async () => {
|
||||
it( 'can update settings', async () => {
|
||||
// Go to general settings page
|
||||
await merchant.openSettings('general');
|
||||
await merchant.openSettings( 'general' );
|
||||
|
||||
// Make sure the general tab is active
|
||||
await expect(page).toMatchElement('a.nav-tab-active', {text: 'General'});
|
||||
await expect( page ).toMatchElement( 'a.nav-tab-active', {
|
||||
text: 'General',
|
||||
} );
|
||||
|
||||
// Set selling location to all countries first,
|
||||
// so we can choose california as base location.
|
||||
await expect(page).toSelect('#woocommerce_allowed_countries', 'Sell to all countries');
|
||||
await expect( page ).toSelect(
|
||||
'#woocommerce_allowed_countries',
|
||||
'Sell to all countries'
|
||||
);
|
||||
await settingsPageSaveChanges();
|
||||
|
||||
// Verify that settings have been saved
|
||||
await Promise.all([
|
||||
expect(page).toMatchElement('#message', {text: 'Your settings have been saved.'}),
|
||||
expect(page).toMatchElement('#woocommerce_allowed_countries', {text: 'Sell to all countries'}),
|
||||
]);
|
||||
await Promise.all( [
|
||||
expect( page ).toMatchElement( '#message', {
|
||||
text: 'Your settings have been saved.',
|
||||
} ),
|
||||
expect( page ).toMatchElement(
|
||||
'#woocommerce_allowed_countries',
|
||||
{ text: 'Sell to all countries' }
|
||||
),
|
||||
] );
|
||||
|
||||
// Set base location with state CA.
|
||||
await expect(page).toSelect('select[name="woocommerce_default_country"]', 'United States (US) — California');
|
||||
await expect( page ).toSelect(
|
||||
'select[name="woocommerce_default_country"]',
|
||||
'United States (US) — California'
|
||||
);
|
||||
await settingsPageSaveChanges();
|
||||
|
||||
// Verify that settings have been saved
|
||||
await Promise.all([
|
||||
expect(page).toMatchElement('#message', {text: 'Your settings have been saved.'}),
|
||||
expect(page).toMatchElement('select[name="woocommerce_default_country"]', {text: 'United States (US) — California'}),
|
||||
]);
|
||||
await Promise.all( [
|
||||
expect( page ).toMatchElement( '#message', {
|
||||
text: 'Your settings have been saved.',
|
||||
} ),
|
||||
expect(
|
||||
page
|
||||
).toMatchElement(
|
||||
'select[name="woocommerce_default_country"]',
|
||||
{ text: 'United States (US) — California' }
|
||||
),
|
||||
] );
|
||||
|
||||
// Set selling location to specific countries first, so we can choose U.S as base location (without state).
|
||||
// This will makes specific countries option appears.
|
||||
await expect(page).toSelect('#woocommerce_allowed_countries', 'Sell to specific countries');
|
||||
await expect(page).toSelect('select[name="woocommerce_specific_allowed_countries[]"]', 'United States (US)');
|
||||
await expect( page ).toSelect(
|
||||
'#woocommerce_allowed_countries',
|
||||
'Sell to specific countries'
|
||||
);
|
||||
await expect( page ).toSelect(
|
||||
'select[name="woocommerce_specific_allowed_countries[]"]',
|
||||
'United States (US)'
|
||||
);
|
||||
await settingsPageSaveChanges();
|
||||
|
||||
// Verify that settings have been saved
|
||||
await Promise.all([
|
||||
expect(page).toMatchElement('#message', {text: 'Your settings have been saved.'}),
|
||||
expect(page).toMatchElement('#woocommerce_allowed_countries', {text: 'Sell to specific countries'}),
|
||||
expect(page).toMatchElement('select[name="woocommerce_specific_allowed_countries[]"]', {text: 'United States (US)'}),
|
||||
]);
|
||||
await Promise.all( [
|
||||
expect( page ).toMatchElement( '#message', {
|
||||
text: 'Your settings have been saved.',
|
||||
} ),
|
||||
expect( page ).toMatchElement(
|
||||
'#woocommerce_allowed_countries',
|
||||
{ text: 'Sell to specific countries' }
|
||||
),
|
||||
expect(
|
||||
page
|
||||
).toMatchElement(
|
||||
'select[name="woocommerce_specific_allowed_countries[]"]',
|
||||
{ text: 'United States (US)' }
|
||||
),
|
||||
] );
|
||||
|
||||
// Set currency options.
|
||||
await expect(page).toFill('#woocommerce_price_thousand_sep', ',');
|
||||
await expect(page).toFill('#woocommerce_price_decimal_sep', '.');
|
||||
await expect(page).toFill('#woocommerce_price_num_decimals', '2');
|
||||
await expect( page ).toFill(
|
||||
'#woocommerce_price_thousand_sep',
|
||||
','
|
||||
);
|
||||
await expect( page ).toFill(
|
||||
'#woocommerce_price_decimal_sep',
|
||||
'.'
|
||||
);
|
||||
await expect( page ).toFill(
|
||||
'#woocommerce_price_num_decimals',
|
||||
'2'
|
||||
);
|
||||
await settingsPageSaveChanges();
|
||||
|
||||
// Verify that settings have been saved
|
||||
await Promise.all([
|
||||
expect(page).toMatchElement('#message', {text: 'Your settings have been saved.'}),
|
||||
verifyValueOfInputField('#woocommerce_price_thousand_sep', ','),
|
||||
verifyValueOfInputField('#woocommerce_price_decimal_sep', '.'),
|
||||
verifyValueOfInputField('#woocommerce_price_num_decimals', '2'),
|
||||
]);
|
||||
});
|
||||
});
|
||||
await Promise.all( [
|
||||
expect( page ).toMatchElement( '#message', {
|
||||
text: 'Your settings have been saved.',
|
||||
} ),
|
||||
verifyValueOfInputField(
|
||||
'#woocommerce_price_thousand_sep',
|
||||
','
|
||||
),
|
||||
verifyValueOfInputField(
|
||||
'#woocommerce_price_decimal_sep',
|
||||
'.'
|
||||
),
|
||||
verifyValueOfInputField(
|
||||
'#woocommerce_price_num_decimals',
|
||||
'2'
|
||||
),
|
||||
] );
|
||||
} );
|
||||
} );
|
||||
};
|
||||
|
||||
module.exports = runUpdateGeneralSettingsTest;
|
||||
|
|
|
@ -12,65 +12,124 @@ const {
|
|||
} = require( '@woocommerce/e2e-utils' );
|
||||
|
||||
const runProductSettingsTest = () => {
|
||||
describe('WooCommerce Products > Downloadable Products Settings', () => {
|
||||
beforeAll(async () => {
|
||||
describe( 'WooCommerce Products > Downloadable Products Settings', () => {
|
||||
beforeAll( async () => {
|
||||
await merchant.login();
|
||||
});
|
||||
} );
|
||||
|
||||
it('can update settings', async () => {
|
||||
it( 'can update settings', async () => {
|
||||
// Go to downloadable products settings page
|
||||
await merchant.openSettings('products', 'downloadable');
|
||||
await merchant.openSettings( 'products', 'downloadable' );
|
||||
|
||||
// Make sure the product tab is active
|
||||
await expect(page).toMatchElement('a.nav-tab-active', {text: 'Products'});
|
||||
await expect(page).toMatchElement('ul.subsubsub > li > a.current', {text: 'Downloadable products'});
|
||||
await expect( page ).toMatchElement( 'a.nav-tab-active', {
|
||||
text: 'Products',
|
||||
} );
|
||||
await expect( page ).toMatchElement(
|
||||
'ul.subsubsub > li > a.current',
|
||||
{
|
||||
text: 'Downloadable products',
|
||||
}
|
||||
);
|
||||
|
||||
await expect(page).toSelect('#woocommerce_file_download_method', 'Redirect only (Insecure)');
|
||||
await setCheckbox('#woocommerce_downloads_require_login');
|
||||
await setCheckbox('#woocommerce_downloads_grant_access_after_payment');
|
||||
await setCheckbox('#woocommerce_downloads_redirect_fallback_allowed');
|
||||
await unsetCheckbox('#woocommerce_downloads_add_hash_to_filename');
|
||||
await expect( page ).toSelect(
|
||||
'#woocommerce_file_download_method',
|
||||
'Redirect only (Insecure)'
|
||||
);
|
||||
await setCheckbox( '#woocommerce_downloads_require_login' );
|
||||
await setCheckbox(
|
||||
'#woocommerce_downloads_grant_access_after_payment'
|
||||
);
|
||||
await setCheckbox(
|
||||
'#woocommerce_downloads_redirect_fallback_allowed'
|
||||
);
|
||||
await unsetCheckbox(
|
||||
'#woocommerce_downloads_add_hash_to_filename'
|
||||
);
|
||||
await settingsPageSaveChanges();
|
||||
|
||||
// Verify that settings have been saved
|
||||
await Promise.all([
|
||||
expect(page).toMatchElement('#message', {text: 'Your settings have been saved.'}),
|
||||
expect(page).toMatchElement('#woocommerce_file_download_method', {text: 'Redirect only (Insecure)'}),
|
||||
verifyCheckboxIsSet('#woocommerce_downloads_require_login'),
|
||||
verifyCheckboxIsSet('#woocommerce_downloads_grant_access_after_payment'),
|
||||
verifyCheckboxIsSet('#woocommerce_downloads_redirect_fallback_allowed'),
|
||||
verifyCheckboxIsUnset('#woocommerce_downloads_add_hash_to_filename')
|
||||
]);
|
||||
await Promise.all( [
|
||||
expect( page ).toMatchElement( '#message', {
|
||||
text: 'Your settings have been saved.',
|
||||
} ),
|
||||
expect( page ).toMatchElement(
|
||||
'#woocommerce_file_download_method',
|
||||
{
|
||||
text: 'Redirect only (Insecure)',
|
||||
}
|
||||
),
|
||||
verifyCheckboxIsSet( '#woocommerce_downloads_require_login' ),
|
||||
verifyCheckboxIsSet(
|
||||
'#woocommerce_downloads_grant_access_after_payment'
|
||||
),
|
||||
verifyCheckboxIsSet(
|
||||
'#woocommerce_downloads_redirect_fallback_allowed'
|
||||
),
|
||||
verifyCheckboxIsUnset(
|
||||
'#woocommerce_downloads_add_hash_to_filename'
|
||||
),
|
||||
] );
|
||||
|
||||
await page.reload();
|
||||
await expect(page).toSelect('#woocommerce_file_download_method', 'X-Accel-Redirect/X-Sendfile');
|
||||
await unsetCheckbox('#woocommerce_downloads_require_login');
|
||||
await unsetCheckbox('#woocommerce_downloads_grant_access_after_payment');
|
||||
await unsetCheckbox('#woocommerce_downloads_redirect_fallback_allowed');
|
||||
await setCheckbox('#woocommerce_downloads_add_hash_to_filename');
|
||||
await expect( page ).toSelect(
|
||||
'#woocommerce_file_download_method',
|
||||
'X-Accel-Redirect/X-Sendfile'
|
||||
);
|
||||
await unsetCheckbox( '#woocommerce_downloads_require_login' );
|
||||
await unsetCheckbox(
|
||||
'#woocommerce_downloads_grant_access_after_payment'
|
||||
);
|
||||
await unsetCheckbox(
|
||||
'#woocommerce_downloads_redirect_fallback_allowed'
|
||||
);
|
||||
await setCheckbox( '#woocommerce_downloads_add_hash_to_filename' );
|
||||
await settingsPageSaveChanges();
|
||||
|
||||
// Verify that settings have been saved
|
||||
await Promise.all([
|
||||
expect(page).toMatchElement('#message', {text: 'Your settings have been saved.'}),
|
||||
expect(page).toMatchElement('#woocommerce_file_download_method', {text: 'X-Accel-Redirect/X-Sendfile'}),
|
||||
verifyCheckboxIsUnset('#woocommerce_downloads_require_login'),
|
||||
verifyCheckboxIsUnset('#woocommerce_downloads_grant_access_after_payment'),
|
||||
verifyCheckboxIsUnset('#woocommerce_downloads_redirect_fallback_allowed'),
|
||||
verifyCheckboxIsSet('#woocommerce_downloads_add_hash_to_filename')
|
||||
]);
|
||||
await Promise.all( [
|
||||
expect( page ).toMatchElement( '#message', {
|
||||
text: 'Your settings have been saved.',
|
||||
} ),
|
||||
expect( page ).toMatchElement(
|
||||
'#woocommerce_file_download_method',
|
||||
{
|
||||
text: 'X-Accel-Redirect/X-Sendfile',
|
||||
}
|
||||
),
|
||||
verifyCheckboxIsUnset( '#woocommerce_downloads_require_login' ),
|
||||
verifyCheckboxIsUnset(
|
||||
'#woocommerce_downloads_grant_access_after_payment'
|
||||
),
|
||||
verifyCheckboxIsUnset(
|
||||
'#woocommerce_downloads_redirect_fallback_allowed'
|
||||
),
|
||||
verifyCheckboxIsSet(
|
||||
'#woocommerce_downloads_add_hash_to_filename'
|
||||
),
|
||||
] );
|
||||
|
||||
await page.reload();
|
||||
await expect(page).toSelect('#woocommerce_file_download_method', 'Force downloads');
|
||||
await expect( page ).toSelect(
|
||||
'#woocommerce_file_download_method',
|
||||
'Force downloads'
|
||||
);
|
||||
await settingsPageSaveChanges();
|
||||
|
||||
// Verify that settings have been saved
|
||||
await Promise.all([
|
||||
expect(page).toMatchElement('#message', {text: 'Your settings have been saved.'}),
|
||||
expect(page).toMatchElement('#woocommerce_file_download_method', {text: 'Force downloads'})
|
||||
]);
|
||||
});
|
||||
});
|
||||
await Promise.all( [
|
||||
expect( page ).toMatchElement( '#message', {
|
||||
text: 'Your settings have been saved.',
|
||||
} ),
|
||||
expect( page ).toMatchElement(
|
||||
'#woocommerce_file_download_method',
|
||||
{
|
||||
text: 'Force downloads',
|
||||
}
|
||||
),
|
||||
] );
|
||||
} );
|
||||
} );
|
||||
};
|
||||
|
||||
module.exports = runProductSettingsTest;
|
||||
|
|
|
@ -1,72 +1,76 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
const { merchant, withRestApi } = require('@woocommerce/e2e-utils');
|
||||
const { merchant, withRestApi } = require( '@woocommerce/e2e-utils' );
|
||||
|
||||
const runAddShippingClassesTest = () => {
|
||||
describe('Merchant can add shipping classes', () => {
|
||||
beforeAll(async () => {
|
||||
describe( 'Merchant can add shipping classes', () => {
|
||||
beforeAll( async () => {
|
||||
await merchant.login();
|
||||
|
||||
// Go to Shipping Classes page
|
||||
await merchant.openSettings('shipping', 'classes');
|
||||
});
|
||||
await merchant.openSettings( 'shipping', 'classes' );
|
||||
} );
|
||||
|
||||
afterAll(async () => {
|
||||
afterAll( async () => {
|
||||
await withRestApi.deleteAllShippingClasses( false );
|
||||
});
|
||||
} );
|
||||
|
||||
it('can add shipping classes', async () => {
|
||||
it( 'can add shipping classes', async () => {
|
||||
const shippingClassSlug = {
|
||||
name: 'Small Items',
|
||||
slug: 'small-items',
|
||||
description: 'Small items that don\'t cost much to ship.'
|
||||
description: "Small items that don't cost much to ship.",
|
||||
};
|
||||
const shippingClassNoSlug = {
|
||||
name: 'Poster Pack',
|
||||
slug: '',
|
||||
description: ''
|
||||
description: '',
|
||||
};
|
||||
const shippingClasses = [shippingClassSlug, shippingClassNoSlug];
|
||||
const shippingClasses = [ shippingClassSlug, shippingClassNoSlug ];
|
||||
|
||||
// Add shipping classes
|
||||
for (const { name, slug, description } of shippingClasses) {
|
||||
await expect(page).toClick('.wc-shipping-class-add');
|
||||
await expect(page).toFill(
|
||||
for ( const { name, slug, description } of shippingClasses ) {
|
||||
await expect( page ).toClick( '.wc-shipping-class-add' );
|
||||
await expect( page ).toFill(
|
||||
'.editing:last-child [data-attribute="name"]',
|
||||
name
|
||||
);
|
||||
await expect(page).toFill(
|
||||
await expect( page ).toFill(
|
||||
'.editing:last-child [data-attribute="slug"]',
|
||||
slug
|
||||
);
|
||||
await expect(page).toFill(
|
||||
await expect( page ).toFill(
|
||||
'.editing:last-child [data-attribute="description"]',
|
||||
description
|
||||
);
|
||||
}
|
||||
await expect(page).toClick('.wc-shipping-class-save');
|
||||
await expect( page ).toClick( '.wc-shipping-class-save' );
|
||||
|
||||
// Set the expected auto-generated slug
|
||||
shippingClassNoSlug.slug = 'poster-pack';
|
||||
|
||||
// Verify that the specified shipping classes were saved
|
||||
for (const { name, slug, description } of shippingClasses) {
|
||||
const row = await expect(
|
||||
page
|
||||
).toMatchElement('.wc-shipping-class-rows tr', { text: slug, timeout: 50000 });
|
||||
for ( const { name, slug, description } of shippingClasses ) {
|
||||
const row = await expect( page ).toMatchElement(
|
||||
'.wc-shipping-class-rows tr',
|
||||
{
|
||||
text: slug,
|
||||
timeout: 50000,
|
||||
}
|
||||
);
|
||||
|
||||
await expect(row).toMatchElement(
|
||||
await expect( row ).toMatchElement(
|
||||
'.wc-shipping-class-name',
|
||||
name
|
||||
);
|
||||
await expect(row).toMatchElement(
|
||||
await expect( row ).toMatchElement(
|
||||
'.wc-shipping-class-description',
|
||||
description
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
} );
|
||||
} );
|
||||
};
|
||||
|
||||
module.exports = runAddShippingClassesTest;
|
||||
|
|
|
@ -15,14 +15,12 @@ const {
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
const {
|
||||
it,
|
||||
describe,
|
||||
beforeAll,
|
||||
} = require( '@jest/globals' );
|
||||
const { it, describe, beforeAll } = require( '@jest/globals' );
|
||||
|
||||
const config = require( 'config' );
|
||||
const simpleProductPrice = config.has( 'products.simple.price' ) ? config.get( 'products.simple.price' ) : '9.99';
|
||||
const simpleProductPrice = config.has( 'products.simple.price' )
|
||||
? config.get( 'products.simple.price' )
|
||||
: '9.99';
|
||||
const california = 'state:US:CA';
|
||||
const sanFranciscoZIP = '94107';
|
||||
const shippingZoneNameUS = 'US with Flat rate';
|
||||
|
@ -30,41 +28,56 @@ const shippingZoneNameFL = 'CA with Free shipping';
|
|||
const shippingZoneNameSF = 'SF with Local pickup';
|
||||
|
||||
const runAddNewShippingZoneTest = () => {
|
||||
describe('WooCommerce Shipping Settings - Add new shipping zone', () => {
|
||||
describe( 'WooCommerce Shipping Settings - Add new shipping zone', () => {
|
||||
let productId;
|
||||
|
||||
beforeAll(async () => {
|
||||
beforeAll( async () => {
|
||||
productId = await createSimpleProduct();
|
||||
await withRestApi.deleteAllShippingZones( false );
|
||||
await merchant.login();
|
||||
});
|
||||
} );
|
||||
|
||||
afterAll( async () => {
|
||||
await shopper.logout();
|
||||
} );
|
||||
|
||||
it('add shipping zone for San Francisco with free Local pickup', async () => {
|
||||
it( 'add shipping zone for San Francisco with free Local pickup', async () => {
|
||||
// Add a new shipping zone for San Francisco 94107, CA, US with Local pickup
|
||||
await addShippingZoneAndMethod(shippingZoneNameSF, california, sanFranciscoZIP, 'local_pickup');
|
||||
});
|
||||
await addShippingZoneAndMethod(
|
||||
shippingZoneNameSF,
|
||||
california,
|
||||
sanFranciscoZIP,
|
||||
'local_pickup'
|
||||
);
|
||||
} );
|
||||
|
||||
it('add shipping zone for California with Free shipping', async () => {
|
||||
it( 'add shipping zone for California with Free shipping', async () => {
|
||||
// Add a new shipping zone for CA, US with Free shipping
|
||||
await addShippingZoneAndMethod(shippingZoneNameFL, california, ' ', 'free_shipping');
|
||||
});
|
||||
await addShippingZoneAndMethod(
|
||||
shippingZoneNameFL,
|
||||
california,
|
||||
' ',
|
||||
'free_shipping'
|
||||
);
|
||||
} );
|
||||
|
||||
it('add shipping zone for the US with Flat rate', async () => {
|
||||
it( 'add shipping zone for the US with Flat rate', async () => {
|
||||
// Add a new shipping zone for the US with Flat rate
|
||||
await addShippingZoneAndMethod(shippingZoneNameUS);
|
||||
await addShippingZoneAndMethod( shippingZoneNameUS );
|
||||
|
||||
// Set Flat rate cost
|
||||
await expect(page).toClick('a.wc-shipping-zone-method-settings', {text: 'Flat rate'});
|
||||
await clearAndFillInput('#woocommerce_flat_rate_cost', '10');
|
||||
await expect(page).toClick('.wc-backbone-modal-main button#btn-ok');
|
||||
await expect( page ).toClick(
|
||||
'a.wc-shipping-zone-method-settings',
|
||||
{ text: 'Flat rate' }
|
||||
);
|
||||
await clearAndFillInput( '#woocommerce_flat_rate_cost', '10' );
|
||||
await expect( page ).toClick(
|
||||
'.wc-backbone-modal-main button#btn-ok'
|
||||
);
|
||||
await merchant.logout();
|
||||
});
|
||||
} );
|
||||
|
||||
it('allows customer to pay for a Flat rate shipping method', async() => {
|
||||
it( 'allows customer to pay for a Flat rate shipping method', async () => {
|
||||
await shopper.login();
|
||||
|
||||
// Add product to cart as a shopper
|
||||
|
@ -73,61 +86,85 @@ const runAddNewShippingZoneTest = () => {
|
|||
await shopper.goToCart();
|
||||
|
||||
// Set shipping country to United States (US)
|
||||
await expect(page).toClick('a.shipping-calculator-button');
|
||||
await expect(page).toClick('#select2-calc_shipping_country-container');
|
||||
await selectOptionInSelect2('United States (US)');
|
||||
await expect( page ).toClick( 'a.shipping-calculator-button' );
|
||||
await expect( page ).toClick(
|
||||
'#select2-calc_shipping_country-container'
|
||||
);
|
||||
await selectOptionInSelect2( 'United States (US)' );
|
||||
|
||||
// Set shipping state to New York
|
||||
await expect(page).toClick('#select2-calc_shipping_state-container');
|
||||
await selectOptionInSelect2('New York');
|
||||
await expect(page).toClick('button[name="calc_shipping"]');
|
||||
await expect( page ).toClick(
|
||||
'#select2-calc_shipping_state-container'
|
||||
);
|
||||
await selectOptionInSelect2( 'New York' );
|
||||
await expect( page ).toClick( 'button[name="calc_shipping"]' );
|
||||
|
||||
await uiUnblocked();
|
||||
|
||||
// Verify shipping costs
|
||||
await page.waitForSelector('.order-total');
|
||||
await expect(page).toMatchElement('.shipping .amount', {text: '$10.00'});
|
||||
await expect(page).toMatchElement('.order-total .amount', {text: `$1${simpleProductPrice}`});
|
||||
});
|
||||
await page.waitForSelector( '.order-total' );
|
||||
await expect( page ).toMatchElement( '.shipping .amount', {
|
||||
text: '$10.00',
|
||||
} );
|
||||
await expect( page ).toMatchElement( '.order-total .amount', {
|
||||
text: `$1${ simpleProductPrice }`,
|
||||
} );
|
||||
} );
|
||||
|
||||
it('allows customer to benefit from a Free shipping if in CA', async () => {
|
||||
it( 'allows customer to benefit from a Free shipping if in CA', async () => {
|
||||
await page.reload();
|
||||
|
||||
// Set shipping state to California
|
||||
await expect(page).toClick('a.shipping-calculator-button');
|
||||
await expect(page).toClick('#select2-calc_shipping_state-container');
|
||||
await selectOptionInSelect2('California');
|
||||
await expect( page ).toClick( 'a.shipping-calculator-button' );
|
||||
await expect( page ).toClick(
|
||||
'#select2-calc_shipping_state-container'
|
||||
);
|
||||
await selectOptionInSelect2( 'California' );
|
||||
|
||||
// Set shipping postcode to 94000
|
||||
await clearAndFillInput('#calc_shipping_postcode', '94000');
|
||||
await expect(page).toClick('button[name="calc_shipping"]');
|
||||
await clearAndFillInput( '#calc_shipping_postcode', '94000' );
|
||||
await expect( page ).toClick( 'button[name="calc_shipping"]' );
|
||||
|
||||
await uiUnblocked();
|
||||
|
||||
// Verify shipping method and cost
|
||||
await page.waitForSelector('.order-total');
|
||||
await expect(page).toMatchElement('.shipping ul#shipping_method > li', {text: 'Free shipping'});
|
||||
await expect(page).toMatchElement('.order-total .amount', {text: `$${simpleProductPrice}`});
|
||||
});
|
||||
await page.waitForSelector( '.order-total' );
|
||||
await expect( page ).toMatchElement(
|
||||
'.shipping ul#shipping_method > li',
|
||||
{
|
||||
text: 'Free shipping',
|
||||
}
|
||||
);
|
||||
await expect( page ).toMatchElement( '.order-total .amount', {
|
||||
text: `$${ simpleProductPrice }`,
|
||||
} );
|
||||
} );
|
||||
|
||||
it('allows customer to benefit from a free Local pickup if in SF', async () => {
|
||||
it( 'allows customer to benefit from a free Local pickup if in SF', async () => {
|
||||
await page.reload();
|
||||
|
||||
// Set shipping postcode to 94107
|
||||
await expect(page).toClick('a.shipping-calculator-button');
|
||||
await clearAndFillInput('#calc_shipping_postcode', '94107');
|
||||
await expect(page).toClick('button[name="calc_shipping"]');
|
||||
await expect( page ).toClick( 'a.shipping-calculator-button' );
|
||||
await clearAndFillInput( '#calc_shipping_postcode', '94107' );
|
||||
await expect( page ).toClick( 'button[name="calc_shipping"]' );
|
||||
|
||||
await uiUnblocked();
|
||||
|
||||
// Verify shipping method and cost
|
||||
await page.waitForSelector('.order-total');
|
||||
await expect(page).toMatchElement('.shipping ul#shipping_method > li', {text: 'Local pickup'});
|
||||
await expect(page).toMatchElement('.order-total .amount', {text: `$${simpleProductPrice}`});
|
||||
await page.waitForSelector( '.order-total' );
|
||||
await expect( page ).toMatchElement(
|
||||
'.shipping ul#shipping_method > li',
|
||||
{
|
||||
text: 'Local pickup',
|
||||
}
|
||||
);
|
||||
await expect( page ).toMatchElement( '.order-total .amount', {
|
||||
text: `$${ simpleProductPrice }`,
|
||||
} );
|
||||
|
||||
await shopper.removeFromCart( productId );
|
||||
});
|
||||
});
|
||||
} );
|
||||
} );
|
||||
};
|
||||
|
||||
module.exports = runAddNewShippingZoneTest;
|
||||
|
|
|
@ -14,165 +14,254 @@ const {
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
const {
|
||||
it,
|
||||
describe,
|
||||
beforeAll,
|
||||
} = require( '@jest/globals' );
|
||||
const { it, describe, beforeAll } = require( '@jest/globals' );
|
||||
|
||||
const runTaxSettingsTest = () => {
|
||||
describe('WooCommerce Tax Settings', () => {
|
||||
beforeAll(async () => {
|
||||
describe( 'WooCommerce Tax Settings', () => {
|
||||
beforeAll( async () => {
|
||||
await merchant.login();
|
||||
});
|
||||
} );
|
||||
|
||||
it('can enable tax calculation', async () => {
|
||||
it( 'can enable tax calculation', async () => {
|
||||
// Go to general settings page
|
||||
await merchant.openSettings('general');
|
||||
await merchant.openSettings( 'general' );
|
||||
|
||||
// Make sure the general tab is active
|
||||
await expect(page).toMatchElement('a.nav-tab-active', {text: 'General'});
|
||||
await expect( page ).toMatchElement( 'a.nav-tab-active', {
|
||||
text: 'General',
|
||||
} );
|
||||
|
||||
// Enable tax calculation
|
||||
await setCheckbox('input[name="woocommerce_calc_taxes"]');
|
||||
await setCheckbox( 'input[name="woocommerce_calc_taxes"]' );
|
||||
await settingsPageSaveChanges();
|
||||
|
||||
// Verify that settings have been saved
|
||||
await Promise.all([
|
||||
expect(page).toMatchElement('#message', {text: 'Your settings have been saved.'}),
|
||||
verifyCheckboxIsSet('#woocommerce_calc_taxes'),
|
||||
]);
|
||||
await Promise.all( [
|
||||
expect( page ).toMatchElement( '#message', {
|
||||
text: 'Your settings have been saved.',
|
||||
} ),
|
||||
verifyCheckboxIsSet( '#woocommerce_calc_taxes' ),
|
||||
] );
|
||||
|
||||
// Verify that tax settings are now present
|
||||
await expect(page).toMatchElement('a.nav-tab', {text: 'Tax'});
|
||||
});
|
||||
await expect( page ).toMatchElement( 'a.nav-tab', { text: 'Tax' } );
|
||||
} );
|
||||
|
||||
it('can set tax options', async () => {
|
||||
it( 'can set tax options', async () => {
|
||||
// Go to tax settings page
|
||||
await merchant.openSettings('tax');
|
||||
await merchant.openSettings( 'tax' );
|
||||
|
||||
// Make sure the tax tab is active
|
||||
await expect(page).toMatchElement('a.nav-tab-active', {text: 'Tax'});
|
||||
await expect( page ).toMatchElement( 'a.nav-tab-active', {
|
||||
text: 'Tax',
|
||||
} );
|
||||
|
||||
// Prices exclusive of tax
|
||||
await expect(page).toClick('input[name="woocommerce_prices_include_tax"][value="no"]');
|
||||
await expect( page ).toClick(
|
||||
'input[name="woocommerce_prices_include_tax"][value="no"]'
|
||||
);
|
||||
// Tax based on customer shipping address
|
||||
await expect(page).toSelect('#woocommerce_tax_based_on', 'Customer shipping address');
|
||||
await expect( page ).toSelect(
|
||||
'#woocommerce_tax_based_on',
|
||||
'Customer shipping address'
|
||||
);
|
||||
// Standard tax class for shipping
|
||||
await expect(page).toSelect('#woocommerce_shipping_tax_class', 'Standard');
|
||||
await expect( page ).toSelect(
|
||||
'#woocommerce_shipping_tax_class',
|
||||
'Standard'
|
||||
);
|
||||
// Leave rounding unchecked (no-op)
|
||||
// Display prices excluding tax
|
||||
await expect(page).toSelect('#woocommerce_tax_display_shop', 'Excluding tax');
|
||||
await expect( page ).toSelect(
|
||||
'#woocommerce_tax_display_shop',
|
||||
'Excluding tax'
|
||||
);
|
||||
// Display prices including tax in cart and at checkout
|
||||
await expect(page).toSelect('#woocommerce_tax_display_cart', 'Including tax');
|
||||
await expect( page ).toSelect(
|
||||
'#woocommerce_tax_display_cart',
|
||||
'Including tax'
|
||||
);
|
||||
// Display a single tax total
|
||||
await expect(page).toSelect('#woocommerce_tax_total_display', 'As a single total');
|
||||
await expect( page ).toSelect(
|
||||
'#woocommerce_tax_total_display',
|
||||
'As a single total'
|
||||
);
|
||||
|
||||
await settingsPageSaveChanges();
|
||||
|
||||
// Verify that settings have been saved
|
||||
await Promise.all([
|
||||
expect(page).toMatchElement('#message', {text: 'Your settings have been saved.'}),
|
||||
verifyValueOfInputField('input[name="woocommerce_prices_include_tax"][value="no"]', 'no'),
|
||||
expect(page).toMatchElement('#woocommerce_tax_based_on', {text: 'Customer shipping address'}),
|
||||
expect(page).toMatchElement('#woocommerce_shipping_tax_class', {text: 'Standard'}),
|
||||
expect(page).toMatchElement('#woocommerce_tax_display_shop', {text: 'Excluding tax'}),
|
||||
expect(page).toMatchElement('#woocommerce_tax_display_cart', {text: 'Including tax'}),
|
||||
expect(page).toMatchElement('#woocommerce_tax_total_display', {text: 'As a single total'}),
|
||||
]);
|
||||
});
|
||||
await Promise.all( [
|
||||
expect( page ).toMatchElement( '#message', {
|
||||
text: 'Your settings have been saved.',
|
||||
} ),
|
||||
verifyValueOfInputField(
|
||||
'input[name="woocommerce_prices_include_tax"][value="no"]',
|
||||
'no'
|
||||
),
|
||||
expect( page ).toMatchElement( '#woocommerce_tax_based_on', {
|
||||
text: 'Customer shipping address',
|
||||
} ),
|
||||
expect( page ).toMatchElement(
|
||||
'#woocommerce_shipping_tax_class',
|
||||
{
|
||||
text: 'Standard',
|
||||
}
|
||||
),
|
||||
expect( page ).toMatchElement(
|
||||
'#woocommerce_tax_display_shop',
|
||||
{ text: 'Excluding tax' }
|
||||
),
|
||||
expect( page ).toMatchElement(
|
||||
'#woocommerce_tax_display_cart',
|
||||
{ text: 'Including tax' }
|
||||
),
|
||||
expect( page ).toMatchElement(
|
||||
'#woocommerce_tax_total_display',
|
||||
{ text: 'As a single total' }
|
||||
),
|
||||
] );
|
||||
} );
|
||||
|
||||
it('can add tax classes', async () => {
|
||||
it( 'can add tax classes', async () => {
|
||||
// Go to tax settings page
|
||||
await merchant.openSettings('tax');
|
||||
await merchant.openSettings( 'tax' );
|
||||
|
||||
// Make sure the tax tab is active
|
||||
await expect(page).toMatchElement('a.nav-tab-active', {text: 'Tax'});
|
||||
await expect( page ).toMatchElement( 'a.nav-tab-active', {
|
||||
text: 'Tax',
|
||||
} );
|
||||
|
||||
// Remove additional tax classes
|
||||
await clearAndFillInput('#woocommerce_tax_classes', '');
|
||||
await clearAndFillInput( '#woocommerce_tax_classes', '' );
|
||||
await settingsPageSaveChanges();
|
||||
|
||||
// Verify that settings have been saved
|
||||
await Promise.all([
|
||||
expect(page).toMatchElement('#message', {text: 'Your settings have been saved.'}),
|
||||
expect(page).toMatchElement('#woocommerce_tax_classes', {text: ''}),
|
||||
]);
|
||||
await Promise.all( [
|
||||
expect( page ).toMatchElement( '#message', {
|
||||
text: 'Your settings have been saved.',
|
||||
} ),
|
||||
expect( page ).toMatchElement( '#woocommerce_tax_classes', {
|
||||
text: '',
|
||||
} ),
|
||||
] );
|
||||
|
||||
// Add a "fancy" tax class
|
||||
await clearAndFillInput('#woocommerce_tax_classes', 'Fancy');
|
||||
await clearAndFillInput( '#woocommerce_tax_classes', 'Fancy' );
|
||||
await settingsPageSaveChanges();
|
||||
|
||||
// Verify that settings have been saved
|
||||
await Promise.all([
|
||||
expect(page).toMatchElement('#message', {text: 'Your settings have been saved.'}),
|
||||
expect(page).toMatchElement('ul.subsubsub > li > a', {text: 'Fancy rates'}),
|
||||
]);
|
||||
});
|
||||
await Promise.all( [
|
||||
expect( page ).toMatchElement( '#message', {
|
||||
text: 'Your settings have been saved.',
|
||||
} ),
|
||||
expect( page ).toMatchElement( 'ul.subsubsub > li > a', {
|
||||
text: 'Fancy rates',
|
||||
} ),
|
||||
] );
|
||||
} );
|
||||
|
||||
it('can set rate settings', async () => {
|
||||
it( 'can set rate settings', async () => {
|
||||
// Go to "fancy" rates tax settings page
|
||||
await merchant.openSettings('tax', 'fancy');
|
||||
await merchant.openSettings( 'tax', 'fancy' );
|
||||
|
||||
// Make sure the tax tab is active, with the "fancy" subsection
|
||||
await expect(page).toMatchElement('a.nav-tab-active', {text: 'Tax'});
|
||||
await expect(page).toMatchElement('ul.subsubsub > li > a.current', {text: 'Fancy rates'});
|
||||
await expect( page ).toMatchElement( 'a.nav-tab-active', {
|
||||
text: 'Tax',
|
||||
} );
|
||||
await expect( page ).toMatchElement(
|
||||
'ul.subsubsub > li > a.current',
|
||||
{
|
||||
text: 'Fancy rates',
|
||||
}
|
||||
);
|
||||
|
||||
// Create a state tax
|
||||
await expect(page).toClick('.wc_tax_rates a.insert');
|
||||
await expect(page).toFill('input[name^="tax_rate_country[new-0"]', 'US');
|
||||
await expect(page).toFill('input[name^="tax_rate_state[new-0"]', 'CA');
|
||||
await expect(page).toFill('input[name^="tax_rate[new-0"]', '7.5');
|
||||
await expect(page).toFill('input[name^="tax_rate_name[new-0"]', 'CA State Tax');
|
||||
await expect( page ).toClick( '.wc_tax_rates a.insert' );
|
||||
await expect( page ).toFill(
|
||||
'input[name^="tax_rate_country[new-0"]',
|
||||
'US'
|
||||
);
|
||||
await expect( page ).toFill(
|
||||
'input[name^="tax_rate_state[new-0"]',
|
||||
'CA'
|
||||
);
|
||||
await expect( page ).toFill(
|
||||
'input[name^="tax_rate[new-0"]',
|
||||
'7.5'
|
||||
);
|
||||
await expect( page ).toFill(
|
||||
'input[name^="tax_rate_name[new-0"]',
|
||||
'CA State Tax'
|
||||
);
|
||||
|
||||
// Create a federal tax
|
||||
await expect(page).toClick('.wc_tax_rates a.insert');
|
||||
await expect(page).toFill('input[name^="tax_rate_country[new-1"]', 'US');
|
||||
await expect(page).toFill('input[name^="tax_rate[new-1"]', '1.5');
|
||||
await expect(page).toFill('input[name^="tax_rate_priority[new-1"]', '2');
|
||||
await expect(page).toFill('input[name^="tax_rate_name[new-1"]', 'Federal Tax');
|
||||
await expect(page).toClick('input[name^="tax_rate_shipping[new-1"]');
|
||||
await expect( page ).toClick( '.wc_tax_rates a.insert' );
|
||||
await expect( page ).toFill(
|
||||
'input[name^="tax_rate_country[new-1"]',
|
||||
'US'
|
||||
);
|
||||
await expect( page ).toFill(
|
||||
'input[name^="tax_rate[new-1"]',
|
||||
'1.5'
|
||||
);
|
||||
await expect( page ).toFill(
|
||||
'input[name^="tax_rate_priority[new-1"]',
|
||||
'2'
|
||||
);
|
||||
await expect( page ).toFill(
|
||||
'input[name^="tax_rate_name[new-1"]',
|
||||
'Federal Tax'
|
||||
);
|
||||
await expect( page ).toClick(
|
||||
'input[name^="tax_rate_shipping[new-1"]'
|
||||
);
|
||||
|
||||
// Save changes (AJAX here)
|
||||
await expect(page).toClick('button.woocommerce-save-button');
|
||||
await expect( page ).toClick( 'button.woocommerce-save-button' );
|
||||
await uiUnblocked();
|
||||
|
||||
// Verify 2 tax rates
|
||||
expect(await page.$$('#rates tr')).toHaveLength(2);
|
||||
expect( await page.$$( '#rates tr' ) ).toHaveLength( 2 );
|
||||
|
||||
// Delete federal rate
|
||||
await expect(page).toClick('#rates tr:nth-child(2) input');
|
||||
await expect(page).toClick('.wc_tax_rates a.remove_tax_rates');
|
||||
await expect( page ).toClick( '#rates tr:nth-child(2) input' );
|
||||
await expect( page ).toClick( '.wc_tax_rates a.remove_tax_rates' );
|
||||
|
||||
// Save changes (AJAX here)
|
||||
await expect(page).toClick('button.woocommerce-save-button');
|
||||
await expect( page ).toClick( 'button.woocommerce-save-button' );
|
||||
await uiUnblocked();
|
||||
|
||||
// Verify 1 rate
|
||||
expect(await page.$$('#rates tr')).toHaveLength(1);
|
||||
await expect(page).toMatchElement(
|
||||
expect( await page.$$( '#rates tr' ) ).toHaveLength( 1 );
|
||||
await expect( page ).toMatchElement(
|
||||
'#rates tr:first-of-type input[name^="tax_rate_state"][value="CA"]'
|
||||
);
|
||||
});
|
||||
} );
|
||||
|
||||
it('can remove tax classes', async () => {
|
||||
it( 'can remove tax classes', async () => {
|
||||
// Go to tax settings page
|
||||
await merchant.openSettings('tax');
|
||||
await merchant.openSettings( 'tax' );
|
||||
|
||||
// Make sure the tax tab is active
|
||||
await expect(page).toMatchElement('a.nav-tab-active', {text: 'Tax'});
|
||||
await expect( page ).toMatchElement( 'a.nav-tab-active', {
|
||||
text: 'Tax',
|
||||
} );
|
||||
|
||||
// Remove "fancy" tax class
|
||||
await clearAndFillInput('#woocommerce_tax_classes', ' ');
|
||||
await clearAndFillInput( '#woocommerce_tax_classes', ' ' );
|
||||
await settingsPageSaveChanges();
|
||||
|
||||
// Verify that settings have been saved
|
||||
await Promise.all([
|
||||
expect(page).toMatchElement('#message', {text: 'Your settings have been saved.'}),
|
||||
expect(page).not.toMatchElement('ul.subsubsub > li > a', {text: 'Fancy rates'}),
|
||||
]);
|
||||
});
|
||||
});
|
||||
await Promise.all( [
|
||||
expect( page ).toMatchElement( '#message', {
|
||||
text: 'Your settings have been saved.',
|
||||
} ),
|
||||
expect( page ).not.toMatchElement( 'ul.subsubsub > li > a', {
|
||||
text: 'Fancy rates',
|
||||
} ),
|
||||
] );
|
||||
} );
|
||||
} );
|
||||
};
|
||||
|
||||
module.exports = runTaxSettingsTest;
|
||||
|
|
|
@ -15,13 +15,15 @@ const {
|
|||
const { it, describe, beforeAll } = require( '@jest/globals' );
|
||||
|
||||
const config = require( 'config' );
|
||||
const firstProductPrice = config.has( 'products.simple.price' ) ? config.get( 'products.simple.price' ) : '9.99';
|
||||
const firstProductPrice = config.has( 'products.simple.price' )
|
||||
? config.get( 'products.simple.price' )
|
||||
: '9.99';
|
||||
const secondProductPrice = '4.99';
|
||||
const fourProductPrice = firstProductPrice * 4;
|
||||
var twoProductsPrice = (+firstProductPrice) + (+secondProductPrice);
|
||||
var firstProductPriceWithFlatRate = (+firstProductPrice) + (+5);
|
||||
var fourProductPriceWithFlatRate = (+fourProductPrice) + (+5);
|
||||
var twoProductsPriceWithFlatRate = (+twoProductsPrice) + (+5);
|
||||
const twoProductsPrice = +firstProductPrice + +secondProductPrice;
|
||||
const firstProductPriceWithFlatRate = +firstProductPrice + +5;
|
||||
const fourProductPriceWithFlatRate = +fourProductPrice + +5;
|
||||
const twoProductsPriceWithFlatRate = +twoProductsPrice + +5;
|
||||
const firstProductName = 'First Product';
|
||||
const secondProductName = 'Second Product';
|
||||
const shippingZoneNameDE = 'Germany Free Shipping';
|
||||
|
@ -30,98 +32,146 @@ const shippingZoneNameFR = 'France Flat Local';
|
|||
const shippingCountryFR = 'country:FR';
|
||||
|
||||
const runCartCalculateShippingTest = () => {
|
||||
describe('Cart Calculate Shipping', () => {
|
||||
describe( 'Cart Calculate Shipping', () => {
|
||||
let firstProductId;
|
||||
let secondProductId;
|
||||
|
||||
beforeAll(async () => {
|
||||
firstProductId = await createSimpleProduct(firstProductName);
|
||||
secondProductId = await createSimpleProduct(secondProductName, secondProductPrice);
|
||||
beforeAll( async () => {
|
||||
firstProductId = await createSimpleProduct( firstProductName );
|
||||
secondProductId = await createSimpleProduct(
|
||||
secondProductName,
|
||||
secondProductPrice
|
||||
);
|
||||
|
||||
await withRestApi.resetSettingsGroupToDefault( 'general', false );
|
||||
|
||||
// Add a new shipping zone Germany with Free shipping
|
||||
await withRestApi.addShippingZoneAndMethod(shippingZoneNameDE, shippingCountryDE, ' ', 'free_shipping', '', [], false );
|
||||
await withRestApi.addShippingZoneAndMethod(
|
||||
shippingZoneNameDE,
|
||||
shippingCountryDE,
|
||||
' ',
|
||||
'free_shipping',
|
||||
'',
|
||||
[],
|
||||
false
|
||||
);
|
||||
|
||||
// Add a new shipping zone for France with Flat rate & Local pickup
|
||||
await withRestApi.addShippingZoneAndMethod(shippingZoneNameFR, shippingCountryFR, ' ', 'flat_rate', '5', ['local_pickup'], false );
|
||||
await withRestApi.addShippingZoneAndMethod(
|
||||
shippingZoneNameFR,
|
||||
shippingCountryFR,
|
||||
' ',
|
||||
'flat_rate',
|
||||
'5',
|
||||
[ 'local_pickup' ],
|
||||
false
|
||||
);
|
||||
|
||||
await shopper.emptyCart();
|
||||
});
|
||||
} );
|
||||
|
||||
afterAll(async () => {
|
||||
afterAll( async () => {
|
||||
await withRestApi.deleteAllShippingZones( false );
|
||||
});
|
||||
} );
|
||||
|
||||
it('allows customer to calculate Free Shipping if in Germany', async () => {
|
||||
it( 'allows customer to calculate Free Shipping if in Germany', async () => {
|
||||
await shopper.goToShop();
|
||||
await shopper.addToCartFromShopPage( firstProductId );
|
||||
await shopper.goToCart();
|
||||
|
||||
// Set shipping country to Germany
|
||||
await expect(page).toClick('a.shipping-calculator-button');
|
||||
await expect(page).toClick('#select2-calc_shipping_country-container');
|
||||
await selectOptionInSelect2('Germany');
|
||||
await expect(page).toClick('button[name="calc_shipping"]');
|
||||
await expect( page ).toClick( 'a.shipping-calculator-button' );
|
||||
await expect( page ).toClick(
|
||||
'#select2-calc_shipping_country-container'
|
||||
);
|
||||
await selectOptionInSelect2( 'Germany' );
|
||||
await expect( page ).toClick( 'button[name="calc_shipping"]' );
|
||||
await uiUnblocked();
|
||||
|
||||
// Verify shipping costs
|
||||
await page.waitForSelector('.order-total');
|
||||
await expect(page).toMatchElement('.shipping ul#shipping_method > li', {text: 'Free shipping'});
|
||||
await expect(page).toMatchElement('.order-total .amount', {text: `$${firstProductPrice}`});
|
||||
});
|
||||
await page.waitForSelector( '.order-total' );
|
||||
await expect( page ).toMatchElement(
|
||||
'.shipping ul#shipping_method > li',
|
||||
{
|
||||
text: 'Free shipping',
|
||||
}
|
||||
);
|
||||
await expect( page ).toMatchElement( '.order-total .amount', {
|
||||
text: `$${ firstProductPrice }`,
|
||||
} );
|
||||
} );
|
||||
|
||||
it('allows customer to calculate Flat rate and Local pickup if in France', async () => {
|
||||
await page.reload( { waitUntil: ['networkidle0', 'domcontentloaded'] } );
|
||||
it( 'allows customer to calculate Flat rate and Local pickup if in France', async () => {
|
||||
await page.reload( {
|
||||
waitUntil: [ 'networkidle0', 'domcontentloaded' ],
|
||||
} );
|
||||
|
||||
// Set shipping country to France
|
||||
await expect(page).toClick('a.shipping-calculator-button');
|
||||
await expect(page).toClick('#select2-calc_shipping_country-container');
|
||||
await selectOptionInSelect2('France');
|
||||
await expect(page).toClick('button[name="calc_shipping"]');
|
||||
await expect( page ).toClick( 'a.shipping-calculator-button' );
|
||||
await expect( page ).toClick(
|
||||
'#select2-calc_shipping_country-container'
|
||||
);
|
||||
await selectOptionInSelect2( 'France' );
|
||||
await expect( page ).toClick( 'button[name="calc_shipping"]' );
|
||||
await uiUnblocked();
|
||||
|
||||
// Verify shipping costs
|
||||
await page.waitForSelector('.order-total');
|
||||
await expect(page).toMatchElement('.shipping .amount', {text: '$5.00'});
|
||||
await expect(page).toMatchElement('.order-total .amount', {text: `$${firstProductPriceWithFlatRate}`});
|
||||
});
|
||||
await page.waitForSelector( '.order-total' );
|
||||
await expect( page ).toMatchElement( '.shipping .amount', {
|
||||
text: '$5.00',
|
||||
} );
|
||||
await expect( page ).toMatchElement( '.order-total .amount', {
|
||||
text: `$${ firstProductPriceWithFlatRate }`,
|
||||
} );
|
||||
} );
|
||||
|
||||
it('should show correct total cart price after updating quantity', async () => {
|
||||
await shopper.setCartQuantity(firstProductName, 4);
|
||||
await expect(page).toClick('button', {text: 'Update cart'});
|
||||
it( 'should show correct total cart price after updating quantity', async () => {
|
||||
await shopper.setCartQuantity( firstProductName, 4 );
|
||||
await expect( page ).toClick( 'button', { text: 'Update cart' } );
|
||||
await uiUnblocked();
|
||||
await expect(page).toMatchElement('.order-total .amount', {text: `$${fourProductPriceWithFlatRate}`});
|
||||
});
|
||||
await expect( page ).toMatchElement( '.order-total .amount', {
|
||||
text: `$${ fourProductPriceWithFlatRate }`,
|
||||
} );
|
||||
} );
|
||||
|
||||
it('should show correct total cart price with 2 products and flat rate', async () => {
|
||||
it( 'should show correct total cart price with 2 products and flat rate', async () => {
|
||||
await shopper.goToShop();
|
||||
await shopper.addToCartFromShopPage( secondProductId );
|
||||
await shopper.goToCart();
|
||||
|
||||
await shopper.setCartQuantity(firstProductName, 1);
|
||||
await expect(page).toClick('button', {text: 'Update cart'});
|
||||
await shopper.setCartQuantity( firstProductName, 1 );
|
||||
await expect( page ).toClick( 'button', { text: 'Update cart' } );
|
||||
await uiUnblocked();
|
||||
await page.waitForSelector('.order-total');
|
||||
await expect(page).toMatchElement('.shipping .amount', {text: '$5.00'});
|
||||
await expect(page).toMatchElement('.order-total .amount', {text: `$${twoProductsPriceWithFlatRate}`});
|
||||
});
|
||||
await page.waitForSelector( '.order-total' );
|
||||
await expect( page ).toMatchElement( '.shipping .amount', {
|
||||
text: '$5.00',
|
||||
} );
|
||||
await expect( page ).toMatchElement( '.order-total .amount', {
|
||||
text: `$${ twoProductsPriceWithFlatRate }`,
|
||||
} );
|
||||
} );
|
||||
|
||||
it('should show correct total cart price with 2 products without flat rate', async () => {
|
||||
await page.reload( { waitUntil: ['networkidle0', 'domcontentloaded'] } );
|
||||
it( 'should show correct total cart price with 2 products without flat rate', async () => {
|
||||
await page.reload( {
|
||||
waitUntil: [ 'networkidle0', 'domcontentloaded' ],
|
||||
} );
|
||||
|
||||
// Set shipping country to Spain
|
||||
await expect(page).toClick('a.shipping-calculator-button');
|
||||
await expect(page).toClick('#select2-calc_shipping_country-container');
|
||||
await selectOptionInSelect2('Spain');
|
||||
await expect(page).toClick('button[name="calc_shipping"]');
|
||||
await expect( page ).toClick( 'a.shipping-calculator-button' );
|
||||
await expect( page ).toClick(
|
||||
'#select2-calc_shipping_country-container'
|
||||
);
|
||||
await selectOptionInSelect2( 'Spain' );
|
||||
await expect( page ).toClick( 'button[name="calc_shipping"]' );
|
||||
await uiUnblocked();
|
||||
|
||||
// Verify shipping costs
|
||||
await page.waitForSelector('.order-total');
|
||||
await expect(page).toMatchElement('.order-total .amount', {text: `$${twoProductsPrice}`});
|
||||
});
|
||||
});
|
||||
await page.waitForSelector( '.order-total' );
|
||||
await expect( page ).toMatchElement( '.order-total .amount', {
|
||||
text: `$${ twoProductsPrice }`,
|
||||
} );
|
||||
} );
|
||||
} );
|
||||
};
|
||||
|
||||
module.exports = runCartCalculateShippingTest;
|
||||
|
|
|
@ -16,56 +16,79 @@ const { getCouponId, getCouponsTable } = require( '../utils/coupons' );
|
|||
const { it, describe, beforeAll } = require( '@jest/globals' );
|
||||
|
||||
const runCartApplyCouponsTest = () => {
|
||||
describe('Cart applying coupons', () => {
|
||||
describe( 'Cart applying coupons', () => {
|
||||
let productId;
|
||||
|
||||
beforeAll(async () => {
|
||||
beforeAll( async () => {
|
||||
productId = await createSimpleProduct();
|
||||
await shopper.emptyCart();
|
||||
await shopper.goToShop();
|
||||
await shopper.addToCartFromShopPage( productId );
|
||||
await uiUnblocked();
|
||||
await shopper.goToCart();
|
||||
});
|
||||
} );
|
||||
|
||||
it.each( getCouponsTable() )( 'allows cart to apply %s coupon', async ( couponType, cartDiscount, orderTotal ) => {
|
||||
const coupon = await getCouponId( couponType );
|
||||
await applyCoupon(coupon);
|
||||
await expect(page).toMatchElement('.woocommerce-message', { text: 'Coupon code applied successfully.' });
|
||||
it.each( getCouponsTable() )(
|
||||
'allows cart to apply %s coupon',
|
||||
async ( couponType, cartDiscount, orderTotal ) => {
|
||||
const coupon = await getCouponId( couponType );
|
||||
await applyCoupon( coupon );
|
||||
await expect( page ).toMatchElement( '.woocommerce-message', {
|
||||
text: 'Coupon code applied successfully.',
|
||||
} );
|
||||
|
||||
// Verify discount applied and order total
|
||||
await page.waitForSelector('.order-total');
|
||||
await expect(page).toMatchElement('.cart-discount .amount', cartDiscount);
|
||||
await expect(page).toMatchElement('.order-total .amount', orderTotal);
|
||||
await removeCoupon(coupon);
|
||||
});
|
||||
// Verify discount applied and order total
|
||||
await page.waitForSelector( '.order-total' );
|
||||
await expect( page ).toMatchElement(
|
||||
'.cart-discount .amount',
|
||||
cartDiscount
|
||||
);
|
||||
await expect( page ).toMatchElement(
|
||||
'.order-total .amount',
|
||||
orderTotal
|
||||
);
|
||||
await removeCoupon( coupon );
|
||||
}
|
||||
);
|
||||
|
||||
it('prevents cart applying same coupon twice', async () => {
|
||||
it( 'prevents cart applying same coupon twice', async () => {
|
||||
const couponId = await getCouponId( 'fixed cart' );
|
||||
await applyCoupon( couponId );
|
||||
await expect(page).toMatchElement('.woocommerce-message', {text: 'Coupon code applied successfully.'});
|
||||
await expect( page ).toMatchElement( '.woocommerce-message', {
|
||||
text: 'Coupon code applied successfully.',
|
||||
} );
|
||||
await applyCoupon( couponId );
|
||||
// Verify only one discount applied
|
||||
// This is a work around for Puppeteer inconsistently finding 'Coupon code already applied'
|
||||
await expect(page).toMatchElement('.cart-discount .amount', {text: '$5.00'});
|
||||
await expect(page).toMatchElement('.order-total .amount', {text: '$4.99'});
|
||||
});
|
||||
await expect( page ).toMatchElement( '.cart-discount .amount', {
|
||||
text: '$5.00',
|
||||
} );
|
||||
await expect( page ).toMatchElement( '.order-total .amount', {
|
||||
text: '$4.99',
|
||||
} );
|
||||
} );
|
||||
|
||||
it('allows cart to apply multiple coupons', async () => {
|
||||
it( 'allows cart to apply multiple coupons', async () => {
|
||||
await applyCoupon( await getCouponId( 'fixed product' ) );
|
||||
await expect(page).toMatchElement('.woocommerce-message', {text: 'Coupon code applied successfully.'});
|
||||
await expect( page ).toMatchElement( '.woocommerce-message', {
|
||||
text: 'Coupon code applied successfully.',
|
||||
} );
|
||||
|
||||
// Verify discount applied and order total
|
||||
await page.waitForSelector('.order-total');
|
||||
await expect(page).toMatchElement('.order-total .amount', {text: '$0.00'});
|
||||
});
|
||||
await page.waitForSelector( '.order-total' );
|
||||
await expect( page ).toMatchElement( '.order-total .amount', {
|
||||
text: '$0.00',
|
||||
} );
|
||||
} );
|
||||
|
||||
it('restores cart total when coupons are removed', async () => {
|
||||
it( 'restores cart total when coupons are removed', async () => {
|
||||
await removeCoupon( await getCouponId( 'fixed cart' ) );
|
||||
await removeCoupon( await getCouponId( 'fixed product' ) );
|
||||
await expect(page).toMatchElement('.order-total .amount', {text: '$9.99'});
|
||||
});
|
||||
});
|
||||
await expect( page ).toMatchElement( '.order-total .amount', {
|
||||
text: '$9.99',
|
||||
} );
|
||||
} );
|
||||
} );
|
||||
};
|
||||
|
||||
module.exports = runCartApplyCouponsTest;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
const {
|
||||
const {
|
||||
shopper,
|
||||
merchant,
|
||||
createSimpleProduct,
|
||||
|
@ -14,63 +14,59 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
const {
|
||||
it,
|
||||
describe,
|
||||
beforeAll,
|
||||
afterAll,
|
||||
} = require( '@jest/globals' );
|
||||
const { it, describe, beforeAll, afterAll } = require( '@jest/globals' );
|
||||
|
||||
const config = require( 'config' );
|
||||
const simpleProductName = config.get( 'products.simple.name' );
|
||||
|
||||
const runCartRedirectionTest = () => {
|
||||
describe('Cart > Redirect to cart from shop', () => {
|
||||
describe( 'Cart > Redirect to cart from shop', () => {
|
||||
let simplePostIdValue;
|
||||
beforeAll(async () => {
|
||||
beforeAll( async () => {
|
||||
simplePostIdValue = await createSimpleProduct();
|
||||
|
||||
// Set checkbox in settings to enable cart redirection
|
||||
await merchant.login();
|
||||
await merchant.openSettings('products');
|
||||
await setCheckbox('#woocommerce_cart_redirect_after_add');
|
||||
await merchant.openSettings( 'products' );
|
||||
await setCheckbox( '#woocommerce_cart_redirect_after_add' );
|
||||
await settingsPageSaveChanges();
|
||||
|
||||
await merchant.logout();
|
||||
});
|
||||
} );
|
||||
|
||||
it('can redirect user to cart from shop page', async () => {
|
||||
it( 'can redirect user to cart from shop page', async () => {
|
||||
await shopper.goToShop();
|
||||
|
||||
// Add to cart from shop page
|
||||
const addToCartXPath = `//li[contains(@class, "type-product") and a/h2[contains(text(), "${ simpleProductName }")]]` +
|
||||
'//a[contains(@class, "add_to_cart_button") and contains(@class, "ajax_add_to_cart")';
|
||||
const addToCartXPath =
|
||||
`//li[contains(@class, "type-product") and a/h2[contains(text(), "${ simpleProductName }")]]` +
|
||||
'//a[contains(@class, "add_to_cart_button") and contains(@class, "ajax_add_to_cart")';
|
||||
const [ addToCartButton ] = await page.$x( addToCartXPath + ']' );
|
||||
addToCartButton.click();
|
||||
await utils.waitForTimeout( 1000 ); // to avoid flakiness
|
||||
|
||||
await shopper.productIsInCart(simpleProductName);
|
||||
await shopper.productIsInCart( simpleProductName );
|
||||
await shopper.removeFromCart( simplePostIdValue );
|
||||
});
|
||||
} );
|
||||
|
||||
it('can redirect user to cart from detail page', async () => {
|
||||
await shopper.goToProduct(simplePostIdValue);
|
||||
it( 'can redirect user to cart from detail page', async () => {
|
||||
await shopper.goToProduct( simplePostIdValue );
|
||||
|
||||
// Add to cart from detail page
|
||||
await shopper.addToCart();
|
||||
await utils.waitForTimeout( 1000 ); // to avoid flakiness
|
||||
|
||||
await shopper.productIsInCart(simpleProductName);
|
||||
await shopper.productIsInCart( simpleProductName );
|
||||
await shopper.removeFromCart( simplePostIdValue );
|
||||
});
|
||||
} );
|
||||
|
||||
afterAll(async () => {
|
||||
afterAll( async () => {
|
||||
await merchant.login();
|
||||
await merchant.openSettings('products');
|
||||
await unsetCheckbox('#woocommerce_cart_redirect_after_add');
|
||||
await merchant.openSettings( 'products' );
|
||||
await unsetCheckbox( '#woocommerce_cart_redirect_after_add' );
|
||||
await settingsPageSaveChanges();
|
||||
});
|
||||
});
|
||||
} );
|
||||
} );
|
||||
};
|
||||
|
||||
module.exports = runCartRedirectionTest;
|
||||
|
|
|
@ -15,83 +15,95 @@ const { it, describe, beforeAll } = require( '@jest/globals' );
|
|||
|
||||
const config = require( 'config' );
|
||||
const simpleProductName = config.get( 'products.simple.name' );
|
||||
const singleProductPrice = config.has('products.simple.price') ? config.get('products.simple.price') : '9.99';
|
||||
const singleProductPrice = config.has( 'products.simple.price' )
|
||||
? config.get( 'products.simple.price' )
|
||||
: '9.99';
|
||||
const twoProductPrice = singleProductPrice * 2;
|
||||
|
||||
const runCartPageTest = () => {
|
||||
describe('Cart page', () => {
|
||||
describe( 'Cart page', () => {
|
||||
let productId;
|
||||
|
||||
beforeAll(async () => {
|
||||
beforeAll( async () => {
|
||||
productId = await createSimpleProduct();
|
||||
await withRestApi.resetSettingsGroupToDefault( 'general', false );
|
||||
await withRestApi.resetSettingsGroupToDefault( 'products', false );
|
||||
await withRestApi.resetSettingsGroupToDefault( 'tax', false );
|
||||
});
|
||||
} );
|
||||
|
||||
it('should display no item in the cart', async () => {
|
||||
it( 'should display no item in the cart', async () => {
|
||||
await shopper.goToCart();
|
||||
await expect(page).toMatchElement('.cart-empty', {text: 'Your cart is currently empty.'});
|
||||
});
|
||||
await expect( page ).toMatchElement( '.cart-empty', {
|
||||
text: 'Your cart is currently empty.',
|
||||
} );
|
||||
} );
|
||||
|
||||
it('should add the product to the cart from the shop page', async () => {
|
||||
it( 'should add the product to the cart from the shop page', async () => {
|
||||
await shopper.goToShop();
|
||||
await shopper.addToCartFromShopPage( productId );
|
||||
|
||||
await shopper.goToCart();
|
||||
await shopper.productIsInCart(simpleProductName);
|
||||
});
|
||||
await shopper.productIsInCart( simpleProductName );
|
||||
} );
|
||||
|
||||
it('should increase item qty when "Add to cart" of the same product is clicked', async () => {
|
||||
it( 'should increase item qty when "Add to cart" of the same product is clicked', async () => {
|
||||
await shopper.goToShop();
|
||||
await shopper.addToCartFromShopPage( productId );
|
||||
|
||||
await shopper.goToCart();
|
||||
await shopper.productIsInCart(simpleProductName, 2);
|
||||
});
|
||||
await shopper.productIsInCart( simpleProductName, 2 );
|
||||
} );
|
||||
|
||||
it('should update qty when updated via qty input', async () => {
|
||||
it( 'should update qty when updated via qty input', async () => {
|
||||
await shopper.goToCart();
|
||||
await shopper.setCartQuantity(simpleProductName, 4);
|
||||
await expect(page).toClick('button', {text: 'Update cart'});
|
||||
await shopper.setCartQuantity( simpleProductName, 4 );
|
||||
await expect( page ).toClick( 'button', { text: 'Update cart' } );
|
||||
await uiUnblocked();
|
||||
|
||||
await shopper.productIsInCart(simpleProductName, 4);
|
||||
});
|
||||
await shopper.productIsInCart( simpleProductName, 4 );
|
||||
} );
|
||||
|
||||
it('should remove the item from the cart when remove is clicked', async () => {
|
||||
it( 'should remove the item from the cart when remove is clicked', async () => {
|
||||
await shopper.goToCart();
|
||||
await shopper.removeFromCart( productId );
|
||||
await uiUnblocked();
|
||||
|
||||
await expect(page).toMatchElement('.cart-empty', {text: 'Your cart is currently empty.'});
|
||||
});
|
||||
await expect( page ).toMatchElement( '.cart-empty', {
|
||||
text: 'Your cart is currently empty.',
|
||||
} );
|
||||
} );
|
||||
|
||||
it('should update subtotal in cart totals when adding product to the cart', async () => {
|
||||
it( 'should update subtotal in cart totals when adding product to the cart', async () => {
|
||||
await shopper.goToShop();
|
||||
await shopper.addToCartFromShopPage( productId );
|
||||
|
||||
await shopper.goToCart();
|
||||
await shopper.productIsInCart(simpleProductName, 1);
|
||||
await expect(page).toMatchElement('.cart-subtotal .amount', {text: `$${ singleProductPrice }`});
|
||||
await shopper.productIsInCart( simpleProductName, 1 );
|
||||
await expect( page ).toMatchElement( '.cart-subtotal .amount', {
|
||||
text: `$${ singleProductPrice }`,
|
||||
} );
|
||||
|
||||
await shopper.setCartQuantity(simpleProductName, 2);
|
||||
await expect(page).toClick('button', {text: 'Update cart'});
|
||||
await shopper.setCartQuantity( simpleProductName, 2 );
|
||||
await expect( page ).toClick( 'button', { text: 'Update cart' } );
|
||||
await uiUnblocked();
|
||||
|
||||
await expect(page).toMatchElement('.cart-subtotal .amount', {text: `$${ twoProductPrice }`});
|
||||
});
|
||||
await expect( page ).toMatchElement( '.cart-subtotal .amount', {
|
||||
text: `$${ twoProductPrice }`,
|
||||
} );
|
||||
} );
|
||||
|
||||
it('should go to the checkout page when "Proceed to Checkout" is clicked', async () => {
|
||||
it( 'should go to the checkout page when "Proceed to Checkout" is clicked', async () => {
|
||||
await shopper.goToCart();
|
||||
await Promise.all([
|
||||
page.waitForNavigation({waitUntil: 'networkidle0'}),
|
||||
expect(page).toClick('.checkout-button', {text: 'Proceed to checkout'}),
|
||||
]);
|
||||
await Promise.all( [
|
||||
page.waitForNavigation( { waitUntil: 'networkidle0' } ),
|
||||
expect( page ).toClick( '.checkout-button', {
|
||||
text: 'Proceed to checkout',
|
||||
} ),
|
||||
] );
|
||||
|
||||
await expect(page).toMatchElement('#order_review');
|
||||
});
|
||||
});
|
||||
await expect( page ).toMatchElement( '#order_review' );
|
||||
} );
|
||||
} );
|
||||
};
|
||||
|
||||
module.exports = runCartPageTest;
|
||||
|
|
|
@ -16,12 +16,11 @@ const { getCouponId, getCouponsTable } = require( '../utils/coupons' );
|
|||
*/
|
||||
const { it, describe, beforeAll } = require( '@jest/globals' );
|
||||
|
||||
|
||||
const runCheckoutApplyCouponsTest = () => {
|
||||
describe('Checkout coupons', () => {
|
||||
describe( 'Checkout coupons', () => {
|
||||
let productId;
|
||||
|
||||
beforeAll(async () => {
|
||||
beforeAll( async () => {
|
||||
productId = await createSimpleProduct();
|
||||
await shopper.emptyCart();
|
||||
await shopper.goToShop();
|
||||
|
@ -29,48 +28,71 @@ const runCheckoutApplyCouponsTest = () => {
|
|||
await shopper.addToCartFromShopPage( productId );
|
||||
await uiUnblocked();
|
||||
await shopper.goToCheckout();
|
||||
});
|
||||
} );
|
||||
|
||||
it.each( getCouponsTable() )( 'allows checkout to apply %s coupon', async ( couponType, cartDiscount, orderTotal ) => {
|
||||
const coupon = await getCouponId( couponType );
|
||||
await applyCoupon(coupon);
|
||||
await expect(page).toMatchElement('.woocommerce-message', { text: 'Coupon code applied successfully.' });
|
||||
it.each( getCouponsTable() )(
|
||||
'allows checkout to apply %s coupon',
|
||||
async ( couponType, cartDiscount, orderTotal ) => {
|
||||
const coupon = await getCouponId( couponType );
|
||||
await applyCoupon( coupon );
|
||||
await expect( page ).toMatchElement( '.woocommerce-message', {
|
||||
text: 'Coupon code applied successfully.',
|
||||
} );
|
||||
|
||||
// Wait for page to expand total calculations to avoid flakyness
|
||||
await page.waitForSelector('.order-total');
|
||||
// Wait for page to expand total calculations to avoid flakyness
|
||||
await page.waitForSelector( '.order-total' );
|
||||
|
||||
// Verify discount applied and order total
|
||||
await expect(page).toMatchElement('.cart-discount .amount', cartDiscount);
|
||||
await expect(page).toMatchElement('.order-total .amount', orderTotal);
|
||||
await removeCoupon(coupon);
|
||||
});
|
||||
// Verify discount applied and order total
|
||||
await expect( page ).toMatchElement(
|
||||
'.cart-discount .amount',
|
||||
cartDiscount
|
||||
);
|
||||
await expect( page ).toMatchElement(
|
||||
'.order-total .amount',
|
||||
orderTotal
|
||||
);
|
||||
await removeCoupon( coupon );
|
||||
}
|
||||
);
|
||||
|
||||
it('prevents checkout applying same coupon twice', async () => {
|
||||
it( 'prevents checkout applying same coupon twice', async () => {
|
||||
const couponId = await getCouponId( 'fixed cart' );
|
||||
await applyCoupon( couponId );
|
||||
await expect(page).toMatchElement('.woocommerce-message', {text: 'Coupon code applied successfully.'});
|
||||
await expect( page ).toMatchElement( '.woocommerce-message', {
|
||||
text: 'Coupon code applied successfully.',
|
||||
} );
|
||||
await applyCoupon( couponId );
|
||||
// Verify only one discount applied
|
||||
// This is a work around for Puppeteer inconsistently finding 'Coupon code already applied'
|
||||
await expect(page).toMatchElement('.cart-discount .amount', {text: '$5.00'});
|
||||
await expect(page).toMatchElement('.order-total .amount', {text: '$4.99'});
|
||||
});
|
||||
await expect( page ).toMatchElement( '.cart-discount .amount', {
|
||||
text: '$5.00',
|
||||
} );
|
||||
await expect( page ).toMatchElement( '.order-total .amount', {
|
||||
text: '$4.99',
|
||||
} );
|
||||
} );
|
||||
|
||||
it('allows checkout to apply multiple coupons', async () => {
|
||||
it( 'allows checkout to apply multiple coupons', async () => {
|
||||
await applyCoupon( await getCouponId( 'fixed product' ) );
|
||||
await expect(page).toMatchElement('.woocommerce-message', {text: 'Coupon code applied successfully.'});
|
||||
await expect( page ).toMatchElement( '.woocommerce-message', {
|
||||
text: 'Coupon code applied successfully.',
|
||||
} );
|
||||
|
||||
// Verify discount applied and order total
|
||||
await page.waitForSelector('.order-total');
|
||||
await expect(page).toMatchElement('.order-total .amount', {text: '$0.00'});
|
||||
});
|
||||
await page.waitForSelector( '.order-total' );
|
||||
await expect( page ).toMatchElement( '.order-total .amount', {
|
||||
text: '$0.00',
|
||||
} );
|
||||
} );
|
||||
|
||||
it('restores checkout total when coupons are removed', async () => {
|
||||
it( 'restores checkout total when coupons are removed', async () => {
|
||||
await removeCoupon( await getCouponId( 'fixed cart' ) );
|
||||
await removeCoupon( await getCouponId( 'fixed product' ) );
|
||||
await expect(page).toMatchElement('.order-total .amount', {text: '$9.99'});
|
||||
});
|
||||
});
|
||||
await expect( page ).toMatchElement( '.order-total .amount', {
|
||||
text: '$9.99',
|
||||
} );
|
||||
} );
|
||||
} );
|
||||
};
|
||||
|
||||
module.exports = runCheckoutApplyCouponsTest;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
const {
|
||||
const {
|
||||
shopper,
|
||||
merchant,
|
||||
createSimpleProduct,
|
||||
|
@ -21,21 +21,28 @@ const config = require( 'config' );
|
|||
const customerBilling = config.get( 'addresses.customer.billing' );
|
||||
|
||||
const runCheckoutCreateAccountTest = () => {
|
||||
describe('Shopper Checkout Create Account', () => {
|
||||
describe( 'Shopper Checkout Create Account', () => {
|
||||
let productId;
|
||||
|
||||
beforeAll(async () => {
|
||||
beforeAll( async () => {
|
||||
productId = await createSimpleProduct();
|
||||
await withRestApi.deleteCustomerByEmail( customerBilling.email );
|
||||
|
||||
// Set checkbox for creating an account during checkout
|
||||
await merchant.login();
|
||||
await merchant.openSettings('account');
|
||||
await setCheckbox('#woocommerce_enable_signup_and_login_from_checkout');
|
||||
await merchant.openSettings( 'account' );
|
||||
await setCheckbox(
|
||||
'#woocommerce_enable_signup_and_login_from_checkout'
|
||||
);
|
||||
await settingsPageSaveChanges();
|
||||
|
||||
// Set free shipping within California
|
||||
await addShippingZoneAndMethod('Free Shipping CA', 'state:US:CA', ' ', 'free_shipping' );
|
||||
await addShippingZoneAndMethod(
|
||||
'Free Shipping CA',
|
||||
'state:US:CA',
|
||||
' ',
|
||||
'free_shipping'
|
||||
);
|
||||
|
||||
await merchant.logout();
|
||||
|
||||
|
@ -46,25 +53,29 @@ const runCheckoutCreateAccountTest = () => {
|
|||
await shopper.goToCheckout();
|
||||
}, 45000 );
|
||||
|
||||
it('can create an account during checkout', async () => {
|
||||
it( 'can create an account during checkout', async () => {
|
||||
// Fill all the details for a new customer
|
||||
await shopper.fillBillingDetails( customerBilling );
|
||||
await uiUnblocked();
|
||||
|
||||
// Set checkbox for creating account during checkout
|
||||
await setCheckbox('#createaccount');
|
||||
await setCheckbox( '#createaccount' );
|
||||
|
||||
// Place an order
|
||||
await shopper.placeOrder();
|
||||
await expect(page).toMatchElement('h1.entry-title', {text: 'Order received'});
|
||||
});
|
||||
await expect( page ).toMatchElement( 'h1.entry-title', {
|
||||
text: 'Order received',
|
||||
} );
|
||||
} );
|
||||
|
||||
it('can verify that the customer has been created', async () => {
|
||||
it( 'can verify that the customer has been created', async () => {
|
||||
await merchant.login();
|
||||
await merchant.openAllUsersView();
|
||||
await expect(page).toMatchElement('td.email.column-email > a', { text: customerBilling.email });
|
||||
});
|
||||
});
|
||||
await expect( page ).toMatchElement( 'td.email.column-email > a', {
|
||||
text: customerBilling.email,
|
||||
} );
|
||||
} );
|
||||
} );
|
||||
};
|
||||
|
||||
module.exports = runCheckoutCreateAccountTest;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
const {
|
||||
const {
|
||||
shopper,
|
||||
merchant,
|
||||
createSimpleProduct,
|
||||
|
@ -15,19 +15,19 @@
|
|||
*/
|
||||
const { it, describe, beforeAll } = require( '@jest/globals' );
|
||||
|
||||
const config = require('config');
|
||||
const config = require( 'config' );
|
||||
|
||||
const runCheckoutLoginAccountTest = () => {
|
||||
describe('Shopper Checkout Login Account', () => {
|
||||
describe( 'Shopper Checkout Login Account', () => {
|
||||
let productId;
|
||||
|
||||
beforeAll(async () => {
|
||||
beforeAll( async () => {
|
||||
productId = await createSimpleProduct();
|
||||
|
||||
// Set checkbox for logging to account during checkout
|
||||
await merchant.login();
|
||||
await merchant.openSettings('account');
|
||||
await setCheckbox('#woocommerce_enable_checkout_login_reminder');
|
||||
await merchant.openSettings( 'account' );
|
||||
await setCheckbox( '#woocommerce_enable_checkout_login_reminder' );
|
||||
await settingsPageSaveChanges();
|
||||
await merchant.logout();
|
||||
|
||||
|
@ -36,42 +36,54 @@ const runCheckoutLoginAccountTest = () => {
|
|||
await shopper.addToCartFromShopPage( productId );
|
||||
await uiUnblocked();
|
||||
await shopper.goToCheckout();
|
||||
});
|
||||
} );
|
||||
|
||||
afterAll( async () => {
|
||||
await shopper.logout();
|
||||
} );
|
||||
|
||||
it('can login to an existing account during checkout', async () => {
|
||||
it( 'can login to an existing account during checkout', async () => {
|
||||
// Click to login during checkout
|
||||
await page.waitForSelector('.woocommerce-form-login-toggle');
|
||||
await expect(page).toClick('.woocommerce-info > a.showlogin');
|
||||
await page.waitForSelector( '.woocommerce-form-login-toggle' );
|
||||
await expect( page ).toClick( '.woocommerce-info > a.showlogin' );
|
||||
|
||||
// Fill shopper's login credentials and proceed further
|
||||
await page.type( '#username', config.get('users.customer.username') );
|
||||
await page.type( '#password', config.get('users.customer.password') );
|
||||
await page.type(
|
||||
'#username',
|
||||
config.get( 'users.customer.username' )
|
||||
);
|
||||
await page.type(
|
||||
'#password',
|
||||
config.get( 'users.customer.password' )
|
||||
);
|
||||
|
||||
await Promise.all([
|
||||
page.waitForNavigation({waitUntil: 'networkidle0'}),
|
||||
page.click('button[name="login"]'),
|
||||
]);
|
||||
await Promise.all( [
|
||||
page.waitForNavigation( { waitUntil: 'networkidle0' } ),
|
||||
page.click( 'button[name="login"]' ),
|
||||
] );
|
||||
|
||||
// Place an order
|
||||
await shopper.placeOrder();
|
||||
await expect(page).toMatchElement('h1.entry-title', {text: 'Order received'});
|
||||
await expect( page ).toMatchElement( 'h1.entry-title', {
|
||||
text: 'Order received',
|
||||
} );
|
||||
|
||||
// Verify the email of a logged in user
|
||||
await expect(page).toMatchElement('ul > li.email', {text: 'Email: john.doe@example.com'});
|
||||
await expect( page ).toMatchElement( 'ul > li.email', {
|
||||
text: 'Email: john.doe@example.com',
|
||||
} );
|
||||
|
||||
// Verify the user is logged in on my account page
|
||||
await shopper.gotoMyAccount();
|
||||
|
||||
await Promise.all( [
|
||||
await expect(page.url()).toMatch('my-account/'),
|
||||
await expect(page).toMatchElement('h1', {text: 'My account'}),
|
||||
await expect( page.url() ).toMatch( 'my-account/' ),
|
||||
await expect( page ).toMatchElement( 'h1', {
|
||||
text: 'My account',
|
||||
} ),
|
||||
] );
|
||||
});
|
||||
});
|
||||
} );
|
||||
} );
|
||||
};
|
||||
|
||||
module.exports = runCheckoutLoginAccountTest;
|
||||
|
|
|
@ -16,7 +16,9 @@ const { it, describe, beforeAll, afterAll } = require( '@jest/globals' );
|
|||
|
||||
const config = require( 'config' );
|
||||
const simpleProductName = config.get( 'products.simple.name' );
|
||||
const singleProductPrice = config.has('products.simple.price') ? config.get('products.simple.price') : '9.99';
|
||||
const singleProductPrice = config.has( 'products.simple.price' )
|
||||
? config.get( 'products.simple.price' )
|
||||
: '9.99';
|
||||
const twoProductPrice = singleProductPrice * 2;
|
||||
const threeProductPrice = singleProductPrice * 3;
|
||||
const fourProductPrice = singleProductPrice * 4;
|
||||
|
@ -28,128 +30,233 @@ let customerOrderId;
|
|||
const runCheckoutPageTest = () => {
|
||||
let productId;
|
||||
|
||||
describe('Checkout page', () => {
|
||||
beforeAll(async () => {
|
||||
describe( 'Checkout page', () => {
|
||||
beforeAll( async () => {
|
||||
productId = await createSimpleProduct();
|
||||
await withRestApi.resetSettingsGroupToDefault( 'general', false );
|
||||
await withRestApi.resetSettingsGroupToDefault( 'products', false );
|
||||
await withRestApi.resetSettingsGroupToDefault( 'tax', false );
|
||||
|
||||
// Set free shipping within California
|
||||
await withRestApi.addShippingZoneAndMethod('Free Shipping CA', 'state:US:CA', '', 'free_shipping', '', [], false );
|
||||
await withRestApi.addShippingZoneAndMethod(
|
||||
'Free Shipping CA',
|
||||
'state:US:CA',
|
||||
'',
|
||||
'free_shipping',
|
||||
'',
|
||||
[],
|
||||
false
|
||||
);
|
||||
|
||||
// Set base location with state CA.
|
||||
await withRestApi.updateSettingOption( 'general', 'woocommerce_default_country', { value: 'US:CA' } );
|
||||
await withRestApi.updateSettingOption(
|
||||
'general',
|
||||
'woocommerce_default_country',
|
||||
{ value: 'US:CA' }
|
||||
);
|
||||
|
||||
// Sell to all countries
|
||||
await withRestApi.updateSettingOption( 'general', 'woocommerce_allowed_countries', { value: 'all' } );
|
||||
await withRestApi.updateSettingOption(
|
||||
'general',
|
||||
'woocommerce_allowed_countries',
|
||||
{ value: 'all' }
|
||||
);
|
||||
|
||||
// Set currency to USD
|
||||
await withRestApi.updateSettingOption( 'general', 'woocommerce_currency', { value: 'USD' } );
|
||||
await withRestApi.updateSettingOption(
|
||||
'general',
|
||||
'woocommerce_currency',
|
||||
{ value: 'USD' }
|
||||
);
|
||||
// Tax calculation should have been enabled by another test - no-op
|
||||
|
||||
// Enable BACS payment method
|
||||
await withRestApi.updatePaymentGateway( 'bacs', { enabled: true }, false );
|
||||
await withRestApi.updatePaymentGateway(
|
||||
'bacs',
|
||||
{ enabled: true },
|
||||
false
|
||||
);
|
||||
|
||||
// Enable COD payment method
|
||||
await withRestApi.updatePaymentGateway( 'cod', { enabled: true }, false );
|
||||
});
|
||||
await withRestApi.updatePaymentGateway(
|
||||
'cod',
|
||||
{ enabled: true },
|
||||
false
|
||||
);
|
||||
} );
|
||||
|
||||
afterAll(async () => {
|
||||
afterAll( async () => {
|
||||
await withRestApi.deleteAllShippingZones( false );
|
||||
});
|
||||
} );
|
||||
|
||||
it('should display cart items in order review', async () => {
|
||||
it( 'should display cart items in order review', async () => {
|
||||
await shopper.goToShop();
|
||||
await shopper.addToCartFromShopPage( productId );
|
||||
await shopper.goToCheckout();
|
||||
await shopper.productIsInCheckout(simpleProductName, `1`, singleProductPrice, singleProductPrice);
|
||||
});
|
||||
await shopper.productIsInCheckout(
|
||||
simpleProductName,
|
||||
`1`,
|
||||
singleProductPrice,
|
||||
singleProductPrice
|
||||
);
|
||||
} );
|
||||
|
||||
it('allows customer to choose available payment methods', async () => {
|
||||
it( 'allows customer to choose available payment methods', async () => {
|
||||
await shopper.goToShop();
|
||||
await shopper.addToCartFromShopPage( productId );
|
||||
await shopper.goToCheckout();
|
||||
await shopper.productIsInCheckout(simpleProductName, `2`, twoProductPrice, twoProductPrice);
|
||||
await shopper.productIsInCheckout(
|
||||
simpleProductName,
|
||||
`2`,
|
||||
twoProductPrice,
|
||||
twoProductPrice
|
||||
);
|
||||
|
||||
await expect(page).toClick('.wc_payment_method label', {text: 'Direct bank transfer'});
|
||||
await expect(page).toClick('.wc_payment_method label', {text: 'Cash on delivery'});
|
||||
});
|
||||
await expect( page ).toClick( '.wc_payment_method label', {
|
||||
text: 'Direct bank transfer',
|
||||
} );
|
||||
await expect( page ).toClick( '.wc_payment_method label', {
|
||||
text: 'Cash on delivery',
|
||||
} );
|
||||
} );
|
||||
|
||||
it('allows customer to fill billing details', async () => {
|
||||
it( 'allows customer to fill billing details', async () => {
|
||||
await shopper.goToShop();
|
||||
await shopper.addToCartFromShopPage( productId );
|
||||
await shopper.goToCheckout();
|
||||
await shopper.productIsInCheckout(simpleProductName, `3`, threeProductPrice, threeProductPrice);
|
||||
await shopper.fillBillingDetails(config.get('addresses.customer.billing'));
|
||||
});
|
||||
await shopper.productIsInCheckout(
|
||||
simpleProductName,
|
||||
`3`,
|
||||
threeProductPrice,
|
||||
threeProductPrice
|
||||
);
|
||||
await shopper.fillBillingDetails(
|
||||
config.get( 'addresses.customer.billing' )
|
||||
);
|
||||
} );
|
||||
|
||||
it('allows customer to fill shipping details', async () => {
|
||||
it( 'allows customer to fill shipping details', async () => {
|
||||
await shopper.goToShop();
|
||||
await shopper.addToCartFromShopPage( productId );
|
||||
await shopper.goToCheckout();
|
||||
await shopper.productIsInCheckout(simpleProductName, `4`, fourProductPrice, fourProductPrice);
|
||||
await shopper.productIsInCheckout(
|
||||
simpleProductName,
|
||||
`4`,
|
||||
fourProductPrice,
|
||||
fourProductPrice
|
||||
);
|
||||
|
||||
// Select checkbox to ship to a different address
|
||||
await page.evaluate(() => {
|
||||
document.querySelector('#ship-to-different-address-checkbox').click();
|
||||
});
|
||||
await page.evaluate( () => {
|
||||
document
|
||||
.querySelector( '#ship-to-different-address-checkbox' )
|
||||
.click();
|
||||
} );
|
||||
await uiUnblocked();
|
||||
|
||||
await shopper.fillShippingDetails(config.get('addresses.customer.shipping'));
|
||||
});
|
||||
await shopper.fillShippingDetails(
|
||||
config.get( 'addresses.customer.shipping' )
|
||||
);
|
||||
} );
|
||||
|
||||
it('allows guest customer to place order', async () => {
|
||||
it( 'allows guest customer to place order', async () => {
|
||||
await shopper.goToShop();
|
||||
await shopper.addToCartFromShopPage( productId );
|
||||
await shopper.goToCheckout();
|
||||
await shopper.productIsInCheckout(simpleProductName, `5`, fiveProductPrice, fiveProductPrice);
|
||||
await shopper.fillBillingDetails(config.get('addresses.customer.billing'));
|
||||
await shopper.productIsInCheckout(
|
||||
simpleProductName,
|
||||
`5`,
|
||||
fiveProductPrice,
|
||||
fiveProductPrice
|
||||
);
|
||||
await shopper.fillBillingDetails(
|
||||
config.get( 'addresses.customer.billing' )
|
||||
);
|
||||
|
||||
await uiUnblocked();
|
||||
|
||||
await expect(page).toClick('.wc_payment_method label', {text: 'Cash on delivery'});
|
||||
await expect(page).toMatchElement('.payment_method_cod', {text: 'Pay with cash upon delivery.'});
|
||||
await expect( page ).toClick( '.wc_payment_method label', {
|
||||
text: 'Cash on delivery',
|
||||
} );
|
||||
await expect( page ).toMatchElement( '.payment_method_cod', {
|
||||
text: 'Pay with cash upon delivery.',
|
||||
} );
|
||||
await uiUnblocked();
|
||||
await shopper.placeOrder();
|
||||
|
||||
await expect(page).toMatch('Order received');
|
||||
await expect( page ).toMatch( 'Order received' );
|
||||
|
||||
// Get order ID from the order received html element on the page
|
||||
let orderReceivedHtmlElement = await page.$('.woocommerce-order-overview__order.order');
|
||||
let orderReceivedText = await page.evaluate(element => element.textContent, orderReceivedHtmlElement);
|
||||
guestOrderId = orderReceivedText.split(/(\s+)/)[6].toString();
|
||||
});
|
||||
const orderReceivedHtmlElement = await page.$(
|
||||
'.woocommerce-order-overview__order.order'
|
||||
);
|
||||
const orderReceivedText = await page.evaluate(
|
||||
( element ) => element.textContent,
|
||||
orderReceivedHtmlElement
|
||||
);
|
||||
guestOrderId = orderReceivedText.split( /(\s+)/ )[ 6 ].toString();
|
||||
} );
|
||||
|
||||
it('allows existing customer to place order', async () => {
|
||||
it( 'allows existing customer to place order', async () => {
|
||||
await shopper.login();
|
||||
await shopper.goToShop();
|
||||
await shopper.addToCartFromShopPage( productId );
|
||||
await shopper.goToCheckout();
|
||||
await shopper.productIsInCheckout(simpleProductName, `1`, singleProductPrice, singleProductPrice);
|
||||
await shopper.fillBillingDetails(config.get('addresses.customer.billing'));
|
||||
await shopper.productIsInCheckout(
|
||||
simpleProductName,
|
||||
`1`,
|
||||
singleProductPrice,
|
||||
singleProductPrice
|
||||
);
|
||||
await shopper.fillBillingDetails(
|
||||
config.get( 'addresses.customer.billing' )
|
||||
);
|
||||
|
||||
await uiUnblocked();
|
||||
|
||||
await expect(page).toClick('.wc_payment_method label', {text: 'Cash on delivery'});
|
||||
await expect(page).toMatchElement('.payment_method_cod', {text: 'Pay with cash upon delivery.'});
|
||||
await expect( page ).toClick( '.wc_payment_method label', {
|
||||
text: 'Cash on delivery',
|
||||
} );
|
||||
await expect( page ).toMatchElement( '.payment_method_cod', {
|
||||
text: 'Pay with cash upon delivery.',
|
||||
} );
|
||||
await uiUnblocked();
|
||||
await shopper.placeOrder();
|
||||
|
||||
await expect(page).toMatch('Order received');
|
||||
await expect( page ).toMatch( 'Order received' );
|
||||
|
||||
// Get order ID from the order received html element on the page
|
||||
let orderReceivedHtmlElement = await page.$('.woocommerce-order-overview__order.order');
|
||||
let orderReceivedText = await page.evaluate(element => element.textContent, orderReceivedHtmlElement);
|
||||
customerOrderId = orderReceivedText.split(/(\s+)/)[6].toString();
|
||||
});
|
||||
const orderReceivedHtmlElement = await page.$(
|
||||
'.woocommerce-order-overview__order.order'
|
||||
);
|
||||
const orderReceivedText = await page.evaluate(
|
||||
( element ) => element.textContent,
|
||||
orderReceivedHtmlElement
|
||||
);
|
||||
customerOrderId = orderReceivedText
|
||||
.split( /(\s+)/ )[ 6 ]
|
||||
.toString();
|
||||
} );
|
||||
|
||||
it('merchant can confirm the order was received', async () => {
|
||||
it( 'merchant can confirm the order was received', async () => {
|
||||
await merchant.login();
|
||||
await merchant.verifyOrder(guestOrderId, simpleProductName, singleProductPrice, 5, fiveProductPrice);
|
||||
await merchant.verifyOrder(customerOrderId, simpleProductName, singleProductPrice, 1, singleProductPrice, true);
|
||||
});
|
||||
});
|
||||
await merchant.verifyOrder(
|
||||
guestOrderId,
|
||||
simpleProductName,
|
||||
singleProductPrice,
|
||||
5,
|
||||
fiveProductPrice
|
||||
);
|
||||
await merchant.verifyOrder(
|
||||
customerOrderId,
|
||||
simpleProductName,
|
||||
singleProductPrice,
|
||||
1,
|
||||
singleProductPrice,
|
||||
true
|
||||
);
|
||||
} );
|
||||
} );
|
||||
};
|
||||
|
||||
module.exports = runCheckoutPageTest;
|
||||
|
|
|
@ -17,37 +17,42 @@ const { it, describe, beforeAll, afterAll } = require( '@jest/globals' );
|
|||
const customerEmailAddress = 'john.doe.test@example.com';
|
||||
|
||||
const runMyAccountCreateAccountTest = () => {
|
||||
describe('Shopper My Account Create Account', () => {
|
||||
beforeAll(async () => {
|
||||
describe( 'Shopper My Account Create Account', () => {
|
||||
beforeAll( async () => {
|
||||
await withRestApi.deleteCustomerByEmail( customerEmailAddress );
|
||||
await merchant.login();
|
||||
|
||||
// Set checkbox in the settings to enable registration in my account
|
||||
await merchant.openSettings('account');
|
||||
await setCheckbox('#woocommerce_enable_myaccount_registration');
|
||||
await merchant.openSettings( 'account' );
|
||||
await setCheckbox( '#woocommerce_enable_myaccount_registration' );
|
||||
await settingsPageSaveChanges();
|
||||
|
||||
await merchant.logout();
|
||||
});
|
||||
} );
|
||||
|
||||
afterAll( async () => {
|
||||
await shopper.logout();
|
||||
} );
|
||||
|
||||
it('can create a new account via my account', async () => {
|
||||
it( 'can create a new account via my account', async () => {
|
||||
await shopper.gotoMyAccount();
|
||||
await page.waitForSelector('.woocommerce-form-register');
|
||||
await expect(page).toFill('input#reg_email', customerEmailAddress);
|
||||
await expect(page).toClick('button[name="register"]');
|
||||
await page.waitForNavigation({waitUntil: 'networkidle0'});
|
||||
await expect(page).toMatchElement('h1', 'My account');
|
||||
await page.waitForSelector( '.woocommerce-form-register' );
|
||||
await expect( page ).toFill(
|
||||
'input#reg_email',
|
||||
customerEmailAddress
|
||||
);
|
||||
await expect( page ).toClick( 'button[name="register"]' );
|
||||
await page.waitForNavigation( { waitUntil: 'networkidle0' } );
|
||||
await expect( page ).toMatchElement( 'h1', 'My account' );
|
||||
|
||||
// Verify user has been created successfully
|
||||
await merchant.login();
|
||||
await merchant.openAllUsersView();
|
||||
await expect(page).toMatchElement('td.email.column-email > a', {text: customerEmailAddress});
|
||||
});
|
||||
});
|
||||
await expect( page ).toMatchElement( 'td.email.column-email > a', {
|
||||
text: customerEmailAddress,
|
||||
} );
|
||||
} );
|
||||
} );
|
||||
};
|
||||
|
||||
module.exports = runMyAccountCreateAccountTest;
|
||||
|
|
|
@ -6,7 +6,7 @@ const {
|
|||
shopper,
|
||||
merchant,
|
||||
createSimpleProduct,
|
||||
uiUnblocked
|
||||
uiUnblocked,
|
||||
} = require( '@woocommerce/e2e-utils' );
|
||||
|
||||
/**
|
||||
|
@ -20,39 +20,46 @@ const config = require( 'config' );
|
|||
const simpleProductName = config.get( 'products.simple.name' );
|
||||
|
||||
const runMyAccountPayOrderTest = () => {
|
||||
describe('Customer can pay for their order through My Account', () => {
|
||||
beforeAll(async () => {
|
||||
describe( 'Customer can pay for their order through My Account', () => {
|
||||
beforeAll( async () => {
|
||||
simplePostIdValue = await createSimpleProduct();
|
||||
await shopper.login();
|
||||
await shopper.goToProduct(simplePostIdValue);
|
||||
await shopper.addToCart(simpleProductName);
|
||||
await shopper.goToProduct( simplePostIdValue );
|
||||
await shopper.addToCart( simpleProductName );
|
||||
await shopper.goToCheckout();
|
||||
await shopper.fillBillingDetails(config.get('addresses.customer.billing'));
|
||||
await shopper.fillBillingDetails(
|
||||
config.get( 'addresses.customer.billing' )
|
||||
);
|
||||
await uiUnblocked();
|
||||
await shopper.placeOrder();
|
||||
|
||||
// Get order ID from the order received html element on the page
|
||||
orderNum = await page.$$eval(".woocommerce-order-overview__order strong", elements => elements.map(item => item.textContent));
|
||||
orderNum = await page.$$eval(
|
||||
'.woocommerce-order-overview__order strong',
|
||||
( elements ) => elements.map( ( item ) => item.textContent )
|
||||
);
|
||||
|
||||
await merchant.login();
|
||||
await merchant.updateOrderStatus(orderNum, 'Pending payment');
|
||||
await merchant.updateOrderStatus( orderNum, 'Pending payment' );
|
||||
await merchant.logout();
|
||||
});
|
||||
} );
|
||||
|
||||
afterAll( async () => {
|
||||
await shopper.logout();
|
||||
} );
|
||||
|
||||
it('allows customer to pay for their order in My Account', async () => {
|
||||
it( 'allows customer to pay for their order in My Account', async () => {
|
||||
await shopper.login();
|
||||
await shopper.goToOrders();
|
||||
await expect(page).toClick('a.woocommerce-button.button.pay');
|
||||
await page.waitForNavigation({waitUntil: 'networkidle0'});
|
||||
await expect(page).toMatchElement('.entry-title', {text: 'Pay for order'});
|
||||
await expect( page ).toClick( 'a.woocommerce-button.button.pay' );
|
||||
await page.waitForNavigation( { waitUntil: 'networkidle0' } );
|
||||
await expect( page ).toMatchElement( '.entry-title', {
|
||||
text: 'Pay for order',
|
||||
} );
|
||||
await shopper.placeOrder();
|
||||
await expect(page).toMatch('Order received');
|
||||
});
|
||||
});
|
||||
}
|
||||
await expect( page ).toMatch( 'Order received' );
|
||||
} );
|
||||
} );
|
||||
};
|
||||
|
||||
module.exports = runMyAccountPayOrderTest;
|
||||
|
|
|
@ -2,9 +2,7 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
const {
|
||||
shopper,
|
||||
} = require( '@woocommerce/e2e-utils' );
|
||||
const { shopper } = require( '@woocommerce/e2e-utils' );
|
||||
|
||||
/**
|
||||
* External dependencies
|
||||
|
@ -12,35 +10,74 @@ const {
|
|||
const { it, describe } = require( '@jest/globals' );
|
||||
|
||||
const pages = [
|
||||
['Orders', 'my-account/orders', shopper.goToOrders],
|
||||
['Downloads', 'my-account/downloads', shopper.goToDownloads],
|
||||
['Addresses', 'my-account/edit-address', shopper.goToAddresses],
|
||||
['Account details', 'my-account/edit-account', shopper.goToAccountDetails]
|
||||
[ 'Orders', 'my-account/orders', shopper.goToOrders ],
|
||||
[ 'Downloads', 'my-account/downloads', shopper.goToDownloads ],
|
||||
[ 'Addresses', 'my-account/edit-address', shopper.goToAddresses ],
|
||||
[
|
||||
'Account details',
|
||||
'my-account/edit-account',
|
||||
shopper.goToAccountDetails,
|
||||
],
|
||||
];
|
||||
|
||||
const runMyAccountPageTest = () => {
|
||||
describe('My account page', () => {
|
||||
describe( 'My account page', () => {
|
||||
afterAll( async () => {
|
||||
await shopper.logout();
|
||||
} );
|
||||
|
||||
it('allows customer to login', async () => {
|
||||
it( 'allows customer to login', async () => {
|
||||
await shopper.login();
|
||||
expect(page).toMatch('Hello');
|
||||
await expect(page).toMatchElement('.woocommerce-MyAccount-navigation-link', { text: 'Dashboard' });
|
||||
await expect(page).toMatchElement('.woocommerce-MyAccount-navigation-link', { text: 'Orders' });
|
||||
await expect(page).toMatchElement('.woocommerce-MyAccount-navigation-link', { text: 'Downloads' });
|
||||
await expect(page).toMatchElement('.woocommerce-MyAccount-navigation-link', { text: 'Addresses' });
|
||||
await expect(page).toMatchElement('.woocommerce-MyAccount-navigation-link', { text: 'Account details' });
|
||||
await expect(page).toMatchElement('.woocommerce-MyAccount-navigation-link', { text: 'Logout' });
|
||||
});
|
||||
expect( page ).toMatch( 'Hello' );
|
||||
await expect( page ).toMatchElement(
|
||||
'.woocommerce-MyAccount-navigation-link',
|
||||
{
|
||||
text: 'Dashboard',
|
||||
}
|
||||
);
|
||||
await expect( page ).toMatchElement(
|
||||
'.woocommerce-MyAccount-navigation-link',
|
||||
{
|
||||
text: 'Orders',
|
||||
}
|
||||
);
|
||||
await expect( page ).toMatchElement(
|
||||
'.woocommerce-MyAccount-navigation-link',
|
||||
{
|
||||
text: 'Downloads',
|
||||
}
|
||||
);
|
||||
await expect( page ).toMatchElement(
|
||||
'.woocommerce-MyAccount-navigation-link',
|
||||
{
|
||||
text: 'Addresses',
|
||||
}
|
||||
);
|
||||
await expect( page ).toMatchElement(
|
||||
'.woocommerce-MyAccount-navigation-link',
|
||||
{
|
||||
text: 'Account details',
|
||||
}
|
||||
);
|
||||
await expect( page ).toMatchElement(
|
||||
'.woocommerce-MyAccount-navigation-link',
|
||||
{
|
||||
text: 'Logout',
|
||||
}
|
||||
);
|
||||
} );
|
||||
|
||||
it.each(pages)('allows customer to see %s page', async (pageTitle, path, goToPage) => {
|
||||
await goToPage();
|
||||
expect(page.url()).toMatch(path);
|
||||
await expect(page).toMatchElement('h1', { text: pageTitle });
|
||||
});
|
||||
});
|
||||
}
|
||||
it.each( pages )(
|
||||
'allows customer to see %s page',
|
||||
async ( pageTitle, path, goToPage ) => {
|
||||
await goToPage();
|
||||
expect( page.url() ).toMatch( path );
|
||||
await expect( page ).toMatchElement( 'h1', {
|
||||
text: pageTitle,
|
||||
} );
|
||||
}
|
||||
);
|
||||
} );
|
||||
};
|
||||
|
||||
module.exports = runMyAccountPageTest;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
const {
|
||||
const {
|
||||
shopper,
|
||||
merchant,
|
||||
createSimpleProduct,
|
||||
|
@ -23,38 +23,45 @@ const customerEmail = config.get( 'addresses.customer.billing.email' );
|
|||
const storeName = 'WooCommerce Core E2E Test Suite';
|
||||
|
||||
const runOrderEmailReceivingTest = () => {
|
||||
describe('Shopper Order Email Receiving', () => {
|
||||
beforeAll(async () => {
|
||||
describe( 'Shopper Order Email Receiving', () => {
|
||||
beforeAll( async () => {
|
||||
simplePostIdValue = await createSimpleProduct();
|
||||
|
||||
await merchant.login();
|
||||
await deleteAllEmailLogs();
|
||||
await merchant.logout();
|
||||
});
|
||||
} );
|
||||
|
||||
afterAll( async () => {
|
||||
await shopper.logout();
|
||||
} );
|
||||
|
||||
it('should receive order email after purchasing an item', async () => {
|
||||
it( 'should receive order email after purchasing an item', async () => {
|
||||
await shopper.login();
|
||||
|
||||
// Go to the shop and purchase an item
|
||||
await shopper.goToProduct(simplePostIdValue);
|
||||
await shopper.addToCart(simpleProductName);
|
||||
await shopper.goToProduct( simplePostIdValue );
|
||||
await shopper.addToCart( simpleProductName );
|
||||
await shopper.goToCheckout();
|
||||
await uiUnblocked();
|
||||
await shopper.placeOrder();
|
||||
// Get order ID from the order received html element on the page
|
||||
orderId = await page.$$eval(".woocommerce-order-overview__order strong", elements => elements.map(item => item.textContent));
|
||||
orderId = await page.$$eval(
|
||||
'.woocommerce-order-overview__order strong',
|
||||
( elements ) => elements.map( ( item ) => item.textContent )
|
||||
);
|
||||
|
||||
// Verify the new order email has been received
|
||||
await merchant.login();
|
||||
await merchant.openEmailLog();
|
||||
await expect( page ).toMatchElement( '.column-receiver', { text: customerEmail } );
|
||||
await expect( page ).toMatchElement( '.column-subject', { text: `[${storeName}]: New order #${orderId}` } );
|
||||
});
|
||||
});
|
||||
await expect( page ).toMatchElement( '.column-receiver', {
|
||||
text: customerEmail,
|
||||
} );
|
||||
await expect( page ).toMatchElement( '.column-subject', {
|
||||
text: `[${ storeName }]: New order #${ orderId }`,
|
||||
} );
|
||||
} );
|
||||
} );
|
||||
};
|
||||
|
||||
module.exports = runOrderEmailReceivingTest;
|
||||
|
|
|
@ -15,9 +15,15 @@ const { it, beforeAll } = require( '@jest/globals' );
|
|||
|
||||
const config = require( 'config' );
|
||||
const simpleProductName = config.get( 'products.simple.name' );
|
||||
const singleProductPrice = config.has('products.simple.price') ? config.get('products.simple.price') : '9.99';
|
||||
const singleProductPrice2 = config.has('products.simple.price') ? '1' + singleProductPrice : '19.99';
|
||||
const singleProductPrice3 = config.has('products.simple.price') ? '2' + singleProductPrice : '29.99';
|
||||
const singleProductPrice = config.has( 'products.simple.price' )
|
||||
? config.get( 'products.simple.price' )
|
||||
: '9.99';
|
||||
const singleProductPrice2 = config.has( 'products.simple.price' )
|
||||
? '1' + singleProductPrice
|
||||
: '19.99';
|
||||
const singleProductPrice3 = config.has( 'products.simple.price' )
|
||||
? '2' + singleProductPrice
|
||||
: '29.99';
|
||||
const clothing = 'Clothing';
|
||||
const audio = 'Audio';
|
||||
const hardware = 'Hardware';
|
||||
|
@ -26,60 +32,88 @@ const productTitle = 'li.first > a > h2.woocommerce-loop-product__title';
|
|||
const getWordPressVersion = async () => {
|
||||
const context = await getEnvironmentContext();
|
||||
return context.wpVersion;
|
||||
}
|
||||
};
|
||||
|
||||
const runProductBrowseSearchSortTest = () => {
|
||||
utils.describeIf( getWordPressVersion() >= 5.8 )( 'Search, browse by categories and sort items in the shop', () => {
|
||||
beforeAll(async () => {
|
||||
// Create 1st product with Clothing category
|
||||
await createSimpleProductWithCategory(simpleProductName + ' 1', singleProductPrice, clothing);
|
||||
// Create 2nd product with Audio category
|
||||
await createSimpleProductWithCategory(simpleProductName + ' 2', singleProductPrice2, audio);
|
||||
// Create 3rd product with Hardware category
|
||||
await createSimpleProductWithCategory(simpleProductName + ' 3', singleProductPrice3, hardware);
|
||||
});
|
||||
utils.describeIf( getWordPressVersion() >= 5.8 )(
|
||||
'Search, browse by categories and sort items in the shop',
|
||||
() => {
|
||||
beforeAll( async () => {
|
||||
// Create 1st product with Clothing category
|
||||
await createSimpleProductWithCategory(
|
||||
simpleProductName + ' 1',
|
||||
singleProductPrice,
|
||||
clothing
|
||||
);
|
||||
// Create 2nd product with Audio category
|
||||
await createSimpleProductWithCategory(
|
||||
simpleProductName + ' 2',
|
||||
singleProductPrice2,
|
||||
audio
|
||||
);
|
||||
// Create 3rd product with Hardware category
|
||||
await createSimpleProductWithCategory(
|
||||
simpleProductName + ' 3',
|
||||
singleProductPrice3,
|
||||
hardware
|
||||
);
|
||||
} );
|
||||
|
||||
it('should let user search the store', async () => {
|
||||
await shopper.goToShop();
|
||||
await shopper.searchForProduct(simpleProductName + ' 1');
|
||||
page.waitForNavigation({waitUntil: 'networkidle0'});
|
||||
});
|
||||
it( 'should let user search the store', async () => {
|
||||
await shopper.goToShop();
|
||||
await shopper.searchForProduct( simpleProductName + ' 1' );
|
||||
page.waitForNavigation( { waitUntil: 'networkidle0' } );
|
||||
} );
|
||||
|
||||
it('should let user browse products by categories', async () => {
|
||||
// Browse through Clothing category link
|
||||
await Promise.all([
|
||||
page.click('span.posted_in > a', {text: clothing}),
|
||||
page.waitForNavigation({waitUntil: 'networkidle0'}),
|
||||
]);
|
||||
it( 'should let user browse products by categories', async () => {
|
||||
// Browse through Clothing category link
|
||||
await Promise.all( [
|
||||
page.click( 'span.posted_in > a', { text: clothing } ),
|
||||
page.waitForNavigation( { waitUntil: 'networkidle0' } ),
|
||||
] );
|
||||
|
||||
// Verify Clothing category page
|
||||
await page.waitForSelector(productTitle);
|
||||
await expect(page).toMatchElement(productTitle, {text: simpleProductName + ' 1'});
|
||||
await expect(page).toClick(productTitle, {text: simpleProductName + ' 1'});
|
||||
page.waitForNavigation({waitUntil: 'networkidle0'});
|
||||
await page.waitForSelector('h1.entry-title');
|
||||
await expect(page).toMatchElement('h1.entry-title', simpleProductName + ' 1');
|
||||
});
|
||||
// Verify Clothing category page
|
||||
await page.waitForSelector( productTitle );
|
||||
await expect( page ).toMatchElement( productTitle, {
|
||||
text: simpleProductName + ' 1',
|
||||
} );
|
||||
await expect( page ).toClick( productTitle, {
|
||||
text: simpleProductName + ' 1',
|
||||
} );
|
||||
page.waitForNavigation( { waitUntil: 'networkidle0' } );
|
||||
await page.waitForSelector( 'h1.entry-title' );
|
||||
await expect( page ).toMatchElement(
|
||||
'h1.entry-title',
|
||||
simpleProductName + ' 1'
|
||||
);
|
||||
} );
|
||||
|
||||
it('should let user sort the products in the shop', async () => {
|
||||
await shopper.goToShop();
|
||||
it( 'should let user sort the products in the shop', async () => {
|
||||
await shopper.goToShop();
|
||||
|
||||
// Sort by price high to low
|
||||
await page.select('.orderby', 'price-desc');
|
||||
// Verify the first product in sort order
|
||||
await expect(page).toMatchElement(productTitle, {text: simpleProductName + ' 3'});
|
||||
// Sort by price high to low
|
||||
await page.select( '.orderby', 'price-desc' );
|
||||
// Verify the first product in sort order
|
||||
await expect( page ).toMatchElement( productTitle, {
|
||||
text: simpleProductName + ' 3',
|
||||
} );
|
||||
|
||||
// Sort by price low to high
|
||||
await page.select('.orderby', 'price');
|
||||
// Verify the first product in sort order
|
||||
await expect(page).toMatchElement(productTitle, {text: simpleProductName + ' 1'});
|
||||
// Sort by price low to high
|
||||
await page.select( '.orderby', 'price' );
|
||||
// Verify the first product in sort order
|
||||
await expect( page ).toMatchElement( productTitle, {
|
||||
text: simpleProductName + ' 1',
|
||||
} );
|
||||
|
||||
// Sort by date of creation, latest to oldest
|
||||
await page.select('.orderby', 'date');
|
||||
// Verify the first product in sort order
|
||||
await expect(page).toMatchElement(productTitle, {text: simpleProductName + ' 3'});
|
||||
});
|
||||
});
|
||||
// Sort by date of creation, latest to oldest
|
||||
await page.select( '.orderby', 'date' );
|
||||
// Verify the first product in sort order
|
||||
await expect( page ).toMatchElement( productTitle, {
|
||||
text: simpleProductName + ' 3',
|
||||
} );
|
||||
} );
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
module.exports = runProductBrowseSearchSortTest;
|
||||
|
|
|
@ -24,123 +24,147 @@ const defaultVariableProduct = config.get( 'products.variable' );
|
|||
let variableProductId;
|
||||
|
||||
// Variables for grouped product
|
||||
const simpleProductPrice = config.has('products.simple.price') ? config.get('products.simple.price') : '9.99';
|
||||
const simpleProductPrice = config.has( 'products.simple.price' )
|
||||
? config.get( 'products.simple.price' )
|
||||
: '9.99';
|
||||
const simple1 = {
|
||||
name: simpleProductName + ' 1',
|
||||
regularPrice: simpleProductPrice
|
||||
regularPrice: simpleProductPrice,
|
||||
};
|
||||
const simple2 = {
|
||||
name: simpleProductName + ' 2',
|
||||
regularPrice: simpleProductPrice
|
||||
regularPrice: simpleProductPrice,
|
||||
};
|
||||
const groupedProduct = {
|
||||
name: 'Grouped Product',
|
||||
groupedProducts: [simple1, simple2]
|
||||
groupedProducts: [ simple1, simple2 ],
|
||||
};
|
||||
let groupedPostIdValue;
|
||||
|
||||
const runSingleProductPageTest = () => {
|
||||
describe('Single Product Page', () => {
|
||||
beforeAll(async () => {
|
||||
describe( 'Single Product Page', () => {
|
||||
beforeAll( async () => {
|
||||
simplePostIdValue = await createSimpleProduct();
|
||||
});
|
||||
} );
|
||||
|
||||
it('should be able to add simple products to the cart', async () => {
|
||||
it( 'should be able to add simple products to the cart', async () => {
|
||||
// Add 5 simple products to cart
|
||||
await shopper.goToProduct(simplePostIdValue);
|
||||
await expect(page).toFill('div.quantity input.qty', '5');
|
||||
await shopper.goToProduct( simplePostIdValue );
|
||||
await expect( page ).toFill( 'div.quantity input.qty', '5' );
|
||||
await shopper.addToCart();
|
||||
await expect(page).toMatchElement('.woocommerce-message', {text: 'have been added to your cart.'});
|
||||
await expect( page ).toMatchElement( '.woocommerce-message', {
|
||||
text: 'have been added to your cart.',
|
||||
} );
|
||||
|
||||
// Verify cart contents
|
||||
await shopper.goToCart();
|
||||
await shopper.productIsInCart(simpleProductName, 5);
|
||||
});
|
||||
await shopper.productIsInCart( simpleProductName, 5 );
|
||||
} );
|
||||
|
||||
it('should be able to remove simple products from the cart', async () => {
|
||||
it( 'should be able to remove simple products from the cart', async () => {
|
||||
// Remove items from cart
|
||||
await shopper.removeFromCart( simplePostIdValue );
|
||||
await uiUnblocked();
|
||||
await expect(page).toMatchElement('.cart-empty', {text: 'Your cart is currently empty.'});
|
||||
});
|
||||
});
|
||||
await expect( page ).toMatchElement( '.cart-empty', {
|
||||
text: 'Your cart is currently empty.',
|
||||
} );
|
||||
} );
|
||||
} );
|
||||
|
||||
describe('Variable Product Page', () => {
|
||||
beforeAll(async () => {
|
||||
describe( 'Variable Product Page', () => {
|
||||
beforeAll( async () => {
|
||||
variableProductId = await createVariableProduct();
|
||||
});
|
||||
} );
|
||||
|
||||
it('should be able to add variation products to the cart', async () => {
|
||||
it( 'should be able to add variation products to the cart', async () => {
|
||||
// Add a product with one set of variations to cart
|
||||
await shopper.goToProduct(variableProductId);
|
||||
await shopper.goToProduct( variableProductId );
|
||||
|
||||
for (const attr of defaultVariableProduct.attributes) {
|
||||
for ( const attr of defaultVariableProduct.attributes ) {
|
||||
const { name, options } = attr;
|
||||
const selectElem = `#${name.toLowerCase()}`;
|
||||
const value = options[0];
|
||||
const selectElem = `#${ name.toLowerCase() }`;
|
||||
const value = options[ 0 ];
|
||||
|
||||
await expect(page).toSelect(selectElem, value);
|
||||
await expect( page ).toSelect( selectElem, value );
|
||||
}
|
||||
|
||||
await shopper.addToCart();
|
||||
await expect(page).toMatchElement('.woocommerce-message', {text: 'has been added to your cart.'});
|
||||
await expect( page ).toMatchElement( '.woocommerce-message', {
|
||||
text: 'has been added to your cart.',
|
||||
} );
|
||||
|
||||
// Verify cart contents
|
||||
await shopper.goToCart();
|
||||
await shopper.productIsInCart(defaultVariableProduct.name);
|
||||
});
|
||||
await shopper.productIsInCart( defaultVariableProduct.name );
|
||||
} );
|
||||
|
||||
it('should be able to remove variation products from the cart', async () => {
|
||||
it( 'should be able to remove variation products from the cart', async () => {
|
||||
// Remove items from cart
|
||||
await shopper.removeFromCart( variableProductId );
|
||||
await uiUnblocked();
|
||||
await expect(page).toMatchElement('.cart-empty', {text: 'Your cart is currently empty.'});
|
||||
});
|
||||
});
|
||||
await expect( page ).toMatchElement( '.cart-empty', {
|
||||
text: 'Your cart is currently empty.',
|
||||
} );
|
||||
} );
|
||||
} );
|
||||
|
||||
describe('Grouped Product Page', () => {
|
||||
beforeAll(async () => {
|
||||
groupedPostIdValue = await createGroupedProduct(groupedProduct);
|
||||
});
|
||||
describe( 'Grouped Product Page', () => {
|
||||
beforeAll( async () => {
|
||||
groupedPostIdValue = await createGroupedProduct( groupedProduct );
|
||||
} );
|
||||
|
||||
it('should be able to add grouped products to the cart', async () => {
|
||||
it( 'should be able to add grouped products to the cart', async () => {
|
||||
// Add a grouped product to cart
|
||||
await shopper.goToProduct(groupedPostIdValue);
|
||||
await page.waitForSelector('form.grouped_form');
|
||||
await shopper.goToProduct( groupedPostIdValue );
|
||||
await page.waitForSelector( 'form.grouped_form' );
|
||||
await shopper.addToCart();
|
||||
await expect(page).toMatchElement('.woocommerce-error',
|
||||
{text: 'Please choose the quantity of items you wish to add to your cart…'});
|
||||
const quantityFields = await page.$$('div.quantity input.qty');
|
||||
await quantityFields[0].click({clickCount: 3});
|
||||
await quantityFields[0].type('5');
|
||||
await quantityFields[1].click({clickCount: 3});
|
||||
await quantityFields[1].type('5');
|
||||
await expect( page ).toMatchElement( '.woocommerce-error', {
|
||||
text:
|
||||
'Please choose the quantity of items you wish to add to your cart…',
|
||||
} );
|
||||
const quantityFields = await page.$$( 'div.quantity input.qty' );
|
||||
await quantityFields[ 0 ].click( { clickCount: 3 } );
|
||||
await quantityFields[ 0 ].type( '5' );
|
||||
await quantityFields[ 1 ].click( { clickCount: 3 } );
|
||||
await quantityFields[ 1 ].type( '5' );
|
||||
await shopper.addToCart();
|
||||
await expect(page).toMatchElement('.woocommerce-message',
|
||||
{text: '“'+simpleProductName+' 1” and “'+simpleProductName+' 2” have been added to your cart.'});
|
||||
await expect( page ).toMatchElement( '.woocommerce-message', {
|
||||
text:
|
||||
'“' +
|
||||
simpleProductName +
|
||||
' 1” and “' +
|
||||
simpleProductName +
|
||||
' 2” have been added to your cart.',
|
||||
} );
|
||||
|
||||
// Verify cart contents
|
||||
await shopper.goToCart();
|
||||
await shopper.productIsInCart(simpleProductName+' 1');
|
||||
await shopper.productIsInCart(simpleProductName+' 2');
|
||||
});
|
||||
await shopper.productIsInCart( simpleProductName + ' 1' );
|
||||
await shopper.productIsInCart( simpleProductName + ' 2' );
|
||||
} );
|
||||
|
||||
it('should be able to remove grouped products from the cart', async () => {
|
||||
it( 'should be able to remove grouped products from the cart', async () => {
|
||||
// Remove items from cart
|
||||
await shopper.removeFromCart( simpleProductName+' 1' );
|
||||
await shopper.removeFromCart( simpleProductName + ' 1' );
|
||||
await uiUnblocked();
|
||||
await expect(page).toMatchElement('.woocommerce-message', {text: '“'+simpleProductName+' 1” removed.'});
|
||||
await expect( page ).toMatchElement( '.woocommerce-message', {
|
||||
text: '“' + simpleProductName + ' 1” removed.',
|
||||
} );
|
||||
await Promise.all( [
|
||||
// Reload page and perform item removal, since removeFromCart won't remove it when placed in a row
|
||||
page.reload(),
|
||||
page.waitForNavigation( { waitUntil: 'networkidle0' } ),
|
||||
] );
|
||||
await shopper.removeFromCart(simpleProductName+' 2');
|
||||
await shopper.removeFromCart( simpleProductName + ' 2' );
|
||||
await uiUnblocked();
|
||||
await expect(page).toMatchElement('.woocommerce-message', {text: '“'+simpleProductName+' 2” removed.'});
|
||||
await expect(page).toMatchElement('.cart-empty', {text: 'Your cart is currently empty.'});
|
||||
});
|
||||
});
|
||||
await expect( page ).toMatchElement( '.woocommerce-message', {
|
||||
text: '“' + simpleProductName + ' 2” removed.',
|
||||
} );
|
||||
await expect( page ).toMatchElement( '.cart-empty', {
|
||||
text: 'Your cart is currently empty.',
|
||||
} );
|
||||
} );
|
||||
} );
|
||||
};
|
||||
|
||||
module.exports = runSingleProductPageTest;
|
||||
|
|
|
@ -2,105 +2,128 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
const {
|
||||
shopper,
|
||||
createVariableProduct,
|
||||
} = require( '@woocommerce/e2e-utils' );
|
||||
const config = require('config');
|
||||
const { shopper, createVariableProduct } = require( '@woocommerce/e2e-utils' );
|
||||
const config = require( 'config' );
|
||||
|
||||
let variablePostIdValue;
|
||||
|
||||
const cartDialogMessage = 'Please select some product options before adding this product to your cart.';
|
||||
const attributes = config.get( 'products.variable.attributes' )
|
||||
const cartDialogMessage =
|
||||
'Please select some product options before adding this product to your cart.';
|
||||
const attributes = config.get( 'products.variable.attributes' );
|
||||
|
||||
const runVariableProductUpdateTest = () => {
|
||||
describe('Shopper > Update variable product',() => {
|
||||
beforeAll(async () => {
|
||||
describe( 'Shopper > Update variable product', () => {
|
||||
beforeAll( async () => {
|
||||
variablePostIdValue = await createVariableProduct();
|
||||
});
|
||||
} );
|
||||
|
||||
it('shopper can change variable attributes to the same value', async () => {
|
||||
await shopper.goToProduct(variablePostIdValue);
|
||||
it( 'shopper can change variable attributes to the same value', async () => {
|
||||
await shopper.goToProduct( variablePostIdValue );
|
||||
|
||||
for (const a of attributes) {
|
||||
for ( const a of attributes ) {
|
||||
const { name, options } = a;
|
||||
const attrHTMLId = `#${name.toLowerCase()}`;
|
||||
const attrHTMLId = `#${ name.toLowerCase() }`;
|
||||
|
||||
await expect(page).toSelect(attrHTMLId, options[0]);
|
||||
await expect( page ).toSelect( attrHTMLId, options[ 0 ] );
|
||||
}
|
||||
|
||||
await expect(page).toMatchElement('.woocommerce-variation-price', {
|
||||
text: '9.99'
|
||||
});
|
||||
});
|
||||
await expect( page ).toMatchElement(
|
||||
'.woocommerce-variation-price',
|
||||
{
|
||||
text: '9.99',
|
||||
}
|
||||
);
|
||||
} );
|
||||
|
||||
it('shopper can change attributes to combination with dimensions and weight', async () => {
|
||||
await shopper.goToProduct(variablePostIdValue);
|
||||
await expect(page).toSelect(
|
||||
`#${attributes[0].name.toLowerCase()}`,
|
||||
attributes[0].options[0]
|
||||
it( 'shopper can change attributes to combination with dimensions and weight', async () => {
|
||||
await shopper.goToProduct( variablePostIdValue );
|
||||
await expect( page ).toSelect(
|
||||
`#${ attributes[ 0 ].name.toLowerCase() }`,
|
||||
attributes[ 0 ].options[ 0 ]
|
||||
);
|
||||
await expect(page).toSelect(
|
||||
`#${attributes[1].name.toLowerCase()}`,
|
||||
attributes[1].options[1]
|
||||
await expect( page ).toSelect(
|
||||
`#${ attributes[ 1 ].name.toLowerCase() }`,
|
||||
attributes[ 1 ].options[ 1 ]
|
||||
);
|
||||
await expect(page).toSelect(
|
||||
`#${attributes[2].name.toLowerCase()}`,
|
||||
attributes[2].options[0]
|
||||
await expect( page ).toSelect(
|
||||
`#${ attributes[ 2 ].name.toLowerCase() }`,
|
||||
attributes[ 2 ].options[ 0 ]
|
||||
);
|
||||
|
||||
await expect(page).toMatchElement('.woocommerce-variation-price', { text: '20.00' });
|
||||
await expect(page).toMatchElement('.woocommerce-variation-availability', { text: 'Out of stock' });
|
||||
await expect(page).toMatchElement('.woocommerce-product-attributes-item--weight', { text: '200 kg' });
|
||||
await expect(page).toMatchElement('.woocommerce-product-attributes-item--dimensions', { text: '10 × 20 × 15 cm' });
|
||||
|
||||
});
|
||||
|
||||
it('shopper can change variable product attributes to variation with a different price', async () => {
|
||||
await shopper.goToProduct(variablePostIdValue);
|
||||
await expect(page).toSelect(
|
||||
`#${attributes[0].name.toLowerCase()}`,
|
||||
attributes[0].options[0]
|
||||
await expect( page ).toMatchElement(
|
||||
'.woocommerce-variation-price',
|
||||
{ text: '20.00' }
|
||||
);
|
||||
await expect(page).toSelect(
|
||||
`#${attributes[1].name.toLowerCase()}`,
|
||||
attributes[1].options[0]
|
||||
await expect( page ).toMatchElement(
|
||||
'.woocommerce-variation-availability',
|
||||
{
|
||||
text: 'Out of stock',
|
||||
}
|
||||
);
|
||||
await expect(page).toSelect(
|
||||
`#${attributes[2].name.toLowerCase()}`,
|
||||
attributes[2].options[1]
|
||||
await expect( page ).toMatchElement(
|
||||
'.woocommerce-product-attributes-item--weight',
|
||||
{
|
||||
text: '200 kg',
|
||||
}
|
||||
);
|
||||
await expect(
|
||||
page
|
||||
).toMatchElement(
|
||||
'.woocommerce-product-attributes-item--dimensions',
|
||||
{ text: '10 × 20 × 15 cm' }
|
||||
);
|
||||
} );
|
||||
|
||||
it( 'shopper can change variable product attributes to variation with a different price', async () => {
|
||||
await shopper.goToProduct( variablePostIdValue );
|
||||
await expect( page ).toSelect(
|
||||
`#${ attributes[ 0 ].name.toLowerCase() }`,
|
||||
attributes[ 0 ].options[ 0 ]
|
||||
);
|
||||
await expect( page ).toSelect(
|
||||
`#${ attributes[ 1 ].name.toLowerCase() }`,
|
||||
attributes[ 1 ].options[ 0 ]
|
||||
);
|
||||
await expect( page ).toSelect(
|
||||
`#${ attributes[ 2 ].name.toLowerCase() }`,
|
||||
attributes[ 2 ].options[ 1 ]
|
||||
);
|
||||
|
||||
await expect(page).toMatchElement('.woocommerce-variation-price', { text: '11.99' });
|
||||
});
|
||||
await expect( page ).toMatchElement(
|
||||
'.woocommerce-variation-price',
|
||||
{ text: '11.99' }
|
||||
);
|
||||
} );
|
||||
|
||||
it('shopper can reset variations', async () => {
|
||||
await shopper.goToProduct(variablePostIdValue);
|
||||
await expect(page).toSelect(
|
||||
`#${attributes[0].name.toLowerCase()}`,
|
||||
attributes[0].options[0]
|
||||
it( 'shopper can reset variations', async () => {
|
||||
await shopper.goToProduct( variablePostIdValue );
|
||||
await expect( page ).toSelect(
|
||||
`#${ attributes[ 0 ].name.toLowerCase() }`,
|
||||
attributes[ 0 ].options[ 0 ]
|
||||
);
|
||||
await expect(page).toSelect(
|
||||
`#${attributes[1].name.toLowerCase()}`,
|
||||
attributes[1].options[1]
|
||||
await expect( page ).toSelect(
|
||||
`#${ attributes[ 1 ].name.toLowerCase() }`,
|
||||
attributes[ 1 ].options[ 1 ]
|
||||
);
|
||||
await expect(page).toSelect(
|
||||
`#${attributes[2].name.toLowerCase()}`,
|
||||
attributes[2].options[0]
|
||||
await expect( page ).toSelect(
|
||||
`#${ attributes[ 2 ].name.toLowerCase() }`,
|
||||
attributes[ 2 ].options[ 0 ]
|
||||
);
|
||||
|
||||
await expect(page).toClick('.reset_variations');
|
||||
await expect( page ).toClick( '.reset_variations' );
|
||||
|
||||
// Verify the reset by attempting to add the product to the cart
|
||||
const couponDialog = await expect(page).toDisplayDialog(async () => {
|
||||
await expect(page).toClick('.single_add_to_cart_button');
|
||||
});
|
||||
const couponDialog = await expect( page ).toDisplayDialog(
|
||||
async () => {
|
||||
await expect( page ).toClick(
|
||||
'.single_add_to_cart_button'
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
expect(couponDialog.message()).toMatch(cartDialogMessage);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
expect( couponDialog.message() ).toMatch( cartDialogMessage );
|
||||
} );
|
||||
} );
|
||||
};
|
||||
|
||||
module.exports = runVariableProductUpdateTest;
|
||||
|
|
|
@ -6,7 +6,7 @@ const { createCoupon } = require( '@woocommerce/e2e-utils' );
|
|||
const couponsTable = [
|
||||
[ 'fixed cart', { text: '$5.00' }, { text: '$4.99' } ],
|
||||
[ 'percentage', { text: '$4.99' }, { text: '$5.00' } ],
|
||||
[ 'fixed product', { text: '$5.00' }, { text: '$4.99' } ]
|
||||
[ 'fixed product', { text: '$5.00' }, { text: '$4.99' } ],
|
||||
];
|
||||
|
||||
let couponFixedCart;
|
||||
|
@ -28,12 +28,18 @@ const getCouponId = async ( couponType ) => {
|
|||
return couponFixedCart;
|
||||
case 'percentage':
|
||||
if ( ! couponPercentage ) {
|
||||
couponPercentage = await createCoupon( '50', 'Percentage discount' );
|
||||
couponPercentage = await createCoupon(
|
||||
'50',
|
||||
'Percentage discount'
|
||||
);
|
||||
}
|
||||
return couponPercentage;
|
||||
case 'fixed product':
|
||||
if ( ! couponFixedProduct ) {
|
||||
couponFixedProduct = await createCoupon( '5', 'Fixed product discount' );
|
||||
couponFixedProduct = await createCoupon(
|
||||
'5',
|
||||
'Fixed product discount'
|
||||
);
|
||||
}
|
||||
return couponFixedProduct;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
module.exports = {
|
||||
extends: [
|
||||
'plugin:jest/recommended',
|
||||
],
|
||||
extends: [ 'plugin:@woocommerce/eslint-plugin/recommended' ],
|
||||
env: {
|
||||
'jest/globals': true,
|
||||
},
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: dev
|
||||
|
||||
Standardize linting: Ensure e2e packages are lintable
|
|
@ -29,9 +29,9 @@
|
|||
"@wordpress/jest-preset-default": "^7.1.3",
|
||||
"app-root-path": "^3.0.0",
|
||||
"commander": "4.1.1",
|
||||
"config": "3.3.3",
|
||||
"config": "3.3.3",
|
||||
"jest": "^25.1.0",
|
||||
"jest-circus": "25.1.0",
|
||||
"jest-circus": "25.1.0",
|
||||
"jest-each": "25.5.0",
|
||||
"jest-puppeteer": "^4.4.0",
|
||||
"node-stream-zip": "^1.13.6",
|
||||
|
@ -53,7 +53,7 @@
|
|||
"@wordpress/babel-plugin-import-jsx-pragma": "1.1.3",
|
||||
"@wordpress/babel-preset-default": "3.0.2",
|
||||
"@wordpress/browserslist-config": "^4.1.0",
|
||||
"@wordpress/eslint-plugin": "7.3.0",
|
||||
"@woocommerce/eslint-plugin": "workspace:*",
|
||||
"eslint": "^8.1.0",
|
||||
"ndb": "^1.1.5",
|
||||
"semver": "^7.3.2"
|
||||
|
@ -66,7 +66,7 @@
|
|||
"clean": "rm -rf ./build ./build-module",
|
||||
"compile": "e2e-builds",
|
||||
"build": "pnpm run clean && pnpm run compile",
|
||||
"prepack": "pnpm run build",
|
||||
"prepare": "pnpm run build",
|
||||
"docker:up": "./bin/docker-compose.sh up",
|
||||
"docker:wait": "bash ./bin/wait-for-build.sh",
|
||||
"docker:down": "./bin/docker-compose.sh down",
|
||||
|
@ -75,14 +75,15 @@
|
|||
"test:e2e": "bash ./bin/wait-for-build.sh && ./bin/e2e-test-integration.js",
|
||||
"test:e2e-debug": "bash ./bin/wait-for-build.sh && ./bin/e2e-test-integration.js --dev --debug",
|
||||
"test:e2e-dev": "bash ./bin/wait-for-build.sh && ./bin/e2e-test-integration.js --dev",
|
||||
"lint": "eslint src"
|
||||
"lint": "eslint src --ext=js,ts,tsx",
|
||||
"lint:fix": "eslint src --ext=js,ts,tsx --fix"
|
||||
},
|
||||
"bin": {
|
||||
"wc-e2e": "bin/wc-e2e.sh"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.(t|j)s?(x)": [
|
||||
"eslint --fix"
|
||||
"pnpm lint:fix"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,8 +78,8 @@ global.it = ( () => {
|
|||
/**
|
||||
* Save a screenshot during a test if the test fails.
|
||||
*
|
||||
* @param testName
|
||||
* @param callback
|
||||
* @param testName
|
||||
* @param callback
|
||||
* @return {Promise<void>}
|
||||
*/
|
||||
const screenshotTest = async ( testName, callback ) => {
|
||||
|
|
|
@ -67,7 +67,7 @@ const initializeSlack = () => {
|
|||
/**
|
||||
* Post a message to a Slack channel for a failed test.
|
||||
*
|
||||
* @param testName
|
||||
* @param testName
|
||||
* @return {Promise<void>}
|
||||
*/
|
||||
async function sendFailedTestMessageToSlack( testName ) {
|
||||
|
@ -131,7 +131,7 @@ async function sendFailedTestMessageToSlack( testName ) {
|
|||
/**
|
||||
* Post a screenshot to a Slack channel for a failed test.
|
||||
*
|
||||
* @param screenshotOfFailedTest
|
||||
* @param screenshotOfFailedTest
|
||||
* @return {Promise<void>}
|
||||
*/
|
||||
async function sendFailedTestScreenshotToSlack( screenshotOfFailedTest ) {
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: dev
|
||||
|
||||
Standardize linting: Ensure e2e packages are lintable
|
|
@ -45,7 +45,13 @@
|
|||
"clean": "rm -rf ./build ./build-module",
|
||||
"compile": "e2e-builds",
|
||||
"build": "pnpm run clean && pnpm run compile",
|
||||
"prepack": "pnpm run build",
|
||||
"lint": "eslint src"
|
||||
"prepare": "pnpm run build",
|
||||
"lint": "eslint src --ext=js,ts,tsx",
|
||||
"lint:fix": "eslint src --ext=js,ts,tsx --fix"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.(t|j)s?(x)": [
|
||||
"pnpm lint:fix"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ const uuid = require( 'uuid' );
|
|||
/**
|
||||
* Verify and publish
|
||||
*
|
||||
* @param noticeText The text that appears in the notice after publishing.
|
||||
* @param noticeText The text that appears in the notice after publishing.
|
||||
*/
|
||||
const verifyAndPublish = async ( noticeText ) => {
|
||||
// Wait for auto save
|
||||
|
@ -53,7 +53,7 @@ const verifyAndPublish = async ( noticeText ) => {
|
|||
/**
|
||||
* Wait for primary button to be enabled and click.
|
||||
*
|
||||
* @param waitForNetworkIdle - Wait for network idle after click
|
||||
* @param waitForNetworkIdle - Wait for network idle after click
|
||||
* @return {Promise<void>}
|
||||
*/
|
||||
const waitAndClickPrimary = async ( waitForNetworkIdle = true ) => {
|
||||
|
@ -231,8 +231,8 @@ const completeOnboardingWizard = async () => {
|
|||
/**
|
||||
* Create simple product.
|
||||
*
|
||||
* @param {string} productTitle Defaults to Simple Product. Customizable title.
|
||||
* @param {string} productPrice Defaults to $9.99. Customizable pricing.
|
||||
* @param {string} productTitle Defaults to Simple Product. Customizable title.
|
||||
* @param {string} productPrice Defaults to $9.99. Customizable pricing.
|
||||
* @param {Object} additionalProps Defaults to nothing. Additional product properties.
|
||||
*/
|
||||
const createSimpleProduct = async (
|
||||
|
@ -252,9 +252,9 @@ const createSimpleProduct = async (
|
|||
/**
|
||||
* Create simple product with categories
|
||||
*
|
||||
* @param productName Product's name which can be changed when writing a test
|
||||
* @param productPrice Product's price which can be changed when writing a test
|
||||
* @param categoryName Product's category which can be changed when writing a test
|
||||
* @param productName Product's name which can be changed when writing a test
|
||||
* @param productPrice Product's price which can be changed when writing a test
|
||||
* @param categoryName Product's category which can be changed when writing a test
|
||||
*/
|
||||
const createSimpleProductWithCategory = async (
|
||||
productName,
|
||||
|
@ -281,10 +281,10 @@ const createSimpleProductWithCategory = async (
|
|||
/**
|
||||
* Create simple downloadable product
|
||||
*
|
||||
* @param name Product's name. Defaults to 'Simple Product' (see createSimpleProduct definition).
|
||||
* @param downloadLimit Product's download limit. Defaults to '-1' (unlimited).
|
||||
* @param downloadName Product's download name. Defaults to 'Single'.
|
||||
* @param price Product's price. Defaults to '$9.99' (see createSimpleProduct definition).
|
||||
* @param name Product's name. Defaults to 'Simple Product' (see createSimpleProduct definition).
|
||||
* @param downloadLimit Product's download limit. Defaults to '-1' (unlimited).
|
||||
* @param downloadName Product's download name. Defaults to 'Single'.
|
||||
* @param price Product's price. Defaults to '$9.99' (see createSimpleProduct definition).
|
||||
*/
|
||||
const createSimpleDownloadableProduct = async (
|
||||
name,
|
||||
|
@ -312,7 +312,7 @@ const createSimpleDownloadableProduct = async (
|
|||
* Create variable product.
|
||||
* Also, create variations for all attributes.
|
||||
*
|
||||
* @param varProduct Defaults to the variable product object in `default.json`
|
||||
* @param varProduct Defaults to the variable product object in `default.json`
|
||||
* @return the ID of the created variable product
|
||||
*/
|
||||
const createVariableProduct = async ( varProduct = defaultVariableProduct ) => {
|
||||
|
@ -383,7 +383,7 @@ const createVariableProduct = async ( varProduct = defaultVariableProduct ) => {
|
|||
/**
|
||||
* Create grouped product.
|
||||
*
|
||||
* @param groupedProduct Defaults to the grouped product object in `default.json`
|
||||
* @param groupedProduct Defaults to the grouped product object in `default.json`
|
||||
* @return ID of the grouped product
|
||||
*/
|
||||
const createGroupedProduct = async (
|
||||
|
@ -446,7 +446,7 @@ const createOrder = async ( orderOptions = {} ) => {
|
|||
/**
|
||||
* Create a basic order with the provided order status.
|
||||
*
|
||||
* @param orderStatus Status of the new order. Defaults to `Pending payment`.
|
||||
* @param orderStatus Status of the new order. Defaults to `Pending payment`.
|
||||
*/
|
||||
const createSimpleOrder = async ( orderStatus = 'Pending payment' ) => {
|
||||
// Go to 'Add new order' page
|
||||
|
@ -481,7 +481,7 @@ const createSimpleOrder = async ( orderStatus = 'Pending payment' ) => {
|
|||
* Creates a batch of orders from the given `statuses`
|
||||
* using the "Batch Create Order" API.
|
||||
*
|
||||
* @param statuses Array of order statuses
|
||||
* @param statuses Array of order statuses
|
||||
*/
|
||||
const batchCreateOrders = async ( statuses ) => {
|
||||
const defaultOrder = config.get( 'orders.basicPaidOrder' );
|
||||
|
@ -505,8 +505,8 @@ const batchCreateOrders = async ( statuses ) => {
|
|||
/**
|
||||
* Adds a product to an order in the merchant.
|
||||
*
|
||||
* @param orderId ID of the order to add the product to.
|
||||
* @param productName Name of the product being added to the order.
|
||||
* @param orderId ID of the order to add the product to.
|
||||
* @param productName Name of the product being added to the order.
|
||||
*/
|
||||
const addProductToOrder = async ( orderId, productName ) => {
|
||||
await merchant.goToOrder( orderId );
|
||||
|
@ -539,8 +539,8 @@ const addProductToOrder = async ( orderId, productName ) => {
|
|||
/**
|
||||
* Creates a basic coupon with the provided coupon amount. Returns the coupon code.
|
||||
*
|
||||
* @param couponAmount Amount to be applied. Defaults to 5.
|
||||
* @param discountType Type of a coupon. Defaults to Fixed cart discount.
|
||||
* @param couponAmount Amount to be applied. Defaults to 5.
|
||||
* @param discountType Type of a coupon. Defaults to Fixed cart discount.
|
||||
*/
|
||||
const createCoupon = async (
|
||||
couponAmount = '5',
|
||||
|
@ -576,10 +576,10 @@ const createCoupon = async (
|
|||
/**
|
||||
* Adds a shipping zone along with a shipping method.
|
||||
*
|
||||
* @param zoneName Shipping zone name.
|
||||
* @param zoneLocation Shiping zone location. Defaults to country:US. For states use: state:US:CA
|
||||
* @param zipCode Shipping zone zip code. Defaults to empty one space.
|
||||
* @param zoneMethod Shipping method type. Defaults to flat_rate (use also: free_shipping or local_pickup)
|
||||
* @param zoneName Shipping zone name.
|
||||
* @param zoneLocation Shiping zone location. Defaults to country:US. For states use: state:US:CA
|
||||
* @param zipCode Shipping zone zip code. Defaults to empty one space.
|
||||
* @param zoneMethod Shipping method type. Defaults to flat_rate (use also: free_shipping or local_pickup)
|
||||
*/
|
||||
const addShippingZoneAndMethod = async (
|
||||
zoneName,
|
||||
|
@ -626,8 +626,8 @@ const addShippingZoneAndMethod = async (
|
|||
/**
|
||||
* Click the Update button on the order details page.
|
||||
*
|
||||
* @param noticeText The text that appears in the notice after updating the order.
|
||||
* @param waitForSave Optionally wait for auto save.
|
||||
* @param noticeText The text that appears in the notice after updating the order.
|
||||
* @param waitForSave Optionally wait for auto save.
|
||||
*/
|
||||
const clickUpdateOrder = async ( noticeText, waitForSave = false ) => {
|
||||
if ( waitForSave ) {
|
||||
|
|
|
@ -531,7 +531,7 @@ const merchant = {
|
|||
/**
|
||||
* Deactivate a plugin by the plugin's name with the option to delete the plugin as well.
|
||||
*
|
||||
* @param {string} pluginName The name of the plugin to deactivate. For example, `WooCommerce`.
|
||||
* @param {string} pluginName The name of the plugin to deactivate. For example, `WooCommerce`.
|
||||
* @param {boolean} deletePlugin Pass in `true` to delete the plugin. Defaults to `false`.
|
||||
*/
|
||||
deactivatePlugin: async ( pluginName, deletePlugin = false ) => {
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
* Take a string name and generate the slug for it.
|
||||
* Example: 'My plugin' => 'my-plugin'
|
||||
*
|
||||
* @param text string to convert to a slug
|
||||
* @param text string to convert to a slug
|
||||
*
|
||||
* Sourced from: https://gist.github.com/spyesx/561b1d65d4afb595f295
|
||||
* Sourced from: https://gist.github.com/spyesx/561b1d65d4afb595f295
|
||||
*/
|
||||
export const getSlug = ( text ) => {
|
||||
text = text.trim().toLowerCase();
|
||||
|
@ -39,7 +39,7 @@ export const itIf = ( condition ) => ( condition ? it : it.skip );
|
|||
/**
|
||||
* Wait for a timeout in milliseconds
|
||||
*
|
||||
* @param timeout delay time in milliseconds
|
||||
* @param timeout delay time in milliseconds
|
||||
* @return {Promise<void>}
|
||||
*/
|
||||
export const waitForTimeout = async ( timeout ) => {
|
||||
|
|
|
@ -16,9 +16,9 @@ const userEndpoint = '/wp/v2/users';
|
|||
/**
|
||||
* Utility function to delete all merchant created data store objects.
|
||||
*
|
||||
* @param repository
|
||||
* @param defaultObjectId
|
||||
* @param statuses Status of the object to check
|
||||
* @param repository
|
||||
* @param defaultObjectId
|
||||
* @param statuses Status of the object to check
|
||||
* @return {Promise<void>}
|
||||
*/
|
||||
const deleteAllRepositoryObjects = async (
|
||||
|
@ -226,13 +226,13 @@ export const withRestApi = {
|
|||
/**
|
||||
* Adds a shipping zone along with a shipping method using the API.
|
||||
*
|
||||
* @param zoneName Shipping zone name.
|
||||
* @param zoneLocation Shiping zone location. Defaults to country:US. For states use: state:US:CA.
|
||||
* @param zipCode Shipping zone zip code. Default is no zip code.
|
||||
* @param zoneMethod Shipping method type. Defaults to flat_rate (use also: free_shipping or local_pickup).
|
||||
* @param cost Shipping method cost. Default is no cost.
|
||||
* @param additionalZoneMethods Array of additional zone methods to add to the shipping zone.
|
||||
* @param {boolean} testResponse Test the response status code.
|
||||
* @param zoneName Shipping zone name.
|
||||
* @param zoneLocation Shiping zone location. Defaults to country:US. For states use: state:US:CA.
|
||||
* @param zipCode Shipping zone zip code. Default is no zip code.
|
||||
* @param zoneMethod Shipping method type. Defaults to flat_rate (use also: free_shipping or local_pickup).
|
||||
* @param cost Shipping method cost. Default is no cost.
|
||||
* @param additionalZoneMethods Array of additional zone methods to add to the shipping zone.
|
||||
* @param {boolean} testResponse Test the response status code.
|
||||
*/
|
||||
addShippingZoneAndMethod: async (
|
||||
zoneName,
|
||||
|
@ -367,7 +367,7 @@ export const withRestApi = {
|
|||
/**
|
||||
* Delete a customer account by their email address if the user exists.
|
||||
*
|
||||
* @param emailAddress Customer user account email address.
|
||||
* @param emailAddress Customer user account email address.
|
||||
* @return {Promise<void>}
|
||||
*/
|
||||
deleteCustomerByEmail: async ( emailAddress ) => {
|
||||
|
@ -394,8 +394,8 @@ export const withRestApi = {
|
|||
/**
|
||||
* Reset a settings group to default values except selects.
|
||||
*
|
||||
* @param settingsGroup
|
||||
* @param {boolean} testResponse Test the response status code.
|
||||
* @param settingsGroup
|
||||
* @param {boolean} testResponse Test the response status code.
|
||||
* @return {Promise<void>}
|
||||
*/
|
||||
resetSettingsGroupToDefault: async (
|
||||
|
@ -437,8 +437,8 @@ export const withRestApi = {
|
|||
* Update a setting to the supplied value.
|
||||
*
|
||||
* @param {string} settingsGroup The settings group to update.
|
||||
* @param {string} settingId The setting ID to update
|
||||
* @param {Object} payload An object with a key/value pair to update.
|
||||
* @param {string} settingId The setting ID to update
|
||||
* @param {Object} payload An object with a key/value pair to update.
|
||||
*/
|
||||
updateSettingOption: async ( settingsGroup, settingId, payload = {} ) => {
|
||||
const settingsClient = Setting.restRepository( client );
|
||||
|
@ -447,9 +447,9 @@ export const withRestApi = {
|
|||
/**
|
||||
* Update a payment gateway.
|
||||
*
|
||||
* @param {string} paymentGatewayId The ID of the payment gateway to update.
|
||||
* @param {Object} payload An object with the key/value pair to update.
|
||||
* @param {boolean} testResponse Test the response status code.
|
||||
* @param {string} paymentGatewayId The ID of the payment gateway to update.
|
||||
* @param {Object} payload An object with the key/value pair to update.
|
||||
* @param {boolean} testResponse Test the response status code.
|
||||
*/
|
||||
updatePaymentGateway: async (
|
||||
paymentGatewayId,
|
||||
|
@ -467,7 +467,7 @@ export const withRestApi = {
|
|||
/**
|
||||
* Create a batch of orders using the "Batch Create Order" API endpoint.
|
||||
*
|
||||
* @param orders Array of orders to be created
|
||||
* @param orders Array of orders to be created
|
||||
* @param {boolean} testResponse Test the response status code.
|
||||
*/
|
||||
batchCreateOrders: async ( orders, testResponse = true ) => {
|
||||
|
|
|
@ -114,8 +114,8 @@ export const backboneUnblocked = async () => {
|
|||
/**
|
||||
* Conditionally wait for a selector without throwing an error.
|
||||
*
|
||||
* @param selector
|
||||
* @param timeoutInSeconds
|
||||
* @param selector
|
||||
* @param timeoutInSeconds
|
||||
* @return {Promise<boolean>}
|
||||
*/
|
||||
export const waitForSelectorWithoutThrow = async (
|
||||
|
@ -136,7 +136,7 @@ export const waitForSelectorWithoutThrow = async (
|
|||
/**
|
||||
* Publish, verify that item was published. Trash, verify that item was trashed.
|
||||
*
|
||||
* @param {string} button (Publish)
|
||||
* @param {string} button (Publish)
|
||||
* @param {string} publishNotice
|
||||
* @param {string} publishVerification
|
||||
* @param {string} trashVerification
|
||||
|
@ -193,7 +193,7 @@ export const verifyCheckboxIsUnset = async ( selector ) => {
|
|||
* Verify the value of input field once it was saved (can be used for radio buttons verification as well).
|
||||
*
|
||||
* @param {string} selector Selector of the input field that needs to be verified.
|
||||
* @param {string} value Value of the input field that needs to be verified.
|
||||
* @param {string} value Value of the input field that needs to be verified.
|
||||
*/
|
||||
export const verifyValueOfInputField = async ( selector, value ) => {
|
||||
await page.focus( selector );
|
||||
|
@ -249,7 +249,7 @@ export const evalAndClick = async ( selector ) => {
|
|||
/**
|
||||
* Select a value from select2 search input field.
|
||||
*
|
||||
* @param {string} value Value of what to be selected
|
||||
* @param {string} value Value of what to be selected
|
||||
* @param {string} selector Selector of the select2 search field
|
||||
*/
|
||||
export const selectOptionInSelect2 = async (
|
||||
|
@ -266,8 +266,8 @@ export const selectOptionInSelect2 = async (
|
|||
/**
|
||||
* Search by any term for an order
|
||||
*
|
||||
* @param {string} value Value to be entered into the search field
|
||||
* @param {string} orderId Order ID
|
||||
* @param {string} value Value to be entered into the search field
|
||||
* @param {string} orderId Order ID
|
||||
* @param {string} customerName Customer's full name attached to order ID.
|
||||
*/
|
||||
export const searchForOrder = async ( value, orderId, customerName ) => {
|
||||
|
@ -284,7 +284,7 @@ export const searchForOrder = async ( value, orderId, customerName ) => {
|
|||
* Apply a coupon code within cart or checkout.
|
||||
* Method will try to apply a coupon in the checkout, otherwise will try to apply in the cart.
|
||||
*
|
||||
* @param couponCode string
|
||||
* @param couponCode string
|
||||
* @return {Promise<void>}
|
||||
*/
|
||||
export const applyCoupon = async ( couponCode ) => {
|
||||
|
@ -310,7 +310,7 @@ export const applyCoupon = async ( couponCode ) => {
|
|||
/**
|
||||
* Remove one coupon within cart or checkout.
|
||||
*
|
||||
* @param couponCode Coupon name.
|
||||
* @param couponCode Coupon name.
|
||||
* @return {Promise<void>}
|
||||
*/
|
||||
export const removeCoupon = async ( couponCode ) => {
|
||||
|
@ -348,7 +348,7 @@ export const selectOrderAction = async ( action ) => {
|
|||
*
|
||||
* @param {string} buttonSelector Selector of button to click
|
||||
* @param {string} resultSelector Selector to wait for after click
|
||||
* @param {number} timeout Timeout length in milliseconds. Default 5000.
|
||||
* @param {number} timeout Timeout length in milliseconds. Default 5000.
|
||||
* @return {Promise<void>}
|
||||
*/
|
||||
export const clickAndWaitForSelector = async (
|
||||
|
@ -367,9 +367,9 @@ export const clickAndWaitForSelector = async (
|
|||
* Behavior can be modified with @param options. Possible keys: `visible`, `hidden`, `timeout`.
|
||||
* More details at: https://pptr.dev/#?product=Puppeteer&show=api-pagewaitforselectorselector-options
|
||||
*
|
||||
* @param {Puppeteer.Page} page Puppeteer representation of the page.
|
||||
* @param {string} selector CSS selector of the element
|
||||
* @param {Object} options Custom options to modify function behavior.
|
||||
* @param {Puppeteer.Page} page Puppeteer representation of the page.
|
||||
* @param {string} selector CSS selector of the element
|
||||
* @param {Object} options Custom options to modify function behavior.
|
||||
*/
|
||||
export async function waitForSelector( page, selector, options = {} ) {
|
||||
// set up default options
|
||||
|
@ -384,7 +384,7 @@ export async function waitForSelector( page, selector, options = {} ) {
|
|||
* Retrieves the desired HTML attribute from a selector.
|
||||
* For example, the 'value' attribute of an input element.
|
||||
*
|
||||
* @param {string} selector Selector of the element you want to get the attribute from.
|
||||
* @param {string} selector Selector of the element you want to get the attribute from.
|
||||
* @param {string} attribute The desired HTML attribute.
|
||||
* @return {Promise<string>}
|
||||
*/
|
||||
|
@ -399,8 +399,8 @@ export async function getSelectorAttribute( selector, attribute ) {
|
|||
/**
|
||||
* Asserts the value of the desired HTML attribute of a selector.
|
||||
*
|
||||
* @param {string} selector Selector of the element you want to verify.
|
||||
* @param {string} attribute The desired HTML attribute.
|
||||
* @param {string} selector Selector of the element you want to verify.
|
||||
* @param {string} attribute The desired HTML attribute.
|
||||
* @param {string} expectedValue The expected value.
|
||||
*/
|
||||
export async function verifyValueOfElementAttribute(
|
||||
|
|
|
@ -4,9 +4,9 @@ export class AdminEdit {
|
|||
/**
|
||||
* Publish the object being edited and verify published status
|
||||
*
|
||||
* @param button Publish button selector
|
||||
* @param publishNotice Publish notice selector
|
||||
* @param publishVerification Expected notice on successful publish
|
||||
* @param button Publish button selector
|
||||
* @param publishNotice Publish notice selector
|
||||
* @param publishVerification Expected notice on successful publish
|
||||
* @return {Promise<void>}
|
||||
*/
|
||||
async verifyPublish( button, publishNotice, publishVerification ) {
|
||||
|
|
209
pnpm-lock.yaml
209
pnpm-lock.yaml
|
@ -187,8 +187,10 @@ importers:
|
|||
|
||||
packages/js/api-core-tests:
|
||||
specifiers:
|
||||
'@woocommerce/eslint-plugin': workspace:*
|
||||
allure-commandline: ^2.17.2
|
||||
dotenv: ^10.0.0
|
||||
eslint: ^8.12.0
|
||||
jest: ^25.1.0
|
||||
jest-allure: ^0.1.3
|
||||
jest-runner-groups: ^2.1.0
|
||||
|
@ -202,6 +204,9 @@ importers:
|
|||
jest-runner-groups: 2.1.0
|
||||
postman-collection: 4.1.0
|
||||
supertest: 6.1.6
|
||||
devDependencies:
|
||||
'@woocommerce/eslint-plugin': link:../eslint-plugin
|
||||
eslint: 8.12.0
|
||||
|
||||
packages/js/components:
|
||||
specifiers:
|
||||
|
@ -605,13 +610,17 @@ importers:
|
|||
packages/js/e2e-builds:
|
||||
specifiers:
|
||||
'@babel/core': 7.12.9
|
||||
'@woocommerce/eslint-plugin': workspace:*
|
||||
chalk: ^4.1.2
|
||||
eslint: ^8.12.0
|
||||
glob: ^7.2.0
|
||||
lodash: ^4.17.21
|
||||
mkdirp: ^1.0.4
|
||||
devDependencies:
|
||||
'@babel/core': 7.12.9
|
||||
'@woocommerce/eslint-plugin': link:../eslint-plugin
|
||||
chalk: 4.1.2
|
||||
eslint: 8.12.0
|
||||
glob: 7.2.0
|
||||
lodash: 4.17.21
|
||||
mkdirp: 1.0.4
|
||||
|
@ -628,11 +637,13 @@ importers:
|
|||
'@babel/preset-env': 7.12.7
|
||||
'@jest/globals': ^26.4.2
|
||||
'@woocommerce/e2e-builds': workspace:*
|
||||
'@woocommerce/eslint-plugin': workspace:*
|
||||
'@wordpress/babel-plugin-import-jsx-pragma': 1.1.3
|
||||
'@wordpress/babel-preset-default': 3.0.2
|
||||
'@wordpress/browserslist-config': ^4.1.0
|
||||
'@wordpress/deprecated': ^3.2.3
|
||||
config: 3.3.3
|
||||
eslint: ^8.12.0
|
||||
dependencies:
|
||||
'@jest/globals': 26.6.2
|
||||
'@wordpress/deprecated': 3.2.3
|
||||
|
@ -647,9 +658,11 @@ importers:
|
|||
'@babel/polyfill': 7.12.1
|
||||
'@babel/preset-env': 7.12.7_@babel+core@7.12.9
|
||||
'@woocommerce/e2e-builds': link:../e2e-builds
|
||||
'@woocommerce/eslint-plugin': link:../eslint-plugin
|
||||
'@wordpress/babel-plugin-import-jsx-pragma': 1.1.3_@babel+core@7.12.9
|
||||
'@wordpress/babel-preset-default': 3.0.2
|
||||
'@wordpress/browserslist-config': 4.1.0
|
||||
eslint: 8.12.0
|
||||
|
||||
packages/js/e2e-environment:
|
||||
specifiers:
|
||||
|
@ -666,11 +679,11 @@ importers:
|
|||
'@slack/web-api': ^6.1.0
|
||||
'@woocommerce/api': ^0.2.0
|
||||
'@woocommerce/e2e-builds': workspace:*
|
||||
'@woocommerce/eslint-plugin': workspace:*
|
||||
'@wordpress/babel-plugin-import-jsx-pragma': 1.1.3
|
||||
'@wordpress/babel-preset-default': 3.0.2
|
||||
'@wordpress/browserslist-config': ^4.1.0
|
||||
'@wordpress/e2e-test-utils': ^4.16.1
|
||||
'@wordpress/eslint-plugin': 7.3.0
|
||||
'@wordpress/jest-preset-default': ^7.1.3
|
||||
app-root-path: ^3.0.0
|
||||
commander: 4.1.1
|
||||
|
@ -716,10 +729,10 @@ importers:
|
|||
'@babel/polyfill': 7.12.1
|
||||
'@babel/preset-env': 7.12.7_@babel+core@7.12.9
|
||||
'@woocommerce/e2e-builds': link:../e2e-builds
|
||||
'@woocommerce/eslint-plugin': link:../eslint-plugin
|
||||
'@wordpress/babel-plugin-import-jsx-pragma': 1.1.3_@babel+core@7.12.9
|
||||
'@wordpress/babel-preset-default': 3.0.2
|
||||
'@wordpress/browserslist-config': 4.1.0
|
||||
'@wordpress/eslint-plugin': 7.3.0_eslint@8.2.0+typescript@4.2.4
|
||||
eslint: 8.2.0
|
||||
ndb: 1.1.5
|
||||
semver: 7.3.5
|
||||
|
@ -13960,22 +13973,6 @@ packages:
|
|||
- typescript
|
||||
dev: true
|
||||
|
||||
/@typescript-eslint/experimental-utils/2.34.0_eslint@8.2.0+typescript@4.2.4:
|
||||
resolution: {integrity: sha512-eS6FTkq+wuMJ+sgtuNTtcqavWXqsflWcfBnlYhg/nS4aZ1leewkXGbvBhaapn1q6qf4M71bsR1tez5JTRMuqwA==}
|
||||
engines: {node: ^8.10.0 || ^10.13.0 || >=11.10.1}
|
||||
peerDependencies:
|
||||
eslint: '*'
|
||||
dependencies:
|
||||
'@types/json-schema': 7.0.9
|
||||
'@typescript-eslint/typescript-estree': 2.34.0_typescript@4.2.4
|
||||
eslint: 8.2.0
|
||||
eslint-scope: 5.1.1
|
||||
eslint-utils: 2.1.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
- typescript
|
||||
dev: true
|
||||
|
||||
/@typescript-eslint/experimental-utils/3.10.1_eslint@6.8.0+typescript@3.9.7:
|
||||
resolution: {integrity: sha512-DewqIgscDzmAfd5nOGe4zm6Bl7PKtMG2Ad0KG8CUZAHlXfAKTF9Ol5PXhiMh39yRL2ChRH1cuuUGOcVyyrhQIw==}
|
||||
engines: {node: ^10.12.0 || >=12.0.0}
|
||||
|
@ -14316,27 +14313,6 @@ packages:
|
|||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@typescript-eslint/typescript-estree/2.34.0_typescript@4.2.4:
|
||||
resolution: {integrity: sha512-OMAr+nJWKdlVM9LOqCqh3pQQPwxHAN7Du8DR6dmwCrAmxtiXQnhHJ6tBNtf+cggqfo51SG/FCwnKhXCIM7hnVg==}
|
||||
engines: {node: ^8.10.0 || ^10.13.0 || >=11.10.1}
|
||||
peerDependencies:
|
||||
typescript: '*'
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
dependencies:
|
||||
debug: 4.3.3
|
||||
eslint-visitor-keys: 1.3.0
|
||||
glob: 7.2.0
|
||||
is-glob: 4.0.3
|
||||
lodash: 4.17.21
|
||||
semver: 7.3.5
|
||||
tsutils: 3.21.0_typescript@4.2.4
|
||||
typescript: 4.2.4
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@typescript-eslint/typescript-estree/2.34.0_typescript@4.6.2:
|
||||
resolution: {integrity: sha512-OMAr+nJWKdlVM9LOqCqh3pQQPwxHAN7Du8DR6dmwCrAmxtiXQnhHJ6tBNtf+cggqfo51SG/FCwnKhXCIM7hnVg==}
|
||||
engines: {node: ^8.10.0 || ^10.13.0 || >=11.10.1}
|
||||
|
@ -15881,30 +15857,6 @@ packages:
|
|||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@wordpress/eslint-plugin/7.3.0_eslint@8.2.0+typescript@4.2.4:
|
||||
resolution: {integrity: sha512-7wIFzzc14E1XuuT9haBuhoA9FRUGWlbD4Oek+XkiZlzNVqZI3slgbtIFJ6/Mfij1V18rv6Ns9a1cPJLtCU8JHQ==}
|
||||
peerDependencies:
|
||||
eslint: ^6 || ^7
|
||||
dependencies:
|
||||
'@wordpress/prettier-config': 0.4.0
|
||||
babel-eslint: 10.1.0_eslint@8.2.0
|
||||
cosmiconfig: 7.0.1
|
||||
eslint: 8.2.0
|
||||
eslint-config-prettier: 6.15.0_eslint@8.2.0
|
||||
eslint-plugin-jest: 23.20.0_eslint@8.2.0+typescript@4.2.4
|
||||
eslint-plugin-jsdoc: 30.7.13_eslint@8.2.0
|
||||
eslint-plugin-jsx-a11y: 6.5.1_eslint@8.2.0
|
||||
eslint-plugin-prettier: 3.4.1_1786dfa66f4aafe2692523a4f07ad974
|
||||
eslint-plugin-react: 7.29.4_eslint@8.2.0
|
||||
eslint-plugin-react-hooks: 4.3.0_eslint@8.2.0
|
||||
globals: 12.4.0
|
||||
prettier: /wp-prettier/2.0.5
|
||||
requireindex: 1.2.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
- typescript
|
||||
dev: true
|
||||
|
||||
/@wordpress/eslint-plugin/7.4.0_eslint@7.32.0+typescript@4.6.2:
|
||||
resolution: {integrity: sha512-HJpDYz2drtC9rY8MiYtYJ3cimioEIweGyb3P2DQTjUZ3sC4AGg+97PhXLHUdKfsFQ31JRxyLS9kKuGdDVBwWww==}
|
||||
engines: {node: '>=10', npm: '>=6.9'}
|
||||
|
@ -17437,24 +17389,6 @@ packages:
|
|||
- supports-color
|
||||
dev: true
|
||||
|
||||
/babel-eslint/10.1.0_eslint@8.2.0:
|
||||
resolution: {integrity: sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg==}
|
||||
engines: {node: '>=6'}
|
||||
deprecated: babel-eslint is now @babel/eslint-parser. This package will no longer receive updates.
|
||||
peerDependencies:
|
||||
eslint: '>= 4.12.1'
|
||||
dependencies:
|
||||
'@babel/code-frame': 7.16.0
|
||||
'@babel/parser': 7.16.4
|
||||
'@babel/traverse': 7.16.3
|
||||
'@babel/types': 7.16.0
|
||||
eslint: 8.2.0
|
||||
eslint-visitor-keys: 1.3.0
|
||||
resolve: 1.20.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/babel-generator/6.26.1:
|
||||
resolution: {integrity: sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==}
|
||||
dependencies:
|
||||
|
@ -21613,16 +21547,6 @@ packages:
|
|||
get-stdin: 6.0.0
|
||||
dev: true
|
||||
|
||||
/eslint-config-prettier/6.15.0_eslint@8.2.0:
|
||||
resolution: {integrity: sha512-a1+kOYLR8wMGustcgAjdydMsQ2A/2ipRPwRKUmfYaSxc9ZPcrku080Ctl6zrZzZNs/U82MjSv+qKREkoq3bJaw==}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
eslint: '>=3.14.1'
|
||||
dependencies:
|
||||
eslint: 8.2.0
|
||||
get-stdin: 6.0.0
|
||||
dev: true
|
||||
|
||||
/eslint-config-prettier/8.5.0:
|
||||
resolution: {integrity: sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==}
|
||||
hasBin: true
|
||||
|
@ -21801,19 +21725,6 @@ packages:
|
|||
- typescript
|
||||
dev: true
|
||||
|
||||
/eslint-plugin-jest/23.20.0_eslint@8.2.0+typescript@4.2.4:
|
||||
resolution: {integrity: sha512-+6BGQt85OREevBDWCvhqj1yYA4+BFK4XnRZSGJionuEYmcglMZYLNNBBemwzbqUAckURaHdJSBcjHPyrtypZOw==}
|
||||
engines: {node: '>=8'}
|
||||
peerDependencies:
|
||||
eslint: '>=5'
|
||||
dependencies:
|
||||
'@typescript-eslint/experimental-utils': 2.34.0_eslint@8.2.0+typescript@4.2.4
|
||||
eslint: 8.2.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
- typescript
|
||||
dev: true
|
||||
|
||||
/eslint-plugin-jest/25.7.0_6bef967891becc1ab6057e2949a5834f:
|
||||
resolution: {integrity: sha512-PWLUEXeeF7C9QGKqvdSbzLOiLTx+bno7/HC9eefePfEb257QFHg7ye3dh80AZVkaa/RQsBB1Q/ORQvg2X7F0NQ==}
|
||||
engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
|
||||
|
@ -21896,24 +21807,6 @@ packages:
|
|||
- supports-color
|
||||
dev: true
|
||||
|
||||
/eslint-plugin-jsdoc/30.7.13_eslint@8.2.0:
|
||||
resolution: {integrity: sha512-YM4WIsmurrp0rHX6XiXQppqKB8Ne5ATiZLJe2+/fkp9l9ExXFr43BbAbjZaVrpCT+tuPYOZ8k1MICARHnURUNQ==}
|
||||
engines: {node: '>=10'}
|
||||
peerDependencies:
|
||||
eslint: ^6.0.0 || ^7.0.0
|
||||
dependencies:
|
||||
comment-parser: 0.7.6
|
||||
debug: 4.3.4
|
||||
eslint: 8.2.0
|
||||
jsdoctypeparser: 9.0.0
|
||||
lodash: 4.17.21
|
||||
regextras: 0.7.1
|
||||
semver: 7.3.5
|
||||
spdx-expression-parse: 3.0.1
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/eslint-plugin-jsdoc/37.9.7:
|
||||
resolution: {integrity: sha512-8alON8yYcStY94o0HycU2zkLKQdcS+qhhOUNQpfONHHwvI99afbmfpYuPqf6PbLz5pLZldG3Te5I0RbAiTN42g==}
|
||||
engines: {node: ^12 || ^14 || ^16 || ^17}
|
||||
|
@ -22051,27 +21944,6 @@ packages:
|
|||
language-tags: 1.0.5
|
||||
minimatch: 3.1.2
|
||||
|
||||
/eslint-plugin-jsx-a11y/6.5.1_eslint@8.2.0:
|
||||
resolution: {integrity: sha512-sVCFKX9fllURnXT2JwLN5Qgo24Ug5NF6dxhkmxsMEUZhXRcGg+X3e1JbJ84YePQKBl5E0ZjAH5Q4rkdcGY99+g==}
|
||||
engines: {node: '>=4.0'}
|
||||
peerDependencies:
|
||||
eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8
|
||||
dependencies:
|
||||
'@babel/runtime': 7.17.7
|
||||
aria-query: 4.2.2
|
||||
array-includes: 3.1.4
|
||||
ast-types-flow: 0.0.7
|
||||
axe-core: 4.3.5
|
||||
axobject-query: 2.2.0
|
||||
damerau-levenshtein: 1.0.7
|
||||
emoji-regex: 9.2.2
|
||||
eslint: 8.2.0
|
||||
has: 1.0.3
|
||||
jsx-ast-utils: 3.2.1
|
||||
language-tags: 1.0.5
|
||||
minimatch: 3.1.2
|
||||
dev: true
|
||||
|
||||
/eslint-plugin-markdown/1.0.2:
|
||||
resolution: {integrity: sha512-BfvXKsO0K+zvdarNc801jsE/NTLmig4oKhZ1U3aSUgTf2dB/US5+CrfGxMsCK2Ki1vS1R3HPok+uYpufFndhzw==}
|
||||
engines: {node: ^6.14.0 || ^8.10.0 || >=9.10.0}
|
||||
|
@ -22081,23 +21953,6 @@ packages:
|
|||
unified: 6.2.0
|
||||
dev: true
|
||||
|
||||
/eslint-plugin-prettier/3.4.1_1786dfa66f4aafe2692523a4f07ad974:
|
||||
resolution: {integrity: sha512-htg25EUYUeIhKHXjOinK4BgCcDwtLHjqaxCDsMy5nbnUMkKFvIhMVCp+5GFUXQ4Nr8lBsPqtGAqBenbpFqAA2g==}
|
||||
engines: {node: '>=6.0.0'}
|
||||
peerDependencies:
|
||||
eslint: '>=5.0.0'
|
||||
eslint-config-prettier: '*'
|
||||
prettier: '>=1.13.0'
|
||||
peerDependenciesMeta:
|
||||
eslint-config-prettier:
|
||||
optional: true
|
||||
dependencies:
|
||||
eslint: 8.2.0
|
||||
eslint-config-prettier: 6.15.0_eslint@8.2.0
|
||||
prettier: /wp-prettier/2.0.5
|
||||
prettier-linter-helpers: 1.0.0
|
||||
dev: true
|
||||
|
||||
/eslint-plugin-prettier/3.4.1_41158af9eda640c62e4773187c5a8429:
|
||||
resolution: {integrity: sha512-htg25EUYUeIhKHXjOinK4BgCcDwtLHjqaxCDsMy5nbnUMkKFvIhMVCp+5GFUXQ4Nr8lBsPqtGAqBenbpFqAA2g==}
|
||||
engines: {node: '>=6.0.0'}
|
||||
|
@ -22206,15 +22061,6 @@ packages:
|
|||
dependencies:
|
||||
eslint: 8.12.0
|
||||
|
||||
/eslint-plugin-react-hooks/4.3.0_eslint@8.2.0:
|
||||
resolution: {integrity: sha512-XslZy0LnMn+84NEG9jSGR6eGqaZB3133L8xewQo3fQagbQuGt7a63gf+P1NGKZavEYEC3UXaWEAA/AqDkuN6xA==}
|
||||
engines: {node: '>=10'}
|
||||
peerDependencies:
|
||||
eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0
|
||||
dependencies:
|
||||
eslint: 8.2.0
|
||||
dev: true
|
||||
|
||||
/eslint-plugin-react/7.29.4:
|
||||
resolution: {integrity: sha512-CVCXajliVh509PcZYRFyu/BoUEz452+jtQJq2b3Bae4v3xBUWPLCmtmBM+ZinG4MzwmxJgJ2M5rMqhqLVn7MtQ==}
|
||||
engines: {node: '>=4'}
|
||||
|
@ -22305,29 +22151,6 @@ packages:
|
|||
semver: 6.3.0
|
||||
string.prototype.matchall: 4.0.6
|
||||
|
||||
/eslint-plugin-react/7.29.4_eslint@8.2.0:
|
||||
resolution: {integrity: sha512-CVCXajliVh509PcZYRFyu/BoUEz452+jtQJq2b3Bae4v3xBUWPLCmtmBM+ZinG4MzwmxJgJ2M5rMqhqLVn7MtQ==}
|
||||
engines: {node: '>=4'}
|
||||
peerDependencies:
|
||||
eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8
|
||||
dependencies:
|
||||
array-includes: 3.1.4
|
||||
array.prototype.flatmap: 1.2.5
|
||||
doctrine: 2.1.0
|
||||
eslint: 8.2.0
|
||||
estraverse: 5.3.0
|
||||
jsx-ast-utils: 3.2.1
|
||||
minimatch: 3.1.2
|
||||
object.entries: 1.1.5
|
||||
object.fromentries: 2.0.5
|
||||
object.hasown: 1.1.0
|
||||
object.values: 1.1.5
|
||||
prop-types: 15.8.1
|
||||
resolve: 2.0.0-next.3
|
||||
semver: 6.3.0
|
||||
string.prototype.matchall: 4.0.6
|
||||
dev: true
|
||||
|
||||
/eslint-plugin-testing-library/5.1.0_eslint@8.12.0+typescript@4.6.2:
|
||||
resolution: {integrity: sha512-YSNzasJUbyhOTe14ZPygeOBvcPvcaNkwHwrj4vdf+uirr2D32JTDaKi6CP5Os2aWtOcvt4uBSPXp9h5xGoqvWQ==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0, npm: '>=6'}
|
||||
|
@ -37310,7 +37133,7 @@ packages:
|
|||
serialize-javascript: 6.0.0
|
||||
source-map: 0.6.1
|
||||
terser: 5.10.0_acorn@8.7.0
|
||||
webpack: 5.70.0
|
||||
webpack: 5.70.0_webpack-cli@3.3.12
|
||||
transitivePeerDependencies:
|
||||
- acorn
|
||||
dev: true
|
||||
|
|
Loading…
Reference in New Issue