Code review feedback

This commit is contained in:
Greg 2021-09-07 16:20:44 -06:00
parent 1ce5f7a863
commit 095a74347a
17 changed files with 152 additions and 205 deletions

View File

@ -28,6 +28,7 @@
"docker:down": "npx wc-e2e docker:down",
"docker:ssh": "npx wc-e2e docker:ssh",
"docker:up": "npx wc-e2e docker:up",
"test:api": "cd ./tests/e2e/api-core-tests && jest --group=api",
"test:e2e": "npx wc-e2e test:e2e",
"test:e2e-debug": "npx wc-e2e test:e2e-debug",
"test:e2e-dev": "npx wc-e2e test:e2e-dev",
@ -47,6 +48,7 @@
"@typescript-eslint/experimental-utils": "3.10.1",
"@typescript-eslint/parser": "3.10.1",
"@woocommerce/api": "file:tests/e2e/api",
"@woocommerce/api-core-tests": "file:tests/e2e/api-core-tests",
"@woocommerce/e2e-core-tests": "file:tests/e2e/core-tests",
"@woocommerce/e2e-environment": "file:tests/e2e/env",
"@woocommerce/e2e-utils": "file:tests/e2e/utils",
@ -132,6 +134,7 @@
"no-e2e": {
"exclude": [
"@woocommerce/api",
"@woocommerce/api-core-tests",
"@woocommerce/e2e-core-tests",
"@woocommerce/e2e-environment",
"@woocommerce/e2e-utils",

View File

@ -5,14 +5,14 @@
BASE_URL=""
# The admin user's username or generated consumer key
# USERNAME="admin"
# USERNAME="ck_1234"
USERNAME=""
# USER_KEY="admin"
# USER_KEY="ck_1234"
USER_KEY=""
# The admin user's password or generated consumer secret
# PASSWORD="password"
# PASSWORD="cs_1234"
PASSWORD=""
# USER_SECRET="password"
# USER_SECRET="cs_1234"
USER_SECRET=""
# Optional setting to output verbose logs from Jest
# VERBOSE=true

View File

@ -1,22 +1,3 @@
# Editors
project.xml
project.properties
/nbproject/private/
.buildpath
.project
.settings*
.idea
.vscode
*.sublime-project
*.sublime-workspace
.sublimelinterrc
# OS X metadata
.DS_Store
# Windows thumbnail cache
Thumbs.db
# Node modules
node_modules/

View File

@ -11,14 +11,20 @@ Before running the tests, the following environment variables need to be configu
BASE_URL="https://mysite.com"
# The admin user's username or generated consumer key
USERNAME=""
USER_KEY=""
# The admin user's password or generated consumer secret
PASSWORD=""
USER_SECRET=""
```
For local setup, create a `.env` file in this folder with the three required values described above.
Alternatively, these values can be passed in via the command line. For example:
```shell
BASE_URL=http://localhost:8084 USER_KEY=admin USER_SECRET=password npm run test:api
```
When using a username and password combination instead of a consumer secret and consumer key, make sure to have the [JSON Basic Authentication plugin](https://github.com/WP-API/Basic-Auth) installed and activated on the test site.
For more information about authentication with the WooCommerce API, please see the [Authentication](https://woocommerce.github.io/woocommerce-rest-api-docs/?javascript#authentication) section in the WooCommerce REST API documentation.

View File

@ -25,9 +25,9 @@ const coupon = {
exclude_sale_items: false,
minimum_amount: '100.00',
maximum_amount: '',
email_restrictions: []
}
email_restrictions: [],
};
module.exports = {
coupon
}
coupon,
};

View File

@ -1,9 +1,9 @@
const order = require('./order');
const coupon = require('./coupon');
const { order } = require('./order');
const { coupon } = require('./coupon');
const shared = require('./shared');
module.exports = {
order,
coupon,
shared,
}
};

View File

@ -7,34 +7,6 @@ const { customerBilling, customerShipping } = require('./shared');
*
* https://woocommerce.github.io/woocommerce-rest-api-docs/#order-properties
*/
const productLineItems = {
name: '',
product_id: '',
variation_id: 0,
quantity: 0,
tax_class: '',
subtotal: '',
total: '',
}
const shippingLines = {
method_title: '',
method_id: '',
total: '',
}
const feeLines = {
name: '',
tax_class: '',
tax_status: '',
total: '',
}
const couponLines = {
code: ''
}
const order = {
payment_method: '',
payment_method_title: '',
@ -45,19 +17,38 @@ const order = {
customer_id: 0,
billing: customerBilling,
shipping: customerShipping,
line_items: [
productLineItems
],
shipping_lines: [
shippingLines
],
fee_lines: [
feeLines
],
coupon_lines: [
couponLines
]
}
line_items: [],
shipping_lines: [],
fee_lines: [],
coupon_lines: [],
};
const productLineItems = {
name: '',
product_id: '',
variation_id: 0,
quantity: 0,
tax_class: '',
subtotal: '',
total: '',
};
const shippingLines = {
method_title: '',
method_id: 'flat_rate',
total: '',
};
const feeLines = {
name: 'Fee',
tax_class: '',
tax_status: 'none',
total: '',
};
const couponLines = {
code: '10off',
};
module.exports = {
order,
@ -65,4 +56,4 @@ module.exports = {
shippingLines,
feeLines,
couponLines,
}
};

View File

@ -1,87 +1,46 @@
/**
* Shared model for batch updates for a resource.
*
* Note that by default the update is limited to 100 objects to be created, updated, or deleted.
*/
const batchUpdatePayload = {
create: [],
update: [],
delete: [],
}
/**
* Batch create a resource.
* Note that by default the update endpoint is limited to 100 objects to be created, updated, or deleted.
*
* @param {Array} resourcesToCreate A list of resource objects to create.
* @returns
* @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.
*/
const batchCreate = ( resourcesToCreate = [] ) => {
if ( resourcesToCreate.length === 0 ) {
const batch = ( action, resources = [], payload = {} ) => {
if ( ! [ 'create', 'update', 'delete' ].includes( action ) ) {
return;
}
// Build array of resources to create
const createArray = [];
resourcesToCreate.forEach( ( resource ) => {
createArray.push( resource );
});
batchUpdatePayload.create = createArray
return createArray;
}
/**
* Batch update resources.
*
* @param {Array} resourcesToUpdate A list of resource objects to update.
* @returns
*/
const batchUpdate = ( resourcesToUpdate = [] ) => {
if ( resourcesToUpdate.length === 0 ) {
return
}
// Build array of resources to update
const updateArray = [];
resourcesToUpdate.forEach( ( resource ) => {
updateArray.push( resource );
});
return updateArray;
}
/**
* Batch delete resources.
*
* @param {Array} resourceIds A list of IDs of resource objects to delete.
* @returns
*/
const batchDelete = ( resourceIds = [] ) => {
if ( resourceIds.length === 0 ) {
if ( resources.length === 0 ) {
return;
}
// Build array of resources to delete
const deleteArray = [];
resourceIds.forEach( ( id ) => {
deleteArray.push( id );
});
if ( action === 'create' ) {
payload.create = [ ...resources ];
}
return deleteArray;
}
if ( action === 'update' ) {
payload.update = [ ...resources ];
}
if ( action === 'delete' ) {
payload.delete = [ ...resources ];
}
return payload;
};
const getBatchPayloadExample = ( resource ) => {
batchUpdatePayload.create = batchCreate( [ resource ] );
batchUpdatePayload.update = batchUpdate( [ resource ] );
batchUpdatePayload.delete = batchDelete( [ 1, 2, 3 ] );
let batchUpdatePayload = {};
batchUpdatePayload = batch( 'create', [ resource ], batchUpdatePayload );
batchUpdatePayload = batch( 'update', [ resource ], batchUpdatePayload );
batchUpdatePayload = batch( 'delete', [ 1, 2, 3 ], batchUpdatePayload );
return batchUpdatePayload;
}
};
module.exports = {
batchUpdatePayload,
batchCreate,
batchUpdate,
batchDelete,
getBatchPayloadExample
}
batch,
getBatchPayloadExample,
};

View File

@ -17,7 +17,7 @@ const customerBilling = {
postcode: '94107',
phone: '123456789',
email: 'john.doe@example.com',
}
};
/**
* Customer shipping object.
@ -37,9 +37,9 @@ const customerShipping = {
state: 'NY',
postcode: '14201',
phone: '123456789',
}
};
module.exports = {
customerBilling,
customerShipping
}
customerShipping,
};

View File

@ -8,5 +8,7 @@ const errorResponse = {
message: '',
data: {
status: 400
}
}
},
};
module.exports = { errorResponse };

View File

@ -1,20 +1,14 @@
const { customerBilling, customerShipping } = require('./customer');
const {
batchUpdatePayload,
batchCreate,
batchUpdate,
batchDelete,
batch,
getBatchPayloadExample
} = require('./batch-update');
const errorRessponse = require('./customer');
const { errorResponse } = require('./error-response');
module.exports = {
customerBilling,
customerShipping,
batchUpdatePayload,
batchCreate,
batchUpdate,
batchDelete,
batch,
getBatchPayloadExample,
errorRessponse
}
errorResponse,
};

View File

@ -17,21 +17,21 @@ 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',
method: 'GET',
path: 'coupons',
responseCode: 200,
coupons: async () => { getRequest( 'coupons' ) }
coupons: async () => { getRequest( 'coupons' ) },
},
update: {
name: 'Update a coupon',
@ -39,7 +39,7 @@ 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',
@ -49,7 +49,7 @@ const couponsApi = {
payload: {
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 +57,8 @@ 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 };

View File

@ -3,5 +3,5 @@ const { couponsApi } = require('./coupons');
module.exports = {
ordersApi,
couponsApi
}
couponsApi,
};

View File

@ -17,29 +17,29 @@ const ordersApi = {
path: 'orders',
responseCode: 201,
payload: order,
order: async ( orderDetails ) => postRequest( 'orders', orderDetails )
order: async ( orderDetails ) => postRequest( 'orders', orderDetails ),
},
retrieve: {
name: 'Retrieve an order',
method: 'GET',
path: 'orders/<id>',
responseCode: 200,
order: async ( orderId ) => getRequest( `orders/${orderId}` )
order: async ( orderId ) => getRequest( `orders/${orderId}` ),
},
listAll: {
name: 'List all orders',
method: 'GET',
path: 'orders',
responseCode: 200,
orders: async () => { getRequest( 'orders' ) }
orders: async () => { getRequest( 'orders' ) },
},
update: {
name: 'Update an order',
method: 'PUT',
path: 'orders/<id>',
responseCode: 200,
payload: order,
order: async ( orderId, orderDetails ) => putRequest( `orders/${orderId}`, orderDetails )
payload: order.order,
order: async ( orderId, orderDetails ) => putRequest( `orders/${orderId}`, orderDetails ),
},
delete: {
name: 'Delete an order',
@ -49,18 +49,20 @@ const ordersApi = {
payload: {
force: false
},
order: async ( orderId, deletePermanently ) => deleteRequest( `orders/${orderId}`, deletePermanently )
order: async ( orderId, deletePermanently ) => deleteRequest( `orders/${orderId}`, deletePermanently ),
},
batch: {
name: 'Batch update orders',
method: 'POST',
path: 'orders/batch',
responseCode: 200,
payload: shared.getBatchPayloadExample( order ),
orders: async ( batchUpdatePayload ) => postRequest( `orders/batch`, batchUpdatePayload )
payload: shared.getBatchPayloadExample( order.order ),
orders: async ( batchUpdatePayload ) => postRequest( `orders/batch`, batchUpdatePayload ),
},
}
};
// TODO -- build example payload here? Remove ID etc from the example and just add here?
module.exports = {
ordersApi,
}
};

View File

@ -4,9 +4,9 @@ const verboseOutput = VERBOSE === 'true';
// Update the API path if the `USE_INDEX_PERMALINKS` flag is set
const useIndexPermalinks = USE_INDEX_PERMALINKS === 'true';
let apiPath = `${BASE_URL}/wp-json/wc/v3/`;
if (useIndexPermalinks) {
apiPath = `${BASE_URL}/?rest_route=/wc/v3/`;
let apiPath = `${BASE_URL}/?rest_route=/wc/v3/`;
if ( useIndexPermalinks ) {
apiPath = `${BASE_URL}/wp-json/wc/v3/`;
}
module.exports = {

View File

@ -3,8 +3,8 @@ const { Collection, ItemGroup, Item } = require('postman-collection');
require('dotenv').config();
const {
BASE_URL,
USERNAME,
PASSWORD,
USER_KEY,
USER_SECRET,
USE_INDEX_PERMALINKS
} = process.env;
@ -16,18 +16,25 @@ const {
*/
// Set up our empty collection
if ( typeof USER_KEY === 'undefined' ) {
console.log('No USER_KEY was defined.');
}
if ( typeof USER_SECRET === 'undefined' ) {
console.log('No USER_SECRET was defined.');
}
const postmanCollection = new Collection( {
auth: {
type: 'basic',
basic: [
{
key: 'username',
value: USERNAME,
value: USER_KEY,
type: 'string'
},
{
key: 'password',
value: PASSWORD,
value: USER_SECRET,
type: 'string'
},
]
@ -38,11 +45,15 @@ const postmanCollection = new Collection( {
} );
// Get the API url
if ( typeof BASE_URL === 'undefined' ) {
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}/wp-json/wc/v3`;
let apiPath = `${BASE_URL}/?rest_route=/wc/v3/`;
if ( useIndexPermalinks ) {
apiPath = `${BASE_URL}/?rest_route=/wc/v3`;
apiPath = `${BASE_URL}/wp-json/wc/v3/`;
}
// Set this here for use in `request.js`
global.API_PATH = `${apiPath}/`;
@ -84,9 +95,7 @@ for ( const key in resources ) {
mode: 'raw',
raw: JSON.stringify( api.payload ),
options: {
raw: {
language: 'json'
}
raw: { language: 'json' }
}
},
},
@ -94,7 +103,7 @@ for ( const key in resources ) {
folder.items.add( request );
}
postmanCollection.items.add( folder ) ;
postmanCollection.items.add( folder );
}
// We need to convert the collection to JSON so that it can be exported to a file

