diff --git a/packages/resource-deleter/test/integration/cli.spec.ts b/packages/resource-deleter/test/integration/cli.spec.ts index cf2f899..af1cad1 100644 --- a/packages/resource-deleter/test/integration/cli.spec.ts +++ b/packages/resource-deleter/test/integration/cli.spec.ts @@ -49,6 +49,15 @@ describe('Resource Deleter', () => { return client.execute(request); } + // Deleting in declaration order fails, because a resource cannot be removed + // while another still references it (a product-type referenced by a product, + // for example). Reverse order removes dependents first -- the same order the + // per-resource delete tests below rely on. + const clearAllResources = () => + Promise.each(Object.keys(resources).reverse(), (name: MethodNames) => { + return clearData(apiConfig, name); + }); + beforeAll(async () => { // Get test credentials const credentials = await getCredentials(); @@ -59,18 +68,20 @@ describe('Resource Deleter', () => { credentials, }; + // clear anything a previous run left behind before seeding, so the + // suite recovers on its own from an interrupted teardown + await clearAllResources(); + // create resources on API await Promise.each(Object.keys(resources), (name: MethodNames) => { return createData(apiConfig, name, resources[name]); }); - }, 30000); + }, 60000); // clear resources on API afterAll(async () => { - await Promise.each(Object.keys(resources), (name: MethodNames) => { - clearData(apiConfig, name); - }); - }, 45000); + await clearAllResources(); + }, 60000); describe('CLI basic functionality', () => { it('should print usage information given the help flag', async () => { diff --git a/packages/resource-deleter/test/integration/helpers/helpers.ts b/packages/resource-deleter/test/integration/helpers/helpers.ts index 107fd49..8704775 100644 --- a/packages/resource-deleter/test/integration/helpers/helpers.ts +++ b/packages/resource-deleter/test/integration/helpers/helpers.ts @@ -41,7 +41,7 @@ export function clearData( : payload.body.results; return Promise.all( - results.map((result): Promise> => { + results.map(async (result): Promise> => { let request: ClientRequest; if (service instanceof ByProjectKeyCustomObjectsRequestBuilder) { @@ -53,9 +53,28 @@ export function clearData( .delete({ queryArgs: { version: result.version } }) .clientRequest(); } else { - request = service - .withId({ ID: result.id }) - .delete({ queryArgs: { version: result.version } }) + const serviceBuilder = service.withId({ ID: result.id }); + let version = result.version; + + // A published product cannot be deleted, so unpublish it first. + // Unpublishing bumps the version, which the delete then needs. + // Mirrors how the deleter itself handles this in src/main.ts, + // including overriding a built request rather than calling + // .post(), whose update-action union is too complex to type. + if (result.masterData?.published) { + await client.execute({ + ...serviceBuilder.get().clientRequest(), + method: 'POST', + body: JSON.stringify({ + version, + actions: [{ action: 'unpublish' }], + }), + }); + version += 1; + } + + request = serviceBuilder + .delete({ queryArgs: { version } }) .clientRequest(); }