Fix and consolidate linting across the monorepo (#35012)

This commit is contained in:
Sam Seay 2022-10-12 15:05:01 +13:00 committed by GitHub
parent 7aca607899
commit 55b49cb50a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
113 changed files with 3637 additions and 1936 deletions

View File

@ -7,7 +7,7 @@ concurrency:
jobs:
lint-test-js:
name: Test JS
name: Lint and Test JS
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v3
@ -15,5 +15,8 @@ jobs:
- name: Setup WooCommerce Monorepo
uses: ./.github/actions/setup-woocommerce-monorepo
- name: Lint
run: pnpm run -r --filter='woocommerce/client/admin...' --filter='!@woocommerce/e2e*' --filter='!@woocommerce/api' --color lint
- name: Test
run: pnpm run test --filter='woocommerce/client/admin...' --filter='!@woocommerce/e2e*' --filter='!@woocommerce/api' --color

View File

@ -9,6 +9,15 @@
"semverRange": "^",
"workspace": true,
"versionGroups": [
{
"dependencies": [
"@typescript-eslint/**"
],
"pinVersion": "latest",
"packages": [
"**"
]
},
{
"dependencies": [
"react",

View File

@ -29,7 +29,7 @@
"@types/node": "14.14.33",
"@woocommerce/eslint-plugin": "workspace:*",
"@wordpress/data": "^6.15.0",
"@wordpress/eslint-plugin": "^11.0.0",
"@wordpress/eslint-plugin": "^11.1.0",
"@wordpress/prettier-config": "^1.1.1",
"babel-loader": "^8.2.3",
"chalk": "^4.1.2",

View File

@ -435,7 +435,7 @@ export const testSubscriptionsInclusion = () => {
} );
describe( 'A US store will see the Subscriptions inclusion', () => {
const profileWizard = new OnboardingWizard( page );
const login = new Login( page );
new Login( page );
beforeAll( async () => {
await resetWooCommerceState();

View File

@ -2,6 +2,8 @@
* External dependencies
*/
import { afterAll, beforeAll, describe, it } from '@jest/globals';
// TODO fix the type for this module.
// eslint-disable-next-line
import { createSimpleProduct, withRestApi } from '@woocommerce/e2e-utils';
/**

View File

@ -52,7 +52,9 @@ const verifyPublishAndTrash = async (
if ( button === '.order_actions li .save_order' ) {
await expect( page ).toMatchElement(
'#select2-order_status-container',
{ text: 'Processing' }
{
text: 'Processing',
}
);
await expect( page ).toMatchElement(
'#woocommerce-order-notes .note_content',

View File

@ -3,4 +3,5 @@ module.exports = {
rules: {
'jsdoc/check-tag-names': 'off',
},
root: true,
};

View File

@ -195,6 +195,7 @@ const createSampleData = async () => {
} );
// Create an order with all possible numerical fields (taxes, fees, refunds, etc).
// eslint-disable-next-line
const { body: taxSetting } = await getRequest(
'settings/general/woocommerce_calc_taxes'
);
@ -202,6 +203,7 @@ const createSampleData = async () => {
value: 'yes',
} );
// eslint-disable-next-line
const { body: taxRate } = await postRequest( 'taxes', {
country: '*',
state: '*',
@ -209,15 +211,18 @@ const createSampleData = async () => {
city: '*',
rate: '5.5000',
name: 'Tax',
// eslint-disable-next-line
rate: '5.5',
shipping: true,
} );
// eslint-disable-next-line
const { body: coupon } = await postRequest( 'coupons', {
code: 'save5',
amount: '5',
} );
// eslint-disable-next-line
const { body: order4 } = await ordersApi.create.order( {
...orderBaseData,
line_items: [

View File

@ -273,8 +273,7 @@ const createSampleSimpleProducts = async ( categories, attributes, tags ) => {
{
id: '2579cf07-8b08-4c25-888a-b6258dd1f035',
name: 'Single',
file:
'https://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2017/08/single.jpg',
file: 'https://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2017/08/single.jpg',
},
],
download_limit: 1,
@ -336,14 +335,12 @@ const createSampleSimpleProducts = async ( categories, attributes, tags ) => {
{
id: 'cc10249f-1de2-44d4-93d3-9f88ae629f76',
name: 'Single 1',
file:
'https://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2017/08/single.jpg',
file: 'https://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2017/08/single.jpg',
},
{
id: 'aea8ef69-ccdc-4d83-8e21-3c395ebb9411',
name: 'Single 2',
file:
'https://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2017/08/album.jpg',
file: 'https://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2017/08/album.jpg',
},
],
download_limit: 1,

View File

@ -6,9 +6,9 @@
* - `flat_rate`
* - `local_pickup`
*
* @param methodId
* @param cost
* @return shipping method object that can serve as a request payload for adding a shipping method to a shipping zone.
* @param {string} methodId
* @param {string} cost
* @return {Object} shipping method object that can serve as a request payload for adding a shipping method to a shipping zone.
*/
const getShippingMethodExample = ( methodId, cost ) => {
const shippingMethodExample = {

View File

@ -13,7 +13,7 @@ const shippingZone = {
/**
* Constructs a default shipping zone object.
*
* @return default shipping zone
* @return {Object} default shipping zone
*/
const getShippingZoneExample = () => {
return shippingZone;

View File

@ -29,6 +29,7 @@ const taxRatesApi = {
method: 'GET',
path: 'taxes/<id>',
responseCode: 200,
// eslint-disable-next-line no-undef
taxRate: async ( taxRateId ) => taxes( `coupons/${ taxRateId }` ),
},
listAll: {

View File

@ -47,9 +47,11 @@ const variationsApi = {
path: 'products/<product_id>/variations/<id>',
responseCode: 200,
payload: getVariationExample(),
// eslint-disable-next-line
variation: async ( productId, variationId, variationDetails ) =>
putRequest(
`products/${ productId }/variations/${ variationId }`,
// eslint-disable-next-line
taxRateDetails
),
},
@ -75,6 +77,7 @@ const variationsApi = {
payload: shared.getBatchPayloadExample( getVariationExample() ),
variations: async ( batchUpdatePayload ) =>
postRequest(
// eslint-disable-next-line
`products/${ productId }/variations/${ variationId }`,
batchUpdatePayload
),

View File

@ -167,6 +167,7 @@ describe( 'Coupons API tests', () => {
expect( deletedCouponIds ).toEqual( couponIdsToDelete );
// Verify that the 2 deleted coupons cannot be retrieved.
// eslint-disable-next-line
for ( const couponId of couponIdsToDelete ) {
const { status } = await couponsApi.retrieve.coupon( couponId );
@ -202,6 +203,7 @@ describe( 'Coupons API tests', () => {
const actualCreatedCoupons = response.body.create;
// Save their coupon ID's
// eslint-disable-next-line
for ( const coupon of allCoupons ) {
const { id } = actualCreatedCoupons.find(
( { code } ) => coupon.code === code

View File

@ -199,6 +199,7 @@ describe( 'Orders API test', () => {
expectedLineTaxTotal,
] of expectedTaxTotalsPerLineItem ) {
const { total_tax: actualLineTaxTotal } = body.line_items.find(
// eslint-disable-next-line
( { product_id } ) => product_id === product.id
);

View File

@ -162,6 +162,7 @@ describe( 'Orders API tests', () => {
per_page: 10,
} );
expect( allOrders.statusCode ).toEqual( 200 );
// eslint-disable-next-line
const allOrdersIds = allOrders.body.map( ( order ) => order.id );
expect( allOrdersIds ).toHaveLength( ORDERS_COUNT );
@ -286,6 +287,7 @@ describe( 'Orders API tests', () => {
} );
expect( result1.statusCode ).toEqual( 200 );
expect( result1.body ).toHaveLength( 5 );
// eslint-disable-next-line
result1.body.forEach( ( order ) =>
expect( order ).toEqual(
expect.objectContaining( {
@ -299,6 +301,7 @@ describe( 'Orders API tests', () => {
} );
expect( result2.statusCode ).toEqual( 200 );
expect( result2.body ).toHaveLength( 3 );
// eslint-disable-next-line
result2.body.forEach( ( order ) =>
expect( order ).toEqual(
expect.objectContaining( {
@ -317,6 +320,7 @@ describe( 'Orders API tests', () => {
} );
expect( result1.statusCode ).toEqual( 200 );
expect( result1.body ).toHaveLength( 2 );
// eslint-disable-next-line
result1.body.forEach( ( order ) =>
expect( order ).toEqual(
expect.objectContaining( {
@ -340,6 +344,7 @@ describe( 'Orders API tests', () => {
);
};
// eslint-disable-next-line
const verifyOrderPrecision = ( order, dp ) => {
expectPrecisionToMatch( order.discount_total, dp );
expectPrecisionToMatch( order.discount_tax, dp );
@ -413,6 +418,7 @@ describe( 'Orders API tests', () => {
} );
expect( result1.statusCode ).toEqual( 200 );
expect( result1.body ).toHaveLength( 7 );
// eslint-disable-next-line
result1.body.forEach( ( order ) =>
expect( order.billing.email ).toContain( 'example.com' )
);
@ -439,6 +445,7 @@ describe( 'Orders API tests', () => {
} );
expect( result4.statusCode ).toEqual( 200 );
expect( result4.body ).toHaveLength( 5 );
// eslint-disable-next-line
result4.body.forEach( ( order ) =>
expect( order.billing.last_name ).toEqual( 'Doe' )
);
@ -449,6 +456,7 @@ describe( 'Orders API tests', () => {
} );
expect( result5.statusCode ).toEqual( 200 );
expect( result5.body ).toHaveLength( 2 );
// eslint-disable-next-line
result5.body.forEach( ( order ) =>
expect( order ).toEqual(
expect.objectContaining( {
@ -472,7 +480,9 @@ describe( 'Orders API tests', () => {
// Verify all dates are in descending order.
let lastDate = Date.now();
// eslint-disable-next-line
result.body.forEach( ( { date_created } ) => {
// eslint-disable-next-line
const created = Date.parse( date_created + '.000Z' );
expect( lastDate ).toBeGreaterThanOrEqual( created );
lastDate = created;
@ -488,7 +498,9 @@ describe( 'Orders API tests', () => {
// Verify all dates are in ascending order.
let lastDate = 0;
// eslint-disable-next-line
result.body.forEach( ( { date_created } ) => {
// eslint-disable-next-line
const created = Date.parse( date_created + '.000Z' );
expect( created ).toBeGreaterThanOrEqual( lastDate );
lastDate = created;

View File

@ -101,9 +101,8 @@ describe( 'Products API tests: CRUD', () => {
expect( body.id ).toEqual( productId );
// Verify that the product can no longer be retrieved.
const {
status: retrieveDeletedProductStatus,
} = await productsApi.retrieve.product( productId );
const { status: retrieveDeletedProductStatus } =
await productsApi.retrieve.product( productId );
expect( retrieveDeletedProductStatus ).toEqual( 404 );
} );
@ -156,6 +155,7 @@ describe( 'Products API tests: CRUD', () => {
// Verify that the regular price of each product was updated
for ( let i = 0; i < actualUpdatedProducts.length; i++ ) {
// eslint-disable-next-line
const { id, regular_price } = actualUpdatedProducts[ i ];
expect( id ).toEqual( expectedProducts[ i ].id );
@ -186,6 +186,7 @@ describe( 'Products API tests: CRUD', () => {
// Verify that the deleted product ID's can no longer be retrieved
for ( const id of idsToDelete ) {
// eslint-disable-next-line
const { status } = await productsApi.retrieve.product( id );
expect( status ).toEqual( 404 );

View File

@ -28,10 +28,8 @@ describe( 'Shipping methods API tests', () => {
async ( methodTitle, methodId, cost ) => {
const shippingMethod = getShippingMethodExample( methodId, cost );
const {
status,
body,
} = await shippingMethodsApi.create.shippingMethod(
const { status, body } =
await shippingMethodsApi.create.shippingMethod(
shippingZoneId,
shippingMethod
);

View File

@ -12,9 +12,11 @@ const { BASE_URL, USER_KEY, USER_SECRET, USE_INDEX_PERMALINKS } = process.env;
// Set up our empty collection
if ( typeof USER_KEY === 'undefined' ) {
// eslint-disable-next-line
console.log( 'No USER_KEY was defined.' );
}
if ( typeof USER_SECRET === 'undefined' ) {
// eslint-disable-next-line
console.log( 'No USER_SECRET was defined.' );
}
@ -41,6 +43,7 @@ const postmanCollection = new Collection( {
// Get the API url
if ( typeof BASE_URL === 'undefined' ) {
// eslint-disable-next-line
console.log( 'No BASE_URL was defined.' );
}
@ -62,6 +65,7 @@ postmanCollection.variables.add( {
// Get the API request data
const resources = require( '../../endpoints' );
// eslint-disable-next-line
resourceKeys = Object.keys( resources );
// Add the requests to folders in the collection
@ -108,8 +112,10 @@ fs.writeFile(
JSON.stringify( collectionJSON ),
( err ) => {
if ( err ) {
// eslint-disable-next-line
console.log( err );
}
// eslint-disable-next-line
console.log( 'File saved!' );
}
);

View File

@ -1,5 +1,6 @@
require( 'dotenv' ).config();
const { USER_KEY, USER_SECRET } = process.env;
// eslint-disable-next-line
const request = require( 'supertest' )( API_PATH );
/**
@ -7,7 +8,7 @@ const request = require( 'supertest' )( API_PATH );
*
* @param {string} requestPath The path of the request.
* @param {Object} queryString Optional. An object of one or more `key: value` query string parameters.
* @return {Response}
* @return {Response} The response object.
*/
const getRequest = async ( requestPath, queryString = {} ) => {
const response = await request
@ -23,7 +24,7 @@ const getRequest = async ( requestPath, queryString = {} ) => {
*
* @param {string} requestPath The path of the request.
* @param {Object} requestBody The body of the request to submit.
* @return {Response}
* @return {Response} The response object.
*/
const postRequest = async ( requestPath, requestBody ) => {
const response = await request
@ -39,7 +40,7 @@ const postRequest = async ( requestPath, requestBody ) => {
*
* @param {string} requestPath The path of the request.
* @param {Object} requestBody The body of the request to submit.
* @return {Request}
* @return {Request} The request object.
*/
const putRequest = async ( requestPath, requestBody ) => {
const response = await request
@ -55,7 +56,7 @@ const putRequest = async ( requestPath, requestBody ) => {
*
* @param {string} requestPath The path of the request.
* @param {boolean} deletePermanently Flag to permanently delete the resource.
* @return {Response}
* @return {Response} The response object.
*/
const deleteRequest = async ( requestPath, deletePermanently = false ) => {
const requestBody = deletePermanently ? { force: true } : {};

View File

@ -6,3 +6,4 @@ jest.config.js
package.json
package-lock.json
tsconfig.json
__tests__

View File

@ -1,32 +1,12 @@
module.exports = {
parser: '@typescript-eslint/parser',
env: {
'jest/globals': true,
},
ignorePatterns: [ 'dist/', 'node_modules/' ],
extends: [ 'plugin:@woocommerce/eslint-plugin/recommended' ],
plugins: [ 'jest' ],
root: true,
rules: {
'no-unused-vars': 'off',
'no-dupe-class-members': 'off',
'no-useless-constructor': 'off',
'@typescript-eslint/no-useless-constructor': 2,
// These warning rules are stop gaps for eslint issues that need to be fixed later.
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-use-before-define': 'off',
'@typescript-eslint/ban-ts-comment': 'off',
'@typescript-eslint/no-unused-vars': 'off',
},
plugins: [ '@typescript-eslint/eslint-plugin' ],
extends: [ 'plugin:@wordpress/eslint-plugin/recommended-with-formatting' ],
overrides: [
{
files: [ '**/*.js', '**/*.ts' ],
settings: {
jsdoc: {
mode: 'typescript',
},
},
},
{
files: [ '**/*.spec.ts', '**/*.test.ts' ],
rules: {
'no-console': 'off',
},
},
],
};

View File

@ -53,6 +53,7 @@
"@types/node": "13.13.5",
"@typescript-eslint/eslint-plugin": "^5.3.1",
"@typescript-eslint/parser": "^5.3.1",
"@woocommerce/eslint-plugin": "workspace:*",
"axios-mock-adapter": "^1.20.0",
"eslint": "^8.2.0",
"jest": "^27",

View File

@ -1,10 +1,13 @@
/**
* Internal dependencies
*/
import { Model } from '../models';
/**
* A dummy model that can be used in test files.
*/
export class DummyModel extends Model {
public name: string = '';
public name = '';
public constructor( partial?: Partial< DummyModel > ) {
super();

View File

@ -1,3 +1,6 @@
/**
* Internal dependencies
*/
import { Model, ModelID } from '../models';
/**
@ -352,7 +355,8 @@ implements
UpdatesModels< T >,
UpdatesChildModels< T >,
DeletesModels< T >,
DeletesChildModels< T > {
DeletesChildModels< T >
{
/**
* The hook used to list models.
*
@ -460,7 +464,7 @@ implements
}
return ( this.listHook as ListChildFn< T > )(
( paramsOrParent as unknown ) as ParentID< T >,
paramsOrParent as unknown as ParentID< T >,
params
);
}
@ -493,7 +497,7 @@ implements
}
return ( this.createHook as CreateChildFn< T > )(
( propertiesOrParent as unknown ) as ParentID< T >,
propertiesOrParent as unknown as ParentID< T >,
properties as Partial< ModelClass< T > >
);
}
@ -520,7 +524,7 @@ implements
}
return ( this.readHook as ReadChildFn< T > )(
( idOrParent as unknown ) as ParentID< T >,
idOrParent as unknown as ParentID< T >,
childID
);
}
@ -547,14 +551,14 @@ implements
if ( properties === undefined ) {
return ( this.updateHook as UpdateFn< T > )(
idOrParent as ModelID,
( propertiesOrChildID as unknown ) as UpdateParams< T >
propertiesOrChildID as unknown as UpdateParams< T >
);
}
return ( this.updateHook as UpdateChildFn< T > )(
( idOrParent as unknown ) as ParentID< T >,
idOrParent as unknown as ParentID< T >,
propertiesOrChildID as ModelID,
( properties as unknown ) as UpdateParams< T >
properties as unknown as UpdateParams< T >
);
}
@ -580,7 +584,7 @@ implements
}
return ( this.deleteHook as DeleteChildFn< T > )(
( idOrParent as unknown ) as ParentID< T >,
idOrParent as unknown as ParentID< T >,
childID
);
}

View File

@ -1,3 +1,6 @@
/**
* Internal dependencies
*/
import { Model, ModelConstructor } from '../models';
/**

View File

@ -1,3 +1,6 @@
/**
* Internal dependencies
*/
import { ModelTransformation, TransformationOrder } from '../model-transformer';
/**

View File

@ -1,3 +1,6 @@
/**
* Internal dependencies
*/
import { ModelTransformation } from '../model-transformer';
/**

View File

@ -1,3 +1,6 @@
/**
* Internal dependencies
*/
import { ModelTransformation, TransformationOrder } from '../model-transformer';
export class IgnorePropertyTransformation implements ModelTransformation {

View File

@ -1,3 +1,6 @@
/**
* Internal dependencies
*/
import { ModelTransformation, TransformationOrder } from '../model-transformer';
import { Model } from '../../models';
@ -15,7 +18,8 @@ type KeyChanges< T extends Model > = {
* other transformations to prevent the changed key from causing problems.
*/
export class KeyChangeTransformation< T extends Model >
implements ModelTransformation {
implements ModelTransformation
{
/**
* Ensure that this transformation always happens at the very end since it changes the keys
* in the transformed object.

View File

@ -1,3 +1,6 @@
/**
* Internal dependencies
*/
import {
ModelTransformation,
ModelTransformer,
@ -11,7 +14,8 @@ import { Model, ModelConstructor } from '../../models';
* @template T
*/
export class ModelTransformerTransformation< T extends Model >
implements ModelTransformation {
implements ModelTransformation
{
public readonly fromModelOrder = TransformationOrder.Normal;
/**

View File

@ -1,3 +1,6 @@
/**
* Internal dependencies
*/
import { ModelTransformation, TransformationOrder } from '../model-transformer';
/**
@ -134,6 +137,7 @@ export class PropertyTypeTransformation implements ModelTransformation {
case PropertyType.String:
return String( value );
case PropertyType.Integer:
// eslint-disable-next-line
return parseInt( value );
case PropertyType.Float:
return parseFloat( value );

View File

@ -1,5 +1,12 @@
import { HTTPClient, HTTPResponse } from '../http-client';
/**
* External dependencies
*/
import axios, { AxiosInstance, AxiosRequestConfig } from 'axios';
/**
* Internal dependencies
*/
import { HTTPClient, HTTPResponse } from '../http-client';
import { AxiosInterceptor } from './axios-interceptor';
import { AxiosResponseInterceptor } from './axios-response-interceptor';

View File

@ -1,3 +1,6 @@
/**
* External dependencies
*/
import { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';
/**

View File

@ -1,6 +1,13 @@
/**
* External dependencies
*/
import type { AxiosRequestConfig } from 'axios';
import * as createHmac from 'create-hmac';
import * as OAuth from 'oauth-1.0a';
/**
* Internal dependencies
*/
import { AxiosInterceptor } from './axios-interceptor';
import { buildURLWithParams } from './utils';
@ -56,6 +63,7 @@ export class AxiosOAuthInterceptor extends AxiosInterceptor {
request.headers.Authorization = this.oauth.toHeader(
this.oauth.authorize( {
url,
// eslint-disable-next-line
method: request.method!,
} )
).Authorization;

View File

@ -1,4 +1,11 @@
/**
* External dependencies
*/
import { AxiosResponse } from 'axios';
/**
* Internal dependencies
*/
import { AxiosInterceptor } from './axios-interceptor';
import { HTTPResponse } from '../http-client';

View File

@ -1,5 +1,12 @@
import { AxiosInterceptor } from './axios-interceptor';
/**
* External dependencies
*/
import { AxiosRequestConfig } from 'axios';
/**
* Internal dependencies
*/
import { AxiosInterceptor } from './axios-interceptor';
import { buildURL } from './utils';
/**

View File

@ -1,3 +1,6 @@
/**
* External dependencies
*/
import { AxiosRequestConfig } from 'axios';
// @ts-ignore

View File

@ -1,6 +1,13 @@
/**
* External dependencies
*/
import { AxiosRequestConfig } from 'axios';
/**
* Internal dependencies
*/
import { HTTPClient } from './http-client';
import { AxiosClient, AxiosOAuthInterceptor } from './axios';
import { AxiosRequestConfig } from 'axios';
import { AxiosInterceptor } from './axios/axios-interceptor';
import { AxiosURLToQueryInterceptor } from './axios/axios-url-to-query-interceptor';

View File

@ -1,3 +1,6 @@
/**
* Internal dependencies
*/
import { Model } from '../model';
import { HTTPClient } from '../../http';
import { couponRESTRepository } from '../../repositories';
@ -126,7 +129,7 @@ export class Coupon extends Model {
*
* @type {number}
*/
public readonly usageCount: Number = 0;
public readonly usageCount: number = 0;
/**
* Flags if the coupon can only be used on its own and not combined with other coupons.
@ -154,21 +157,21 @@ export class Coupon extends Model {
*
* @type {number}
*/
public readonly usageLimit: Number = -1;
public readonly usageLimit: number = -1;
/**
* How many times the coupon can be used per customer.
*
* @type {number}
*/
public readonly usageLimitPerUser: Number = -1;
public readonly usageLimitPerUser: number = -1;
/**
* Max number of items in the cart the coupon can be applied to.
*
* @type {number}
*/
public readonly limitUsageToXItems: Number = -1;
public readonly limitUsageToXItems: number = -1;
/**
* Flags if the free shipping option requires a coupon. This coupon will enable free shipping.

View File

@ -1,3 +1,6 @@
/**
* Internal dependencies
*/
import { HTTPClient } from '../../http';
import { orderRESTRepository } from '../../repositories';
import {

View File

@ -1,3 +1,6 @@
/**
* Internal dependencies
*/
import { MetaData } from '../../shared-types';
import { Model, ModelID } from '../../model';
import { TaxStatus } from './types';

View File

@ -1,3 +1,6 @@
/**
* Internal dependencies
*/
import { AbstractProductData } from './data';
import { ModelID } from '../../model';
import { CatalogVisibility, ProductTerm, ProductAttribute } from '../shared';
@ -153,4 +156,4 @@ export abstract class AbstractProduct extends AbstractProductData {
};
}
export interface IProductCommon extends AbstractProduct {}
export type IProductCommon = AbstractProduct;

View File

@ -1,3 +1,6 @@
/**
* Internal dependencies
*/
import { Model } from '../../model';
/**
@ -12,4 +15,4 @@ abstract class AbstractProductCrossSells extends Model {
public readonly crossSellIds: Array< number > = [];
}
export interface IProductCrossSells extends AbstractProductCrossSells {}
export type IProductCrossSells = AbstractProductCrossSells;

View File

@ -1,3 +1,6 @@
/**
* Internal dependencies
*/
import { Model } from '../../model';
import { MetaData, PostStatus, ObjectLinks } from '../../shared-types';
import { ProductImage } from '../shared';

View File

@ -1,3 +1,6 @@
/**
* Internal dependencies
*/
import { Model } from '../../model';
import { ProductDownload } from '../shared';
@ -48,4 +51,4 @@ abstract class AbstractProductDelivery extends Model {
public readonly purchaseNote: string = '';
}
export interface IProductDelivery extends AbstractProductDelivery {}
export type IProductDelivery = AbstractProductDelivery;

View File

@ -1,3 +1,6 @@
/**
* Internal dependencies
*/
import { Model } from '../../model';
/**
@ -19,4 +22,4 @@ abstract class AbstractProductExternal extends Model {
public readonly externalUrl: string = '';
}
export interface IProductExternal extends AbstractProductExternal {}
export type IProductExternal = AbstractProductExternal;

View File

@ -1,3 +1,6 @@
/**
* Internal dependencies
*/
import { Model } from '../../model';
/**
@ -12,4 +15,4 @@ abstract class AbstractProductGrouped extends Model {
public readonly groupedProducts: Array< number > = [];
}
export interface IProductGrouped extends AbstractProductGrouped {}
export type IProductGrouped = AbstractProductGrouped;

View File

@ -1,3 +1,6 @@
/**
* Internal dependencies
*/
import { Model } from '../../model';
import { BackorderStatus, StockStatus } from '../shared';
@ -62,4 +65,4 @@ abstract class AbstractProductInventory extends Model {
public readonly lowStockThreshold: number = -1;
}
export interface IProductInventory extends AbstractProductInventory {}
export type IProductInventory = AbstractProductInventory;

View File

@ -1,3 +1,6 @@
/**
* Internal dependencies
*/
import { Model } from '../../model';
/**
@ -54,4 +57,4 @@ abstract class AbstractProductPrice extends Model {
public readonly saleEnd: Date | null = null;
}
export interface IProductPrice extends AbstractProductPrice {}
export type IProductPrice = AbstractProductPrice;

View File

@ -1,3 +1,6 @@
/**
* Internal dependencies
*/
import { Model } from '../../model';
import { Taxability } from '../shared';
@ -20,4 +23,4 @@ abstract class AbstractProductSalesTax extends Model {
public readonly taxClass: string = '';
}
export interface IProductSalesTax extends AbstractProductSalesTax {}
export type IProductSalesTax = AbstractProductSalesTax;

View File

@ -1,3 +1,6 @@
/**
* Internal dependencies
*/
import { Model } from '../../model';
/**
@ -61,4 +64,4 @@ abstract class AbstractProductShipping extends Model {
public readonly shippingClassId: number = 0;
}
export interface IProductShipping extends AbstractProductShipping {}
export type IProductShipping = AbstractProductShipping;

View File

@ -1,3 +1,6 @@
/**
* Internal dependencies
*/
import { Model } from '../../model';
/**
@ -12,4 +15,4 @@ abstract class AbstractProductUpSells extends Model {
public readonly upSellIds: Array< number > = [];
}
export interface IProductUpSells extends AbstractProductUpSells {}
export type IProductUpSells = AbstractProductUpSells;

View File

@ -1,3 +1,6 @@
/**
* Internal dependencies
*/
import {
AbstractProduct,
IProductCommon,
@ -51,7 +54,8 @@ export type ExternalProductRepositoryParams = ModelRepositoryParams<
* @typedef ListsExternalProducts
* @alias ListsModels.<ExternalProduct>
*/
export type ListsExternalProducts = ListsModels< ExternalProductRepositoryParams >;
export type ListsExternalProducts =
ListsModels< ExternalProductRepositoryParams >;
/**
* An interface for external simple products using the repository.
@ -59,7 +63,8 @@ export type ListsExternalProducts = ListsModels< ExternalProductRepositoryParams
* @typedef CreatesExternalProducts
* @alias CreatesModels.<ExternalProduct>
*/
export type CreatesExternalProducts = CreatesModels< ExternalProductRepositoryParams >;
export type CreatesExternalProducts =
CreatesModels< ExternalProductRepositoryParams >;
/**
* An interface for reading external products using the repository.
@ -67,7 +72,8 @@ export type CreatesExternalProducts = CreatesModels< ExternalProductRepositoryPa
* @typedef ReadsExternalProducts
* @alias ReadsModels.<ExternalProduct>
*/
export type ReadsExternalProducts = ReadsModels< ExternalProductRepositoryParams >;
export type ReadsExternalProducts =
ReadsModels< ExternalProductRepositoryParams >;
/**
* An interface for updating external products using the repository.
@ -75,7 +81,8 @@ export type ReadsExternalProducts = ReadsModels< ExternalProductRepositoryParams
* @typedef UpdatesExternalProducts
* @alias UpdatesModels.<ExternalProduct>
*/
export type UpdatesExternalProducts = UpdatesModels< ExternalProductRepositoryParams >;
export type UpdatesExternalProducts =
UpdatesModels< ExternalProductRepositoryParams >;
/**
* An interface for deleting external products using the repository.
@ -83,7 +90,8 @@ export type UpdatesExternalProducts = UpdatesModels< ExternalProductRepositoryPa
* @typedef DeletesExternalProducts
* @alias DeletesModels.<ExternalProduct>
*/
export type DeletesExternalProducts = DeletesModels< ExternalProductRepositoryParams >;
export type DeletesExternalProducts =
DeletesModels< ExternalProductRepositoryParams >;
/**
* The base for the external product object.
@ -95,7 +103,8 @@ export class ExternalProduct
IProductExternal,
IProductPrice,
IProductSalesTax,
IProductUpSells {
IProductUpSells
{
/**
* @see ./abstracts/external.ts
*/

View File

@ -1,3 +1,6 @@
/**
* Internal dependencies
*/
import {
AbstractProduct,
IProductCommon,
@ -44,7 +47,8 @@ export type GroupedProductRepositoryParams = ModelRepositoryParams<
* @typedef ListsGroupedProducts
* @alias ListsModels.<GroupedProduct>
*/
export type ListsGroupedProducts = ListsModels< GroupedProductRepositoryParams >;
export type ListsGroupedProducts =
ListsModels< GroupedProductRepositoryParams >;
/**
* An interface for creating Grouped products using the repository.
@ -52,7 +56,8 @@ export type ListsGroupedProducts = ListsModels< GroupedProductRepositoryParams >
* @typedef CreatesGroupedProducts
* @alias CreatesModels.<GroupedProduct>
*/
export type CreatesGroupedProducts = CreatesModels< GroupedProductRepositoryParams >;
export type CreatesGroupedProducts =
CreatesModels< GroupedProductRepositoryParams >;
/**
* An interface for reading Grouped products using the repository.
@ -60,7 +65,8 @@ export type CreatesGroupedProducts = CreatesModels< GroupedProductRepositoryPara
* @typedef ReadsGroupedProducts
* @alias ReadsModels.<GroupedProduct>
*/
export type ReadsGroupedProducts = ReadsModels< GroupedProductRepositoryParams >;
export type ReadsGroupedProducts =
ReadsModels< GroupedProductRepositoryParams >;
/**
* An interface for updating Grouped products using the repository.
@ -68,7 +74,8 @@ export type ReadsGroupedProducts = ReadsModels< GroupedProductRepositoryParams >
* @typedef UpdatesGroupedProducts
* @alias UpdatesModels.<GroupedProduct>
*/
export type UpdatesGroupedProducts = UpdatesModels< GroupedProductRepositoryParams >;
export type UpdatesGroupedProducts =
UpdatesModels< GroupedProductRepositoryParams >;
/**
* An interface for deleting Grouped products using the repository.
@ -76,14 +83,16 @@ export type UpdatesGroupedProducts = UpdatesModels< GroupedProductRepositoryPara
* @typedef DeletesGroupedProducts
* @alias DeletesModels.<GroupedProduct>
*/
export type DeletesGroupedProducts = DeletesModels< GroupedProductRepositoryParams >;
export type DeletesGroupedProducts =
DeletesModels< GroupedProductRepositoryParams >;
/**
* The base for the Grouped product object.
*/
export class GroupedProduct
extends AbstractProduct
implements IProductCommon, IProductGrouped, IProductUpSells {
implements IProductCommon, IProductGrouped, IProductUpSells
{
/**
* @see ./abstracts/grouped.ts
*/

View File

@ -1,3 +1,6 @@
/**
* Internal dependencies
*/
import {
AbstractProduct,
IProductCommon,
@ -71,7 +74,8 @@ export type ListsSimpleProducts = ListsModels< SimpleProductRepositoryParams >;
* @typedef CreatesSimpleProducts
* @alias CreatesModels.<SimpleProduct>
*/
export type CreatesSimpleProducts = CreatesModels< SimpleProductRepositoryParams >;
export type CreatesSimpleProducts =
CreatesModels< SimpleProductRepositoryParams >;
/**
* An interface for reading simple products using the repository.
@ -87,7 +91,8 @@ export type ReadsSimpleProducts = ReadsModels< SimpleProductRepositoryParams >;
* @typedef UpdatesSimpleProducts
* @alias UpdatesModels.<SimpleProduct>
*/
export type UpdatesSimpleProducts = UpdatesModels< SimpleProductRepositoryParams >;
export type UpdatesSimpleProducts =
UpdatesModels< SimpleProductRepositoryParams >;
/**
* An interface for deleting simple products using the repository.
@ -95,7 +100,8 @@ export type UpdatesSimpleProducts = UpdatesModels< SimpleProductRepositoryParams
* @typedef DeletesSimpleProducts
* @alias DeletesModels.<SimpleProduct>
*/
export type DeletesSimpleProducts = DeletesModels< SimpleProductRepositoryParams >;
export type DeletesSimpleProducts =
DeletesModels< SimpleProductRepositoryParams >;
/**
* The base for the simple product object.
@ -110,7 +116,8 @@ export class SimpleProduct
IProductPrice,
IProductSalesTax,
IProductShipping,
IProductUpSells {
IProductUpSells
{
/**
* @see ./abstracts/cross-sells.ts
*/

View File

@ -1,3 +1,6 @@
/**
* Internal dependencies
*/
import {
AbstractProduct,
IProductCommon,
@ -59,7 +62,8 @@ export type VariableProductRepositoryParams = ModelRepositoryParams<
* @typedef ListsVariableProducts
* @alias ListsModels.<VariableProduct>
*/
export type ListsVariableProducts = ListsModels< VariableProductRepositoryParams >;
export type ListsVariableProducts =
ListsModels< VariableProductRepositoryParams >;
/**
* An interface for creating variable products using the repository.
@ -67,7 +71,8 @@ export type ListsVariableProducts = ListsModels< VariableProductRepositoryParams
* @typedef CreatesVariableProducts
* @alias CreatesModels.<VariableProduct>
*/
export type CreatesVariableProducts = CreatesModels< VariableProductRepositoryParams >;
export type CreatesVariableProducts =
CreatesModels< VariableProductRepositoryParams >;
/**
* An interface for reading variable products using the repository.
@ -75,7 +80,8 @@ export type CreatesVariableProducts = CreatesModels< VariableProductRepositoryPa
* @typedef ReadsVariableProducts
* @alias ReadsModels.<VariableProduct>
*/
export type ReadsVariableProducts = ReadsModels< VariableProductRepositoryParams >;
export type ReadsVariableProducts =
ReadsModels< VariableProductRepositoryParams >;
/**
* An interface for updating variable products using the repository.
@ -83,7 +89,8 @@ export type ReadsVariableProducts = ReadsModels< VariableProductRepositoryParams
* @typedef UpdatesVariableProducts
* @alias UpdatesModels.<VariableProduct>
*/
export type UpdatesVariableProducts = UpdatesModels< VariableProductRepositoryParams >;
export type UpdatesVariableProducts =
UpdatesModels< VariableProductRepositoryParams >;
/**
* An interface for deleting variable products using the repository.
@ -91,7 +98,8 @@ export type UpdatesVariableProducts = UpdatesModels< VariableProductRepositoryPa
* @typedef DeletesVariableProducts
* @alias DeletesModels.<VariableProduct>
*/
export type DeletesVariableProducts = DeletesModels< VariableProductRepositoryParams >;
export type DeletesVariableProducts =
DeletesModels< VariableProductRepositoryParams >;
/**
* The base for the Variable product object.
@ -104,7 +112,8 @@ export class VariableProduct
IProductInventory,
IProductSalesTax,
IProductShipping,
IProductUpSells {
IProductUpSells
{
/**
* @see ./abstracts/cross-sells.ts
*/

View File

@ -1,3 +1,6 @@
/**
* Internal dependencies
*/
import { ModelID } from '../model';
import {
AbstractProductData,
@ -59,7 +62,8 @@ export type ProductVariationRepositoryParams = ModelRepositoryParams<
* @typedef ListsProductVariations
* @alias ListsModels.<ProductVariation>
*/
export type ListsProductVariations = ListsChildModels< ProductVariationRepositoryParams >;
export type ListsProductVariations =
ListsChildModels< ProductVariationRepositoryParams >;
/**
* An interface for creating variable products using the repository.
@ -67,7 +71,8 @@ export type ListsProductVariations = ListsChildModels< ProductVariationRepositor
* @typedef CreatesProductVariations
* @alias CreatesModels.<ProductVariation>
*/
export type CreatesProductVariations = CreatesChildModels< ProductVariationRepositoryParams >;
export type CreatesProductVariations =
CreatesChildModels< ProductVariationRepositoryParams >;
/**
* An interface for reading variable products using the repository.
@ -75,7 +80,8 @@ export type CreatesProductVariations = CreatesChildModels< ProductVariationRepos
* @typedef ReadsProductVariations
* @alias ReadsModels.<ProductVariation>
*/
export type ReadsProductVariations = ReadsChildModels< ProductVariationRepositoryParams >;
export type ReadsProductVariations =
ReadsChildModels< ProductVariationRepositoryParams >;
/**
* An interface for updating variable products using the repository.
@ -83,7 +89,8 @@ export type ReadsProductVariations = ReadsChildModels< ProductVariationRepositor
* @typedef UpdatesProductVariations
* @alias UpdatesModels.<ProductVariation>
*/
export type UpdatesProductVariations = UpdatesChildModels< ProductVariationRepositoryParams >;
export type UpdatesProductVariations =
UpdatesChildModels< ProductVariationRepositoryParams >;
/**
* An interface for deleting variable products using the repository.
@ -91,7 +98,8 @@ export type UpdatesProductVariations = UpdatesChildModels< ProductVariationRepos
* @typedef DeletesProductVariations
* @alias DeletesModels.<ProductVariation>
*/
export type DeletesProductVariations = DeletesChildModels< ProductVariationRepositoryParams >;
export type DeletesProductVariations =
DeletesChildModels< ProductVariationRepositoryParams >;
/**
* The base for the product variation object.
@ -103,7 +111,8 @@ export class ProductVariation
IProductInventory,
IProductPrice,
IProductSalesTax,
IProductShipping {
IProductShipping
{
/**
* @see ./abstracts/delivery.ts
*/

View File

@ -1,3 +1,6 @@
/**
* Internal dependencies
*/
import { Model, ModelID } from '../model';
import { HTTPClient } from '../../http';
import { settingGroupRESTRepository } from '../../repositories';
@ -7,7 +10,8 @@ import { ListsModels, ModelRepositoryParams } from '../../framework';
* 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 SettingGroupRepositoryParams = ModelRepositoryParams< SettingGroup >;
export type SettingGroupRepositoryParams =
ModelRepositoryParams< SettingGroup >;
/**
* An interface for listing setting groups using the repository.

View File

@ -1,3 +1,6 @@
/**
* Internal dependencies
*/
import { Model, ModelID } from '../model';
import { HTTPClient } from '../../http';
import { settingRESTRepository } from '../../repositories';

View File

@ -1,3 +1,6 @@
/**
* Internal dependencies
*/
import { Model } from './model';
/**

View File

@ -1,3 +1,6 @@
/**
* Internal dependencies
*/
import { HTTPClient } from '../../../http';
import { ModelRepository } from '../../../framework';
import {

View File

@ -1,3 +1,6 @@
/**
* Internal dependencies
*/
import couponRESTRepository from './coupon';
export { couponRESTRepository };

View File

@ -1,3 +1,6 @@
/**
* Internal dependencies
*/
import {
IgnorePropertyTransformation,
KeyChangeTransformation,
@ -5,7 +8,6 @@ import {
PropertyType,
PropertyTypeTransformation,
} from '../../../framework';
import { Coupon } from '../../../models';
/**

View File

@ -1,3 +1,6 @@
/**
* Internal dependencies
*/
import orderRESTRepository from './order';
export { orderRESTRepository };

View File

@ -1,3 +1,6 @@
/**
* Internal dependencies
*/
import { HTTPClient } from '../../../http';
import { ModelRepository } from '../../../framework';
import {

View File

@ -1,3 +1,6 @@
/**
* Internal dependencies
*/
import {
IgnorePropertyTransformation,
KeyChangeTransformation,

View File

@ -1,3 +1,6 @@
/**
* Internal dependencies
*/
import { HTTPClient } from '../../../http';
import { ModelRepository } from '../../../framework';
import {

View File

@ -1,3 +1,6 @@
/**
* Internal dependencies
*/
import { HTTPClient } from '../../../http';
import { ModelRepository } from '../../../framework';
import {

View File

@ -1,3 +1,6 @@
/**
* Internal dependencies
*/
import { createProductTransformer } from './shared';
import { groupedProductRESTRepository } from './grouped-product';
import { simpleProductRESTRepository } from './simple-product';

View File

@ -1,3 +1,6 @@
/**
* Internal dependencies
*/
import {
AddPropertyTransformation,
CustomTransformation,

View File

@ -1,3 +1,6 @@
/**
* Internal dependencies
*/
import { HTTPClient } from '../../../http';
import { ModelRepository } from '../../../framework';
import {

View File

@ -1,3 +1,6 @@
/**
* Internal dependencies
*/
import { HTTPClient } from '../../../http';
import { ModelRepository } from '../../../framework';
import {

View File

@ -1,3 +1,6 @@
/**
* Internal dependencies
*/
import { HTTPClient } from '../../../http';
import { ModelRepository } from '../../../framework';
import {
@ -66,9 +69,8 @@ export function productVariationRESTRepository(
...shipping,
];
const transformer = createProductDataTransformer< ProductVariation >(
transformations
);
const transformer =
createProductDataTransformer< ProductVariation >( transformations );
return new ModelRepository(
restListChild< ProductVariationRepositoryParams >(

View File

@ -1,3 +1,6 @@
/**
* Internal dependencies
*/
import settingRESTRepository from './setting';
import settingGroupRESTRepository from './setting-group';

View File

@ -1,3 +1,6 @@
/**
* Internal dependencies
*/
import { HTTPClient } from '../../../http';
import {
ModelRepository,

View File

@ -1,3 +1,6 @@
/**
* Internal dependencies
*/
import { HTTPClient } from '../../../http';
import {
ModelRepository,

View File

@ -1,4 +1,8 @@
/**
* Internal dependencies
*/
import { HTTPClient } from '../../http';
import { ModelID, MetaData, ModelConstructor } from '../../models';
import {
ListFn,
ModelRepositoryParams,
@ -20,7 +24,6 @@ import {
// @ts-ignore
ModelParentID,
} from '../../framework';
import { ModelID, MetaData, ModelConstructor } from '../../models';
/**
* Creates a new transformer for metadata models.

View File

@ -1,3 +1,6 @@
/**
* Internal dependencies
*/
import { Setting, UpdatesSettings } from '../models';
/**

View File

@ -0,0 +1,3 @@
// Import the default config file and expose it in the project root.
// Useful for editor integrations.
module.exports = require( '@wordpress/prettier-config' );

View File

@ -1,3 +1,11 @@
module.exports = {
extends: ['plugin:@woocommerce/eslint-plugin/recommended'],
plugins: ['jest'],
root: true,
env: {
'jest/globals': true,
},
globals: {
page: true,
},
};

View File

@ -41,7 +41,8 @@
"@wordpress/babel-plugin-import-jsx-pragma": "1.1.3",
"@wordpress/babel-preset-default": "3.0.2",
"@wordpress/browserslist-config": "^4.1.0",
"eslint": "^8.12.0"
"eslint": "^8.12.0",
"eslint-plugin-jest": "23.20.0"
},
"peerDependencies": {
"@woocommerce/api": "^0.2.0",

View File

@ -12,7 +12,7 @@ module.exports = {
'no-useless-constructor': 'off',
'@typescript-eslint/no-useless-constructor': 2,
},
plugins: [ '@typescript-eslint/eslint-plugin' ],
plugins: [ '@typescript-eslint/eslint-plugin', 'jest' ],
extends: [ 'plugin:@wordpress/eslint-plugin/recommended-with-formatting' ],
overrides: [
{
@ -30,4 +30,8 @@ module.exports = {
},
},
],
globals: {
page: true,
browser: true,
},
};

View File

@ -31,13 +31,14 @@
"@babel/polyfill": "7.12.1",
"@babel/preset-env": "7.12.7",
"@typescript-eslint/eslint-plugin": "^5.3.0",
"@woocommerce/eslint-plugin": "workspace:*",
"@typescript-eslint/parser": "^5.3.0",
"@woocommerce/eslint-plugin": "workspace:*",
"@woocommerce/internal-e2e-builds": "workspace:*",
"@wordpress/babel-plugin-import-jsx-pragma": "1.1.3",
"@wordpress/babel-preset-default": "3.0.2",
"@wordpress/browserslist-config": "^4.1.0",
"eslint": "^8.1.0"
"eslint": "^8.1.0",
"eslint-plugin-jest": "23.20.0"
},
"peerDependencies": {
"@woocommerce/api": "^0.2.0"

View File

@ -1,7 +1,3 @@
/**
* @format
*/
/**
* Internal dependencies
*/
@ -34,7 +30,7 @@ const uuid = require( 'uuid' );
/**
* Verify and publish
*
* @param noticeText The text that appears in the notice after publishing.
* @param {string} noticeText The text that appears in the notice after publishing.
*/
const verifyAndPublish = async ( noticeText ) => {
// Wait for auto save
@ -53,7 +49,7 @@ const verifyAndPublish = async ( noticeText ) => {
/**
* Wait for primary button to be enabled and click.
*
* @param waitForNetworkIdle - Wait for network idle after click
* @param {boolean} waitForNetworkIdle - Wait for network idle after click
* @return {Promise<void>}
*/
const waitAndClickPrimary = async ( waitForNetworkIdle = true ) => {
@ -258,9 +254,9 @@ const createSimpleProduct = async (
/**
* Create simple product with categories
*
* @param productName Product's name which can be changed when writing a test
* @param productPrice Product's price which can be changed when writing a test
* @param categoryName Product's category which can be changed when writing a test
* @param {string} productName Product's name which can be changed when writing a test
* @param {string} productPrice Product's price which can be changed when writing a test
* @param {string} categoryName Product's category which can be changed when writing a test
*/
const createSimpleProductWithCategory = async (
productName,
@ -287,10 +283,10 @@ const createSimpleProductWithCategory = async (
/**
* Create simple downloadable product
*
* @param name Product's name. Defaults to 'Simple Product' (see createSimpleProduct definition).
* @param downloadLimit Product's download limit. Defaults to '-1' (unlimited).
* @param downloadName Product's download name. Defaults to 'Single'.
* @param price Product's price. Defaults to '$9.99' (see createSimpleProduct definition).
* @param {string} name Product's name. Defaults to 'Simple Product' (see createSimpleProduct definition).
* @param {number} downloadLimit Product's download limit. Defaults to '-1' (unlimited).
* @param {string} downloadName Product's download name. Defaults to 'Single'.
* @param {string} price Product's price. Defaults to '$9.99' (see createSimpleProduct definition).
*/
const createSimpleDownloadableProduct = async (
name,
@ -318,8 +314,8 @@ const createSimpleDownloadableProduct = async (
* Create variable product.
* Also, create variations for all attributes.
*
* @param varProduct Defaults to the variable product object in `default.json`
* @return the ID of the created variable product
* @param {Object} varProduct Defaults to the variable product object in `default.json`
* @return {number} the ID of the created variable product
*/
const createVariableProduct = async ( varProduct = defaultVariableProduct ) => {
const { attributes } = varProduct;
@ -329,6 +325,7 @@ const createVariableProduct = async ( varProduct = defaultVariableProduct ) => {
const aIdx = 0; // attributes[] index
// Create variation for all attributes
// eslint-disable-next-line no-shadow
const createVariation = ( aIdx ) => {
const { name, options } = attributes[ aIdx ];
const isLastAttribute = aIdx === attributes.length - 1;
@ -389,8 +386,8 @@ const createVariableProduct = async ( varProduct = defaultVariableProduct ) => {
/**
* Create grouped product.
*
* @param groupedProduct Defaults to the grouped product object in `default.json`
* @return ID of the grouped product
* @param {Object} groupedProduct Defaults to the grouped product object in `default.json`
* @return {number} ID of the grouped product
*/
const createGroupedProduct = async (
groupedProduct = defaultGroupedProduct
@ -406,6 +403,7 @@ const createGroupedProduct = async (
}
// Using the api, create the grouped product
// eslint-disable-next-line prefer-const
groupedProductRequest = {
name,
groupedProducts: simpleProductIds,
@ -452,7 +450,7 @@ const createOrder = async ( orderOptions = {} ) => {
/**
* Create a basic order with the provided order status.
*
* @param orderStatus Status of the new order. Defaults to `Pending payment`.
* @param {string} orderStatus Status of the new order. Defaults to `Pending payment`.
*/
const createSimpleOrder = async ( orderStatus = 'Pending payment' ) => {
// Go to 'Add new order' page
@ -487,7 +485,7 @@ const createSimpleOrder = async ( orderStatus = 'Pending payment' ) => {
* Creates a batch of orders from the given `statuses`
* using the "Batch Create Order" API.
*
* @param statuses Array of order statuses
* @param {Array} statuses Array of order statuses
*/
const batchCreateOrders = async ( statuses ) => {
const defaultOrder = config.get( 'orders.basicPaidOrder' );
@ -511,8 +509,8 @@ const batchCreateOrders = async ( statuses ) => {
/**
* Adds a product to an order in the merchant.
*
* @param orderId ID of the order to add the product to.
* @param productName Name of the product being added to the order.
* @param {number} orderId ID of the order to add the product to.
* @param {string} productName Name of the product being added to the order.
*/
const addProductToOrder = async ( orderId, productName ) => {
await merchant.goToOrder( orderId );
@ -545,8 +543,8 @@ const addProductToOrder = async ( orderId, productName ) => {
/**
* Creates a basic coupon with the provided coupon amount. Returns the coupon code.
*
* @param couponAmount Amount to be applied. Defaults to 5.
* @param discountType Type of a coupon. Defaults to Fixed cart discount.
* @param {string} couponAmount Amount to be applied. Defaults to 5.
* @param {string} discountType Type of a coupon. Defaults to Fixed cart discount.
*/
const createCoupon = async (
couponAmount = '5',
@ -582,10 +580,10 @@ const createCoupon = async (
/**
* Adds a shipping zone along with a shipping method.
*
* @param zoneName Shipping zone name.
* @param zoneLocation Shiping zone location. Defaults to country:US. For states use: state:US:CA
* @param zipCode Shipping zone zip code. Defaults to empty one space.
* @param zoneMethod Shipping method type. Defaults to flat_rate (use also: free_shipping or local_pickup)
* @param {string} zoneName Shipping zone name.
* @param {string} zoneLocation Shiping zone location. Defaults to country:US. For states use: state:US:CA
* @param {string} zipCode Shipping zone zip code. Defaults to empty one space.
* @param {string} zoneMethod Shipping method type. Defaults to flat_rate (use also: free_shipping or local_pickup)
*/
const addShippingZoneAndMethod = async (
zoneName,
@ -632,8 +630,8 @@ const addShippingZoneAndMethod = async (
/**
* Click the Update button on the order details page.
*
* @param noticeText The text that appears in the notice after updating the order.
* @param waitForSave Optionally wait for auto save.
* @param {string} noticeText The text that appears in the notice after updating the order.
* @param {boolean} waitForSave Optionally wait for auto save.
*/
const clickUpdateOrder = async ( noticeText, waitForSave = false ) => {
if ( waitForSave ) {

View File

@ -4,8 +4,8 @@ import { Factory } from 'fishery';
/**
* Creates a new factory for creating grouped products.
*
* @param {HTTPClient} httpClient The HTTP client we will give the repository.
* @return {AsyncFactory} The factory for creating models.
* @param {Object} httpClient The HTTP client we will give the repository.
* @return {Object} The factory for creating models.
*/
export function groupedProductFactory( httpClient ) {
const repository = GroupedProduct.restRepository( httpClient );

View File

@ -5,8 +5,8 @@ import crypto from 'crypto';
/**
* Creates a new factory for creating models.
*
* @param {HTTPClient} httpClient The HTTP client we will give the repository.
* @return {AsyncFactory} The factory for creating models.
* @param {Object} httpClient The HTTP client we will give the repository.
* @return {Object} The factory for creating models.
*/
export function simpleProductFactory( httpClient ) {
const repository = SimpleProduct.restRepository( httpClient );

View File

@ -6,8 +6,8 @@ import { Factory } from 'fishery';
* This does not include creating product variations.
* Instead, use `variationFactory()` for that.
*
* @param {HTTPClient} httpClient The HTTP client we will give the repository.
* @return {AsyncFactory} The factory for creating models.
* @param {Object} httpClient The HTTP client we will give the repository.
* @return {Object} The factory for creating models.
*/
export function variableProductFactory( httpClient ) {
const repository = VariableProduct.restRepository( httpClient );

View File

@ -4,8 +4,8 @@ import { Factory } from 'fishery';
/**
* Creates a new factory for creating a product variation.
*
* @param {HTTPClient} httpClient The HTTP client we will give the repository.
* @return {AsyncFactory} The factory for creating models.
* @param {Object} httpClient The HTTP client we will give the repository.
* @return {Object} The factory for creating models.
*/
export function variationFactory( httpClient ) {
const repository = ProductVariation.restRepository( httpClient );

View File

@ -79,4 +79,4 @@ export const MY_ACCOUNT_ACCOUNT_DETAILS = SHOP_MY_ACCOUNT_PAGE + 'edit-account';
*
* @type {boolean}
*/
export const IS_RETEST_MODE = process.env.E2E_RETEST == '1';
export const IS_RETEST_MODE = process.env.E2E_RETEST === '1';

View File

@ -267,10 +267,10 @@ const shopper = {
// Single search results may go directly to product page
if ( await page.waitForSelector( 'h2.entry-title' ) ) {
await expect( page ).toMatchElement( 'h2.entry-title', {
text: prouductName
text: prouductName,
} );
await expect( page ).toClick( 'h2.entry-title > a', {
text: prouductName
text: prouductName,
} );
}
await page.waitForSelector( 'h1.entry-title' );

View File

@ -1,10 +1,10 @@
/**
* Take a string name and generate the slug for it.
* Example: 'My plugin' => 'my-plugin'
*
* @param text string to convert to a slug
*
* Sourced from: https://gist.github.com/spyesx/561b1d65d4afb595f295
*
* @param {string} text string to convert to a slug.
* @return {string} slug.
*/
export const getSlug = ( text ) => {
text = text.trim().toLowerCase();
@ -39,7 +39,7 @@ export const itIf = ( condition ) => ( condition ? it : it.skip );
/**
* Wait for a timeout in milliseconds
*
* @param timeout delay time in milliseconds
* @param {number} timeout delay time in milliseconds
* @return {Promise<void>}
*/
export const waitForTimeout = async ( timeout ) => {

View File

@ -16,9 +16,9 @@ const userEndpoint = '/wp/v2/users';
/**
* Utility function to delete all merchant created data store objects.
*
* @param repository
* @param defaultObjectId
* @param statuses Status of the object to check
* @param {unknown} repository
* @param {number | null} defaultObjectId
* @param {Array<string>} statuses Status of the object to check
* @return {Promise<void>}
*/
const deleteAllRepositoryObjects = async (
@ -27,7 +27,7 @@ const deleteAllRepositoryObjects = async (
statuses = [ 'draft', 'publish', 'trash' ]
) => {
let objects;
const minimum = defaultObjectId == null ? 0 : 1;
const minimum = defaultObjectId === null ? 0 : 1;
for ( let s = 0; s < statuses.length; s++ ) {
const status = statuses[ s ];
@ -35,7 +35,7 @@ const deleteAllRepositoryObjects = async (
while ( objects.length > minimum ) {
for ( let o = 0; o < objects.length; o++ ) {
// Skip default data store object
if ( objects[ o ].id == defaultObjectId ) {
if ( objects[ o ].id === defaultObjectId ) {
continue;
}
// We may be getting a cached copy of the dataset and the object has already been deleted.
@ -52,7 +52,7 @@ const deleteAllRepositoryObjects = async (
* Utility to flatten a tax rate.
*
* @param {Object} taxRate Tax rate to be flattened.
* @return {string}
* @return {string} The flattened tax rate.
*/
const flattenTaxRate = ( taxRate ) => {
return taxRate.rate + '/' + taxRate.class + '/' + taxRate.name;
@ -159,7 +159,7 @@ export const withRestApi = {
if ( productCategories.data && productCategories.data.length ) {
for ( let c = 0; c < productCategories.data.length; c++ ) {
// The default `uncategorized` category can't be deleted
if ( productCategories.data[ c ].slug == 'uncategorized' ) {
if ( productCategories.data[ c ].slug === 'uncategorized' ) {
continue;
}
const response = await client.delete(
@ -226,12 +226,12 @@ export const withRestApi = {
/**
* Adds a shipping zone along with a shipping method using the API.
*
* @param zoneName Shipping zone name.
* @param zoneLocation Shiping zone location. Defaults to country:US. For states use: state:US:CA.
* @param zipCode Shipping zone zip code. Default is no zip code.
* @param zoneMethod Shipping method type. Defaults to flat_rate (use also: free_shipping or local_pickup).
* @param cost Shipping method cost. Default is no cost.
* @param additionalZoneMethods Array of additional zone methods to add to the shipping zone.
* @param {string} zoneName Shipping zone name.
* @param {string} zoneLocation Shiping zone location. Defaults to country:US. For states use: state:US:CA.
* @param {string} zipCode Shipping zone zip code. Default is no zip code.
* @param {string} zoneMethod Shipping method type. Defaults to flat_rate (use also: free_shipping or local_pickup).
* @param {string} cost Shipping method cost. Default is no cost.
* @param {Array} additionalZoneMethods Array of additional zone methods to add to the shipping zone.
* @param {boolean} testResponse Test the response status code.
*/
addShippingZoneAndMethod: async (
@ -310,6 +310,7 @@ export const withRestApi = {
// Add any additional zones, if provided
if ( additionalZoneMethods.length > 0 ) {
for ( let z = 0; z < additionalZoneMethods.length; z++ ) {
// eslint-disable-next-line no-shadow
const response = await client.post(
path + `/${ zoneId }/methods`,
{ method_id: additionalZoneMethods[ z ] }
@ -331,7 +332,7 @@ export const withRestApi = {
if ( shippingZones.data && shippingZones.data.length ) {
for ( let z = 0; z < shippingZones.data.length; z++ ) {
// The data store doesn't support deleting the default zone.
if ( shippingZones.data[ z ].id == 0 ) {
if ( shippingZones.data[ z ].id === 0 ) {
continue;
}
const response = await client.delete(
@ -367,7 +368,7 @@ export const withRestApi = {
/**
* Delete a customer account by their email address if the user exists.
*
* @param emailAddress Customer user account email address.
* @param {string} emailAddress Customer user account email address.
* @return {Promise<void>}
*/
deleteCustomerByEmail: async ( emailAddress ) => {
@ -394,7 +395,7 @@ export const withRestApi = {
/**
* Reset a settings group to default values except selects.
*
* @param settingsGroup
* @param {unknown} settingsGroup
* @param {boolean} testResponse Test the response status code.
* @return {Promise<void>}
*/
@ -411,8 +412,8 @@ export const withRestApi = {
for ( let s = 0; s < settings.length; s++ ) {
// The rest api doesn't allow selects to be set to ''.
if (
settings[ s ].type == 'select' &&
settings[ s ].default == ''
settings[ s ].type === 'select' &&
settings[ s ].default === ''
) {
continue;
}
@ -428,7 +429,7 @@ export const withRestApi = {
defaultSetting
);
// Multi-selects have a default '' but return an empty [].
if ( testResponse && settings[ s ].type != 'multiselect' ) {
if ( testResponse && settings[ s ].type !== 'multiselect' ) {
expect( response.value ).toBe( defaultSetting.value );
}
}
@ -467,7 +468,7 @@ export const withRestApi = {
/**
* Create a batch of orders using the "Batch Create Order" API endpoint.
*
* @param orders Array of orders to be created
* @param {Array} orders Array of orders to be created
* @param {boolean} testResponse Test the response status code.
*/
batchCreateOrders: async ( orders, testResponse = true ) => {
@ -482,8 +483,8 @@ export const withRestApi = {
/**
* Add tax classes.
*
* @param {<Array<Object>>} taxClasses Array of tax class objects.
* @return {Promise<void>}
* @param {Array<Object>} taxClasses Array of tax class objects.
* @return {Promise<void>} Promise resolving once tax classes have been added.
*/
addTaxClasses: async ( taxClasses ) => {
// Only add tax classes which don't already exist.
@ -502,7 +503,7 @@ export const withRestApi = {
/**
* Add tax rates.
*
* @param {<Array<Object>>} taxRates Array of tax rate objects.
* @param {Array<Object>} taxRates Array of tax rate objects.
* @return {Promise<void>}
*/
addTaxRates: async ( taxRates ) => {

View File

@ -122,9 +122,9 @@ export const backboneUnblocked = async () => {
/**
* Conditionally wait for a selector without throwing an error.
*
* @param selector
* @param timeoutInSeconds
* @return {Promise<boolean>}
* @param {string} selector
* @param {number} timeoutInSeconds
* @return {Promise<boolean>} True if selector is found, false otherwise.
*/
export const waitForSelectorWithoutThrow = async (
selector,
@ -292,7 +292,7 @@ export const searchForOrder = async ( value, orderId, customerName ) => {
* Apply a coupon code within cart or checkout.
* Method will try to apply a coupon in the checkout, otherwise will try to apply in the cart.
*
* @param couponCode string
* @param {string} couponCode string
* @return {Promise<void>}
*/
export const applyCoupon = async ( couponCode ) => {
@ -318,7 +318,7 @@ export const applyCoupon = async ( couponCode ) => {
/**
* Remove one coupon within cart or checkout.
*
* @param couponCode Coupon name.
* @param {string} couponCode Coupon name.
* @return {Promise<void>}
*/
export const removeCoupon = async ( couponCode ) => {
@ -375,7 +375,7 @@ export const clickAndWaitForSelector = async (
* Behavior can be modified with @param options. Possible keys: `visible`, `hidden`, `timeout`.
* More details at: https://pptr.dev/#?product=Puppeteer&show=api-pagewaitforselectorselector-options
*
* @param {Puppeteer.Page} page Puppeteer representation of the page.
* @param {Object} page Puppeteer representation of the page.
* @param {string} selector CSS selector of the element
* @param {Object} options Custom options to modify function behavior.
*/
@ -394,11 +394,12 @@ export async function waitForSelector( page, selector, options = {} ) {
*
* @param {string} selector Selector of the element you want to get the attribute from.
* @param {string} attribute The desired HTML attribute.
* @return {Promise<string>}
* @return {Promise<string>} Promise resolving to the attribute value.
*/
export async function getSelectorAttribute( selector, attribute ) {
return await page.$eval(
selector,
// eslint-disable-next-line no-shadow
( element, attribute ) => element.getAttribute( attribute ),
attribute
);

View File

@ -4,10 +4,10 @@ export class AdminEdit {
/**
* Publish the object being edited and verify published status
*
* @param button Publish button selector
* @param publishNotice Publish notice selector
* @param publishVerification Expected notice on successful publish
* @return {Promise<void>}
* @param {string} button Publish button selector
* @param {string} publishNotice Publish notice selector
* @param {string} publishVerification Expected notice on successful publish
* @return {Promise<void>} Promise resolving when the object is published
*/
async verifyPublish( button, publishNotice, publishVerification ) {
// Wait for auto save
@ -24,7 +24,7 @@ export class AdminEdit {
/**
* Get the ID of the object being edited
*
* @return {Promise<*>}
* @return {Promise<*>} Promise resolving to the ID of the object being edited.
*/
async getId() {
const postId = await page.$( '#post_ID' );

View File

@ -31,7 +31,7 @@
"main": "index.js",
"dependencies": {
"@typescript-eslint/parser": "^5.14.0",
"@wordpress/eslint-plugin": "^11.0.0",
"@wordpress/eslint-plugin": "^13.3.0",
"eslint-plugin-react-hooks": "^4.3.0",
"eslint-plugin-testing-library": "^5.1.0",
"requireindex": "^1.2.0"
@ -47,7 +47,7 @@
},
"devDependencies": {
"@babel/core": "^7.17.5",
"eslint": "^8.11.0",
"eslint": "^8.25.0",
"jest": "^27.5.1",
"jest-cli": "^27.5.1",
"rimraf": "^3.0.2",

View File

@ -45,7 +45,7 @@
"devDependencies": {
"@babel/core": "^7.17.5",
"@types/debug": "^4.1.7",
"@wordpress/eslint-plugin": "^11.0.0",
"@woocommerce/eslint-plugin": "workspace:*",
"eslint": "^8.12.0",
"jest": "^27.5.1",
"jest-cli": "^27.5.1",

View File

@ -1,5 +1,3 @@
/** @format */
module.exports = {
root: true,
env: {

View File

@ -237,7 +237,6 @@ module.exports = function ( grunt ) {
grunt.loadNpmTasks( 'grunt-rtlcss' );
grunt.loadNpmTasks( 'grunt-postcss' );
grunt.loadNpmTasks( 'grunt-stylelint' );
grunt.loadNpmTasks( 'gruntify-eslint' );
grunt.loadNpmTasks( 'grunt-contrib-uglify' );
grunt.loadNpmTasks( 'grunt-contrib-cssmin' );
grunt.loadNpmTasks( 'grunt-contrib-concat' );
@ -250,7 +249,7 @@ module.exports = function ( grunt ) {
// Register tasks.
grunt.registerTask( 'default', [ 'js', 'css' ] );
grunt.registerTask( 'js', [ 'eslint', 'copy:js', 'uglify:js_assets' ] );
grunt.registerTask( 'js', [ 'copy:js', 'uglify:js_assets' ] );
grunt.registerTask( 'css', [
'sass',

View File

@ -7,8 +7,7 @@
"main": "Gruntfile.js",
"scripts": {
"turbo:build": "grunt assets",
"build": "pnpm -w exec turbo run turbo:build --filter=$npm_package_name",
"lint": "grunt eslint stylelint --force"
"build": "pnpm -w exec turbo run turbo:build --filter=$npm_package_name"
},
"devDependencies": {
"@wordpress/stylelint-config": "19.1.0",

Some files were not shown because too many files have changed in this diff Show More