View File

@ -1,5 +1,5 @@
require('dotenv').config();
const { USERNAME, PASSWORD } = process.env;
const { USER_KEY, USER_SECRET } = process.env;
const request = require('supertest')( API_PATH );
/**
@ -14,9 +14,9 @@ const getRequest = async ( requestPath, queryString = {} ) => {
.get( requestPath )
.set( 'Accept', 'application/json' )
.query( queryString )
.auth( USERNAME, PASSWORD );
.auth( USER_KEY, USER_SECRET );
return response;
}
};
/**
* Make a POST request.
@ -30,9 +30,9 @@ const postRequest = async ( requestPath, requestBody ) => {
.post( requestPath )
.send( requestBody )
.set( 'Accept', 'application/json' )
.auth( USERNAME, PASSWORD );
.auth( USER_KEY, USER_SECRET );
return response;
}
};
/**
* Make a PUT request.
@ -46,9 +46,9 @@ const putRequest = async ( requestPath, requestBody ) => {
.put( requestPath )
.send( requestBody )
.set( 'Accept', 'application/json' )
.auth( USERNAME, PASSWORD );
.auth( USER_KEY, USER_SECRET );
return response;
}
};
/**
* Make a DELETE request, optionally deleting the resource permanently.
@ -63,8 +63,8 @@ const deleteRequest = async ( requestPath, deletePermanently = false ) => {
.delete( requestPath )
.set( 'Accept', 'application/json' )
.send( requestBody )
.auth( USERNAME, PASSWORD );
.auth( USER_KEY, USER_SECRET );
return response;
}
};
module.exports = { getRequest, postRequest, putRequest, deleteRequest }