Merge pull request #29236 from woocommerce/fix/28883
add variable product support to api package
This commit is contained in:
commit
e52504679d
|
@ -3,7 +3,8 @@
|
||||||
## Added
|
## Added
|
||||||
|
|
||||||
- Support for the external product type.
|
- Support for the external product type.
|
||||||
- Added support for grouped product type
|
- Support for grouped product type.
|
||||||
|
- Support for variable products and product variations.
|
||||||
- Support for coupons.
|
- Support for coupons.
|
||||||
|
|
||||||
# 0.1.1
|
# 0.1.1
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { Model } from '../../models';
|
import { Model } from '../../models';
|
||||||
import {
|
import {
|
||||||
|
CreatesChildModels,
|
||||||
CreatesModels,
|
CreatesModels,
|
||||||
DeletesChildModels,
|
DeletesChildModels,
|
||||||
DeletesModels,
|
DeletesModels,
|
||||||
|
@ -90,7 +91,7 @@ describe( 'ModelRepository', () => {
|
||||||
it( 'should create child', async () => {
|
it( 'should create child', async () => {
|
||||||
const model = new DummyChildModel();
|
const model = new DummyChildModel();
|
||||||
const callback = jest.fn().mockResolvedValue( model );
|
const callback = jest.fn().mockResolvedValue( model );
|
||||||
const repository: CreatesModels< DummyChildParams > = new ModelRepository< DummyChildParams >(
|
const repository: CreatesChildModels< DummyChildParams > = new ModelRepository< DummyChildParams >(
|
||||||
null,
|
null,
|
||||||
callback,
|
callback,
|
||||||
null,
|
null,
|
||||||
|
@ -98,7 +99,7 @@ describe( 'ModelRepository', () => {
|
||||||
null,
|
null,
|
||||||
);
|
);
|
||||||
|
|
||||||
const created = await repository.create( { childName: 'test' } );
|
const created = await repository.create( { parent: 'yes' }, { childName: 'test' } );
|
||||||
expect( created ).toBe( model );
|
expect( created ).toBe( model );
|
||||||
expect( callback ).toHaveBeenCalledWith( { childName: 'test' } );
|
expect( callback ).toHaveBeenCalledWith( { childName: 'test' } );
|
||||||
} );
|
} );
|
||||||
|
|
|
@ -77,6 +77,20 @@ export type ListChildFn< T extends ModelRepositoryParams > = (
|
||||||
*/
|
*/
|
||||||
export type CreateFn< T extends ModelRepositoryParams > = ( properties: Partial< ModelClass< T > > ) => Promise< ModelClass< T > >;
|
export type CreateFn< T extends ModelRepositoryParams > = ( properties: Partial< ModelClass< T > > ) => Promise< ModelClass< T > >;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A callback for creating a child model using a data source.
|
||||||
|
*
|
||||||
|
* @callback CreateChildFn
|
||||||
|
* @param {ModelID} parent The parent identifier for the model.
|
||||||
|
* @param {Partial.<T>} properties The properties of the model to create.
|
||||||
|
* @return {Promise.<T>} Resolves to the created model.
|
||||||
|
* @template {Model} T
|
||||||
|
*/
|
||||||
|
export type CreateChildFn< T extends ModelRepositoryParams > = (
|
||||||
|
parent: ParentID< T >,
|
||||||
|
properties: Partial< ModelClass< T > >
|
||||||
|
) => Promise< ModelClass< T > >;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A callback for reading a model using a data source.
|
* A callback for reading a model using a data source.
|
||||||
*
|
*
|
||||||
|
@ -189,6 +203,21 @@ export interface CreatesModels< T extends ModelRepositoryParams > {
|
||||||
create( properties: Partial< ModelClass< T > > ): Promise< ModelClass< T > >;
|
create( properties: Partial< ModelClass< T > > ): Promise< ModelClass< T > >;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An interface for repositories that can create child models.
|
||||||
|
*
|
||||||
|
* @typedef CreatesChildModels
|
||||||
|
* @property {CreateChildFn.<T>} create Creates a child model using the repository.
|
||||||
|
* @template {Model} T
|
||||||
|
* @template {ModelParentID} P
|
||||||
|
*/
|
||||||
|
export interface CreatesChildModels< T extends ModelRepositoryParams > {
|
||||||
|
create(
|
||||||
|
parent: HasParent< T, ParentID< T >, never >,
|
||||||
|
properties: HasParent< T, Partial< ModelClass< T > >, never >,
|
||||||
|
): Promise< ModelClass< T > >;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An interface for repositories that can read models.
|
* An interface for repositories that can read models.
|
||||||
*
|
*
|
||||||
|
@ -301,7 +330,7 @@ export class ModelRepository< T extends ModelRepositoryParams > implements
|
||||||
* @type {CreateFn.<T>}
|
* @type {CreateFn.<T>}
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
private readonly createHook: CreateFn< T > | null;
|
private readonly createHook: HasParent< T, CreateChildFn< T >, CreateFn< T > > | null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The hook used to read models.
|
* The hook used to read models.
|
||||||
|
@ -338,7 +367,7 @@ export class ModelRepository< T extends ModelRepositoryParams > implements
|
||||||
*/
|
*/
|
||||||
public constructor(
|
public constructor(
|
||||||
listHook: HasParent< T, ListChildFn< T >, ListFn< T > > | null,
|
listHook: HasParent< T, ListChildFn< T >, ListFn< T > > | null,
|
||||||
createHook: CreateFn< T > | null,
|
createHook: HasParent< T, CreateChildFn< T >, CreateFn< T > > | null,
|
||||||
readHook: HasParent< T, ReadChildFn< T >, ReadFn< T > > | null,
|
readHook: HasParent< T, ReadChildFn< T >, ReadFn< T > > | null,
|
||||||
updateHook: HasParent< T, UpdateChildFn< T >, UpdateFn< T > > | null,
|
updateHook: HasParent< T, UpdateChildFn< T >, UpdateFn< T > > | null,
|
||||||
deleteHook: HasParent< T, DeleteChildFn< T >, DeleteFn > | null,
|
deleteHook: HasParent< T, DeleteChildFn< T >, DeleteFn > | null,
|
||||||
|
@ -380,15 +409,28 @@ export class ModelRepository< T extends ModelRepositoryParams > implements
|
||||||
/**
|
/**
|
||||||
* Creates a new model using the repository.
|
* Creates a new model using the repository.
|
||||||
*
|
*
|
||||||
|
* @param {P|ModelID} propertiesOrParent The properties to create the model with or the model parent.
|
||||||
* @param {Partial.<T>} properties The properties to create the model with.
|
* @param {Partial.<T>} properties The properties to create the model with.
|
||||||
* @return {Promise.<T>} Resolves to the created model.
|
* @return {Promise.<T>} Resolves to the created model.
|
||||||
*/
|
*/
|
||||||
public create( properties: Partial< ModelClass< T > > ): Promise< ModelClass< T > > {
|
public create(
|
||||||
|
propertiesOrParent?: HasParent< T, ParentID< T >, Partial< ModelClass<T> > >,
|
||||||
|
properties?: HasParent< T, Partial< ModelClass<T> >, never >,
|
||||||
|
): Promise< ModelClass< T > > {
|
||||||
if ( ! this.createHook ) {
|
if ( ! this.createHook ) {
|
||||||
throw new Error( 'The \'create\' operation is not supported on this model.' );
|
throw new Error( 'The \'create\' operation is not supported on this model.' );
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.createHook( properties );
|
if ( properties === undefined ) {
|
||||||
|
return ( this.createHook as CreateFn< T > )(
|
||||||
|
propertiesOrParent as Partial< ModelClass<T> >,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ( this.createHook as CreateChildFn< T > )(
|
||||||
|
propertiesOrParent as ParentID<T>,
|
||||||
|
properties as Partial< ModelClass<T> >,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
import { Model, ModelID } from '../../model';
|
import { AbstractProductData } from './data';
|
||||||
import { MetaData, PostStatus } from '../../shared-types';
|
import { ModelID } from '../../model';
|
||||||
import {
|
import {
|
||||||
CatalogVisibility,
|
CatalogVisibility,
|
||||||
ProductAttribute,
|
|
||||||
ProductImage,
|
|
||||||
ProductTerm,
|
ProductTerm,
|
||||||
ProductLinks,
|
ProductLinks,
|
||||||
|
ProductAttribute,
|
||||||
} from '../shared';
|
} from '../shared';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -31,7 +30,7 @@ export const buildProductURL = ( id: ModelID ) => baseProductURL() + id;
|
||||||
/**
|
/**
|
||||||
* The base for all product types.
|
* The base for all product types.
|
||||||
*/
|
*/
|
||||||
export abstract class AbstractProduct extends Model {
|
export abstract class AbstractProduct extends AbstractProductData {
|
||||||
/**
|
/**
|
||||||
* The name of the product.
|
* The name of the product.
|
||||||
*
|
*
|
||||||
|
@ -46,34 +45,6 @@ export abstract class AbstractProduct extends Model {
|
||||||
*/
|
*/
|
||||||
public readonly slug: string = '';
|
public readonly slug: string = '';
|
||||||
|
|
||||||
/**
|
|
||||||
* The permalink of the product.
|
|
||||||
*
|
|
||||||
* @type {string}
|
|
||||||
*/
|
|
||||||
public readonly permalink: string = '';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Id of the product.
|
|
||||||
*
|
|
||||||
* @type {number}
|
|
||||||
*/
|
|
||||||
public readonly id: number = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The parent Id of the product.
|
|
||||||
*
|
|
||||||
* @type {number}
|
|
||||||
*/
|
|
||||||
public readonly parentId: number = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The menu order assigned to the product.
|
|
||||||
*
|
|
||||||
* @type {number}
|
|
||||||
*/
|
|
||||||
public readonly menuOrder: number = 0;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The GMT datetime when the product was created.
|
* The GMT datetime when the product was created.
|
||||||
*
|
*
|
||||||
|
@ -88,13 +59,6 @@ export abstract class AbstractProduct extends Model {
|
||||||
*/
|
*/
|
||||||
public readonly modified: Date = new Date();
|
public readonly modified: Date = new Date();
|
||||||
|
|
||||||
/**
|
|
||||||
* The product's current post status.
|
|
||||||
*
|
|
||||||
* @type {PostStatus}
|
|
||||||
*/
|
|
||||||
public readonly postStatus: PostStatus = '';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The product's short description.
|
* The product's short description.
|
||||||
*
|
*
|
||||||
|
@ -102,20 +66,6 @@ export abstract class AbstractProduct extends Model {
|
||||||
*/
|
*/
|
||||||
public readonly shortDescription: string = '';
|
public readonly shortDescription: string = '';
|
||||||
|
|
||||||
/**
|
|
||||||
* The product's full description.
|
|
||||||
*
|
|
||||||
* @type {string}
|
|
||||||
*/
|
|
||||||
public readonly description: string = '';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The product's SKU.
|
|
||||||
*
|
|
||||||
* @type {string}
|
|
||||||
*/
|
|
||||||
public readonly sku: string = '';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An array of the categories this product is in.
|
* An array of the categories this product is in.
|
||||||
*
|
*
|
||||||
|
@ -130,13 +80,6 @@ export abstract class AbstractProduct extends Model {
|
||||||
*/
|
*/
|
||||||
public readonly tags: readonly ProductTerm[] = [];
|
public readonly tags: readonly ProductTerm[] = [];
|
||||||
|
|
||||||
/**
|
|
||||||
* Indicates whether or not the product is currently able to be purchased.
|
|
||||||
*
|
|
||||||
* @type {boolean}
|
|
||||||
*/
|
|
||||||
public readonly isPurchasable: boolean = true;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates whether or not the product should be featured.
|
* Indicates whether or not the product should be featured.
|
||||||
*
|
*
|
||||||
|
@ -144,20 +87,6 @@ export abstract class AbstractProduct extends Model {
|
||||||
*/
|
*/
|
||||||
public readonly isFeatured: boolean = false;
|
public readonly isFeatured: boolean = false;
|
||||||
|
|
||||||
/**
|
|
||||||
* The attributes for the product.
|
|
||||||
*
|
|
||||||
* @type {ReadonlyArray.<ProductAttribute>}
|
|
||||||
*/
|
|
||||||
public readonly attributes: readonly ProductAttribute[] = [];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The images for the product.
|
|
||||||
*
|
|
||||||
* @type {ReadonlyArray.<ProductImage>}
|
|
||||||
*/
|
|
||||||
public readonly images: readonly ProductImage[] = [];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates whether or not the product should be visible in the catalog.
|
* Indicates whether or not the product should be visible in the catalog.
|
||||||
*
|
*
|
||||||
|
@ -165,55 +94,6 @@ export abstract class AbstractProduct extends Model {
|
||||||
*/
|
*/
|
||||||
public readonly catalogVisibility: CatalogVisibility = CatalogVisibility.Everywhere;
|
public readonly catalogVisibility: CatalogVisibility = CatalogVisibility.Everywhere;
|
||||||
|
|
||||||
/**
|
|
||||||
* The current price of the product.
|
|
||||||
*
|
|
||||||
* @type {string}
|
|
||||||
*/
|
|
||||||
public readonly price: string = '';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The rendered HTML for the current price of the product.
|
|
||||||
*
|
|
||||||
* @type {string}
|
|
||||||
*/
|
|
||||||
public readonly priceHtml: string = '';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The regular price of the product when not discounted.
|
|
||||||
*
|
|
||||||
* @type {string}
|
|
||||||
*/
|
|
||||||
public readonly regularPrice: string = '';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Indicates whether or not the product is currently on sale.
|
|
||||||
*
|
|
||||||
* @type {boolean}
|
|
||||||
*/
|
|
||||||
public readonly onSale: boolean = false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The price of the product when on sale.
|
|
||||||
*
|
|
||||||
* @type {string}
|
|
||||||
*/
|
|
||||||
public readonly salePrice: string = '';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The GMT datetime when the product should start to be on sale.
|
|
||||||
*
|
|
||||||
* @type {Date|null}
|
|
||||||
*/
|
|
||||||
public readonly saleStart: Date | null = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The GMT datetime when the product should no longer be on sale.
|
|
||||||
*
|
|
||||||
* @type {Date|null}
|
|
||||||
*/
|
|
||||||
public readonly saleEnd: Date | null = null;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The count of sales of the product
|
* The count of sales of the product
|
||||||
*
|
*
|
||||||
|
@ -250,11 +130,11 @@ export abstract class AbstractProduct extends Model {
|
||||||
public readonly relatedIds: Array<number> = [];
|
public readonly relatedIds: Array<number> = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The extra metadata for the product.
|
* The attributes for the product.
|
||||||
*
|
*
|
||||||
* @type {ReadonlyArray.<MetaData>}
|
* @type {ReadonlyArray.<ProductAttribute>}
|
||||||
*/
|
*/
|
||||||
public readonly metaData: readonly MetaData[] = [];
|
public readonly attributes: readonly ProductAttribute[] = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The products links.
|
* The products links.
|
||||||
|
|
|
@ -0,0 +1,102 @@
|
||||||
|
import { Model } from '../../model';
|
||||||
|
import { MetaData, PostStatus } from '../../shared-types';
|
||||||
|
import { ProductImage, ProductLinks } from '../shared';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base product data.
|
||||||
|
*/
|
||||||
|
export abstract class AbstractProductData extends Model {
|
||||||
|
/**
|
||||||
|
* The permalink of the product.
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
public readonly permalink: string = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Id of the product.
|
||||||
|
*
|
||||||
|
* @type {number}
|
||||||
|
*/
|
||||||
|
public readonly id: number = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The parent Id of the product.
|
||||||
|
*
|
||||||
|
* @type {number}
|
||||||
|
*/
|
||||||
|
public readonly parentId: number = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The menu order assigned to the product.
|
||||||
|
*
|
||||||
|
* @type {number}
|
||||||
|
*/
|
||||||
|
public readonly menuOrder: number = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The GMT datetime when the product was created.
|
||||||
|
*
|
||||||
|
* @type {Date}
|
||||||
|
*/
|
||||||
|
public readonly created: Date = new Date();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The GMT datetime when the product was last modified.
|
||||||
|
*
|
||||||
|
* @type {Date}
|
||||||
|
*/
|
||||||
|
public readonly modified: Date = new Date();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The product's current post status.
|
||||||
|
*
|
||||||
|
* @type {PostStatus}
|
||||||
|
*/
|
||||||
|
public readonly postStatus: PostStatus = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The product's full description.
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
public readonly description: string = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The product's SKU.
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
public readonly sku: string = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether or not the product is currently able to be purchased.
|
||||||
|
*
|
||||||
|
* @type {boolean}
|
||||||
|
*/
|
||||||
|
public readonly isPurchasable: boolean = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The images for the product.
|
||||||
|
*
|
||||||
|
* @type {ReadonlyArray.<ProductImage>}
|
||||||
|
*/
|
||||||
|
public readonly images: readonly ProductImage[] = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The extra metadata for the product.
|
||||||
|
*
|
||||||
|
* @type {ReadonlyArray.<MetaData>}
|
||||||
|
*/
|
||||||
|
public readonly metaData: readonly MetaData[] = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The product data links.
|
||||||
|
*
|
||||||
|
* @type {ReadonlyArray.<ProductLinks>}
|
||||||
|
*/
|
||||||
|
public readonly links: ProductLinks = {
|
||||||
|
collection: [ { href: '' } ],
|
||||||
|
self: [ { href: '' } ],
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
export * from './common';
|
export * from './common';
|
||||||
export * from './cross-sell';
|
export * from './cross-sell';
|
||||||
|
export * from './data';
|
||||||
export * from './delivery';
|
export * from './delivery';
|
||||||
export * from './external';
|
export * from './external';
|
||||||
export * from './grouped';
|
export * from './grouped';
|
||||||
|
|
|
@ -40,7 +40,7 @@ export type GroupedProductRepositoryParams =
|
||||||
* @typedef ListsGroupedProducts
|
* @typedef ListsGroupedProducts
|
||||||
* @alias ListsModels.<GroupedProduct>
|
* @alias ListsModels.<GroupedProduct>
|
||||||
*/
|
*/
|
||||||
export type ListsGroupedProducts = ListsModels< GroupedProductUpdateParams >;
|
export type ListsGroupedProducts = ListsModels< GroupedProductRepositoryParams >;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An interface for creating Grouped products using the repository.
|
* An interface for creating Grouped products using the repository.
|
||||||
|
@ -48,7 +48,7 @@ export type ListsGroupedProducts = ListsModels< GroupedProductUpdateParams >;
|
||||||
* @typedef CreatesGroupedProducts
|
* @typedef CreatesGroupedProducts
|
||||||
* @alias CreatesModels.<GroupedProduct>
|
* @alias CreatesModels.<GroupedProduct>
|
||||||
*/
|
*/
|
||||||
export type CreatesGroupedProducts = CreatesModels< GroupedProductUpdateParams >;
|
export type CreatesGroupedProducts = CreatesModels< GroupedProductRepositoryParams >;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An interface for reading Grouped products using the repository.
|
* An interface for reading Grouped products using the repository.
|
||||||
|
@ -56,7 +56,7 @@ export type CreatesGroupedProducts = CreatesModels< GroupedProductUpdateParams >
|
||||||
* @typedef ReadsGroupedProducts
|
* @typedef ReadsGroupedProducts
|
||||||
* @alias ReadsModels.<GroupedProduct>
|
* @alias ReadsModels.<GroupedProduct>
|
||||||
*/
|
*/
|
||||||
export type ReadsGroupedProducts = ReadsModels< GroupedProductUpdateParams >;
|
export type ReadsGroupedProducts = ReadsModels< GroupedProductRepositoryParams >;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An interface for updating Grouped products using the repository.
|
* An interface for updating Grouped products using the repository.
|
||||||
|
@ -64,7 +64,7 @@ export type ReadsGroupedProducts = ReadsModels< GroupedProductUpdateParams >;
|
||||||
* @typedef UpdatesGroupedProducts
|
* @typedef UpdatesGroupedProducts
|
||||||
* @alias UpdatesModels.<GroupedProduct>
|
* @alias UpdatesModels.<GroupedProduct>
|
||||||
*/
|
*/
|
||||||
export type UpdatesGroupedProducts = UpdatesModels< GroupedProductUpdateParams >;
|
export type UpdatesGroupedProducts = UpdatesModels< GroupedProductRepositoryParams >;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An interface for deleting Grouped products using the repository.
|
* An interface for deleting Grouped products using the repository.
|
||||||
|
@ -72,7 +72,7 @@ export type UpdatesGroupedProducts = UpdatesModels< GroupedProductUpdateParams >
|
||||||
* @typedef DeletesGroupedProducts
|
* @typedef DeletesGroupedProducts
|
||||||
* @alias DeletesModels.<GroupedProduct>
|
* @alias DeletesModels.<GroupedProduct>
|
||||||
*/
|
*/
|
||||||
export type DeletesGroupedProducts = DeletesModels< GroupedProductUpdateParams >;
|
export type DeletesGroupedProducts = DeletesModels< GroupedProductRepositoryParams >;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The base for the Grouped product object.
|
* The base for the Grouped product object.
|
||||||
|
|
|
@ -3,3 +3,5 @@ export * from './shared';
|
||||||
export * from './simple-product';
|
export * from './simple-product';
|
||||||
export * from './grouped-product';
|
export * from './grouped-product';
|
||||||
export * from './external-product';
|
export * from './external-product';
|
||||||
|
export * from './variation';
|
||||||
|
export * from './variable-product';
|
||||||
|
|
|
@ -70,9 +70,9 @@ export class ProductDownload {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A product's attributes.
|
* Attribute base class.
|
||||||
*/
|
*/
|
||||||
export class ProductAttribute {
|
export abstract class AbstractAttribute {
|
||||||
/**
|
/**
|
||||||
* The ID of the attribute.
|
* The ID of the attribute.
|
||||||
*
|
*
|
||||||
|
@ -86,7 +86,12 @@ export class ProductAttribute {
|
||||||
* @type {string}
|
* @type {string}
|
||||||
*/
|
*/
|
||||||
public readonly name: string = '';
|
public readonly name: string = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A product's attributes.
|
||||||
|
*/
|
||||||
|
export class ProductAttribute extends AbstractAttribute {
|
||||||
/**
|
/**
|
||||||
* The sort order of the attribute.
|
* The sort order of the attribute.
|
||||||
*
|
*
|
||||||
|
@ -121,6 +126,29 @@ export class ProductAttribute {
|
||||||
* @param {Partial.<ProductAttribute>} properties The properties to set.
|
* @param {Partial.<ProductAttribute>} properties The properties to set.
|
||||||
*/
|
*/
|
||||||
public constructor( properties?: Partial< ProductAttribute > ) {
|
public constructor( properties?: Partial< ProductAttribute > ) {
|
||||||
|
super();
|
||||||
|
Object.assign( this, properties );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default attributes for variable products.
|
||||||
|
*/
|
||||||
|
export class ProductDefaultAttribute extends AbstractAttribute {
|
||||||
|
/**
|
||||||
|
* The option selected for the attribute.
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
public readonly option: string = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new product default attribute.
|
||||||
|
*
|
||||||
|
* @param {Partial.<ProductDefaultAttribute>} properties The properties to set.
|
||||||
|
*/
|
||||||
|
public constructor( properties?: Partial< ProductDefaultAttribute > ) {
|
||||||
|
super();
|
||||||
Object.assign( this, properties );
|
Object.assign( this, properties );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -220,6 +248,13 @@ export class ProductLinks {
|
||||||
*/
|
*/
|
||||||
public readonly self: readonly ProductLinkItem[] = [];
|
public readonly self: readonly ProductLinkItem[] = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The link to the parent.
|
||||||
|
*
|
||||||
|
* @type {ReadonlyArray.<ProductLinkItem>}
|
||||||
|
*/
|
||||||
|
public readonly up?: readonly ProductLinkItem[] = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new product link list.
|
* Creates a new product link list.
|
||||||
*
|
*
|
||||||
|
|
|
@ -6,14 +6,22 @@
|
||||||
*/
|
*/
|
||||||
export type StockStatus = 'instock' | 'outofstock' | 'onbackorder' | string
|
export type StockStatus = 'instock' | 'outofstock' | 'onbackorder' | string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base product properties.
|
||||||
|
*/
|
||||||
|
export type ProductDataUpdateParams = 'created' | 'postStatus'
|
||||||
|
| 'id' | 'permalink' | 'price' | 'priceHtml'
|
||||||
|
| 'description' | 'sku' | 'attributes' | 'images'
|
||||||
|
| 'regularPrice' | 'salePrice' | 'saleStart' | 'saleEnd'
|
||||||
|
| 'metaData' | 'menuOrder' | 'parentId' | 'links';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Properties common to all product types.
|
* Properties common to all product types.
|
||||||
*/
|
*/
|
||||||
export type ProductCommonUpdateParams = 'name' | 'slug' | 'created' | 'postStatus' | 'shortDescription'
|
export type ProductCommonUpdateParams = 'name' | 'slug' | 'shortDescription'
|
||||||
| 'id' | 'permalink' | 'type' | 'description' | 'sku' | 'categories' | 'tags' | 'isFeatured'
|
| 'categories' | 'tags' | 'isFeatured' | 'averageRating' | 'numRatings'
|
||||||
| 'attributes' | 'images' | 'catalogVisibility' | 'allowReviews'
|
| 'catalogVisibility' | 'allowReviews' | 'upsellIds' | 'type'
|
||||||
| 'metaData' | 'menuOrder' | 'parentId' | 'relatedIds' | 'upsellIds'
|
& ProductDataUpdateParams;
|
||||||
| 'links' | 'relatedIds' | 'menuOrder' | 'parentId';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cross sells property.
|
* Cross sells property.
|
||||||
|
@ -67,4 +75,4 @@ export type ProductDeliveryUpdateParams = 'daysToDownload' | 'downloadLimit' | '
|
||||||
/**
|
/**
|
||||||
* Properties exclusive to the Variable product type.
|
* Properties exclusive to the Variable product type.
|
||||||
*/
|
*/
|
||||||
export type ProductVariableTypeUpdateParams = 'defaultAttributes' | 'variations';
|
export type ProductVariableUpdateParams = 'defaultAttributes' | 'variations';
|
||||||
|
|
|
@ -0,0 +1,173 @@
|
||||||
|
import {
|
||||||
|
AbstractProduct,
|
||||||
|
IProductCommon,
|
||||||
|
IProductCrossSells,
|
||||||
|
IProductInventory,
|
||||||
|
IProductSalesTax,
|
||||||
|
IProductShipping,
|
||||||
|
IProductUpSells,
|
||||||
|
ProductSearchParams,
|
||||||
|
} from './abstract';
|
||||||
|
import {
|
||||||
|
ProductInventoryUpdateParams,
|
||||||
|
ProductCommonUpdateParams,
|
||||||
|
ProductDefaultAttribute,
|
||||||
|
ProductSalesTaxUpdateParams,
|
||||||
|
ProductCrossUpdateParams,
|
||||||
|
ProductShippingUpdateParams,
|
||||||
|
ProductUpSellUpdateParams,
|
||||||
|
ProductVariableUpdateParams,
|
||||||
|
StockStatus,
|
||||||
|
BackorderStatus,
|
||||||
|
Taxability,
|
||||||
|
} from './shared';
|
||||||
|
import { HTTPClient } from '../../http';
|
||||||
|
import { variableProductRESTRepository } from '../../repositories';
|
||||||
|
import {
|
||||||
|
CreatesModels,
|
||||||
|
DeletesModels,
|
||||||
|
ListsModels,
|
||||||
|
ModelRepositoryParams,
|
||||||
|
ReadsModels,
|
||||||
|
UpdatesModels,
|
||||||
|
} from '../../framework';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The parameters that variable products can update.
|
||||||
|
*/
|
||||||
|
type VariableProductUpdateParams = ProductVariableUpdateParams
|
||||||
|
& ProductCommonUpdateParams
|
||||||
|
& ProductCrossUpdateParams
|
||||||
|
& ProductInventoryUpdateParams
|
||||||
|
& ProductSalesTaxUpdateParams
|
||||||
|
& ProductShippingUpdateParams
|
||||||
|
& ProductUpSellUpdateParams;
|
||||||
|
/**
|
||||||
|
* The parameters embedded in this generic can be used in the ModelRepository in order to give
|
||||||
|
* type-safety in an incredibly granular way.
|
||||||
|
*/
|
||||||
|
export type VariableProductRepositoryParams =
|
||||||
|
ModelRepositoryParams< VariableProduct, never, ProductSearchParams, VariableProductUpdateParams >;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An interface for listing variable products using the repository.
|
||||||
|
*
|
||||||
|
* @typedef ListsVariableProducts
|
||||||
|
* @alias ListsModels.<VariableProduct>
|
||||||
|
*/
|
||||||
|
export type ListsVariableProducts = ListsModels< VariableProductRepositoryParams >;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An interface for creating variable products using the repository.
|
||||||
|
*
|
||||||
|
* @typedef CreatesVariableProducts
|
||||||
|
* @alias CreatesModels.<VariableProduct>
|
||||||
|
*/
|
||||||
|
export type CreatesVariableProducts = CreatesModels< VariableProductRepositoryParams >;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An interface for reading variable products using the repository.
|
||||||
|
*
|
||||||
|
* @typedef ReadsVariableProducts
|
||||||
|
* @alias ReadsModels.<VariableProduct>
|
||||||
|
*/
|
||||||
|
export type ReadsVariableProducts = ReadsModels< VariableProductRepositoryParams >;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An interface for updating variable products using the repository.
|
||||||
|
*
|
||||||
|
* @typedef UpdatesVariableProducts
|
||||||
|
* @alias UpdatesModels.<VariableProduct>
|
||||||
|
*/
|
||||||
|
export type UpdatesVariableProducts = UpdatesModels< VariableProductRepositoryParams >;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An interface for deleting variable products using the repository.
|
||||||
|
*
|
||||||
|
* @typedef DeletesVariableProducts
|
||||||
|
* @alias DeletesModels.<VariableProduct>
|
||||||
|
*/
|
||||||
|
export type DeletesVariableProducts = DeletesModels< VariableProductRepositoryParams >;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The base for the Variable product object.
|
||||||
|
*/
|
||||||
|
export class VariableProduct extends AbstractProduct implements
|
||||||
|
IProductCommon,
|
||||||
|
IProductCrossSells,
|
||||||
|
IProductInventory,
|
||||||
|
IProductSalesTax,
|
||||||
|
IProductShipping,
|
||||||
|
IProductUpSells {
|
||||||
|
/**
|
||||||
|
* @see ./abstracts/cross-sells.ts
|
||||||
|
*/
|
||||||
|
public readonly crossSellIds: Array<number> = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ./abstracts/upsell.ts
|
||||||
|
*/
|
||||||
|
public readonly upSellIds: Array<number> = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ./abstracts/inventory.ts
|
||||||
|
*/
|
||||||
|
public readonly onePerOrder: boolean = false;
|
||||||
|
public readonly trackInventory: boolean = false;
|
||||||
|
public readonly remainingStock: number = -1;
|
||||||
|
public readonly stockStatus: StockStatus = ''
|
||||||
|
public readonly backorderStatus: BackorderStatus = BackorderStatus.Allowed;
|
||||||
|
public readonly canBackorder: boolean = false;
|
||||||
|
public readonly isOnBackorder: boolean = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ./abstracts/sales-tax.ts
|
||||||
|
*/
|
||||||
|
public readonly taxStatus: Taxability = Taxability.ProductAndShipping;
|
||||||
|
public readonly taxClass: string = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ./abstracts/shipping.ts
|
||||||
|
*/
|
||||||
|
public readonly weight: string = '';
|
||||||
|
public readonly length: string = '';
|
||||||
|
public readonly width: string = '';
|
||||||
|
public readonly height: string = '';
|
||||||
|
public readonly requiresShipping: boolean = false;
|
||||||
|
public readonly isShippingTaxable: boolean = false;
|
||||||
|
public readonly shippingClass: string = '';
|
||||||
|
public readonly shippingClassId: number = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default product attributes.
|
||||||
|
*
|
||||||
|
* @type {ReadonlyArray.<ProductDefaultAttribute>}
|
||||||
|
*/
|
||||||
|
public readonly defaultAttributes: readonly ProductDefaultAttribute[] = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Product variations.
|
||||||
|
*
|
||||||
|
* @type {ReadonlyArray.<number>}
|
||||||
|
*/
|
||||||
|
public readonly variations: Array<number> = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new Variable product instance with the given properties
|
||||||
|
*
|
||||||
|
* @param {Object} properties The properties to set in the object.
|
||||||
|
*/
|
||||||
|
public constructor( properties?: Partial< VariableProduct > ) {
|
||||||
|
super();
|
||||||
|
Object.assign( this, properties );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a model repository configured for communicating via the REST API.
|
||||||
|
*
|
||||||
|
* @param {HTTPClient} httpClient The client for communicating via HTTP.
|
||||||
|
*/
|
||||||
|
public static restRepository( httpClient: HTTPClient ): ReturnType< typeof variableProductRESTRepository > {
|
||||||
|
return variableProductRESTRepository( httpClient );
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,187 @@
|
||||||
|
import { ModelID } from '../model';
|
||||||
|
import {
|
||||||
|
AbstractProductData,
|
||||||
|
IProductDelivery,
|
||||||
|
IProductInventory,
|
||||||
|
IProductPrice,
|
||||||
|
IProductSalesTax,
|
||||||
|
IProductShipping,
|
||||||
|
ProductSearchParams,
|
||||||
|
} from './abstract';
|
||||||
|
import {
|
||||||
|
ProductDataUpdateParams,
|
||||||
|
ProductDeliveryUpdateParams,
|
||||||
|
ProductInventoryUpdateParams,
|
||||||
|
ProductPriceUpdateParams,
|
||||||
|
ProductSalesTaxUpdateParams,
|
||||||
|
ProductShippingUpdateParams,
|
||||||
|
ProductLinks,
|
||||||
|
Taxability,
|
||||||
|
ProductDownload,
|
||||||
|
StockStatus,
|
||||||
|
BackorderStatus,
|
||||||
|
ProductDefaultAttribute,
|
||||||
|
} from './shared';
|
||||||
|
import {
|
||||||
|
CreatesChildModels,
|
||||||
|
DeletesChildModels,
|
||||||
|
ListsChildModels,
|
||||||
|
ModelRepositoryParams,
|
||||||
|
ReadsChildModels,
|
||||||
|
UpdatesChildModels,
|
||||||
|
} from '../../framework';
|
||||||
|
import { HTTPClient } from '../../http';
|
||||||
|
import { productVariationRESTRepository } from '../../repositories';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The parameters that product variations can update.
|
||||||
|
*/
|
||||||
|
type ProductVariationUpdateParams = ProductDataUpdateParams
|
||||||
|
& ProductDeliveryUpdateParams
|
||||||
|
& ProductInventoryUpdateParams
|
||||||
|
& ProductPriceUpdateParams
|
||||||
|
& ProductSalesTaxUpdateParams
|
||||||
|
& ProductShippingUpdateParams;
|
||||||
|
/**
|
||||||
|
* The parameters embedded in this generic can be used in the ModelRepository in order to give
|
||||||
|
* type-safety in an incredibly granular way.
|
||||||
|
*/
|
||||||
|
export type ProductVariationRepositoryParams =
|
||||||
|
ModelRepositoryParams< ProductVariation, ModelID, ProductSearchParams, ProductVariationUpdateParams >;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An interface for listing variable products using the repository.
|
||||||
|
*
|
||||||
|
* @typedef ListsProductVariations
|
||||||
|
* @alias ListsModels.<ProductVariation>
|
||||||
|
*/
|
||||||
|
export type ListsProductVariations = ListsChildModels< ProductVariationRepositoryParams >;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An interface for creating variable products using the repository.
|
||||||
|
*
|
||||||
|
* @typedef CreatesProductVariations
|
||||||
|
* @alias CreatesModels.<ProductVariation>
|
||||||
|
*/
|
||||||
|
export type CreatesProductVariations = CreatesChildModels< ProductVariationRepositoryParams >;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An interface for reading variable products using the repository.
|
||||||
|
*
|
||||||
|
* @typedef ReadsProductVariations
|
||||||
|
* @alias ReadsModels.<ProductVariation>
|
||||||
|
*/
|
||||||
|
export type ReadsProductVariations = ReadsChildModels< ProductVariationRepositoryParams >;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An interface for updating variable products using the repository.
|
||||||
|
*
|
||||||
|
* @typedef UpdatesProductVariations
|
||||||
|
* @alias UpdatesModels.<ProductVariation>
|
||||||
|
*/
|
||||||
|
export type UpdatesProductVariations = UpdatesChildModels< ProductVariationRepositoryParams >;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An interface for deleting variable products using the repository.
|
||||||
|
*
|
||||||
|
* @typedef DeletesProductVariations
|
||||||
|
* @alias DeletesModels.<ProductVariation>
|
||||||
|
*/
|
||||||
|
export type DeletesProductVariations = DeletesChildModels< ProductVariationRepositoryParams >;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The base for the product variation object.
|
||||||
|
*/
|
||||||
|
export class ProductVariation extends AbstractProductData implements
|
||||||
|
IProductDelivery,
|
||||||
|
IProductInventory,
|
||||||
|
IProductPrice,
|
||||||
|
IProductSalesTax,
|
||||||
|
IProductShipping {
|
||||||
|
/**
|
||||||
|
* @see ./abstracts/delivery.ts
|
||||||
|
*/
|
||||||
|
public readonly isVirtual: boolean = false;
|
||||||
|
public readonly isDownloadable: boolean = false;
|
||||||
|
public readonly downloads: readonly ProductDownload[] = [];
|
||||||
|
public readonly downloadLimit: number = -1;
|
||||||
|
public readonly daysToDownload: number = -1;
|
||||||
|
public readonly purchaseNote: string = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ./abstracts/inventory.ts
|
||||||
|
*/
|
||||||
|
public readonly onePerOrder: boolean = false;
|
||||||
|
public readonly trackInventory: boolean = false;
|
||||||
|
public readonly remainingStock: number = -1;
|
||||||
|
public readonly stockStatus: StockStatus = ''
|
||||||
|
public readonly backorderStatus: BackorderStatus = BackorderStatus.Allowed;
|
||||||
|
public readonly canBackorder: boolean = false;
|
||||||
|
public readonly isOnBackorder: boolean = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ./abstracts/price.ts
|
||||||
|
*/
|
||||||
|
public readonly price: string = '';
|
||||||
|
public readonly priceHtml: string = '';
|
||||||
|
public readonly regularPrice: string = '';
|
||||||
|
public readonly onSale: boolean = false;
|
||||||
|
public readonly salePrice: string = '';
|
||||||
|
public readonly saleStart: Date | null = null;
|
||||||
|
public readonly saleEnd: Date | null = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ./abstracts/sales-tax.ts
|
||||||
|
*/
|
||||||
|
public readonly taxStatus: Taxability = Taxability.ProductAndShipping;
|
||||||
|
public readonly taxClass: string = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ./abstracts/shipping.ts
|
||||||
|
*/
|
||||||
|
public readonly weight: string = '';
|
||||||
|
public readonly length: string = '';
|
||||||
|
public readonly width: string = '';
|
||||||
|
public readonly height: string = '';
|
||||||
|
public readonly requiresShipping: boolean = false;
|
||||||
|
public readonly isShippingTaxable: boolean = false;
|
||||||
|
public readonly shippingClass: string = '';
|
||||||
|
public readonly shippingClassId: number = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The variation links.
|
||||||
|
*
|
||||||
|
* @type {ReadonlyArray.<ProductLinks>}
|
||||||
|
*/
|
||||||
|
public readonly links: ProductLinks = {
|
||||||
|
collection: [ { href: '' } ],
|
||||||
|
self: [ { href: '' } ],
|
||||||
|
up: [ { href: '' } ],
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The attributes for the variation.
|
||||||
|
*
|
||||||
|
* @type {ReadonlyArray.<ProductDefaultAttribute>}
|
||||||
|
*/
|
||||||
|
public readonly attributes: readonly ProductDefaultAttribute[] = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new product variation instance with the given properties
|
||||||
|
*
|
||||||
|
* @param {Object} properties The properties to set in the object.
|
||||||
|
*/
|
||||||
|
public constructor( properties?: Partial< ProductVariation > ) {
|
||||||
|
super();
|
||||||
|
Object.assign( this, properties );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a model repository configured for communicating via the REST API.
|
||||||
|
*
|
||||||
|
* @param {HTTPClient} httpClient The client for communicating via HTTP.
|
||||||
|
*/
|
||||||
|
public static restRepository( httpClient: HTTPClient ): ReturnType< typeof productVariationRESTRepository > {
|
||||||
|
return productVariationRESTRepository( httpClient );
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,10 +2,14 @@ import { createProductTransformer } from './shared';
|
||||||
import { groupedProductRESTRepository } from './grouped-product';
|
import { groupedProductRESTRepository } from './grouped-product';
|
||||||
import { simpleProductRESTRepository } from './simple-product';
|
import { simpleProductRESTRepository } from './simple-product';
|
||||||
import { externalProductRESTRepository } from './external-product';
|
import { externalProductRESTRepository } from './external-product';
|
||||||
|
import { variableProductRESTRepository } from './variable-product';
|
||||||
|
import { productVariationRESTRepository } from './variation';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
createProductTransformer,
|
createProductTransformer,
|
||||||
externalProductRESTRepository,
|
externalProductRESTRepository,
|
||||||
groupedProductRESTRepository,
|
groupedProductRESTRepository,
|
||||||
simpleProductRESTRepository,
|
simpleProductRESTRepository,
|
||||||
|
variableProductRESTRepository,
|
||||||
|
productVariationRESTRepository,
|
||||||
};
|
};
|
||||||
|
|
|
@ -12,6 +12,7 @@ import {
|
||||||
} from '../../../framework';
|
} from '../../../framework';
|
||||||
import {
|
import {
|
||||||
AbstractProduct,
|
AbstractProduct,
|
||||||
|
AbstractProductData,
|
||||||
IProductCrossSells,
|
IProductCrossSells,
|
||||||
IProductDelivery,
|
IProductDelivery,
|
||||||
IProductExternal,
|
IProductExternal,
|
||||||
|
@ -26,6 +27,7 @@ import {
|
||||||
ProductDownload,
|
ProductDownload,
|
||||||
ProductImage,
|
ProductImage,
|
||||||
ProductTerm,
|
ProductTerm,
|
||||||
|
VariableProduct,
|
||||||
} from '../../../models';
|
} from '../../../models';
|
||||||
import { createMetaDataTransformer } from '../shared';
|
import { createMetaDataTransformer } from '../shared';
|
||||||
|
|
||||||
|
@ -110,6 +112,55 @@ function createProductDownloadTransformer(): ModelTransformer< ProductDownload >
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a transformer for the base product property data.
|
||||||
|
*
|
||||||
|
* @param {Array.<ModelTransformation>} transformations Optional transformers to add to the transformer.
|
||||||
|
* @return {ModelTransformer} The created transformer.
|
||||||
|
*/
|
||||||
|
export function createProductDataTransformer< T extends AbstractProductData >(
|
||||||
|
transformations?: ModelTransformation[],
|
||||||
|
): ModelTransformer< T > {
|
||||||
|
if ( ! transformations ) {
|
||||||
|
transformations = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
transformations.push(
|
||||||
|
new IgnorePropertyTransformation(
|
||||||
|
[
|
||||||
|
'date_created',
|
||||||
|
'date_modified',
|
||||||
|
],
|
||||||
|
),
|
||||||
|
new ModelTransformerTransformation( 'images', ProductImage, createProductImageTransformer() ),
|
||||||
|
new ModelTransformerTransformation( 'metaData', MetaData, createMetaDataTransformer() ),
|
||||||
|
new PropertyTypeTransformation(
|
||||||
|
{
|
||||||
|
created: PropertyType.Date,
|
||||||
|
modified: PropertyType.Date,
|
||||||
|
isPurchasable: PropertyType.Boolean,
|
||||||
|
parentId: PropertyType.Integer,
|
||||||
|
menuOrder: PropertyType.Integer,
|
||||||
|
permalink: PropertyType.String,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
new KeyChangeTransformation< AbstractProductData >(
|
||||||
|
{
|
||||||
|
created: 'date_created_gmt',
|
||||||
|
modified: 'date_modified_gmt',
|
||||||
|
postStatus: 'status',
|
||||||
|
isPurchasable: 'purchasable',
|
||||||
|
metaData: 'meta_data',
|
||||||
|
parentId: 'parent_id',
|
||||||
|
menuOrder: 'menu_order',
|
||||||
|
links: '_links',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
return new ModelTransformer( transformations );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a transformer for the shared properties of all products.
|
* Creates a transformer for the shared properties of all products.
|
||||||
*
|
*
|
||||||
|
@ -127,56 +178,34 @@ export function createProductTransformer< T extends AbstractProduct >(
|
||||||
|
|
||||||
transformations.push(
|
transformations.push(
|
||||||
new AddPropertyTransformation( {}, { type } ),
|
new AddPropertyTransformation( {}, { type } ),
|
||||||
new IgnorePropertyTransformation(
|
|
||||||
[
|
|
||||||
'date_created',
|
|
||||||
'date_modified',
|
|
||||||
],
|
|
||||||
),
|
|
||||||
new ModelTransformerTransformation( 'categories', ProductTerm, createProductTermTransformer() ),
|
new ModelTransformerTransformation( 'categories', ProductTerm, createProductTermTransformer() ),
|
||||||
new ModelTransformerTransformation( 'tags', ProductTerm, createProductTermTransformer() ),
|
new ModelTransformerTransformation( 'tags', ProductTerm, createProductTermTransformer() ),
|
||||||
new ModelTransformerTransformation( 'attributes', ProductAttribute, createProductAttributeTransformer() ),
|
new ModelTransformerTransformation( 'attributes', ProductAttribute, createProductAttributeTransformer() ),
|
||||||
new ModelTransformerTransformation( 'images', ProductImage, createProductImageTransformer() ),
|
|
||||||
new ModelTransformerTransformation( 'metaData', MetaData, createMetaDataTransformer() ),
|
|
||||||
new PropertyTypeTransformation(
|
new PropertyTypeTransformation(
|
||||||
{
|
{
|
||||||
created: PropertyType.Date,
|
|
||||||
modified: PropertyType.Date,
|
|
||||||
isPurchasable: PropertyType.Boolean,
|
|
||||||
isFeatured: PropertyType.Boolean,
|
isFeatured: PropertyType.Boolean,
|
||||||
allowReviews: PropertyType.Boolean,
|
allowReviews: PropertyType.Boolean,
|
||||||
averageRating: PropertyType.Integer,
|
averageRating: PropertyType.Integer,
|
||||||
numRatings: PropertyType.Integer,
|
numRatings: PropertyType.Integer,
|
||||||
totalSales: PropertyType.Integer,
|
totalSales: PropertyType.Integer,
|
||||||
parentId: PropertyType.Integer,
|
|
||||||
menuOrder: PropertyType.Integer,
|
|
||||||
permalink: PropertyType.String,
|
|
||||||
relatedIds: PropertyType.Integer,
|
relatedIds: PropertyType.Integer,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
new KeyChangeTransformation< AbstractProduct >(
|
new KeyChangeTransformation< AbstractProduct >(
|
||||||
{
|
{
|
||||||
created: 'date_created_gmt',
|
|
||||||
modified: 'date_modified_gmt',
|
|
||||||
postStatus: 'status',
|
|
||||||
shortDescription: 'short_description',
|
shortDescription: 'short_description',
|
||||||
isPurchasable: 'purchasable',
|
|
||||||
isFeatured: 'featured',
|
isFeatured: 'featured',
|
||||||
catalogVisibility: 'catalog_visibility',
|
catalogVisibility: 'catalog_visibility',
|
||||||
allowReviews: 'reviews_allowed',
|
allowReviews: 'reviews_allowed',
|
||||||
averageRating: 'average_rating',
|
averageRating: 'average_rating',
|
||||||
numRatings: 'rating_count',
|
numRatings: 'rating_count',
|
||||||
metaData: 'meta_data',
|
|
||||||
totalSales: 'total_sales',
|
totalSales: 'total_sales',
|
||||||
parentId: 'parent_id',
|
|
||||||
menuOrder: 'menu_order',
|
|
||||||
relatedIds: 'related_ids',
|
relatedIds: 'related_ids',
|
||||||
links: '_links',
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
return new ModelTransformer( transformations );
|
return createProductDataTransformer< T >( transformations );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -412,6 +441,29 @@ export function createProductShippingTransformation(): ModelTransformation[] {
|
||||||
return transformations;
|
return transformations;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Variable product specific properties transformations
|
||||||
|
*/
|
||||||
|
export function createProductVariableTransformation(): ModelTransformation[] {
|
||||||
|
const transformations = [
|
||||||
|
new PropertyTypeTransformation(
|
||||||
|
{
|
||||||
|
id: PropertyType.Integer,
|
||||||
|
name: PropertyType.String,
|
||||||
|
option: PropertyType.String,
|
||||||
|
variations: PropertyType.Integer,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
new KeyChangeTransformation< VariableProduct >(
|
||||||
|
{
|
||||||
|
defaultAttributes: 'default_attributes',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
return transformations;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transformer for the properties unique to the external product type.
|
* Transformer for the properties unique to the external product type.
|
||||||
*/
|
*/
|
||||||
|
@ -433,4 +485,3 @@ export function createProductExternalTransformation(): ModelTransformation[] {
|
||||||
|
|
||||||
return transformations;
|
return transformations;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
import { HTTPClient } from '../../../http';
|
||||||
|
import { ModelRepository } from '../../../framework';
|
||||||
|
import {
|
||||||
|
VariableProduct,
|
||||||
|
CreatesVariableProducts,
|
||||||
|
DeletesVariableProducts,
|
||||||
|
ListsVariableProducts,
|
||||||
|
ReadsVariableProducts,
|
||||||
|
VariableProductRepositoryParams,
|
||||||
|
UpdatesVariableProducts,
|
||||||
|
baseProductURL,
|
||||||
|
buildProductURL,
|
||||||
|
} from '../../../models';
|
||||||
|
import {
|
||||||
|
createProductTransformer,
|
||||||
|
createProductCrossSellsTransformation,
|
||||||
|
createProductInventoryTransformation,
|
||||||
|
createProductSalesTaxTransformation,
|
||||||
|
createProductShippingTransformation,
|
||||||
|
createProductUpSellsTransformation,
|
||||||
|
createProductVariableTransformation,
|
||||||
|
} from './shared';
|
||||||
|
import {
|
||||||
|
restCreate,
|
||||||
|
restDelete,
|
||||||
|
restList,
|
||||||
|
restRead,
|
||||||
|
restUpdate,
|
||||||
|
} from '../shared';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new ModelRepository instance for interacting with models via the REST API.
|
||||||
|
*
|
||||||
|
* @param {HTTPClient} httpClient The HTTP client for the REST requests to be made using.
|
||||||
|
* @return {
|
||||||
|
* ListsVariableProducts|
|
||||||
|
* CreatesVariableProducts|
|
||||||
|
* ReadsVariableProducts|
|
||||||
|
* UpdatesVariableProducts|
|
||||||
|
* DeletesVariableProducts
|
||||||
|
* } The created repository.
|
||||||
|
*/
|
||||||
|
export function variableProductRESTRepository( httpClient: HTTPClient ): ListsVariableProducts
|
||||||
|
& CreatesVariableProducts
|
||||||
|
& ReadsVariableProducts
|
||||||
|
& UpdatesVariableProducts
|
||||||
|
& DeletesVariableProducts {
|
||||||
|
const crossSells = createProductCrossSellsTransformation();
|
||||||
|
const inventory = createProductInventoryTransformation();
|
||||||
|
const salesTax = createProductSalesTaxTransformation();
|
||||||
|
const shipping = createProductShippingTransformation();
|
||||||
|
const upsells = createProductUpSellsTransformation();
|
||||||
|
const variable = createProductVariableTransformation();
|
||||||
|
const transformations = [
|
||||||
|
...crossSells,
|
||||||
|
...inventory,
|
||||||
|
...salesTax,
|
||||||
|
...shipping,
|
||||||
|
...upsells,
|
||||||
|
...variable,
|
||||||
|
];
|
||||||
|
|
||||||
|
const transformer = createProductTransformer<VariableProduct>( 'variable', transformations );
|
||||||
|
|
||||||
|
return new ModelRepository(
|
||||||
|
restList< VariableProductRepositoryParams >( baseProductURL, VariableProduct, httpClient, transformer ),
|
||||||
|
restCreate< VariableProductRepositoryParams >( baseProductURL, VariableProduct, httpClient, transformer ),
|
||||||
|
restRead< VariableProductRepositoryParams >( buildProductURL, VariableProduct, httpClient, transformer ),
|
||||||
|
restUpdate< VariableProductRepositoryParams >( buildProductURL, VariableProduct, httpClient, transformer ),
|
||||||
|
restDelete< VariableProductRepositoryParams >( buildProductURL, httpClient ),
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
import { HTTPClient } from '../../../http';
|
||||||
|
import { ModelRepository } from '../../../framework';
|
||||||
|
import {
|
||||||
|
ProductVariation,
|
||||||
|
ModelID,
|
||||||
|
CreatesProductVariations,
|
||||||
|
DeletesProductVariations,
|
||||||
|
ListsProductVariations,
|
||||||
|
ReadsProductVariations,
|
||||||
|
ProductVariationRepositoryParams,
|
||||||
|
UpdatesProductVariations,
|
||||||
|
buildProductURL,
|
||||||
|
} from '../../../models';
|
||||||
|
import {
|
||||||
|
createProductDataTransformer,
|
||||||
|
createProductDeliveryTransformation,
|
||||||
|
createProductInventoryTransformation,
|
||||||
|
createProductPriceTransformation,
|
||||||
|
createProductSalesTaxTransformation,
|
||||||
|
createProductShippingTransformation,
|
||||||
|
} from './shared';
|
||||||
|
import {
|
||||||
|
restCreateChild,
|
||||||
|
restDeleteChild,
|
||||||
|
restListChild,
|
||||||
|
restReadChild,
|
||||||
|
restUpdateChild,
|
||||||
|
} from '../shared';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new ModelRepository instance for interacting with models via the REST API.
|
||||||
|
*
|
||||||
|
* @param {HTTPClient} httpClient The HTTP client for the REST requests to be made using.
|
||||||
|
* @return {
|
||||||
|
* ListsProductVariations|
|
||||||
|
* CreatesProductVariations|
|
||||||
|
* ReadsProductVariations|
|
||||||
|
* UpdatesProductVariations|
|
||||||
|
* DeletesProductVariations
|
||||||
|
* } The created repository.
|
||||||
|
*/
|
||||||
|
export function productVariationRESTRepository( httpClient: HTTPClient ): ListsProductVariations
|
||||||
|
& CreatesProductVariations
|
||||||
|
& ReadsProductVariations
|
||||||
|
& UpdatesProductVariations
|
||||||
|
& DeletesProductVariations {
|
||||||
|
const buildURL = ( parent: ModelID ) => buildProductURL( parent ) + '/variations/';
|
||||||
|
const buildChildURL = ( parent: ModelID, id: ModelID ) => buildURL( parent ) + id;
|
||||||
|
const buildDeleteURL = ( parent: ModelID, id: ModelID ) => buildChildURL( parent, id ) + '?force=true';
|
||||||
|
|
||||||
|
const delivery = createProductDeliveryTransformation();
|
||||||
|
const inventory = createProductInventoryTransformation();
|
||||||
|
const price = createProductPriceTransformation();
|
||||||
|
const salesTax = createProductSalesTaxTransformation();
|
||||||
|
const shipping = createProductShippingTransformation();
|
||||||
|
const transformations = [
|
||||||
|
...delivery,
|
||||||
|
...inventory,
|
||||||
|
...price,
|
||||||
|
...salesTax,
|
||||||
|
...shipping,
|
||||||
|
];
|
||||||
|
|
||||||
|
const transformer = createProductDataTransformer<ProductVariation>( transformations );
|
||||||
|
|
||||||
|
return new ModelRepository(
|
||||||
|
restListChild< ProductVariationRepositoryParams >( buildURL, ProductVariation, httpClient, transformer ),
|
||||||
|
restCreateChild< ProductVariationRepositoryParams >( buildURL, ProductVariation, httpClient, transformer ),
|
||||||
|
restReadChild< ProductVariationRepositoryParams >( buildChildURL, ProductVariation, httpClient, transformer ),
|
||||||
|
restUpdateChild< ProductVariationRepositoryParams >( buildChildURL, ProductVariation, httpClient, transformer ),
|
||||||
|
restDeleteChild< ProductVariationRepositoryParams >( buildDeleteURL, httpClient ),
|
||||||
|
);
|
||||||
|
}
|
|
@ -13,6 +13,7 @@ import {
|
||||||
UpdateChildFn,
|
UpdateChildFn,
|
||||||
DeleteChildFn,
|
DeleteChildFn,
|
||||||
CreateFn,
|
CreateFn,
|
||||||
|
CreateChildFn,
|
||||||
ModelTransformer,
|
ModelTransformer,
|
||||||
IgnorePropertyTransformation,
|
IgnorePropertyTransformation,
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
@ -138,6 +139,31 @@ export function restCreate< T extends ModelRepositoryParams >(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a callback for creating child models using the REST API.
|
||||||
|
*
|
||||||
|
* @param {Function} buildURL A callback to build the URL. (This is passed the properties for the new model.)
|
||||||
|
* @param {Function} modelClass The model we're listing.
|
||||||
|
* @param {HTTPClient} httpClient The HTTP client to use for the request.
|
||||||
|
* @param {ModelTransformer} transformer The transformer to use for the response data.
|
||||||
|
* @return {CreateChildFn} The callback for the repository.
|
||||||
|
*/
|
||||||
|
export function restCreateChild< T extends ModelRepositoryParams >(
|
||||||
|
buildURL: ( parent: ParentID< T >, properties: Partial< ModelClass< T > > ) => string,
|
||||||
|
modelClass: ModelConstructor< ModelClass< T > >,
|
||||||
|
httpClient: HTTPClient,
|
||||||
|
transformer: ModelTransformer< ModelClass< T > >,
|
||||||
|
): CreateChildFn< T > {
|
||||||
|
return async ( parent, properties ) => {
|
||||||
|
const response = await httpClient.post(
|
||||||
|
buildURL( parent, properties ),
|
||||||
|
transformer.fromModel( properties ),
|
||||||
|
);
|
||||||
|
|
||||||
|
return Promise.resolve( transformer.toModel( modelClass, response.data ) );
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a callback for reading models using the REST API.
|
* Creates a callback for reading models using the REST API.
|
||||||
*
|
*
|
||||||
|
|
|
@ -15,8 +15,98 @@
|
||||||
"name": "Simple product"
|
"name": "Simple product"
|
||||||
},
|
},
|
||||||
"variable": {
|
"variable": {
|
||||||
"name": "Variable Product with Three Variations"
|
"name": "Variable Product with Three Attributes",
|
||||||
|
"defaultAttributes": [
|
||||||
|
{
|
||||||
|
"id": 0,
|
||||||
|
"name": "Size",
|
||||||
|
"option": "Medium"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 0,
|
||||||
|
"name": "Colour",
|
||||||
|
"option": "Blue"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"attributes": [
|
||||||
|
{
|
||||||
|
"id": 0,
|
||||||
|
"name": "Colour",
|
||||||
|
"isVisibleOnProductPage": true,
|
||||||
|
"isForVariations": true,
|
||||||
|
"options": [
|
||||||
|
"Red",
|
||||||
|
"Green",
|
||||||
|
"Blue"
|
||||||
|
],
|
||||||
|
"sortOrder": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 0,
|
||||||
|
"name": "Size",
|
||||||
|
"isVisibleOnProductPage": true,
|
||||||
|
"isForVariations": true,
|
||||||
|
"options": [
|
||||||
|
"Small",
|
||||||
|
"Medium",
|
||||||
|
"Large"
|
||||||
|
],
|
||||||
|
"sortOrder": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 0,
|
||||||
|
"name": "Logo",
|
||||||
|
"isVisibleOnProductPage": true,
|
||||||
|
"isForVariations": true,
|
||||||
|
"options": [
|
||||||
|
"Woo",
|
||||||
|
"WordPress"
|
||||||
|
],
|
||||||
|
"sortOrder": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
|
"variations": [
|
||||||
|
{
|
||||||
|
"regularPrice": "19.99",
|
||||||
|
"attributes": [
|
||||||
|
{
|
||||||
|
"name": "Size",
|
||||||
|
"option": "Large"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Colour",
|
||||||
|
"option": "Red"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"regularPrice": "18.99",
|
||||||
|
"attributes": [
|
||||||
|
{
|
||||||
|
"name": "Size",
|
||||||
|
"option": "Medium"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Colour",
|
||||||
|
"option": "Green"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"regularPrice": "17.99",
|
||||||
|
"attributes": [
|
||||||
|
{
|
||||||
|
"name": "Size",
|
||||||
|
"option": "Small"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Colour",
|
||||||
|
"option": "Blue"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
"grouped": {
|
"grouped": {
|
||||||
"name": "Grouped Product with Three Children",
|
"name": "Grouped Product with Three Children",
|
||||||
"groupedProducts": [
|
"groupedProducts": [
|
||||||
|
|
|
@ -1,5 +1,12 @@
|
||||||
# Unreleased
|
# Unreleased
|
||||||
|
|
||||||
|
## Added
|
||||||
|
|
||||||
|
- api package test for variable products and product variations
|
||||||
|
- api package test for grouped products
|
||||||
|
- api package test for external products
|
||||||
|
- api package test for coupons
|
||||||
|
|
||||||
# 0.1.1
|
# 0.1.1
|
||||||
|
|
||||||
## Added
|
## Added
|
||||||
|
|
|
@ -57,7 +57,7 @@ const runGroupedProductAPITest = () => {
|
||||||
expect( product ).toEqual( expect.objectContaining( baseGroupedProduct ) );
|
expect( product ).toEqual( expect.objectContaining( baseGroupedProduct ) );
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can retrieve a raw external product', async () => {
|
it('can retrieve a raw grouped product', async () => {
|
||||||
let rawProperties = {
|
let rawProperties = {
|
||||||
id: product.id,
|
id: product.id,
|
||||||
grouped_products: baseGroupedProduct.groupedProducts,
|
grouped_products: baseGroupedProduct.groupedProducts,
|
||||||
|
|
|
@ -0,0 +1,92 @@
|
||||||
|
/* eslint-disable jest/no-export, jest/no-disabled-tests */
|
||||||
|
/**
|
||||||
|
* Internal dependencies
|
||||||
|
*/
|
||||||
|
const { HTTPClientFactory, VariableProduct, ProductVariation } = require( '@woocommerce/api' );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* External dependencies
|
||||||
|
*/
|
||||||
|
const config = require( 'config' );
|
||||||
|
const {
|
||||||
|
it,
|
||||||
|
describe,
|
||||||
|
beforeAll,
|
||||||
|
} = require( '@jest/globals' );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a variable product and retrieve via the API.
|
||||||
|
*/
|
||||||
|
const runVariableProductAPITest = () => {
|
||||||
|
describe('REST API > Variable Product', () => {
|
||||||
|
let client;
|
||||||
|
let defaultVariableProduct;
|
||||||
|
let defaultVariations;
|
||||||
|
let baseVariableProduct;
|
||||||
|
let product;
|
||||||
|
let 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');
|
||||||
|
|
||||||
|
client = HTTPClientFactory.build(url)
|
||||||
|
.withBasicAuth(admin.username, admin.password)
|
||||||
|
.withIndexPermalinks()
|
||||||
|
.create();
|
||||||
|
});
|
||||||
|
|
||||||
|
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));
|
||||||
|
});
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
baseVariableProduct = {
|
||||||
|
id: product.id,
|
||||||
|
...defaultVariableProduct,
|
||||||
|
variations,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
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));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can retrieve transformed product variations', async () => {
|
||||||
|
// Read variations via the repository.
|
||||||
|
const transformed = await variationRepository.list(product.id);
|
||||||
|
expect(transformed).toHaveLength(defaultVariations.length);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can delete a variation', async () => {
|
||||||
|
const variationId = baseVariableProduct.variations.pop();
|
||||||
|
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();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = runVariableProductAPITest;
|
|
@ -36,6 +36,7 @@ const runMerchantOrdersCustomerPaymentPage = require( './merchant/wp-admin-order
|
||||||
const runExternalProductAPITest = require( './api/external-product.test' );
|
const runExternalProductAPITest = require( './api/external-product.test' );
|
||||||
const runCouponApiTest = require( './api/coupon.test' );
|
const runCouponApiTest = require( './api/coupon.test' );
|
||||||
const runGroupedProductAPITest = require( './api/grouped-product.test' );
|
const runGroupedProductAPITest = require( './api/grouped-product.test' );
|
||||||
|
const runVariableProductAPITest = require( './api/variable-product.test' );
|
||||||
|
|
||||||
const runSetupOnboardingTests = () => {
|
const runSetupOnboardingTests = () => {
|
||||||
runActivationTest();
|
runActivationTest();
|
||||||
|
@ -73,6 +74,7 @@ const runMerchantTests = () => {
|
||||||
|
|
||||||
const runApiTests = () => {
|
const runApiTests = () => {
|
||||||
runExternalProductAPITest();
|
runExternalProductAPITest();
|
||||||
|
runVariableProductAPITest();
|
||||||
runCouponApiTest();
|
runCouponApiTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,6 +86,7 @@ module.exports = {
|
||||||
runSetupOnboardingTests,
|
runSetupOnboardingTests,
|
||||||
runExternalProductAPITest,
|
runExternalProductAPITest,
|
||||||
runGroupedProductAPITest,
|
runGroupedProductAPITest,
|
||||||
|
runVariableProductAPITest,
|
||||||
runCouponApiTest,
|
runCouponApiTest,
|
||||||
runCartApplyCouponsTest,
|
runCartApplyCouponsTest,
|
||||||
runCartPageTest,
|
runCartPageTest,
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
/*
|
||||||
|
* Internal dependencies
|
||||||
|
*/
|
||||||
|
const { runVariableProductAPITest } = require( '@woocommerce/e2e-core-tests' );
|
||||||
|
|
||||||
|
runVariableProductAPITest();
|
Loading…
Reference in New Issue