Merge branch 'trunk' of github.com:woocommerce/woocommerce into update/31217
This commit is contained in:
commit
b76b9f3d9d
|
@ -31,7 +31,7 @@ cd "$SCRIPTPATH/$(dirname "$REALPATH")/.."
|
|||
# Run scripts
|
||||
case $1 in
|
||||
'test')
|
||||
jest --group=$2
|
||||
jest --group=$2 --runInBand
|
||||
TESTRESULT=$?
|
||||
;;
|
||||
'make:collection')
|
||||
|
|
|
@ -0,0 +1,292 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
const {
|
||||
postRequest,
|
||||
deleteRequest,
|
||||
getRequest,
|
||||
putRequest,
|
||||
} = require( '../utils/request' );
|
||||
const productsTestSetup = require( './product-list' );
|
||||
const { ordersApi } = require( '../endpoints/orders' );
|
||||
|
||||
const createCustomer = ( data ) => postRequest( 'customers', data );
|
||||
const deleteCustomer = ( id ) => deleteRequest( `customers/${ id }`, true );
|
||||
|
||||
const createSampleData = async () => {
|
||||
const testProductData = await productsTestSetup.createSampleData();
|
||||
|
||||
const orderedProducts = {
|
||||
pocketHoodie: testProductData.simpleProducts.find(
|
||||
( p ) => p.name === 'Hoodie with Pocket'
|
||||
),
|
||||
sunglasses: testProductData.simpleProducts.find(
|
||||
( p ) => p.name === 'Sunglasses'
|
||||
),
|
||||
beanie: testProductData.simpleProducts.find(
|
||||
( p ) => p.name === 'Beanie'
|
||||
),
|
||||
blueVneck: testProductData.variableProducts.vneckVariations.find(
|
||||
( p ) => p.sku === 'woo-vneck-tee-blue'
|
||||
),
|
||||
pennant: testProductData.externalProducts[ 0 ],
|
||||
};
|
||||
|
||||
const johnAddress = {
|
||||
first_name: 'John',
|
||||
last_name: 'Doe',
|
||||
company: 'Automattic',
|
||||
country: 'US',
|
||||
address_1: '60 29th Street',
|
||||
address_2: '#343',
|
||||
city: 'San Francisco',
|
||||
state: 'CA',
|
||||
postcode: '94110',
|
||||
phone: '123456789',
|
||||
};
|
||||
const tinaAddress = {
|
||||
first_name: 'Tina',
|
||||
last_name: 'Clark',
|
||||
company: 'Automattic',
|
||||
country: 'US',
|
||||
address_1: 'Oxford Ave',
|
||||
address_2: '',
|
||||
city: 'Buffalo',
|
||||
state: 'NY',
|
||||
postcode: '14201',
|
||||
phone: '123456789',
|
||||
};
|
||||
const guestShippingAddress = {
|
||||
first_name: 'Ano',
|
||||
last_name: 'Nymous',
|
||||
company: '',
|
||||
country: 'US',
|
||||
address_1: '0 Incognito St',
|
||||
address_2: '',
|
||||
city: 'Erie',
|
||||
state: 'PA',
|
||||
postcode: '16515',
|
||||
phone: '123456789',
|
||||
};
|
||||
const guestBillingAddress = {
|
||||
first_name: 'Ben',
|
||||
last_name: 'Efactor',
|
||||
company: '',
|
||||
country: 'US',
|
||||
address_1: '200 W University Avenue',
|
||||
address_2: '',
|
||||
city: 'Gainesville',
|
||||
state: 'FL',
|
||||
postcode: '32601',
|
||||
phone: '123456789',
|
||||
email: 'ben.efactor@email.net',
|
||||
};
|
||||
|
||||
const { body: john } = await createCustomer( {
|
||||
first_name: 'John',
|
||||
last_name: 'Doe',
|
||||
username: 'john.doe',
|
||||
email: 'john.doe@example.com',
|
||||
billing: {
|
||||
...johnAddress,
|
||||
email: 'john.doe@example.com',
|
||||
},
|
||||
shipping: johnAddress,
|
||||
} );
|
||||
|
||||
const { body: tina } = await createCustomer( {
|
||||
first_name: 'Tina',
|
||||
last_name: 'Clark',
|
||||
username: 'tina.clark',
|
||||
email: 'tina.clark@example.com',
|
||||
billing: {
|
||||
...tinaAddress,
|
||||
email: 'tina.clark@example.com',
|
||||
},
|
||||
shipping: tinaAddress,
|
||||
} );
|
||||
|
||||
const orderBaseData = {
|
||||
payment_method: 'cod',
|
||||
payment_method_title: 'Cash on Delivery',
|
||||
status: 'processing',
|
||||
set_paid: false,
|
||||
currency: 'USD',
|
||||
customer_id: 0,
|
||||
};
|
||||
|
||||
const orders = [];
|
||||
|
||||
// Have "John" order all products.
|
||||
Object.values( orderedProducts ).forEach( async ( product ) => {
|
||||
const { body: order } = await ordersApi.create.order( {
|
||||
...orderBaseData,
|
||||
customer_id: john.id,
|
||||
billing: {
|
||||
...johnAddress,
|
||||
email: 'john.doe@example.com',
|
||||
},
|
||||
shipping: johnAddress,
|
||||
line_items: [
|
||||
{
|
||||
product_id: product.id,
|
||||
quantity: 1,
|
||||
},
|
||||
],
|
||||
} );
|
||||
|
||||
orders.push( order );
|
||||
} );
|
||||
|
||||
// Have "Tina" order some sunglasses and make a child order.
|
||||
// This somewhat resembles a subscription renewal, but we're just testing the `parent` field.
|
||||
const { body: order2 } = await ordersApi.create.order( {
|
||||
...orderBaseData,
|
||||
status: 'completed',
|
||||
set_paid: true,
|
||||
customer_id: tina.id,
|
||||
billing: {
|
||||
...tinaAddress,
|
||||
email: 'tina.clark@example.com',
|
||||
},
|
||||
shipping: tinaAddress,
|
||||
line_items: [
|
||||
{
|
||||
product_id: orderedProducts.sunglasses.id,
|
||||
quantity: 1,
|
||||
},
|
||||
],
|
||||
} );
|
||||
orders.push( order2 );
|
||||
|
||||
const { body: order3 } = await ordersApi.create.order( {
|
||||
...orderBaseData,
|
||||
parent_id: order2.id,
|
||||
customer_id: tina.id,
|
||||
billing: {
|
||||
...tinaAddress,
|
||||
email: 'tina.clark@example.com',
|
||||
},
|
||||
shipping: tinaAddress,
|
||||
line_items: [
|
||||
{
|
||||
product_id: orderedProducts.sunglasses.id,
|
||||
quantity: 1,
|
||||
},
|
||||
],
|
||||
} );
|
||||
orders.push( order3 );
|
||||
|
||||
// Guest order.
|
||||
const { body: guestOrder } = await ordersApi.create.order( {
|
||||
...orderBaseData,
|
||||
billing: guestBillingAddress,
|
||||
shipping: guestShippingAddress,
|
||||
line_items: [
|
||||
{
|
||||
product_id: orderedProducts.pennant.id,
|
||||
quantity: 2,
|
||||
},
|
||||
{
|
||||
product_id: orderedProducts.beanie.id,
|
||||
quantity: 1,
|
||||
},
|
||||
],
|
||||
} );
|
||||
|
||||
// Create an order with all possible numerical fields (taxes, fees, refunds, etc).
|
||||
const { body: taxSetting } = await getRequest(
|
||||
'settings/general/woocommerce_calc_taxes'
|
||||
);
|
||||
await putRequest( 'settings/general/woocommerce_calc_taxes', {
|
||||
value: 'yes',
|
||||
} );
|
||||
|
||||
const { body: taxRate } = await postRequest( 'taxes', {
|
||||
country: '*',
|
||||
state: '*',
|
||||
postcode: '*',
|
||||
city: '*',
|
||||
rate: '5.5000',
|
||||
name: 'Tax',
|
||||
rate: '5.5',
|
||||
shipping: true,
|
||||
} );
|
||||
|
||||
const { body: coupon } = await postRequest( 'coupons', {
|
||||
code: 'save5',
|
||||
amount: '5',
|
||||
} );
|
||||
|
||||
const { body: order4 } = await ordersApi.create.order( {
|
||||
...orderBaseData,
|
||||
line_items: [
|
||||
{
|
||||
product_id: orderedProducts.blueVneck.id,
|
||||
quantity: 1,
|
||||
},
|
||||
],
|
||||
coupon_lines: [ { code: 'save5' } ],
|
||||
shipping_lines: [
|
||||
{
|
||||
method_id: 'flat_rate',
|
||||
total: '5.00',
|
||||
},
|
||||
],
|
||||
fee_lines: [
|
||||
{
|
||||
total: '1.00',
|
||||
name: 'Test Fee',
|
||||
},
|
||||
],
|
||||
} );
|
||||
|
||||
await postRequest( `orders/${ order4.id }/refunds`, {
|
||||
api_refund: false, // Prevent an actual refund request (fails with CoD),
|
||||
line_items: [
|
||||
{
|
||||
id: order4.line_items[ 0 ].id,
|
||||
quantity: 1,
|
||||
refund_total: order4.line_items[ 0 ].total,
|
||||
refund_tax: [
|
||||
{
|
||||
id: order4.line_items[ 0 ].taxes[ 0 ].id,
|
||||
refund_total: order4.line_items[ 0 ].total_tax,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
} );
|
||||
orders.push( order4 );
|
||||
|
||||
return {
|
||||
customers: { john, tina },
|
||||
orders,
|
||||
precisionOrder: order4,
|
||||
hierarchicalOrders: {
|
||||
parent: order2,
|
||||
child: order3,
|
||||
},
|
||||
guestOrder,
|
||||
testProductData,
|
||||
};
|
||||
};
|
||||
|
||||
const deleteSampleData = async ( sampleData ) => {
|
||||
await productsTestSetup.deleteSampleData( sampleData.testProductData );
|
||||
|
||||
sampleData.orders
|
||||
.concat( [ sampleData.guestOrder ] )
|
||||
.forEach( async ( { id } ) => {
|
||||
await ordersApi.delete.order( id, true );
|
||||
} );
|
||||
|
||||
Object.values( sampleData.customers ).forEach( async ( { id } ) => {
|
||||
await deleteCustomer( id );
|
||||
} );
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
createSampleData,
|
||||
deleteSampleData,
|
||||
};
|
File diff suppressed because it is too large
Load Diff
|
@ -1,4 +1,3 @@
|
|||
|
||||
/**
|
||||
* A basic refund.
|
||||
*
|
||||
|
@ -7,7 +6,7 @@
|
|||
* https://woocommerce.github.io/woocommerce-rest-api-docs/#order-refund-properties
|
||||
*
|
||||
*/
|
||||
const refund = {
|
||||
const refund = {
|
||||
api_refund: false,
|
||||
amount: '1.00',
|
||||
reason: 'Late delivery refund.',
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
const { getRequest, postRequest, putRequest, deleteRequest } = require('../utils/request');
|
||||
const { getOrderExample, shared } = require('../data');
|
||||
const {
|
||||
getRequest,
|
||||
postRequest,
|
||||
putRequest,
|
||||
deleteRequest,
|
||||
} = require( '../utils/request' );
|
||||
const { getOrderExample, shared } = require( '../data' );
|
||||
|
||||
/**
|
||||
* WooCommerce Orders endpoints.
|
||||
|
@ -24,14 +29,16 @@ const ordersApi = {
|
|||
method: 'GET',
|
||||
path: 'orders/<id>',
|
||||
responseCode: 200,
|
||||
order: async ( orderId ) => getRequest( `orders/${orderId}` ),
|
||||
order: async ( orderId, ordersQuery = {} ) =>
|
||||
getRequest( `orders/${ orderId }`, ordersQuery ),
|
||||
},
|
||||
listAll: {
|
||||
name: 'List all orders',
|
||||
method: 'GET',
|
||||
path: 'orders',
|
||||
responseCode: 200,
|
||||
orders: async () => getRequest( 'orders' ),
|
||||
orders: async ( ordersQuery = {} ) =>
|
||||
getRequest( 'orders', ordersQuery ),
|
||||
},
|
||||
update: {
|
||||
name: 'Update an order',
|
||||
|
@ -39,7 +46,8 @@ const ordersApi = {
|
|||
path: 'orders/<id>',
|
||||
responseCode: 200,
|
||||
payload: getOrderExample(),
|
||||
order: async ( orderId, orderDetails ) => putRequest( `orders/${orderId}`, orderDetails ),
|
||||
order: async ( orderId, orderDetails ) =>
|
||||
putRequest( `orders/${ orderId }`, orderDetails ),
|
||||
},
|
||||
delete: {
|
||||
name: 'Delete an order',
|
||||
|
@ -47,9 +55,10 @@ const ordersApi = {
|
|||
path: 'orders/<id>',
|
||||
responseCode: 200,
|
||||
payload: {
|
||||
force: false
|
||||
force: false,
|
||||
},
|
||||
order: async ( orderId, deletePermanently ) => deleteRequest( `orders/${orderId}`, deletePermanently ),
|
||||
order: async ( orderId, deletePermanently ) =>
|
||||
deleteRequest( `orders/${ orderId }`, deletePermanently ),
|
||||
},
|
||||
batch: {
|
||||
name: 'Batch update orders',
|
||||
|
@ -57,7 +66,8 @@ const ordersApi = {
|
|||
path: 'orders/batch',
|
||||
responseCode: 200,
|
||||
payload: shared.getBatchPayloadExample( getOrderExample() ),
|
||||
orders: async ( batchUpdatePayload ) => postRequest( `orders/batch`, batchUpdatePayload ),
|
||||
orders: async ( batchUpdatePayload ) =>
|
||||
postRequest( `orders/batch`, batchUpdatePayload ),
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
const {
|
||||
const {
|
||||
getRequest,
|
||||
postRequest,
|
||||
deleteRequest,
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
const { ordersApi } = require('../../endpoints/orders');
|
||||
const { order } = require('../../data');
|
||||
const { ordersApi } = require( '../../endpoints/orders' );
|
||||
const { order } = require( '../../data' );
|
||||
const { createSampleData, deleteSampleData } = require( '../../data/orders' );
|
||||
|
||||
/**
|
||||
* Billing properties to update.
|
||||
*/
|
||||
const updatedCustomerBilling = {
|
||||
const updatedCustomerBilling = {
|
||||
first_name: 'Jane',
|
||||
last_name: 'Doe',
|
||||
company: 'Automattic',
|
||||
|
@ -41,43 +42,523 @@ const updatedCustomerShipping = {
|
|||
* @group orders
|
||||
*
|
||||
*/
|
||||
describe('Orders API tests', () => {
|
||||
let orderId;
|
||||
describe( 'Orders API tests', () => {
|
||||
let orderId, sampleData;
|
||||
|
||||
it('can create an order', async () => {
|
||||
beforeAll( async () => {
|
||||
sampleData = await createSampleData();
|
||||
}, 100000 );
|
||||
|
||||
afterAll( async () => {
|
||||
await deleteSampleData( sampleData );
|
||||
}, 10000 );
|
||||
|
||||
it( 'can create an order', async () => {
|
||||
const response = await ordersApi.create.order( order );
|
||||
expect( response.status ).toEqual( ordersApi.create.responseCode );
|
||||
expect( response.body.id ).toBeDefined();
|
||||
orderId = response.body.id;
|
||||
|
||||
// Validate the data type and verify the order is in a pending state
|
||||
expect( typeof response.body.status ).toBe('string');
|
||||
expect( response.body.status ).toEqual('pending');
|
||||
});
|
||||
expect( typeof response.body.status ).toBe( 'string' );
|
||||
expect( response.body.status ).toEqual( 'pending' );
|
||||
} );
|
||||
|
||||
it('can retrieve an order', async () => {
|
||||
it( 'can retrieve an order', async () => {
|
||||
const response = await ordersApi.retrieve.order( orderId );
|
||||
expect( response.status ).toEqual( ordersApi.retrieve.responseCode );
|
||||
expect( response.body.id ).toEqual( orderId );
|
||||
});
|
||||
} );
|
||||
|
||||
it('can add shipping and billing contacts to an order', async () => {
|
||||
it( 'can add shipping and billing contacts to an order', async () => {
|
||||
// Update the billing and shipping fields on the order
|
||||
order.billing = updatedCustomerBilling;
|
||||
order.shipping = updatedCustomerShipping;
|
||||
|
||||
const response = await ordersApi.update.order( orderId, order );
|
||||
expect( response.status).toEqual( ordersApi.update.responseCode );
|
||||
expect( response.status ).toEqual( ordersApi.update.responseCode );
|
||||
|
||||
expect( response.body.billing ).toEqual( updatedCustomerBilling );
|
||||
expect( response.body.shipping ).toEqual( updatedCustomerShipping );
|
||||
});
|
||||
} );
|
||||
|
||||
it('can permanently delete an order', async () => {
|
||||
it( 'can permanently delete an order', async () => {
|
||||
const response = await ordersApi.delete.order( orderId, true );
|
||||
expect( response.status ).toEqual( ordersApi.delete.responseCode );
|
||||
|
||||
const getOrderResponse = await ordersApi.retrieve.order( orderId );
|
||||
expect( getOrderResponse.status ).toEqual( 404 );
|
||||
});
|
||||
});
|
||||
} );
|
||||
|
||||
describe( 'List all orders', () => {
|
||||
const ORDERS_COUNT = 10;
|
||||
|
||||
it( 'pagination', async () => {
|
||||
const pageSize = 4;
|
||||
const page1 = await ordersApi.listAll.orders( {
|
||||
per_page: pageSize,
|
||||
} );
|
||||
const page2 = await ordersApi.listAll.orders( {
|
||||
per_page: pageSize,
|
||||
page: 2,
|
||||
} );
|
||||
expect( page1.statusCode ).toEqual( 200 );
|
||||
expect( page2.statusCode ).toEqual( 200 );
|
||||
|
||||
// Verify total page count.
|
||||
expect( page1.headers[ 'x-wp-total' ] ).toEqual(
|
||||
ORDERS_COUNT.toString()
|
||||
);
|
||||
expect( page1.headers[ 'x-wp-totalpages' ] ).toEqual( '3' );
|
||||
|
||||
// Verify we get pageSize'd arrays.
|
||||
expect( Array.isArray( page1.body ) ).toBe( true );
|
||||
expect( Array.isArray( page2.body ) ).toBe( true );
|
||||
expect( page1.body ).toHaveLength( pageSize );
|
||||
expect( page2.body ).toHaveLength( pageSize );
|
||||
|
||||
// Ensure all of the order IDs are unique (no page overlap).
|
||||
const allOrderIds = page1.body
|
||||
.concat( page2.body )
|
||||
.reduce( ( acc, { id } ) => {
|
||||
acc[ id ] = 1;
|
||||
return acc;
|
||||
}, {} );
|
||||
expect( Object.keys( allOrderIds ) ).toHaveLength( pageSize * 2 );
|
||||
|
||||
// Verify that offset takes precedent over page number.
|
||||
const page2Offset = await ordersApi.listAll.orders( {
|
||||
per_page: pageSize,
|
||||
page: 2,
|
||||
offset: pageSize + 1,
|
||||
} );
|
||||
// The offset pushes the result set 1 order past the start of page 2.
|
||||
expect( page2Offset.body ).toEqual(
|
||||
expect.not.arrayContaining( [
|
||||
expect.objectContaining( { id: page2.body[ 0 ].id } ),
|
||||
] )
|
||||
);
|
||||
expect( page2Offset.body[ 0 ].id ).toEqual( page2.body[ 1 ].id );
|
||||
|
||||
// Verify the last page only has 1 order as we expect.
|
||||
const lastPage = await ordersApi.listAll.orders( {
|
||||
per_page: pageSize,
|
||||
page: 3,
|
||||
} );
|
||||
expect( Array.isArray( lastPage.body ) ).toBe( true );
|
||||
expect( lastPage.body ).toHaveLength( 2 );
|
||||
|
||||
// Verify a page outside the total page count is empty.
|
||||
const page6 = await ordersApi.listAll.orders( {
|
||||
per_page: pageSize,
|
||||
page: 6,
|
||||
} );
|
||||
expect( Array.isArray( page6.body ) ).toBe( true );
|
||||
expect( page6.body ).toHaveLength( 0 );
|
||||
} );
|
||||
|
||||
it( 'inclusion / exclusion', async () => {
|
||||
const allOrders = await ordersApi.listAll.orders( {
|
||||
per_page: 10,
|
||||
} );
|
||||
expect( allOrders.statusCode ).toEqual( 200 );
|
||||
const allOrdersIds = allOrders.body.map( ( order ) => order.id );
|
||||
expect( allOrdersIds ).toHaveLength( ORDERS_COUNT );
|
||||
|
||||
const ordersToFilter = [
|
||||
allOrdersIds[ 0 ],
|
||||
allOrdersIds[ 2 ],
|
||||
allOrdersIds[ 4 ],
|
||||
allOrdersIds[ 7 ],
|
||||
];
|
||||
|
||||
const included = await ordersApi.listAll.orders( {
|
||||
per_page: 20,
|
||||
include: ordersToFilter.join( ',' ),
|
||||
} );
|
||||
expect( included.statusCode ).toEqual( 200 );
|
||||
expect( included.body ).toHaveLength( ordersToFilter.length );
|
||||
expect( included.body ).toEqual(
|
||||
expect.arrayContaining(
|
||||
ordersToFilter.map( ( id ) =>
|
||||
expect.objectContaining( { id } )
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
const excluded = await ordersApi.listAll.orders( {
|
||||
per_page: 20,
|
||||
exclude: ordersToFilter.join( ',' ),
|
||||
} );
|
||||
expect( excluded.statusCode ).toEqual( 200 );
|
||||
expect( excluded.body ).toHaveLength(
|
||||
ORDERS_COUNT - ordersToFilter.length
|
||||
);
|
||||
expect( excluded.body ).toEqual(
|
||||
expect.not.arrayContaining(
|
||||
ordersToFilter.map( ( id ) =>
|
||||
expect.objectContaining( { id } )
|
||||
)
|
||||
)
|
||||
);
|
||||
} );
|
||||
|
||||
it( 'parent', async () => {
|
||||
const result1 = await ordersApi.listAll.orders( {
|
||||
parent: sampleData.hierarchicalOrders.parent.id,
|
||||
} );
|
||||
expect( result1.statusCode ).toEqual( 200 );
|
||||
expect( result1.body ).toHaveLength( 1 );
|
||||
expect( result1.body[ 0 ].id ).toBe(
|
||||
sampleData.hierarchicalOrders.child.id
|
||||
);
|
||||
|
||||
const result2 = await ordersApi.listAll.orders( {
|
||||
parent_exclude: sampleData.hierarchicalOrders.parent.id,
|
||||
} );
|
||||
expect( result2.statusCode ).toEqual( 200 );
|
||||
expect( result2.body ).toEqual(
|
||||
expect.not.arrayContaining( [
|
||||
expect.objectContaining( {
|
||||
id: sampleData.hierarchicalOrders.child.id,
|
||||
} ),
|
||||
] )
|
||||
);
|
||||
} );
|
||||
|
||||
it( 'status', async () => {
|
||||
const result1 = await ordersApi.listAll.orders( {
|
||||
status: 'completed',
|
||||
} );
|
||||
|
||||
expect( result1.statusCode ).toEqual( 200 );
|
||||
expect( result1.body ).toHaveLength( 2 );
|
||||
expect( result1.body ).toEqual(
|
||||
expect.arrayContaining( [
|
||||
expect.objectContaining( {
|
||||
status: 'completed',
|
||||
customer_id: 0,
|
||||
line_items: expect.arrayContaining( [
|
||||
expect.objectContaining( {
|
||||
name: 'Single',
|
||||
quantity: 2,
|
||||
} ),
|
||||
expect.objectContaining( {
|
||||
name: 'Beanie with Logo',
|
||||
quantity: 3,
|
||||
} ),
|
||||
expect.objectContaining( {
|
||||
name: 'T-Shirt',
|
||||
quantity: 1,
|
||||
} ),
|
||||
] ),
|
||||
} ),
|
||||
expect.objectContaining( {
|
||||
status: 'completed',
|
||||
customer_id: sampleData.customers.tina.id,
|
||||
line_items: expect.arrayContaining( [
|
||||
expect.objectContaining( {
|
||||
name: 'Sunglasses',
|
||||
quantity: 1,
|
||||
} ),
|
||||
] ),
|
||||
} ),
|
||||
] )
|
||||
);
|
||||
|
||||
const result2 = await ordersApi.listAll.orders( {
|
||||
status: 'processing',
|
||||
} );
|
||||
expect( result2.statusCode ).toEqual( 200 );
|
||||
expect( result2.body ).toHaveLength( 8 );
|
||||
expect( result2.body ).toEqual(
|
||||
expect.not.arrayContaining(
|
||||
result1.body.map( ( { id } ) =>
|
||||
expect.objectContaining( { id } )
|
||||
)
|
||||
)
|
||||
);
|
||||
} );
|
||||
|
||||
it( 'customer', async () => {
|
||||
const result1 = await ordersApi.listAll.orders( {
|
||||
customer: sampleData.customers.john.id,
|
||||
} );
|
||||
expect( result1.statusCode ).toEqual( 200 );
|
||||
expect( result1.body ).toHaveLength( 5 );
|
||||
result1.body.forEach( ( order ) =>
|
||||
expect( order ).toEqual(
|
||||
expect.objectContaining( {
|
||||
customer_id: sampleData.customers.john.id,
|
||||
} )
|
||||
)
|
||||
);
|
||||
|
||||
const result2 = await ordersApi.listAll.orders( {
|
||||
customer: 0,
|
||||
} );
|
||||
expect( result2.statusCode ).toEqual( 200 );
|
||||
expect( result2.body ).toHaveLength( 3 );
|
||||
result2.body.forEach( ( order ) =>
|
||||
expect( order ).toEqual(
|
||||
expect.objectContaining( {
|
||||
customer_id: 0,
|
||||
} )
|
||||
)
|
||||
);
|
||||
} );
|
||||
|
||||
it( 'product', async () => {
|
||||
const beanie = sampleData.testProductData.simpleProducts.find(
|
||||
( p ) => p.name === 'Beanie'
|
||||
);
|
||||
const result1 = await ordersApi.listAll.orders( {
|
||||
product: beanie.id,
|
||||
} );
|
||||
expect( result1.statusCode ).toEqual( 200 );
|
||||
expect( result1.body ).toHaveLength( 2 );
|
||||
result1.body.forEach( ( order ) =>
|
||||
expect( order ).toEqual(
|
||||
expect.objectContaining( {
|
||||
line_items: expect.arrayContaining( [
|
||||
expect.objectContaining( {
|
||||
name: 'Beanie',
|
||||
} ),
|
||||
] ),
|
||||
} )
|
||||
)
|
||||
);
|
||||
} );
|
||||
|
||||
// NOTE: This does not verify the `taxes` array nested in line items.
|
||||
// While the precision parameter doesn't affect those values, after some
|
||||
// discussion it seems `dp` may not be supported in v4 of the API.
|
||||
it( 'dp (precision)', async () => {
|
||||
const expectPrecisionToMatch = ( value, dp ) => {
|
||||
expect( value ).toEqual(
|
||||
Number.parseFloat( value ).toFixed( dp )
|
||||
);
|
||||
};
|
||||
|
||||
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 );
|
||||
|
||||
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[ '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[ 'refunds' ].forEach( ( refund ) => {
|
||||
expectPrecisionToMatch( refund[ 'total' ], dp );
|
||||
} );
|
||||
};
|
||||
|
||||
const result1 = await ordersApi.retrieve.order(
|
||||
sampleData.precisionOrder.id,
|
||||
{
|
||||
dp: 1,
|
||||
}
|
||||
);
|
||||
expect( result1.statusCode ).toEqual( 200 );
|
||||
verifyOrderPrecision( result1.body, 1 );
|
||||
|
||||
const result2 = await ordersApi.retrieve.order(
|
||||
sampleData.precisionOrder.id,
|
||||
{
|
||||
dp: 3,
|
||||
}
|
||||
);
|
||||
expect( result2.statusCode ).toEqual( 200 );
|
||||
verifyOrderPrecision( result2.body, 3 );
|
||||
|
||||
const result3 = await ordersApi.retrieve.order(
|
||||
sampleData.precisionOrder.id
|
||||
);
|
||||
expect( result3.statusCode ).toEqual( 200 );
|
||||
verifyOrderPrecision( result3.body, 2 ); // The default value for 'dp' is 2.
|
||||
} );
|
||||
|
||||
it( 'search', async () => {
|
||||
// By default, 'search' looks in:
|
||||
// - _billing_address_index
|
||||
// - _shipping_address_index
|
||||
// - _billing_last_name
|
||||
// - _billing_email
|
||||
// - order_item_name
|
||||
|
||||
// Test billing email.
|
||||
const result1 = await ordersApi.listAll.orders( {
|
||||
search: 'example.com',
|
||||
} );
|
||||
expect( result1.statusCode ).toEqual( 200 );
|
||||
expect( result1.body ).toHaveLength( 7 );
|
||||
result1.body.forEach( ( order ) =>
|
||||
expect( order.billing.email ).toContain( 'example.com' )
|
||||
);
|
||||
|
||||
// Test billing address.
|
||||
const result2 = await ordersApi.listAll.orders( {
|
||||
search: 'gainesville', // Intentionally lowercase.
|
||||
} );
|
||||
expect( result2.statusCode ).toEqual( 200 );
|
||||
expect( result2.body ).toHaveLength( 1 );
|
||||
expect( result2.body[ 0 ].id ).toEqual( sampleData.guestOrder.id );
|
||||
|
||||
// Test shipping address.
|
||||
const result3 = await ordersApi.listAll.orders( {
|
||||
search: 'Incognito',
|
||||
} );
|
||||
expect( result3.statusCode ).toEqual( 200 );
|
||||
expect( result3.body ).toHaveLength( 1 );
|
||||
expect( result3.body[ 0 ].id ).toEqual( sampleData.guestOrder.id );
|
||||
|
||||
// Test billing last name.
|
||||
const result4 = await ordersApi.listAll.orders( {
|
||||
search: 'Doe',
|
||||
} );
|
||||
expect( result4.statusCode ).toEqual( 200 );
|
||||
expect( result4.body ).toHaveLength( 5 );
|
||||
result4.body.forEach( ( order ) =>
|
||||
expect( order.billing.last_name ).toEqual( 'Doe' )
|
||||
);
|
||||
|
||||
// Test order item name.
|
||||
const result5 = await ordersApi.listAll.orders( {
|
||||
search: 'Pennant',
|
||||
} );
|
||||
expect( result5.statusCode ).toEqual( 200 );
|
||||
expect( result5.body ).toHaveLength( 2 );
|
||||
result5.body.forEach( ( order ) =>
|
||||
expect( order ).toEqual(
|
||||
expect.objectContaining( {
|
||||
line_items: expect.arrayContaining( [
|
||||
expect.objectContaining( {
|
||||
name: 'WordPress Pennant',
|
||||
} ),
|
||||
] ),
|
||||
} )
|
||||
)
|
||||
);
|
||||
} );
|
||||
|
||||
describe( 'orderby', () => {
|
||||
// The orders endpoint `orderby` parameter uses WP_Query, so our tests won't
|
||||
// include slug and title, since they are programmatically generated.
|
||||
it( 'default', async () => {
|
||||
// Default = date desc.
|
||||
const result = await ordersApi.listAll.orders();
|
||||
expect( result.statusCode ).toEqual( 200 );
|
||||
|
||||
// Verify all dates are in descending order.
|
||||
let lastDate = Date.now();
|
||||
result.body.forEach( ( { date_created } ) => {
|
||||
const created = Date.parse( date_created + '.000Z' );
|
||||
expect( lastDate ).toBeGreaterThanOrEqual( created );
|
||||
lastDate = created;
|
||||
} );
|
||||
} );
|
||||
|
||||
it( 'date', async () => {
|
||||
const result = await ordersApi.listAll.orders( {
|
||||
order: 'asc',
|
||||
orderby: 'date',
|
||||
} );
|
||||
expect( result.statusCode ).toEqual( 200 );
|
||||
|
||||
// Verify all dates are in ascending order.
|
||||
let lastDate = 0;
|
||||
result.body.forEach( ( { date_created } ) => {
|
||||
const created = Date.parse( date_created + '.000Z' );
|
||||
expect( created ).toBeGreaterThanOrEqual( lastDate );
|
||||
lastDate = created;
|
||||
} );
|
||||
} );
|
||||
|
||||
it( 'id', async () => {
|
||||
const result1 = await ordersApi.listAll.orders( {
|
||||
order: 'asc',
|
||||
orderby: 'id',
|
||||
} );
|
||||
expect( result1.statusCode ).toEqual( 200 );
|
||||
|
||||
// Verify all results are in ascending order.
|
||||
let lastId = 0;
|
||||
result1.body.forEach( ( { id } ) => {
|
||||
expect( id ).toBeGreaterThan( lastId );
|
||||
lastId = id;
|
||||
} );
|
||||
|
||||
const result2 = await ordersApi.listAll.orders( {
|
||||
order: 'desc',
|
||||
orderby: 'id',
|
||||
} );
|
||||
expect( result2.statusCode ).toEqual( 200 );
|
||||
|
||||
// Verify all results are in descending order.
|
||||
lastId = Number.MAX_SAFE_INTEGER;
|
||||
result2.body.forEach( ( { id } ) => {
|
||||
expect( lastId ).toBeGreaterThan( id );
|
||||
lastId = id;
|
||||
} );
|
||||
} );
|
||||
|
||||
it( 'include', async () => {
|
||||
const includeIds = [
|
||||
sampleData.precisionOrder.id,
|
||||
sampleData.hierarchicalOrders.parent.id,
|
||||
sampleData.guestOrder.id,
|
||||
];
|
||||
|
||||
const result1 = await ordersApi.listAll.orders( {
|
||||
order: 'asc',
|
||||
orderby: 'include',
|
||||
include: includeIds.join( ',' ),
|
||||
} );
|
||||
expect( result1.statusCode ).toEqual( 200 );
|
||||
expect( result1.body ).toHaveLength( includeIds.length );
|
||||
|
||||
// Verify all results are in proper order.
|
||||
result1.body.forEach( ( { id }, idx ) => {
|
||||
expect( id ).toBe( includeIds[ idx ] );
|
||||
} );
|
||||
|
||||
const result2 = await ordersApi.listAll.orders( {
|
||||
order: 'desc',
|
||||
orderby: 'include',
|
||||
include: includeIds.join( ',' ),
|
||||
} );
|
||||
expect( result2.statusCode ).toEqual( 200 );
|
||||
expect( result2.body ).toHaveLength( includeIds.length );
|
||||
|
||||
// Verify all results are in proper order.
|
||||
result2.body.forEach( ( { id }, idx ) => {
|
||||
expect( id ).toBe( includeIds[ idx ] );
|
||||
} );
|
||||
} );
|
||||
} );
|
||||
} );
|
||||
} );
|
||||
|
|
|
@ -1,777 +0,0 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
const { createSampleData, deleteSampleData } = require( '../../data/products' );
|
||||
const { productsApi } = require('../../endpoints/products');
|
||||
|
||||
/**
|
||||
* Tests for the WooCommerce Products API.
|
||||
*
|
||||
* @group api
|
||||
* @group products
|
||||
*
|
||||
*/
|
||||
describe( 'Products API tests', () => {
|
||||
|
||||
const PRODUCTS_COUNT = 20;
|
||||
let sampleData;
|
||||
|
||||
beforeAll( async () => {
|
||||
sampleData = await createSampleData();
|
||||
}, 10000 );
|
||||
|
||||
afterAll( async () => {
|
||||
await deleteSampleData( sampleData );
|
||||
}, 10000 );
|
||||
|
||||
describe( 'List all products', () => {
|
||||
|
||||
it( 'defaults', async () => {
|
||||
const result = await productsApi.listAll.products();
|
||||
expect( result.statusCode ).toEqual( 200 );
|
||||
expect( result.headers['x-wp-total'] ).toEqual( PRODUCTS_COUNT.toString() );
|
||||
expect( result.headers['x-wp-totalpages'] ).toEqual( '2' );
|
||||
} );
|
||||
|
||||
it( 'pagination', async () => {
|
||||
const pageSize = 6;
|
||||
const page1 = await productsApi.listAll.products( {
|
||||
per_page: pageSize,
|
||||
} );
|
||||
const page2 = await productsApi.listAll.products( {
|
||||
per_page: pageSize,
|
||||
page: 2,
|
||||
} );
|
||||
expect( page1.statusCode ).toEqual( 200 );
|
||||
expect( page2.statusCode ).toEqual( 200 );
|
||||
|
||||
// Verify total page count.
|
||||
expect( page1.headers['x-wp-total'] ).toEqual( PRODUCTS_COUNT.toString() );
|
||||
expect( page1.headers['x-wp-totalpages'] ).toEqual( '4' );
|
||||
|
||||
// Verify we get pageSize'd arrays.
|
||||
expect( Array.isArray( page1.body ) ).toBe( true );
|
||||
expect( Array.isArray( page2.body ) ).toBe( true );
|
||||
expect( page1.body ).toHaveLength( pageSize );
|
||||
expect( page2.body ).toHaveLength( pageSize );
|
||||
|
||||
// Ensure all of the product IDs are unique (no page overlap).
|
||||
const allProductIds = page1.body.concat( page2.body ).reduce( ( acc, product ) => {
|
||||
acc[ product.id ] = 1;
|
||||
return acc;
|
||||
}, {} );
|
||||
expect( Object.keys( allProductIds ) ).toHaveLength( pageSize * 2 );
|
||||
|
||||
// Verify that offset takes precedent over page number.
|
||||
const page2Offset = await productsApi.listAll.products( {
|
||||
per_page: pageSize,
|
||||
page: 2,
|
||||
offset: pageSize + 1,
|
||||
} );
|
||||
// The offset pushes the result set 1 product past the start of page 2.
|
||||
expect( page2Offset.body ).toEqual(
|
||||
expect.not.arrayContaining( [
|
||||
expect.objectContaining( { id: page2.body[0].id } )
|
||||
] )
|
||||
);
|
||||
expect( page2Offset.body[0].id ).toEqual( page2.body[1].id );
|
||||
|
||||
// Verify the last page only has 2 products as we expect.
|
||||
const lastPage = await productsApi.listAll.products( {
|
||||
per_page: pageSize,
|
||||
page: 4,
|
||||
} );
|
||||
expect( Array.isArray( lastPage.body ) ).toBe( true );
|
||||
expect( lastPage.body ).toHaveLength( 2 );
|
||||
|
||||
// Verify a page outside the total page count is empty.
|
||||
const page6 = await productsApi.listAll.products( {
|
||||
per_page: pageSize,
|
||||
page: 6,
|
||||
} );
|
||||
expect( Array.isArray( page6.body ) ).toBe( true );
|
||||
expect( page6.body ).toHaveLength( 0 );
|
||||
} );
|
||||
|
||||
it( 'search', async () => {
|
||||
// Match in the short description.
|
||||
const result1 = await productsApi.listAll.products( {
|
||||
search: 'external'
|
||||
} );
|
||||
expect( result1.statusCode ).toEqual( 200 );
|
||||
expect( result1.body ).toHaveLength( 1 );
|
||||
expect( result1.body[0].name ).toBe( 'WordPress Pennant' );
|
||||
|
||||
// Match in the product name.
|
||||
const result2 = await productsApi.listAll.products( {
|
||||
search: 'pocket'
|
||||
} );
|
||||
expect( result2.statusCode ).toEqual( 200 );
|
||||
expect( result2.body ).toHaveLength( 1 );
|
||||
expect( result2.body[0].name ).toBe( 'Hoodie with Pocket' );
|
||||
} );
|
||||
|
||||
it( 'inclusion / exclusion', async () => {
|
||||
const allProducts = await productsApi.listAll.products( {
|
||||
per_page: 20,
|
||||
} );
|
||||
expect( allProducts.statusCode ).toEqual( 200 );
|
||||
const allProductIds = allProducts.body.map( product => product.id );
|
||||
expect( allProductIds ).toHaveLength( PRODUCTS_COUNT );
|
||||
|
||||
const productsToFilter = [
|
||||
allProductIds[2],
|
||||
allProductIds[4],
|
||||
allProductIds[7],
|
||||
allProductIds[13],
|
||||
];
|
||||
|
||||
const included = await productsApi.listAll.products( {
|
||||
per_page: 20,
|
||||
include: productsToFilter.join( ',' ),
|
||||
} );
|
||||
expect( included.statusCode ).toEqual( 200 );
|
||||
expect( included.body ).toHaveLength( productsToFilter.length );
|
||||
expect( included.body ).toEqual(
|
||||
expect.arrayContaining(
|
||||
productsToFilter.map( id => expect.objectContaining( { id } ) )
|
||||
)
|
||||
);
|
||||
|
||||
const excluded = await productsApi.listAll.products( {
|
||||
per_page: 20,
|
||||
exclude: productsToFilter.join( ',' ),
|
||||
} );
|
||||
expect( excluded.statusCode ).toEqual( 200 );
|
||||
expect( excluded.body ).toHaveLength( PRODUCTS_COUNT - productsToFilter.length );
|
||||
expect( excluded.body ).toEqual(
|
||||
expect.not.arrayContaining(
|
||||
productsToFilter.map( id => expect.objectContaining( { id } ) )
|
||||
)
|
||||
);
|
||||
|
||||
} );
|
||||
|
||||
it( 'slug', async () => {
|
||||
// Match by slug.
|
||||
const result1 = await productsApi.listAll.products( {
|
||||
slug: 't-shirt-with-logo'
|
||||
} );
|
||||
expect( result1.statusCode ).toEqual( 200 );
|
||||
expect( result1.body ).toHaveLength( 1 );
|
||||
expect( result1.body[0].slug ).toBe( 't-shirt-with-logo' );
|
||||
|
||||
// No matches
|
||||
const result2 = await productsApi.listAll.products( {
|
||||
slug: 'no-product-with-this-slug'
|
||||
} );
|
||||
expect( result2.statusCode ).toEqual( 200 );
|
||||
expect( result2.body ).toHaveLength( 0 );
|
||||
} );
|
||||
|
||||
it( 'sku', async () => {
|
||||
// Match by SKU.
|
||||
const result1 = await productsApi.listAll.products( {
|
||||
sku: 'woo-sunglasses'
|
||||
} );
|
||||
expect( result1.statusCode ).toEqual( 200 );
|
||||
expect( result1.body ).toHaveLength( 1 );
|
||||
expect( result1.body[0].sku ).toBe( 'woo-sunglasses' );
|
||||
|
||||
// No matches
|
||||
const result2 = await productsApi.listAll.products( {
|
||||
sku: 'no-product-with-this-sku'
|
||||
} );
|
||||
expect( result2.statusCode ).toEqual( 200 );
|
||||
expect( result2.body ).toHaveLength( 0 );
|
||||
} );
|
||||
|
||||
it( 'type', async () => {
|
||||
const result1 = await productsApi.listAll.products( {
|
||||
type: 'simple'
|
||||
} );
|
||||
expect( result1.statusCode ).toEqual( 200 );
|
||||
expect( result1.headers['x-wp-total'] ).toEqual( '16' );
|
||||
|
||||
const result2 = await productsApi.listAll.products( {
|
||||
type: 'external'
|
||||
} );
|
||||
expect( result2.statusCode ).toEqual( 200 );
|
||||
expect( result2.body ).toHaveLength( 1 );
|
||||
expect( result2.body[0].name ).toBe( 'WordPress Pennant' );
|
||||
|
||||
const result3 = await productsApi.listAll.products( {
|
||||
type: 'variable'
|
||||
} );
|
||||
expect( result3.statusCode ).toEqual( 200 );
|
||||
expect( result3.body ).toHaveLength( 2 );
|
||||
|
||||
const result4 = await productsApi.listAll.products( {
|
||||
type: 'grouped'
|
||||
} );
|
||||
expect( result4.statusCode ).toEqual( 200 );
|
||||
expect( result4.body ).toHaveLength( 1 );
|
||||
expect( result4.body[0].name ).toBe( 'Logo Collection' );
|
||||
} );
|
||||
|
||||
it( 'featured', async () => {
|
||||
const featured = [
|
||||
expect.objectContaining( { name: 'Hoodie with Zipper' } ),
|
||||
expect.objectContaining( { name: 'Hoodie with Pocket' } ),
|
||||
expect.objectContaining( { name: 'Sunglasses' } ),
|
||||
expect.objectContaining( { name: 'Cap' } ),
|
||||
expect.objectContaining( { name: 'V-Neck T-Shirt' } ),
|
||||
];
|
||||
|
||||
const result1 = await productsApi.listAll.products( {
|
||||
featured: true,
|
||||
} );
|
||||
expect( result1.statusCode ).toEqual( 200 );
|
||||
expect( result1.body ).toHaveLength( featured.length );
|
||||
expect( result1.body ).toEqual( expect.arrayContaining( featured ) );
|
||||
|
||||
const result2 = await productsApi.listAll.products( {
|
||||
featured: false,
|
||||
} );
|
||||
expect( result2.statusCode ).toEqual( 200 );
|
||||
expect( result2.body ).toEqual( expect.not.arrayContaining( featured ) );
|
||||
} );
|
||||
|
||||
it( 'categories', async () => {
|
||||
const accessory = [
|
||||
expect.objectContaining( { name: 'Beanie' } ),
|
||||
]
|
||||
const hoodies = [
|
||||
expect.objectContaining( { name: 'Hoodie with Zipper' } ),
|
||||
expect.objectContaining( { name: 'Hoodie with Pocket' } ),
|
||||
expect.objectContaining( { name: 'Hoodie with Logo' } ),
|
||||
expect.objectContaining( { name: 'Hoodie' } ),
|
||||
];
|
||||
|
||||
// Verify that subcategories are included.
|
||||
const result1 = await productsApi.listAll.products( {
|
||||
per_page: 20,
|
||||
category: sampleData.categories.clothing.id,
|
||||
} );
|
||||
expect( result1.statusCode ).toEqual( 200 );
|
||||
expect( result1.body ).toEqual( expect.arrayContaining( accessory ) );
|
||||
expect( result1.body ).toEqual( expect.arrayContaining( hoodies ) );
|
||||
|
||||
// Verify sibling categories are not.
|
||||
const result2 = await productsApi.listAll.products( {
|
||||
category: sampleData.categories.hoodies.id,
|
||||
} );
|
||||
expect( result2.statusCode ).toEqual( 200 );
|
||||
expect( result2.body ).toEqual( expect.not.arrayContaining( accessory ) );
|
||||
expect( result2.body ).toEqual( expect.arrayContaining( hoodies ) );
|
||||
} );
|
||||
|
||||
it( 'on sale', async () => {
|
||||
const onSale = [
|
||||
expect.objectContaining( { name: 'Beanie with Logo' } ),
|
||||
expect.objectContaining( { name: 'Hoodie with Pocket' } ),
|
||||
expect.objectContaining( { name: 'Single' } ),
|
||||
expect.objectContaining( { name: 'Cap' } ),
|
||||
expect.objectContaining( { name: 'Belt' } ),
|
||||
expect.objectContaining( { name: 'Beanie' } ),
|
||||
expect.objectContaining( { name: 'Hoodie' } ),
|
||||
];
|
||||
|
||||
const result1 = await productsApi.listAll.products( {
|
||||
on_sale: true,
|
||||
} );
|
||||
expect( result1.statusCode ).toEqual( 200 );
|
||||
expect( result1.body ).toHaveLength( onSale.length );
|
||||
expect( result1.body ).toEqual( expect.arrayContaining( onSale ) );
|
||||
|
||||
const result2 = await productsApi.listAll.products( {
|
||||
on_sale: false,
|
||||
} );
|
||||
expect( result2.statusCode ).toEqual( 200 );
|
||||
expect( result2.body ).toEqual( expect.not.arrayContaining( onSale ) );
|
||||
} );
|
||||
|
||||
it( 'price', async () => {
|
||||
const result1 = await productsApi.listAll.products( {
|
||||
min_price: 21,
|
||||
max_price: 28,
|
||||
} );
|
||||
expect( result1.statusCode ).toEqual( 200 );
|
||||
expect( result1.body ).toHaveLength( 1 );
|
||||
expect( result1.body[0].name ).toBe( 'Long Sleeve Tee' );
|
||||
expect( result1.body[0].price ).toBe( '25' );
|
||||
|
||||
const result2 = await productsApi.listAll.products( {
|
||||
max_price: 5,
|
||||
} );
|
||||
expect( result2.statusCode ).toEqual( 200 );
|
||||
expect( result2.body ).toHaveLength( 1 );
|
||||
expect( result2.body[0].name ).toBe( 'Single' );
|
||||
expect( result2.body[0].price ).toBe( '2' );
|
||||
|
||||
const result3 = await productsApi.listAll.products( {
|
||||
min_price: 5,
|
||||
order: 'asc',
|
||||
orderby: 'price',
|
||||
} );
|
||||
expect( result3.statusCode ).toEqual( 200 );
|
||||
expect( result3.body ).toEqual(
|
||||
expect.not.arrayContaining( [
|
||||
expect.objectContaining( { name: 'Single' } )
|
||||
] )
|
||||
);
|
||||
} );
|
||||
|
||||
it( 'before / after', async () => {
|
||||
const before = [
|
||||
expect.objectContaining( { name: 'Album' } ),
|
||||
expect.objectContaining( { name: 'Single' } ),
|
||||
expect.objectContaining( { name: 'T-Shirt with Logo' } ),
|
||||
expect.objectContaining( { name: 'Beanie with Logo' } ),
|
||||
];
|
||||
const after = [
|
||||
expect.objectContaining( { name: 'Hoodie' } ),
|
||||
expect.objectContaining( { name: 'V-Neck T-Shirt' } ),
|
||||
expect.objectContaining( { name: 'Parent Product' } ),
|
||||
expect.objectContaining( { name: 'Child Product' } ),
|
||||
];
|
||||
|
||||
const result1 = await productsApi.listAll.products( {
|
||||
before: '2021-09-05T15:50:19',
|
||||
} );
|
||||
expect( result1.statusCode ).toEqual( 200 );
|
||||
expect( result1.body ).toHaveLength( before.length );
|
||||
expect( result1.body ).toEqual( expect.arrayContaining( before ) );
|
||||
|
||||
const result2 = await productsApi.listAll.products( {
|
||||
after: '2021-09-18T15:50:18',
|
||||
} );
|
||||
expect( result2.statusCode ).toEqual( 200 );
|
||||
expect( result2.body ).toEqual( expect.not.arrayContaining( before ) );
|
||||
expect( result2.body ).toHaveLength( after.length );
|
||||
expect( result2.body ).toEqual( expect.arrayContaining( after ) );
|
||||
} );
|
||||
|
||||
it( 'attributes', async () => {
|
||||
const red = sampleData.attributes.colors.find( term => term.name === 'Red' );
|
||||
|
||||
const redProducts = [
|
||||
expect.objectContaining( { name: 'V-Neck T-Shirt' } ),
|
||||
expect.objectContaining( { name: 'Hoodie' } ),
|
||||
expect.objectContaining( { name: 'Beanie' } ),
|
||||
expect.objectContaining( { name: 'Beanie with Logo' } ),
|
||||
];
|
||||
|
||||
const result = await productsApi.listAll.products( {
|
||||
attribute: 'pa_color',
|
||||
attribute_term: red.id,
|
||||
} );
|
||||
|
||||
expect( result.statusCode ).toEqual( 200 );
|
||||
expect( result.body ).toHaveLength( redProducts.length );
|
||||
expect( result.body ).toEqual( expect.arrayContaining( redProducts ) );
|
||||
} );
|
||||
|
||||
it( 'status', async () => {
|
||||
const result1 = await productsApi.listAll.products( {
|
||||
status: 'pending'
|
||||
} );
|
||||
expect( result1.statusCode ).toEqual( 200 );
|
||||
expect( result1.body ).toHaveLength( 1 );
|
||||
expect( result1.body[0].name ).toBe( 'Polo' );
|
||||
|
||||
const result2 = await productsApi.listAll.products( {
|
||||
status: 'draft'
|
||||
} );
|
||||
expect( result2.statusCode ).toEqual( 200 );
|
||||
expect( result2.body ).toHaveLength( 0 );
|
||||
} );
|
||||
|
||||
it( 'shipping class', async () => {
|
||||
const result = await productsApi.listAll.products( {
|
||||
shipping_class: sampleData.shippingClasses.freight.id,
|
||||
} );
|
||||
expect( result.statusCode ).toEqual( 200 );
|
||||
expect( result.body ).toHaveLength( 1 );
|
||||
expect( result.body[0].name ).toBe( 'Long Sleeve Tee' );
|
||||
} );
|
||||
|
||||
it( 'tax class', async () => {
|
||||
const result = await productsApi.listAll.products( {
|
||||
tax_class: 'reduced-rate',
|
||||
} );
|
||||
expect( result.statusCode ).toEqual( 200 );
|
||||
expect( result.body ).toHaveLength( 1 );
|
||||
expect( result.body[0].name ).toBe( 'Sunglasses' );
|
||||
} );
|
||||
|
||||
it( 'stock status', async () => {
|
||||
const result = await productsApi.listAll.products( {
|
||||
stock_status: 'onbackorder',
|
||||
} );
|
||||
expect( result.statusCode ).toEqual( 200 );
|
||||
expect( result.body ).toHaveLength( 1 );
|
||||
expect( result.body[0].name ).toBe( 'T-Shirt' );
|
||||
} );
|
||||
|
||||
it( 'tags', async () => {
|
||||
const coolProducts = [
|
||||
expect.objectContaining( { name: 'Sunglasses' } ),
|
||||
expect.objectContaining( { name: 'Hoodie with Pocket' } ),
|
||||
expect.objectContaining( { name: 'Beanie' } ),
|
||||
];
|
||||
|
||||
const result = await productsApi.listAll.products( {
|
||||
tag: sampleData.tags.cool.id,
|
||||
} );
|
||||
|
||||
expect( result.statusCode ).toEqual( 200 );
|
||||
expect( result.body ).toHaveLength( coolProducts.length );
|
||||
expect( result.body ).toEqual( expect.arrayContaining( coolProducts ) );
|
||||
} );
|
||||
|
||||
it( 'parent', async () => {
|
||||
const result1 = await productsApi.listAll.products( {
|
||||
parent: sampleData.hierarchicalProducts.parent.id,
|
||||
} );
|
||||
expect( result1.statusCode ).toEqual( 200 );
|
||||
expect( result1.body ).toHaveLength( 1 );
|
||||
expect( result1.body[0].name ).toBe( 'Child Product' );
|
||||
|
||||
const result2 = await productsApi.listAll.products( {
|
||||
parent_exclude: sampleData.hierarchicalProducts.parent.id,
|
||||
} );
|
||||
expect( result2.statusCode ).toEqual( 200 );
|
||||
expect( result2.body ).toEqual( expect.not.arrayContaining( [
|
||||
expect.objectContaining( { name: 'Child Product' } ),
|
||||
] ) );
|
||||
} );
|
||||
|
||||
describe( 'orderby', () => {
|
||||
const productNamesAsc = [
|
||||
'Album',
|
||||
'Beanie',
|
||||
'Beanie with Logo',
|
||||
'Belt',
|
||||
'Cap',
|
||||
'Child Product',
|
||||
'Hoodie',
|
||||
'Hoodie with Logo',
|
||||
'Hoodie with Pocket',
|
||||
'Hoodie with Zipper',
|
||||
'Logo Collection',
|
||||
'Long Sleeve Tee',
|
||||
'Parent Product',
|
||||
'Polo',
|
||||
'Single',
|
||||
'Sunglasses',
|
||||
'T-Shirt',
|
||||
'T-Shirt with Logo',
|
||||
'V-Neck T-Shirt',
|
||||
'WordPress Pennant',
|
||||
];
|
||||
const productNamesDesc = [ ...productNamesAsc ].reverse();
|
||||
const productNamesByRatingAsc = [
|
||||
'Sunglasses',
|
||||
'Cap',
|
||||
'T-Shirt',
|
||||
];
|
||||
const productNamesByRatingDesc = [ ...productNamesByRatingAsc ].reverse();
|
||||
const productNamesByPopularityDesc = [
|
||||
'Beanie with Logo',
|
||||
'Single',
|
||||
'T-Shirt',
|
||||
];
|
||||
const productNamesByPopularityAsc = [ ...productNamesByPopularityDesc ].reverse();
|
||||
|
||||
it( 'default', async () => {
|
||||
// Default = date desc.
|
||||
const result = await productsApi.listAll.products();
|
||||
expect( result.statusCode ).toEqual( 200 );
|
||||
|
||||
// Verify all dates are in descending order.
|
||||
let lastDate = Date.now();
|
||||
result.body.forEach( ( { date_created_gmt } ) => {
|
||||
const created = Date.parse( date_created_gmt + '.000Z' );
|
||||
expect( lastDate ).toBeGreaterThan( created );
|
||||
lastDate = created;
|
||||
} );
|
||||
} );
|
||||
|
||||
it( 'date', async () => {
|
||||
const result = await productsApi.listAll.products( {
|
||||
order: 'asc',
|
||||
orderby: 'date',
|
||||
} );
|
||||
expect( result.statusCode ).toEqual( 200 );
|
||||
|
||||
// Verify all dates are in ascending order.
|
||||
let lastDate = 0;
|
||||
result.body.forEach( ( { date_created_gmt } ) => {
|
||||
const created = Date.parse( date_created_gmt + '.000Z' );
|
||||
expect( created ).toBeGreaterThan( lastDate );
|
||||
lastDate = created;
|
||||
} );
|
||||
} );
|
||||
|
||||
it( 'id', async () => {
|
||||
const result1 = await productsApi.listAll.products( {
|
||||
order: 'asc',
|
||||
orderby: 'id',
|
||||
} );
|
||||
expect( result1.statusCode ).toEqual( 200 );
|
||||
|
||||
// Verify all results are in ascending order.
|
||||
let lastId = 0;
|
||||
result1.body.forEach( ( { id } ) => {
|
||||
expect( id ).toBeGreaterThan( lastId );
|
||||
lastId = id;
|
||||
} );
|
||||
|
||||
const result2 = await productsApi.listAll.products( {
|
||||
order: 'desc',
|
||||
orderby: 'id',
|
||||
} );
|
||||
expect( result2.statusCode ).toEqual( 200 );
|
||||
|
||||
// Verify all results are in descending order.
|
||||
lastId = Number.MAX_SAFE_INTEGER;
|
||||
result2.body.forEach( ( { id } ) => {
|
||||
expect( lastId ).toBeGreaterThan( id );
|
||||
lastId = id;
|
||||
} );
|
||||
} );
|
||||
|
||||
it( 'title', async () => {
|
||||
const result1 = await productsApi.listAll.products( {
|
||||
order: 'asc',
|
||||
orderby: 'title',
|
||||
per_page: productNamesAsc.length,
|
||||
} );
|
||||
expect( result1.statusCode ).toEqual( 200 );
|
||||
|
||||
// Verify all results are in ascending order.
|
||||
result1.body.forEach( ( { name }, idx ) => {
|
||||
expect( name ).toBe( productNamesAsc[ idx ] );
|
||||
} );
|
||||
|
||||
const result2 = await productsApi.listAll.products( {
|
||||
order: 'desc',
|
||||
orderby: 'title',
|
||||
per_page: productNamesDesc.length,
|
||||
} );
|
||||
expect( result2.statusCode ).toEqual( 200 );
|
||||
|
||||
// Verify all results are in descending order.
|
||||
result2.body.forEach( ( { name }, idx ) => {
|
||||
expect( name ).toBe( productNamesDesc[ idx ] );
|
||||
} );
|
||||
} );
|
||||
|
||||
it( 'slug', async () => {
|
||||
const productNamesBySlugAsc = [
|
||||
'Polo', // The Polo isn't published so it has an empty slug.
|
||||
...productNamesAsc.filter( p => p !== 'Polo' ),
|
||||
];
|
||||
const productNamesBySlugDesc = [ ...productNamesBySlugAsc ].reverse();
|
||||
|
||||
const result1 = await productsApi.listAll.products( {
|
||||
order: 'asc',
|
||||
orderby: 'slug',
|
||||
per_page: productNamesBySlugAsc.length,
|
||||
} );
|
||||
expect( result1.statusCode ).toEqual( 200 );
|
||||
|
||||
// Verify all results are in ascending order.
|
||||
result1.body.forEach( ( { name }, idx ) => {
|
||||
expect( name ).toBe( productNamesBySlugAsc[ idx ] );
|
||||
} );
|
||||
|
||||
const result2 = await productsApi.listAll.products( {
|
||||
order: 'desc',
|
||||
orderby: 'slug',
|
||||
per_page: productNamesBySlugDesc.length,
|
||||
} );
|
||||
expect( result2.statusCode ).toEqual( 200 );
|
||||
|
||||
// Verify all results are in descending order.
|
||||
result2.body.forEach( ( { name }, idx ) => {
|
||||
expect( name ).toBe( productNamesBySlugDesc[ idx ] );
|
||||
} );
|
||||
} );
|
||||
|
||||
it( 'price', async () => {
|
||||
const productNamesMinPriceAsc = [
|
||||
'Parent Product',
|
||||
'Child Product',
|
||||
'Single',
|
||||
'WordPress Pennant',
|
||||
'Album',
|
||||
'V-Neck T-Shirt',
|
||||
'Cap',
|
||||
'Beanie with Logo',
|
||||
'T-Shirt with Logo',
|
||||
'Beanie',
|
||||
'T-Shirt',
|
||||
'Logo Collection',
|
||||
'Polo',
|
||||
'Long Sleeve Tee',
|
||||
'Hoodie with Pocket',
|
||||
'Hoodie',
|
||||
'Hoodie with Zipper',
|
||||
'Hoodie with Logo',
|
||||
'Belt',
|
||||
'Sunglasses',
|
||||
];
|
||||
const result1 = await productsApi.listAll.products( {
|
||||
order: 'asc',
|
||||
orderby: 'price',
|
||||
per_page: productNamesMinPriceAsc.length
|
||||
} );
|
||||
expect( result1.statusCode ).toEqual( 200 );
|
||||
expect( result1.body ).toHaveLength( productNamesMinPriceAsc.length );
|
||||
|
||||
// Verify all results are in ascending order.
|
||||
// The query uses the min price calculated in the product meta lookup table,
|
||||
// so we can't just check the price property of the response.
|
||||
result1.body.forEach( ( { name }, idx ) => {
|
||||
expect( name ).toBe( productNamesMinPriceAsc[ idx ] );
|
||||
} );
|
||||
|
||||
const productNamesMaxPriceDesc = [
|
||||
'Sunglasses',
|
||||
'Belt',
|
||||
'Hoodie',
|
||||
'Logo Collection',
|
||||
'Hoodie with Logo',
|
||||
'Hoodie with Zipper',
|
||||
'Hoodie with Pocket',
|
||||
'Long Sleeve Tee',
|
||||
'V-Neck T-Shirt',
|
||||
'Polo',
|
||||
'T-Shirt',
|
||||
'Beanie',
|
||||
'T-Shirt with Logo',
|
||||
'Beanie with Logo',
|
||||
'Cap',
|
||||
'Album',
|
||||
'WordPress Pennant',
|
||||
'Single',
|
||||
'Child Product',
|
||||
'Parent Product',
|
||||
];
|
||||
|
||||
const result2 = await productsApi.listAll.products( {
|
||||
order: 'desc',
|
||||
orderby: 'price',
|
||||
per_page: productNamesMaxPriceDesc.length
|
||||
} );
|
||||
expect( result2.statusCode ).toEqual( 200 );
|
||||
expect( result2.body ).toHaveLength( productNamesMaxPriceDesc.length );
|
||||
|
||||
// Verify all results are in descending order.
|
||||
// The query uses the max price calculated in the product meta lookup table,
|
||||
// so we can't just check the price property of the response.
|
||||
result2.body.forEach( ( { name }, idx ) => {
|
||||
expect( name ).toBe( productNamesMaxPriceDesc[ idx ] );
|
||||
} );
|
||||
} );
|
||||
|
||||
// This case will remain skipped until orderby include is fixed.
|
||||
// See: https://github.com/woocommerce/woocommerce/issues/30354#issuecomment-925955099.
|
||||
it( 'include', async () => {
|
||||
const includeIds = [
|
||||
sampleData.groupedProducts[ 0 ].id,
|
||||
sampleData.simpleProducts[ 3 ].id,
|
||||
sampleData.hierarchicalProducts.parent.id,
|
||||
];
|
||||
|
||||
const result1 = await productsApi.listAll.products( {
|
||||
order: 'asc',
|
||||
orderby: 'include',
|
||||
include: includeIds.join( ',' ),
|
||||
} );
|
||||
expect( result1.statusCode ).toEqual( 200 );
|
||||
expect( result1.body ).toHaveLength( includeIds.length );
|
||||
|
||||
// Verify all results are in proper order.
|
||||
result1.body.forEach( ( { id }, idx ) => {
|
||||
expect( id ).toBe( includeIds[ idx ] );
|
||||
} );
|
||||
|
||||
const result2 = await productsApi.listAll.products( {
|
||||
order: 'desc',
|
||||
orderby: 'include',
|
||||
include: includeIds.join( ',' ),
|
||||
} );
|
||||
expect( result2.statusCode ).toEqual( 200 );
|
||||
expect( result2.body ).toHaveLength( includeIds.length );
|
||||
|
||||
// Verify all results are in proper order.
|
||||
result2.body.forEach( ( { id }, idx ) => {
|
||||
expect( id ).toBe( includeIds[ idx ] );
|
||||
} );
|
||||
} );
|
||||
|
||||
it( 'rating (desc)', async () => {
|
||||
const result2 = await productsApi.listAll.products( {
|
||||
order: 'desc',
|
||||
orderby: 'rating',
|
||||
per_page: productNamesByRatingDesc.length,
|
||||
} );
|
||||
expect( result2.statusCode ).toEqual( 200 );
|
||||
|
||||
// Verify all results are in descending order.
|
||||
result2.body.forEach( ( { name }, idx ) => {
|
||||
expect( name ).toBe( productNamesByRatingDesc[ idx ] );
|
||||
} );
|
||||
} );
|
||||
|
||||
// This case will remain skipped until ratings can be sorted ascending.
|
||||
// See: https://github.com/woocommerce/woocommerce/issues/30354#issuecomment-925955099.
|
||||
it.skip( 'rating (asc)', async () => {
|
||||
const result1 = await productsApi.listAll.products( {
|
||||
order: 'asc',
|
||||
orderby: 'rating',
|
||||
per_page: productNamesByRatingAsc.length,
|
||||
} );
|
||||
expect( result1.statusCode ).toEqual( 200 );
|
||||
|
||||
// Verify all results are in ascending order.
|
||||
result1.body.forEach( ( { name }, idx ) => {
|
||||
expect( name ).toBe( productNamesByRatingAsc[ idx ] );
|
||||
} );
|
||||
} );
|
||||
|
||||
it( 'popularity (desc)', async () => {
|
||||
const result2 = await productsApi.listAll.products( {
|
||||
order: 'desc',
|
||||
orderby: 'popularity',
|
||||
per_page: productNamesByPopularityDesc.length,
|
||||
} );
|
||||
expect( result2.statusCode ).toEqual( 200 );
|
||||
|
||||
// Verify all results are in descending order.
|
||||
result2.body.forEach( ( { name }, idx ) => {
|
||||
expect( name ).toBe( productNamesByPopularityDesc[ idx ] );
|
||||
} );
|
||||
} );
|
||||
|
||||
// This case will remain skipped until popularity can be sorted ascending.
|
||||
// See: https://github.com/woocommerce/woocommerce/issues/30354#issuecomment-925955099.
|
||||
it.skip( 'popularity (asc)', async () => {
|
||||
const result1 = await productsApi.listAll.products( {
|
||||
order: 'asc',
|
||||
orderby: 'popularity',
|
||||
per_page: productNamesByPopularityAsc.length,
|
||||
} );
|
||||
expect( result1.statusCode ).toEqual( 200 );
|
||||
|
||||
// Verify all results are in ascending order.
|
||||
result1.body.forEach( ( { name }, idx ) => {
|
||||
expect( name ).toBe( productNamesByPopularityAsc[ idx ] );
|
||||
} );
|
||||
} );
|
||||
} );
|
||||
} );
|
||||
} );
|
|
@ -10,7 +10,7 @@ rm -rf "$BUILD_PATH"
|
|||
mkdir -p "$DEST_PATH"
|
||||
|
||||
echo "Installing PHP and JS dependencies..."
|
||||
pnpm run install:no-e2e
|
||||
pnpm install
|
||||
composer install || exit "$?"
|
||||
echo "Running JS Build..."
|
||||
pnpm run build:core || exit "$?"
|
||||
|
|
|
@ -9,5 +9,5 @@ runOnChange() {
|
|||
fi
|
||||
}
|
||||
|
||||
runOnChange "package-lock.json" "pnpm run install:no-e2e"
|
||||
runOnChange "package-lock.json" "pnpm install"
|
||||
runOnChange "composer.lock" "SKIP_UPDATE_TEXTDOMAINS=true composer install"
|
||||
|
|
|
@ -15,10 +15,7 @@
|
|||
"scripts": {
|
||||
"composer:install": "composer install",
|
||||
"composer:dump-autoload": "composer dump-autoload",
|
||||
"check:subset-installed": "pnpm list --depth 1 install-subset > /dev/null 2>&1",
|
||||
"preinstall": "npx only-allow pnpm",
|
||||
"install:subset-only": "pnpm install --no-package-lock --no-save install-subset",
|
||||
"install:no-e2e": "pnpm run check:subset-installed --silent || pnpm run install:subset-only && pnpx install-subset i no-e2e",
|
||||
"build": "./bin/build-zip.sh",
|
||||
"build:core": "grunt && pnpm run makepot",
|
||||
"build-watch": "grunt watch",
|
||||
|
@ -128,17 +125,5 @@
|
|||
"> 0.1%",
|
||||
"ie 8",
|
||||
"ie 9"
|
||||
],
|
||||
"subsets": {
|
||||
"no-e2e": {
|
||||
"exclude": [
|
||||
"@woocommerce/api",
|
||||
"@woocommerce/api-core-tests",
|
||||
"@woocommerce/e2e-core-tests",
|
||||
"@woocommerce/e2e-environment",
|
||||
"@woocommerce/e2e-utils",
|
||||
"@wordpress/e2e-test-utils"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
/**
|
||||
* A basic refund.
|
||||
*
|
||||
* For more details on the order refund properties, see:
|
||||
*
|
||||
* https://woocommerce.github.io/woocommerce-rest-api-docs/#order-refund-properties
|
||||
*
|
||||
*/
|
||||
const refund = {
|
||||
api_refund: false,
|
||||
amount: '1.00',
|
||||
reason: 'Late delivery refund.',
|
||||
line_items: [],
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
refund: refund,
|
||||
};
|
|
@ -1,60 +0,0 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
const {
|
||||
getRequest,
|
||||
postRequest,
|
||||
putRequest,
|
||||
deleteRequest,
|
||||
} = require( '../utils/request' );
|
||||
|
||||
/**
|
||||
* WooCommerce Refunds endpoints.
|
||||
*
|
||||
* https://woocommerce.github.io/woocommerce-rest-api-docs/#refunds
|
||||
*/
|
||||
const refundsApi = {
|
||||
name: 'Refunds',
|
||||
create: {
|
||||
name: 'Create a refund',
|
||||
method: 'POST',
|
||||
path: 'orders/<id>/refunds',
|
||||
responseCode: 201,
|
||||
refund: async ( orderId, refundDetails ) =>
|
||||
postRequest( `orders/${ orderId }/refunds`, refundDetails ),
|
||||
},
|
||||
retrieve: {
|
||||
name: 'Retrieve a refund',
|
||||
method: 'GET',
|
||||
path: 'orders/<id>/refunds/<refund_id>',
|
||||
responseCode: 200,
|
||||
refund: async ( orderId, refundId ) =>
|
||||
getRequest( `orders/${ orderId }/refunds/${ refundId }` ),
|
||||
},
|
||||
listAll: {
|
||||
name: 'List all refunds',
|
||||
method: 'GET',
|
||||
path: 'orders/<id>/refunds',
|
||||
responseCode: 200,
|
||||
refunds: async ( orderId ) =>
|
||||
getRequest( `orders/${ orderId }/refunds` ),
|
||||
},
|
||||
delete: {
|
||||
name: 'Delete a refund',
|
||||
method: 'DELETE',
|
||||
path: 'orders/<id>/refunds/<refund_id>',
|
||||
responseCode: 200,
|
||||
payload: {
|
||||
force: false,
|
||||
},
|
||||
refund: async ( orderId, refundId, deletePermanently ) =>
|
||||
deleteRequest(
|
||||
`orders/${ orderId }/refunds/${ refundId }`,
|
||||
deletePermanently
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
refundsApi: refundsApi,
|
||||
};
|
|
@ -1,122 +0,0 @@
|
|||
const { refundsApi } = require( '../../endpoints/refunds' );
|
||||
const { ordersApi } = require( '../../endpoints/orders' );
|
||||
const { productsApi } = require( '../../endpoints/products' );
|
||||
const { refund } = require( '../../data' );
|
||||
|
||||
/**
|
||||
* Tests for the WooCommerce Refunds API.
|
||||
*
|
||||
* @group api
|
||||
* @group refunds
|
||||
*
|
||||
*/
|
||||
describe( 'Refunds API tests', () => {
|
||||
let expectedRefund;
|
||||
let orderId;
|
||||
let productId;
|
||||
|
||||
beforeAll( async () => {
|
||||
// Create a product and save its product ID
|
||||
const product = {
|
||||
name: 'Simple Product for Refunds API tests',
|
||||
regular_price: '100',
|
||||
};
|
||||
const createProductResponse = await productsApi.create.product(
|
||||
product
|
||||
);
|
||||
productId = createProductResponse.body.id;
|
||||
|
||||
// Create an order with a product line item, and save its Order ID
|
||||
const order = {
|
||||
status: 'pending',
|
||||
line_items: [
|
||||
{
|
||||
product_id: productId,
|
||||
},
|
||||
],
|
||||
};
|
||||
const createOrderResponse = await ordersApi.create.order( order );
|
||||
orderId = createOrderResponse.body.id;
|
||||
|
||||
// Setup the expected refund object
|
||||
expectedRefund = {
|
||||
...refund,
|
||||
line_items: [
|
||||
{
|
||||
product_id: productId,
|
||||
},
|
||||
],
|
||||
};
|
||||
} );
|
||||
|
||||
afterAll( async () => {
|
||||
// Cleanup the created product and order
|
||||
await productsApi.delete.product( productId, true );
|
||||
await ordersApi.delete.order( orderId, true );
|
||||
} );
|
||||
|
||||
it( 'can create a refund', async () => {
|
||||
const { status, body } = await refundsApi.create.refund(
|
||||
orderId,
|
||||
expectedRefund
|
||||
);
|
||||
expect( status ).toEqual( refundsApi.create.responseCode );
|
||||
expect( body.id ).toBeDefined();
|
||||
|
||||
// Save the refund ID
|
||||
expectedRefund.id = body.id;
|
||||
|
||||
// Verify that the order was refunded.
|
||||
const getOrderResponse = await ordersApi.retrieve.order( orderId );
|
||||
expect( getOrderResponse.body.refunds ).toHaveLength( 1 );
|
||||
expect( getOrderResponse.body.refunds[ 0 ].id ).toEqual(
|
||||
expectedRefund.id
|
||||
);
|
||||
expect( getOrderResponse.body.refunds[ 0 ].reason ).toEqual(
|
||||
expectedRefund.reason
|
||||
);
|
||||
expect( getOrderResponse.body.refunds[ 0 ].total ).toEqual(
|
||||
`-${ expectedRefund.amount }`
|
||||
);
|
||||
} );
|
||||
|
||||
it( 'can retrieve a refund', async () => {
|
||||
const { status, body } = await refundsApi.retrieve.refund(
|
||||
orderId,
|
||||
expectedRefund.id
|
||||
);
|
||||
|
||||
expect( status ).toEqual( refundsApi.retrieve.responseCode );
|
||||
expect( body.id ).toEqual( expectedRefund.id );
|
||||
} );
|
||||
|
||||
it( 'can list all refunds', async () => {
|
||||
const { status, body } = await refundsApi.listAll.refunds( orderId );
|
||||
|
||||
expect( status ).toEqual( refundsApi.listAll.responseCode );
|
||||
expect( body ).toHaveLength( 1 );
|
||||
expect( body[ 0 ].id ).toEqual( expectedRefund.id );
|
||||
} );
|
||||
|
||||
it( 'can delete a refund', async () => {
|
||||
const { status, body } = await refundsApi.delete.refund(
|
||||
orderId,
|
||||
expectedRefund.id,
|
||||
true
|
||||
);
|
||||
|
||||
expect( status ).toEqual( refundsApi.delete.responseCode );
|
||||
expect( body.id ).toEqual( expectedRefund.id );
|
||||
|
||||
// Verify that the refund cannot be retrieved
|
||||
const retrieveRefundResponse = await refundsApi.retrieve.refund(
|
||||
orderId,
|
||||
expectedRefund.id
|
||||
);
|
||||
expect( retrieveRefundResponse.status ).toEqual( 404 );
|
||||
|
||||
// Verify that the order no longer has a refund
|
||||
const retrieveOrderResponse = await ordersApi.retrieve.order( orderId );
|
||||
expect( retrieveOrderResponse.body.refunds ).toHaveLength( 0 );
|
||||
} );
|
||||
} );
|
3281
pnpm-lock.yaml
3281
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue