Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .github/workflows/integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ name: Integration
# resources the suites create and delete themselves (named cli-it-…). Not on every pull request, to spare the
# rate limits and keep reviews independent of the organization's data: on
# pushes to the integration and main branches, every night, on demand, and
# on pull requests that change the suites themselves.
# on pull requests that change the suites themselves or the dependencies.
on:
push:
branches: [main, monorepo]
Expand All @@ -16,6 +16,9 @@ on:
pull_request:
paths:
- .github/workflows/integration.yml
# Dependency updates (an SDK above all) must work against the real API
- pnpm-workspace.yaml
- pnpm-lock.yaml
- packages/test-utils/src/live.ts
- '**/test/integration/**'

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ Run a single package's script with `pnpm --filter <package name> <script>`, for
CL_CLI_ORGANIZATION=<org slug> CL_CLI_CLIENT_ID=<client id> CL_CLI_CLIENT_SECRET=<client secret> pnpm test:integration
```

Use an integration application of a test organization, never a production one. In CI, [integration.yml](.github/workflows/integration.yml) runs them against `cli-test-org` on pushes to `monorepo` and `main`, every night, on demand, and on pull requests that change the suites. They assert on the shape of the output, not on specific records.
Use an integration application of a test organization, never a production one. In CI, [integration.yml](.github/workflows/integration.yml) runs them against `cli-test-org` on pushes to `monorepo` and `main`, every night, on demand, and on pull requests that change the suites or the dependencies. They assert on the shape of the output, not on specific records.

The suites that change data (`*-write.it.ts`) only work on resources they create and delete themselves, whose names, emails and references start with `cli-it-`. `node scripts/test/live-sweep.mjs` (run before and after the suites in CI) deletes whatever an interrupted run left behind, and nothing else. The checkout and links suites also need `CL_CLI_SALES_CHANNEL_CLIENT_ID`, the client ID of a sales channel application of the organization, and are skipped without it.

Expand Down
4 changes: 2 additions & 2 deletions plugins/links/src/commands/links/list.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { clApi, clColor, clConfig, clUtil, type KeyValSort } from '@commercelayer/cli-core'
import type { Link, QueryArraySortable, QueryPageSize, QueryParamsList, QueryRecordSortable } from '@commercelayer/sdk'
import type { Link, QueryPageSize, QueryParamsList, QuerySort } from '@commercelayer/sdk'
import Table, { type HorizontalAlignment } from 'cli-table3'
import { BaseCommand, cliux, Flags } from '../../base'
import { fillUTCDate, formatDate, linkStatus } from '../../util'
Expand Down Expand Up @@ -96,7 +96,7 @@ Examples:
if (flags.expires) expiresFilter.push(...this.comparisonParam(flags.expires, 'expires'))

const sortBy = this.sortFlag(flags.sort)
const sort: QueryArraySortable<Link> | QueryRecordSortable<Link> = (sortBy && (Object.keys(sortBy).length > 0)) ? sortBy : ['-expires_at', '-starts_at']
const sort: QuerySort<Link> = (sortBy && (Object.keys(sortBy).length > 0)) ? sortBy : ['-expires_at', '-starts_at']

this.commercelayerInit(flags)

Expand Down
4 changes: 2 additions & 2 deletions plugins/provisioning/test/commands/provisioning/fetch.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ describe('provisioning:fetch', () => {
useMockedApi()

it('fetches a resource list', async () => {
api().get('/api/roles').reply(200, list([resource('roles', 'rOl1', { name: 'Admin' })]))
api().get('/api/roles').query(true).reply(200, list([resource('roles', 'rOl1', { name: 'Admin' })]))
const ctx = await runCommand(['provisioning:fetch', 'roles', ...AUTH])
if (ctx.error) throw ctx.error
expect(ctx.stdout).to.contain('rOl1')
})

it('fetches a relationship from a path', async () => {
api().get('/api/roles/rOl1/permissions').reply(200, list([resource('permissions', 'pRm1', { subject: 'orders' })]))
api().get('/api/roles/rOl1/permissions').query(true).reply(200, list([resource('permissions', 'pRm1', { subject: 'orders' })]))
const ctx = await runCommand(['provisioning:fetch', 'roles/rOl1/permissions', ...AUTH])
if (ctx.error) throw ctx.error
expect(ctx.stdout).to.contain('pRm1')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ describe('provisioning:get', () => {
useMockedApi()

it('lists without an ID', async () => {
api().get('/api/roles').reply(200, list([resource('roles', 'rOl1', { name: 'Admin' })]))
api().get('/api/roles').query(true).reply(200, list([resource('roles', 'rOl1', { name: 'Admin' })]))
const ctx = await runCommand(['provisioning:get', 'roles', ...AUTH])
if (ctx.error) throw ctx.error
expect(ctx.stdout).to.contain('rOl1')
Expand Down
5 changes: 3 additions & 2 deletions plugins/provisioning/test/commands/provisioning/list.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ describe('provisioning:list', () => {
it('lists the resources', async () => {
api()
.get('/api/roles')
.query(true)
.reply(200, list([resource('roles', 'rOl1', { name: 'Admin', kind: 'admin' }), resource('roles', 'rOl2', { name: 'Read only', kind: 'read_only' })]))
const ctx = await runCommand(['provisioning:list', 'roles', ...AUTH])
if (ctx.error) throw ctx.error
Expand All @@ -26,7 +27,7 @@ describe('provisioning:list', () => {
})

it('prints unformatted JSON', async () => {
api().get('/api/roles').reply(200, list([resource('roles', 'rOl1', { name: 'Admin' })]))
api().get('/api/roles').query(true).reply(200, list([resource('roles', 'rOl1', { name: 'Admin' })]))
const ctx = await runCommand(['provisioning:list', 'roles', ...AUTH, '-j', '-u'])
if (ctx.error) throw ctx.error
expect(JSON.parse(ctx.stdout.substring(ctx.stdout.indexOf('['), ctx.stdout.lastIndexOf(']') + 1))[0].name).to.equal('Admin')
Expand All @@ -38,7 +39,7 @@ describe('provisioning:list', () => {
})

it('reports the API error', async () => {
api().get('/api/roles').reply(401, apiError(401, 'Invalid token'))
api().get('/api/roles').query(true).reply(401, apiError(401, 'Invalid token'))
const ctx = await runCommand(['provisioning:list', 'roles', ...AUTH])
expect(ctx.error?.message).to.match(/Invalid token/)
})
Expand Down
38 changes: 19 additions & 19 deletions plugins/tags/src/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { clColor, clConfig, clOutput, clToken, clUpdate, clUtil } from '@commercelayer/cli-core'
import * as cliux from '@commercelayer/cli-ux'
import type { CommerceLayerClient, ListResponse, Tag, TaggableResource, TaggableResourceType } from '@commercelayer/sdk'
import commercelayer, { Bundles, BuyXPayYPromotions, CommerceLayerStatic, Coupons, Customers, ExternalPromotions, FixedAmountPromotions, FixedPricePromotions, FreeGiftPromotions, FreeShippingPromotions, GiftCards, LineItemOptions, Orders, PercentageDiscountPromotions, Promotions, Returns, Shipments, SkuOptions, Skus} from '@commercelayer/sdk'
import commercelayer, { CommerceLayerStatic } from '@commercelayer/sdk'
import type { Interfaces } from '@oclif/core'
import { Args, Command, Flags } from '@oclif/core'

Expand Down Expand Up @@ -171,24 +171,24 @@ export default abstract class BaseCommand extends Command {
let attribute: string | undefined

switch (type) {
case Returns.TYPE:
case Shipments.TYPE:
case Orders.TYPE: { attribute = 'number'; break }
case Bundles.TYPE:
case Coupons.TYPE:
case GiftCards.TYPE:
case Skus.TYPE: { attribute = 'code'; break }
case BuyXPayYPromotions.TYPE:
case ExternalPromotions.TYPE:
case FixedAmountPromotions.TYPE:
case FixedPricePromotions.TYPE:
case FreeGiftPromotions.TYPE:
case FreeShippingPromotions.TYPE:
case PercentageDiscountPromotions.TYPE:
case Promotions.TYPE:
case LineItemOptions.TYPE:
case SkuOptions.TYPE: { attribute = 'name'; break }
case Customers.TYPE: { attribute = 'email'; break }
case 'returns':
case 'shipments':
case 'orders': { attribute = 'number'; break }
case 'bundles':
case 'coupons':
case 'gift_cards':
case 'skus': { attribute = 'code'; break }
case 'buy_x_pay_y_promotions':
case 'external_promotions':
case 'fixed_amount_promotions':
case 'fixed_price_promotions':
case 'free_gift_promotions':
case 'free_shipping_promotions':
case 'percentage_discount_promotions':
case 'promotions':
case 'line_item_options':
case 'sku_options': { attribute = 'name'; break }
case 'customers': { attribute = 'email'; break }

}

Expand Down
5 changes: 2 additions & 3 deletions plugins/triggers/src/exec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { clApi, clColor, clText, clUtil } from '@commercelayer/cli-core'
import type { CommerceLayerClient, QueryParamsRetrieve, QueryRecordFields, Resource } from '@commercelayer/sdk'
import type { CommerceLayerClient, QueryParamsRetrieve, Resource } from '@commercelayer/sdk'
import commercelayer, { CommerceLayerStatic } from '@commercelayer/sdk'
import type { Interfaces } from '@oclif/core'
import { Errors } from '@oclif/core'
Expand Down Expand Up @@ -42,8 +42,7 @@ const exec = async <R extends Resource>(resourceType: string, id: string, action
const res: any = { id, [`_${action}`]: flags.value || true }
const params: QueryParamsRetrieve = {}
if (fields && (fields.length > 0)) {
params.fields = {}
params.fields[resourceType as R['type']] = fields as QueryRecordFields[R['type']]
params.fields = { [resourceType]: fields } as QueryParamsRetrieve['fields']
}

const result = resSdk.update(res, params).catch((error: unknown) => {
Expand Down
Loading