From 3b9b4499dc90c548fb4f55c9968013ce9351b90e Mon Sep 17 00:00:00 2001 From: Aaron Zielstorff Date: Tue, 5 May 2026 22:07:35 +0200 Subject: [PATCH 1/5] Improves assertion errors Co-authored-by: Copilot --- scripts/test-engine.mjs | 63 ++++- .../aasDiscovery.integration.test.ts | 38 ++- .../aasRegistry.integration.test.ts | 107 ++++---- .../aasRepo.integration.test.ts | 210 +++++++-------- .../aasService.integration.test.ts | 81 +++--- .../aasxFile.integration.test.ts | 42 ++- ...conceptDescriptionRepo.integration.test.ts | 49 ++-- .../fixtures/assertionHelpers.ts | 149 +++++++++++ .../submodelRegistry.integration.test.ts | 45 ++-- .../submodelRepo.integration.test.ts | 248 ++++++++---------- .../submodelService.integration.test.ts | 45 ++-- 11 files changed, 616 insertions(+), 461 deletions(-) create mode 100644 src/integration-tests/fixtures/assertionHelpers.ts diff --git a/scripts/test-engine.mjs b/scripts/test-engine.mjs index 747723f7..4e10b086 100644 --- a/scripts/test-engine.mjs +++ b/scripts/test-engine.mjs @@ -251,6 +251,40 @@ function escapeXml(value) { .replaceAll("'", '''); } +function normalizeFailureMessage(message) { + if (!message) { + return ''; + } + + return String(message).trim(); +} + +function sanitizeFailureMessages(messages) { + if (!Array.isArray(messages)) { + return []; + } + + return messages.map((message) => normalizeFailureMessage(message)).filter(Boolean); +} + +function compactFailureReason(message) { + const normalized = normalizeFailureMessage(message); + if (!normalized) { + return ''; + } + + const firstLine = normalized + .split('\n') + .map((line) => line.trim()) + .find(Boolean); + + return firstLine || normalized; +} + +function formatFailureDetailLine(message) { + return normalizeFailureMessage(message).replace(/\s+/g, ' ').trim(); +} + function parseVitestResults(vitestReport) { const passedChecks = []; const failedChecks = []; @@ -260,12 +294,14 @@ function parseVitestResults(vitestReport) { let suiteHasFailedAssertion = false; for (const assertion of suite.assertionResults ?? []) { + const failureMessages = sanitizeFailureMessages(assertion.failureMessages); const check = { checkType: 'integration-test', suite: suite.name, name: assertion.fullName || assertion.title, durationMs: assertion.duration, - reason: assertion.failureMessages?.[0] || '', + reason: failureMessages[0] || '', + failureMessages, status: assertion.status, }; @@ -284,12 +320,14 @@ function parseVitestResults(vitestReport) { } if (suite.status === 'failed' && !suiteHasFailedAssertion) { + const suiteMessage = normalizeFailureMessage(suite.message); failedChecks.push({ checkType: 'integration-suite', suite: suite.name, name: `Suite failure: ${suite.name}`, durationMs: 0, - reason: suite.message || 'Suite failed before assertions (setup hook or runtime error).', + reason: suiteMessage || 'Suite failed before assertions (setup hook or runtime error).', + failureMessages: suiteMessage ? [suiteMessage] : [], status: 'failed', }); } @@ -449,7 +487,15 @@ function writeMarkdownReport(report, outputPath) { if (failure.suite) { lines.push(` - suite: ${failure.suite}`); } - lines.push(` - reason: ${failure.reason || 'No failure reason provided'}`); + + const primaryReason = failure.reason || failure.failureMessages?.[0] || 'No failure reason provided'; + lines.push(` - reason: ${primaryReason}`); + + if (Array.isArray(failure.failureMessages) && failure.failureMessages.length > 1) { + for (const extraMessage of failure.failureMessages.slice(1, 5)) { + lines.push(` - detail: ${formatFailureDetailLine(extraMessage)}`); + } + } } } lines.push(''); @@ -498,7 +544,7 @@ function writeJunitReport(report, outputPath) { name: check.name, status: 'failed', durationMs: check.durationMs ?? 0, - message: check.reason || 'No failure message', + message: compactFailureReason(check.reason || check.failureMessages?.[0] || 'No failure message'), }); } @@ -550,7 +596,14 @@ function printConsoleSummary(report, artifactPaths) { console.log('Failed checks:'); for (const failure of report.failedChecks) { console.log(`- [${failure.checkType}] ${failure.name}`); - console.log(` reason: ${failure.reason || 'No failure reason provided'}`); + const primaryReason = failure.reason || failure.failureMessages?.[0] || 'No failure reason provided'; + console.log(` reason: ${primaryReason}`); + + if (Array.isArray(failure.failureMessages) && failure.failureMessages.length > 1) { + for (const extraMessage of failure.failureMessages.slice(1, 3)) { + console.log(` detail: ${formatFailureDetailLine(extraMessage)}`); + } + } } } diff --git a/src/integration-tests/aasDiscovery.integration.test.ts b/src/integration-tests/aasDiscovery.integration.test.ts index 51a283dc..00d2315a 100644 --- a/src/integration-tests/aasDiscovery.integration.test.ts +++ b/src/integration-tests/aasDiscovery.integration.test.ts @@ -3,6 +3,7 @@ import { AasDiscoveryClient } from '../clients/AasDiscoveryClient'; import { Configuration } from '../generated'; import { base64Encode } from '../lib/base64Url'; import { createTestSpecificAssetId1, createTestSpecificAssetId2 } from './fixtures/aasDiscoveryFixtures'; +import { assertApiFailure, assertApiResult } from './fixtures/assertionHelpers'; import { createPerTestCleanupRunner } from './fixtures/testCleanup'; import { getIntegrationBasePath } from './testEngineConfig'; @@ -55,10 +56,7 @@ describe('AAS Discovery Integration Tests', () => { specificAssetId: [specificAssetId1, specificAssetId2], }); - expect(createResponse.success).toBe(true); - if (!createResponse.success) { - throw new Error('Failed to seed AAS discovery asset links fixture'); - } + assertApiResult(createResponse, 'Seed AAS discovery asset links fixture'); registerAssetLinkCleanup(aasIdentifier); return { aasIdentifier, specificAssetId1, specificAssetId2 }; @@ -79,7 +77,7 @@ describe('AAS Discovery Integration Tests', () => { specificAssetId: [specificAssetId1, specificAssetId2], }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { registerAssetLinkCleanup(aasIdentifier); expect(response.statusCode).toBe(201); @@ -100,7 +98,7 @@ describe('AAS Discovery Integration Tests', () => { aasIdentifier, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data).toBeDefined(); @@ -118,7 +116,7 @@ describe('AAS Discovery Integration Tests', () => { configuration, aasIdentifier: nonExistingId, }); - expect(response.success).toBe(false); + assertApiFailure(response); if (!response.success) { expect(response.statusCode).toBe(404); expect(response.error).toBeDefined(); @@ -153,7 +151,7 @@ describe('AAS Discovery Integration Tests', () => { assetIds: [specificAssetId1, specificAssetId2], }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data).toBeDefined(); @@ -176,7 +174,7 @@ describe('AAS Discovery Integration Tests', () => { limit: -1, }); - expect(response.success).toBe(false); + assertApiFailure(response); if (!response.success) { expect(response.statusCode).toBe(400); expect(response.error.messages?.[0]?.code).toBe('400'); @@ -197,7 +195,7 @@ describe('AAS Discovery Integration Tests', () => { cursor: unavailableCursor(), }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data.pagedResult).toEqual({}); @@ -217,7 +215,7 @@ describe('AAS Discovery Integration Tests', () => { assetLink: [specificAssetId1, specificAssetId2], }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data.result).toContainEqual(aasIdentifier); @@ -234,7 +232,7 @@ describe('AAS Discovery Integration Tests', () => { assetLink: [{ name: 'globalAssetId' } as unknown as CoreSpecificAssetId], }); - expect(response.success).toBe(false); + assertApiFailure(response); if (!response.success) { expect(response.statusCode).toBe(400); expect(response.error.messages?.[0]?.code).toBe('400'); @@ -255,7 +253,7 @@ describe('AAS Discovery Integration Tests', () => { cursor: unavailableCursor(), }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data.pagedResult).toEqual({}); @@ -277,7 +275,7 @@ describe('AAS Discovery Integration Tests', () => { specificAssetId: [invalidSpecificAssetId], }); - expect(response.success).toBe(false); + assertApiFailure(response); if (!response.success) { expect(response.statusCode).toBe(400); expect(response.error.messages?.[0]?.code).toBe('400'); @@ -297,7 +295,7 @@ describe('AAS Discovery Integration Tests', () => { specificAssetId: [specificAssetId1], }); - expect(response.success).toBe(false); + assertApiFailure(response); if (!response.success) { expect(response.statusCode).toBe(405); expect(response.error.messages?.[0]?.code).toBe('405'); @@ -317,7 +315,7 @@ describe('AAS Discovery Integration Tests', () => { specificAssetId: [specificAssetId1], }); - expect(response.success).toBe(false); + assertApiFailure(response); if (!response.success) { expect(response.statusCode).toBe(404); expect(response.error.messages?.[0]?.code).toBe('404'); @@ -358,7 +356,7 @@ describe('AAS Discovery Integration Tests', () => { aasIdentifier, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(204); expect(response.data).toBeUndefined(); @@ -377,7 +375,7 @@ describe('AAS Discovery Integration Tests', () => { aasIdentifier: nonExistingAasIdentifier, }); - expect(response.success).toBe(false); + assertApiFailure(response); if (!response.success) { expect(response.statusCode).toBe(404); expect(response.error.messages?.[0]?.code).toBe('404'); @@ -394,7 +392,7 @@ describe('AAS Discovery Integration Tests', () => { aasIdentifier: '', }); - expect(response.success).toBe(false); + assertApiFailure(response); if (!response.success) { expect(response.statusCode).toBe(405); expect(response.error.messages?.[0]?.code).toBe('405'); @@ -410,7 +408,7 @@ describe('AAS Discovery Integration Tests', () => { configuration, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data).toBeDefined(); diff --git a/src/integration-tests/aasRegistry.integration.test.ts b/src/integration-tests/aasRegistry.integration.test.ts index ee3761ee..2d6c33c8 100644 --- a/src/integration-tests/aasRegistry.integration.test.ts +++ b/src/integration-tests/aasRegistry.integration.test.ts @@ -8,6 +8,7 @@ import { createTestShellDescriptor, createTestSubmodelDescriptor, } from './fixtures/aasregistryFixtures'; +import { assertApiFailure, assertApiResult } from './fixtures/assertionHelpers'; import { createPerTestCleanupRunner } from './fixtures/testCleanup'; import { getIntegrationBasePath } from './testEngineConfig'; @@ -87,7 +88,7 @@ describe('AAS Registry Integration Tests', () => { assetAdministrationShellDescriptor: shellDescriptor, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(201); expect(response.data).toEqual(shellDescriptor); @@ -104,7 +105,7 @@ describe('AAS Registry Integration Tests', () => { assetAdministrationShellDescriptor: createInvalidShellDescriptorWithEmptyId(), }); - expect(response.success).toBe(false); + assertApiFailure(response); if (!response.success) { expect(response.statusCode).toBe(400); expect(response.error.messages?.[0]?.code).toBe('400'); @@ -122,7 +123,7 @@ describe('AAS Registry Integration Tests', () => { configuration, assetAdministrationShellDescriptor: shellDescriptor, }); - expect(initialResponse.success).toBe(true); + assertApiResult(initialResponse); const duplicateResponse = await client.postAssetAdministrationShellDescriptor({ configuration, @@ -147,14 +148,14 @@ describe('AAS Registry Integration Tests', () => { configuration, assetAdministrationShellDescriptor: shellDescriptor, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const response = await client.getAssetAdministrationShellDescriptorById({ configuration, aasIdentifier: shellDescriptor.id, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data).toEqual(shellDescriptor); @@ -171,7 +172,7 @@ describe('AAS Registry Integration Tests', () => { aasIdentifier: undefined as unknown as string, }); - expect(response.success).toBe(false); + assertApiFailure(response); if (!response.success) { expect(response.statusCode).toBe(400); expect(response.error.messages?.[0]?.code).toBe('400'); @@ -188,7 +189,7 @@ describe('AAS Registry Integration Tests', () => { aasIdentifier: `https://example.com/ids/aas-desc/non-existing-${uniqueSuffix()}`, }); - expect(response.success).toBe(false); + assertApiFailure(response); if (!response.success) { expect(response.statusCode).toBe(404); expect(response.error.messages?.[0]?.code).toBe('404'); @@ -205,13 +206,13 @@ describe('AAS Registry Integration Tests', () => { configuration, assetAdministrationShellDescriptor: shellDescriptor, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const response = await client.getAllAssetAdministrationShellDescriptors({ configuration, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data.result.length).toBeGreaterThan(0); @@ -229,7 +230,7 @@ describe('AAS Registry Integration Tests', () => { limit: -1, }); - expect(response.success).toBe(false); + assertApiFailure(response); if (!response.success) { expect(response.statusCode).toBe(400); expect(response.error.messages?.[0]?.code).toBe('400'); @@ -246,7 +247,7 @@ describe('AAS Registry Integration Tests', () => { cursor: unavailableCursor(), }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data.pagedResult).toEqual({}); @@ -267,7 +268,7 @@ describe('AAS Registry Integration Tests', () => { assetAdministrationShellDescriptor: shellDescriptor, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(201); expect(response.data).toEqual(shellDescriptor); @@ -284,7 +285,7 @@ describe('AAS Registry Integration Tests', () => { configuration, assetAdministrationShellDescriptor: shellDescriptor, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const updatedShellDescriptor = createUniqueShellDescriptor(); updatedShellDescriptor.id = shellDescriptor.id; @@ -296,7 +297,7 @@ describe('AAS Registry Integration Tests', () => { assetAdministrationShellDescriptor: updatedShellDescriptor, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(204); expect(response.data).toBeUndefined(); @@ -316,7 +317,7 @@ describe('AAS Registry Integration Tests', () => { assetAdministrationShellDescriptor: shellDescriptor, }); - expect(response.success).toBe(false); + assertApiFailure(response); if (!response.success) { expect(response.statusCode).toBe(400); expect(response.error.messages?.[0]?.code).toBe('400'); @@ -333,14 +334,14 @@ describe('AAS Registry Integration Tests', () => { configuration, assetAdministrationShellDescriptor: shellDescriptor, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const response = await client.deleteAssetAdministrationShellDescriptorById({ configuration, aasIdentifier: shellDescriptor.id, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(204); expect(response.data).toBeUndefined(); @@ -357,7 +358,7 @@ describe('AAS Registry Integration Tests', () => { aasIdentifier: undefined as unknown as string, }); - expect(response.success).toBe(false); + assertApiFailure(response); if (!response.success) { expect(response.statusCode).toBe(400); expect(response.error.messages?.[0]?.code).toBe('400'); @@ -374,7 +375,7 @@ describe('AAS Registry Integration Tests', () => { aasIdentifier: `https://example.com/ids/aas-desc/non-existing-${uniqueSuffix()}`, }); - expect(response.success).toBe(false); + assertApiFailure(response); if (!response.success) { expect(response.statusCode).toBe(404); expect(response.error.messages?.[0]?.code).toBe('404'); @@ -392,7 +393,7 @@ describe('AAS Registry Integration Tests', () => { configuration, assetAdministrationShellDescriptor: shellDescriptor, }); - expect(createShellResponse.success).toBe(true); + assertApiResult(createShellResponse); const response = await client.postSubmodelDescriptorThroughSuperpath({ configuration, @@ -400,7 +401,7 @@ describe('AAS Registry Integration Tests', () => { submodelDescriptor, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(201); expect(response.data).toEqual(submodelDescriptor); @@ -420,7 +421,7 @@ describe('AAS Registry Integration Tests', () => { submodelDescriptor, }); - expect(response.success).toBe(false); + assertApiFailure(response); if (!response.success) { expect(response.statusCode).toBe(400); expect(response.error.messages?.[0]?.code).toBe('400'); @@ -438,7 +439,7 @@ describe('AAS Registry Integration Tests', () => { submodelDescriptor: createUniqueSubmodelDescriptor(), }); - expect(response.success).toBe(false); + assertApiFailure(response); if (!response.success) { expect(response.statusCode).toBe(404); expect(response.error.messages?.[0]?.code).toBe('404'); @@ -456,14 +457,14 @@ describe('AAS Registry Integration Tests', () => { configuration, assetAdministrationShellDescriptor: shellDescriptor, }); - expect(createShellResponse.success).toBe(true); + assertApiResult(createShellResponse); const initialResponse = await client.postSubmodelDescriptorThroughSuperpath({ configuration, aasIdentifier: shellDescriptor.id, submodelDescriptor, }); - expect(initialResponse.success).toBe(true); + assertApiResult(initialResponse); const duplicateResponse = await client.postSubmodelDescriptorThroughSuperpath({ configuration, @@ -490,13 +491,13 @@ describe('AAS Registry Integration Tests', () => { configuration, assetAdministrationShellDescriptor: shellDescriptor, }); - expect(createShellResponse.success).toBe(true); + assertApiResult(createShellResponse); const createSubmodelResponse = await client.postSubmodelDescriptorThroughSuperpath({ configuration, aasIdentifier: shellDescriptor.id, submodelDescriptor, }); - expect(createSubmodelResponse.success).toBe(true); + assertApiResult(createSubmodelResponse); const response = await client.getSubmodelDescriptorByIdThroughSuperpath({ configuration, @@ -504,7 +505,7 @@ describe('AAS Registry Integration Tests', () => { submodelIdentifier: submodelDescriptor.id, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data).toEqual(submodelDescriptor); @@ -522,7 +523,7 @@ describe('AAS Registry Integration Tests', () => { submodelIdentifier: createUniqueSubmodelDescriptor().id, }); - expect(response.success).toBe(false); + assertApiFailure(response); if (!response.success) { expect(response.statusCode).toBe(400); expect(response.error.messages?.[0]?.code).toBe('400'); @@ -539,7 +540,7 @@ describe('AAS Registry Integration Tests', () => { configuration, assetAdministrationShellDescriptor: shellDescriptor, }); - expect(createShellResponse.success).toBe(true); + assertApiResult(createShellResponse); const response = await client.getSubmodelDescriptorByIdThroughSuperpath({ configuration, @@ -547,7 +548,7 @@ describe('AAS Registry Integration Tests', () => { submodelIdentifier: `https://example.com/ids/sm-desc/non-existing-${uniqueSuffix()}`, }); - expect(response.success).toBe(false); + assertApiFailure(response); if (!response.success) { expect(response.statusCode).toBe(404); expect(response.error.messages?.[0]?.code).toBe('404'); @@ -565,20 +566,20 @@ describe('AAS Registry Integration Tests', () => { configuration, assetAdministrationShellDescriptor: shellDescriptor, }); - expect(createShellResponse.success).toBe(true); + assertApiResult(createShellResponse); const createSubmodelResponse = await client.postSubmodelDescriptorThroughSuperpath({ configuration, aasIdentifier: shellDescriptor.id, submodelDescriptor, }); - expect(createSubmodelResponse.success).toBe(true); + assertApiResult(createSubmodelResponse); const response = await client.getAllSubmodelDescriptorsThroughSuperpath({ configuration, aasIdentifier: shellDescriptor.id, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data.result.length).toBeGreaterThan(0); @@ -596,7 +597,7 @@ describe('AAS Registry Integration Tests', () => { configuration, assetAdministrationShellDescriptor: shellDescriptor, }); - expect(createShellResponse.success).toBe(true); + assertApiResult(createShellResponse); const response = await client.getAllSubmodelDescriptorsThroughSuperpath({ configuration, @@ -604,7 +605,7 @@ describe('AAS Registry Integration Tests', () => { limit: -1, }); - expect(response.success).toBe(false); + assertApiFailure(response); if (!response.success) { expect(response.statusCode).toBe(400); expect(response.error.messages?.[0]?.code).toBe('400'); @@ -621,7 +622,7 @@ describe('AAS Registry Integration Tests', () => { configuration, assetAdministrationShellDescriptor: shellDescriptor, }); - expect(createShellResponse.success).toBe(true); + assertApiResult(createShellResponse); const response = await client.getAllSubmodelDescriptorsThroughSuperpath({ configuration, @@ -629,7 +630,7 @@ describe('AAS Registry Integration Tests', () => { cursor: unavailableCursor(), }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data.pagedResult).toEqual({}); @@ -647,7 +648,7 @@ describe('AAS Registry Integration Tests', () => { aasIdentifier: `https://example.com/ids/aas-desc/non-existing-${uniqueSuffix()}`, }); - expect(response.success).toBe(false); + assertApiFailure(response); if (!response.success) { expect(response.statusCode).toBe(404); expect(response.error.messages?.[0]?.code).toBe('404'); @@ -665,7 +666,7 @@ describe('AAS Registry Integration Tests', () => { configuration, assetAdministrationShellDescriptor: shellDescriptor, }); - expect(createShellResponse.success).toBe(true); + assertApiResult(createShellResponse); const response = await client.putSubmodelDescriptorByIdThroughSuperpath({ configuration, @@ -674,7 +675,7 @@ describe('AAS Registry Integration Tests', () => { submodelDescriptor, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(201); expect(response.data).toEqual(submodelDescriptor); @@ -692,13 +693,13 @@ describe('AAS Registry Integration Tests', () => { configuration, assetAdministrationShellDescriptor: shellDescriptor, }); - expect(createShellResponse.success).toBe(true); + assertApiResult(createShellResponse); const createSubmodelResponse = await client.postSubmodelDescriptorThroughSuperpath({ configuration, aasIdentifier: shellDescriptor.id, submodelDescriptor, }); - expect(createSubmodelResponse.success).toBe(true); + assertApiResult(createSubmodelResponse); const updatedSubmodelDescriptor = createUniqueSubmodelDescriptor(); updatedSubmodelDescriptor.id = submodelDescriptor.id; @@ -711,7 +712,7 @@ describe('AAS Registry Integration Tests', () => { submodelDescriptor: updatedSubmodelDescriptor, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(204); expect(response.data).toBeUndefined(); @@ -732,7 +733,7 @@ describe('AAS Registry Integration Tests', () => { submodelDescriptor, }); - expect(response.success).toBe(false); + assertApiFailure(response); if (!response.success) { expect(response.statusCode).toBe(400); expect(response.error.messages?.[0]?.code).toBe('400'); @@ -753,7 +754,7 @@ describe('AAS Registry Integration Tests', () => { submodelDescriptor, }); - expect(response.success).toBe(false); + assertApiFailure(response); if (!response.success) { expect(response.statusCode).toBe(404); expect(response.error.messages?.[0]?.code).toBe('404'); @@ -771,13 +772,13 @@ describe('AAS Registry Integration Tests', () => { configuration, assetAdministrationShellDescriptor: shellDescriptor, }); - expect(createShellResponse.success).toBe(true); + assertApiResult(createShellResponse); const createSubmodelResponse = await client.postSubmodelDescriptorThroughSuperpath({ configuration, aasIdentifier: shellDescriptor.id, submodelDescriptor, }); - expect(createSubmodelResponse.success).toBe(true); + assertApiResult(createSubmodelResponse); const response = await client.deleteSubmodelDescriptorByIdThroughSuperpath({ configuration, @@ -785,7 +786,7 @@ describe('AAS Registry Integration Tests', () => { submodelIdentifier: submodelDescriptor.id, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(204); expect(response.data).toBeUndefined(); @@ -803,7 +804,7 @@ describe('AAS Registry Integration Tests', () => { submodelIdentifier: createUniqueSubmodelDescriptor().id, }); - expect(response.success).toBe(false); + assertApiFailure(response); if (!response.success) { expect(response.statusCode).toBe(400); expect(response.error.messages?.[0]?.code).toBe('400'); @@ -820,7 +821,7 @@ describe('AAS Registry Integration Tests', () => { configuration, assetAdministrationShellDescriptor: shellDescriptor, }); - expect(createShellResponse.success).toBe(true); + assertApiResult(createShellResponse); const response = await client.deleteSubmodelDescriptorByIdThroughSuperpath({ configuration, @@ -828,7 +829,7 @@ describe('AAS Registry Integration Tests', () => { submodelIdentifier: `https://example.com/ids/sm-desc/non-existing-${uniqueSuffix()}`, }); - expect(response.success).toBe(false); + assertApiFailure(response); if (!response.success) { expect(response.statusCode).toBe(404); expect(response.error.messages?.[0]?.code).toBe('404'); @@ -844,7 +845,7 @@ describe('AAS Registry Integration Tests', () => { configuration, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data).toBeDefined(); diff --git a/src/integration-tests/aasRepo.integration.test.ts b/src/integration-tests/aasRepo.integration.test.ts index cb5f1b65..b8057774 100644 --- a/src/integration-tests/aasRepo.integration.test.ts +++ b/src/integration-tests/aasRepo.integration.test.ts @@ -1,6 +1,7 @@ import { AasRepositoryClient } from '../clients/AasRepositoryClient'; import { Configuration } from '../generated'; import { createDescription, createGlobalAssetId, createTestShell } from './fixtures/aasFixtures'; +import { assertApiFailureCode, assertApiResult } from './fixtures/assertionHelpers'; import { createAasRepositoryPayloadFixtures } from './fixtures/requestPayloadFixtures'; import { createAttachmentBlob, @@ -27,13 +28,6 @@ describe('AAS Repository Integration Tests', () => { const { submodelReference, submodelMetadataPatch, submodelElementMetadataPatch, operationRequestValueOnly } = createAasRepositoryPayloadFixtures(testSubmodel.id); - type ApiResultLike = { - success: boolean; - statusCode?: number; - data?: unknown; - error?: unknown; - }; - const uniqueSuffix = (): string => `${Date.now()}-${Math.random().toString(36).slice(2)}`; function createUniqueShell(): ReturnType { @@ -67,24 +61,6 @@ describe('AAS Repository Integration Tests', () => { return `missingParent${Date.now()}${Math.random().toString(36).slice(2)}`; } - function assertApiResult(response: ApiResultLike): void { - expect(typeof response.success).toBe('boolean'); - if (response.success) { - expect(response.error).toBeUndefined(); - } else { - expect(response.error).toBeDefined(); - } - } - - function assertApiFailureCode(response: ApiResultLike, expectedCode: string): void { - expect(response.success).toBe(false); - if (!response.success) { - const errorPayload = response.error as { messages?: Array<{ code?: string }> } | undefined; - const messageCodes = (errorPayload?.messages ?? []).map((message) => message.code); - expect(messageCodes).toContain(expectedCode); - } - } - async function createScopedSuperpathFixture(submodelIdentifier?: string): Promise<{ shell: ReturnType; submodel: ReturnType; @@ -94,7 +70,7 @@ describe('AAS Repository Integration Tests', () => { configuration, assetAdministrationShell: shell, }); - expect(shellResponse.success).toBe(true); + assertApiResult(shellResponse); const submodel = createTestSubmodel(); submodel.id = submodelIdentifier ?? `${submodel.id}-aas-${uniqueSuffix()}`; @@ -112,7 +88,7 @@ describe('AAS Repository Integration Tests', () => { submodel, }); - expect(submodelResponse.success).toBe(true); + assertApiResult(submodelResponse); if (submodelResponse.success) { expect([201, 204]).toContain(submodelResponse.statusCode); } @@ -133,7 +109,7 @@ describe('AAS Repository Integration Tests', () => { }); try { - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(201); expect(response.data).toBeDefined(); @@ -172,7 +148,7 @@ describe('AAS Repository Integration Tests', () => { }); try { - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); if (createResponse.success) { expect(createResponse.statusCode).toBe(201); } @@ -202,7 +178,7 @@ describe('AAS Repository Integration Tests', () => { assetAdministrationShell: scopedShell, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const response = await client.getAssetAdministrationShellById({ configuration, @@ -210,7 +186,7 @@ describe('AAS Repository Integration Tests', () => { }); try { - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data).toBeDefined(); @@ -265,14 +241,14 @@ describe('AAS Repository Integration Tests', () => { assetAdministrationShell: scopedShell, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const response = await client.getAllAssetAdministrationShells({ configuration, }); try { - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data).toBeDefined(); @@ -311,14 +287,14 @@ describe('AAS Repository Integration Tests', () => { assetAdministrationShell: scopedShell, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const response = await client.getAllAssetAdministrationShellsReference({ configuration, }); try { - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data).toBeDefined(); @@ -356,7 +332,7 @@ describe('AAS Repository Integration Tests', () => { assetAdministrationShell: scopedShell, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const response = await client.getAssetAdministrationShellByIdReferenceAasRepository({ configuration, @@ -364,7 +340,7 @@ describe('AAS Repository Integration Tests', () => { }); try { - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data).toBeDefined(); @@ -421,7 +397,7 @@ describe('AAS Repository Integration Tests', () => { }); try { - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(201); } @@ -442,7 +418,7 @@ describe('AAS Repository Integration Tests', () => { configuration, assetAdministrationShell: updatedShell, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); if (createResponse.success) { expect(createResponse.statusCode).toBe(201); } @@ -458,7 +434,7 @@ describe('AAS Repository Integration Tests', () => { }); try { - expect(updateResponse.success).toBe(true); + assertApiResult(updateResponse); if (updateResponse.success) { expect(updateResponse.statusCode).toBe(204); } @@ -468,7 +444,7 @@ describe('AAS Repository Integration Tests', () => { aasIdentifier: updatedShell.id, }); - expect(fetchResponse.success).toBe(true); + assertApiResult(fetchResponse); if (fetchResponse.success) { expect(fetchResponse.data).toBeDefined(); expect(fetchResponse.data).toEqual(updatedShell); @@ -506,7 +482,7 @@ describe('AAS Repository Integration Tests', () => { assetAdministrationShell: scopedShell, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const response = await client.getAssetInformation({ configuration, @@ -514,7 +490,7 @@ describe('AAS Repository Integration Tests', () => { }); try { - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data).toBeDefined(); @@ -568,7 +544,7 @@ describe('AAS Repository Integration Tests', () => { assetAdministrationShell: scopedShell, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const updatedAssetInfo = scopedShell.assetInformation; updatedAssetInfo.globalAssetId = createGlobalAssetId(); @@ -580,7 +556,7 @@ describe('AAS Repository Integration Tests', () => { }); try { - expect(updateResponse.success).toBe(true); + assertApiResult(updateResponse); if (updateResponse.success) { expect(updateResponse.statusCode).toBe(204); } @@ -590,7 +566,7 @@ describe('AAS Repository Integration Tests', () => { aasIdentifier: scopedShell.id, }); - expect(fetchResponse.success).toBe(true); + assertApiResult(fetchResponse); if (fetchResponse.success) { expect(fetchResponse.data).toBeDefined(); expect(fetchResponse.data).toEqual(updatedAssetInfo); @@ -644,7 +620,7 @@ describe('AAS Repository Integration Tests', () => { configuration, assetAdministrationShell: scopedShell, }); - expect(createShellResponse.success).toBe(true); + assertApiResult(createShellResponse); const fileName = 'test_thumbnail.png'; const payload = 'base64_encoded_image_data'; @@ -658,7 +634,7 @@ describe('AAS Repository Integration Tests', () => { }); try { - expect(updateResponse.success).toBe(true); + assertApiResult(updateResponse); if (updateResponse.success) { expect(updateResponse.statusCode).toBe(204); } @@ -677,7 +653,7 @@ describe('AAS Repository Integration Tests', () => { configuration, assetAdministrationShell: scopedShell, }); - expect(createShellResponse.success).toBe(true); + assertApiResult(createShellResponse); const fileName = 'test_thumbnail.png'; const payload = 'base64_encoded_image_data'; @@ -688,7 +664,7 @@ describe('AAS Repository Integration Tests', () => { fileName, file, }); - expect(putResponse.success).toBe(true); + assertApiResult(putResponse); const fetchResponse = await client.getThumbnail({ configuration, @@ -696,7 +672,7 @@ describe('AAS Repository Integration Tests', () => { }); try { - expect(fetchResponse.success).toBe(true); + assertApiResult(fetchResponse); if (fetchResponse.success) { expect(fetchResponse.statusCode).toBe(200); expect(fetchResponse.data).toBeDefined(); @@ -787,7 +763,7 @@ describe('AAS Repository Integration Tests', () => { includeConceptDescriptions: true, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.data).toBeDefined(); expect(response.data.size).toBeGreaterThan(0); @@ -813,7 +789,7 @@ describe('AAS Repository Integration Tests', () => { configuration, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data).toBeDefined(); @@ -831,7 +807,7 @@ describe('AAS Repository Integration Tests', () => { configuration, assetAdministrationShell: scopedShell, }); - expect(createShellResponse.success).toBe(true); + assertApiResult(createShellResponse); const response = await client.getAllSubmodelReferences({ configuration, @@ -839,7 +815,7 @@ describe('AAS Repository Integration Tests', () => { }); try { - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data).toBeDefined(); @@ -891,7 +867,7 @@ describe('AAS Repository Integration Tests', () => { configuration, assetAdministrationShell: scopedShell, }); - expect(createShellResponse.success).toBe(true); + assertApiResult(createShellResponse); const response = await client.postSubmodelReference({ configuration, @@ -900,7 +876,7 @@ describe('AAS Repository Integration Tests', () => { }); try { - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(201); expect(response.data).toBeDefined(); @@ -956,7 +932,7 @@ describe('AAS Repository Integration Tests', () => { configuration, assetAdministrationShell: scopedShell, }); - expect(createShellResponse.success).toBe(true); + assertApiResult(createShellResponse); if (createShellResponse.success) { expect(createShellResponse.statusCode).toBe(201); } @@ -970,7 +946,7 @@ describe('AAS Repository Integration Tests', () => { }); try { - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); if (createResponse.success) { expect(createResponse.statusCode).toBe(201); } @@ -1017,7 +993,7 @@ describe('AAS Repository Integration Tests', () => { configuration, assetAdministrationShell: scopedShell, }); - expect(createShellResponse.success).toBe(true); + assertApiResult(createShellResponse); const response = await client.deleteSubmodelReferenceById({ configuration, @@ -1047,7 +1023,7 @@ describe('AAS Repository Integration Tests', () => { configuration, assetAdministrationShell: scopedShell, }); - expect(createShellResponse.success).toBe(true); + assertApiResult(createShellResponse); const createdSubmodel = createTestSubmodel(); createdSubmodel.id = `http://acplt.org/Submodels/Assets/TestAsset/Identification-${uniqueSuffix()}`; @@ -1061,7 +1037,7 @@ describe('AAS Repository Integration Tests', () => { }); try { - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(201); } @@ -1082,7 +1058,7 @@ describe('AAS Repository Integration Tests', () => { configuration, assetAdministrationShell: scopedShell, }); - expect(createShellResponse.success).toBe(true); + assertApiResult(createShellResponse); const seededSubmodel = createTestSubmodel(); seededSubmodel.id = `http://acplt.org/Submodels/Assets/TestAsset/Identification-${uniqueSuffix()}`; @@ -1094,7 +1070,7 @@ describe('AAS Repository Integration Tests', () => { submodelIdentifier: seededSubmodel.id, submodel: seededSubmodel, }); - expect(seedResponse.success).toBe(true); + assertApiResult(seedResponse); if (seedResponse.success) { expect(seedResponse.statusCode).toBe(201); } @@ -1108,7 +1084,7 @@ describe('AAS Repository Integration Tests', () => { }); try { - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(204); } @@ -1173,7 +1149,7 @@ describe('AAS Repository Integration Tests', () => { }); try { - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data).toBeDefined(); @@ -1238,7 +1214,7 @@ describe('AAS Repository Integration Tests', () => { }); try { - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(204); } @@ -1306,7 +1282,7 @@ describe('AAS Repository Integration Tests', () => { }); try { - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data).toBeDefined(); @@ -1376,7 +1352,7 @@ describe('AAS Repository Integration Tests', () => { }); try { - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(204); } @@ -1441,7 +1417,7 @@ describe('AAS Repository Integration Tests', () => { }); try { - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data).toBeDefined(); @@ -1506,7 +1482,7 @@ describe('AAS Repository Integration Tests', () => { }); try { - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(204); } @@ -1571,7 +1547,7 @@ describe('AAS Repository Integration Tests', () => { }); try { - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data).toBeDefined(); @@ -1635,7 +1611,7 @@ describe('AAS Repository Integration Tests', () => { }); try { - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data).toBeDefined(); @@ -1715,7 +1691,7 @@ describe('AAS Repository Integration Tests', () => { }); try { - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); } @@ -1800,7 +1776,7 @@ describe('AAS Repository Integration Tests', () => { }); try { - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(201); } @@ -1852,7 +1828,7 @@ describe('AAS Repository Integration Tests', () => { }); try { - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const duplicateResponse = await client.postSubmodelElementAasRepository({ configuration, @@ -1921,7 +1897,7 @@ describe('AAS Repository Integration Tests', () => { }); try { - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); } @@ -2000,7 +1976,7 @@ describe('AAS Repository Integration Tests', () => { }); try { - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); } @@ -2079,7 +2055,7 @@ describe('AAS Repository Integration Tests', () => { }); try { - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); } @@ -2158,7 +2134,7 @@ describe('AAS Repository Integration Tests', () => { }); try { - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); } @@ -2239,7 +2215,7 @@ describe('AAS Repository Integration Tests', () => { }); try { - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); } @@ -2328,7 +2304,7 @@ describe('AAS Repository Integration Tests', () => { }); try { - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(201); } @@ -2381,7 +2357,7 @@ describe('AAS Repository Integration Tests', () => { submodelElement: duplicateElement, }); try { - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const duplicateResponse = await client.postSubmodelElementByPathAasRepository({ configuration, @@ -2460,7 +2436,7 @@ describe('AAS Repository Integration Tests', () => { }); try { - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(201); } @@ -2487,7 +2463,7 @@ describe('AAS Repository Integration Tests', () => { }); try { - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); if (createResponse.success) { expect(createResponse.statusCode).toBe(201); } @@ -2500,7 +2476,7 @@ describe('AAS Repository Integration Tests', () => { submodelElement: updateElement, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(204); } @@ -2596,7 +2572,7 @@ describe('AAS Repository Integration Tests', () => { }); try { - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(204); } @@ -2686,7 +2662,7 @@ describe('AAS Repository Integration Tests', () => { }); try { - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); } @@ -2771,7 +2747,7 @@ describe('AAS Repository Integration Tests', () => { }); try { - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(204); } @@ -2856,7 +2832,7 @@ describe('AAS Repository Integration Tests', () => { }); try { - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); } @@ -2941,7 +2917,7 @@ describe('AAS Repository Integration Tests', () => { }); try { - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(204); } @@ -3026,7 +3002,7 @@ describe('AAS Repository Integration Tests', () => { }); try { - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); } @@ -3109,7 +3085,7 @@ describe('AAS Repository Integration Tests', () => { }); try { - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); } @@ -3173,7 +3149,7 @@ describe('AAS Repository Integration Tests', () => { }); try { - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect([200, 204]).toContain(response.statusCode); } else { @@ -3203,7 +3179,7 @@ describe('AAS Repository Integration Tests', () => { }); try { - expect(uploadResponse.success).toBe(true); + assertApiResult(uploadResponse); const response = await client.getFileByPathAasRepository({ configuration, @@ -3212,7 +3188,7 @@ describe('AAS Repository Integration Tests', () => { idShortPath: attachmentIdShortPath, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data).toBeDefined(); @@ -3286,7 +3262,7 @@ describe('AAS Repository Integration Tests', () => { }); try { - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(204); } @@ -3375,7 +3351,7 @@ describe('AAS Repository Integration Tests', () => { operationRequest: createTestOperationRequest(), }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect([200, 204]).toContain(response.statusCode); } @@ -3432,7 +3408,7 @@ describe('AAS Repository Integration Tests', () => { operationRequestValueOnly, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); } @@ -3565,7 +3541,7 @@ describe('AAS Repository Integration Tests', () => { handleId: 'coverage-handle-id', }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); } @@ -3622,7 +3598,7 @@ describe('AAS Repository Integration Tests', () => { handleId: 'coverage-handle-id', }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); } @@ -3679,7 +3655,7 @@ describe('AAS Repository Integration Tests', () => { handleId: 'coverage-handle-id', }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); } @@ -3740,7 +3716,7 @@ describe('AAS Repository Integration Tests', () => { }); try { - expect(uploadResponse.success).toBe(true); + assertApiResult(uploadResponse); const response = await client.deleteFileByPathAasRepository({ configuration, @@ -3749,7 +3725,7 @@ describe('AAS Repository Integration Tests', () => { idShortPath: attachmentIdShortPath, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); } else { @@ -3797,7 +3773,7 @@ describe('AAS Repository Integration Tests', () => { }); try { - expect(uploadResponse.success).toBe(true); + assertApiResult(uploadResponse); const deleteResponse = await client.deleteFileByPathAasRepository({ configuration, @@ -3806,7 +3782,7 @@ describe('AAS Repository Integration Tests', () => { idShortPath: attachmentIdShortPath, }); - expect(deleteResponse.success).toBe(true); + assertApiResult(deleteResponse); const response = await client.getFileByPathAasRepository({ configuration, @@ -3874,7 +3850,7 @@ describe('AAS Repository Integration Tests', () => { }); try { - expect(prepareResponse.success).toBe(true); + assertApiResult(prepareResponse); if (prepareResponse.success) { expect([201, 204]).toContain(prepareResponse.statusCode); } @@ -3886,7 +3862,7 @@ describe('AAS Repository Integration Tests', () => { idShortPath: `parentCollection.${updateElement.idShort}`, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(204); } @@ -3991,7 +3967,7 @@ describe('AAS Repository Integration Tests', () => { }); try { - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(204); } @@ -4014,7 +3990,7 @@ describe('AAS Repository Integration Tests', () => { }); try { - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(204); } @@ -4066,7 +4042,7 @@ describe('AAS Repository Integration Tests', () => { assetAdministrationShell: shell, }); - expect(createShellResponse.success).toBe(true); + assertApiResult(createShellResponse); const putThumbnailResponse = await client.putThumbnail({ configuration, @@ -4081,8 +4057,8 @@ describe('AAS Repository Integration Tests', () => { }); try { - expect(putThumbnailResponse.success).toBe(true); - expect(response.success).toBe(true); + assertApiResult(putThumbnailResponse); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(204); } @@ -4103,14 +4079,14 @@ describe('AAS Repository Integration Tests', () => { file: new Blob(['thumb'], { type: 'image/png' }), }); - expect(prepareResponse.success).toBe(true); + assertApiResult(prepareResponse); const response = await client.deleteThumbnail({ configuration, aasIdentifier: testShell.id, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); } @@ -4143,7 +4119,7 @@ describe('AAS Repository Integration Tests', () => { assetAdministrationShell: shell, }); - expect(createShellResponse.success).toBe(true); + assertApiResult(createShellResponse); const response = await client.deleteAssetAdministrationShellById({ configuration, @@ -4151,7 +4127,7 @@ describe('AAS Repository Integration Tests', () => { }); try { - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(204); } diff --git a/src/integration-tests/aasService.integration.test.ts b/src/integration-tests/aasService.integration.test.ts index 06dd3f12..dbc14309 100644 --- a/src/integration-tests/aasService.integration.test.ts +++ b/src/integration-tests/aasService.integration.test.ts @@ -11,6 +11,7 @@ import { base64Encode } from '../lib/base64Url'; import { AasService } from '../services/AasService'; import { createGlobalAssetIdFromAasId, createTestShell } from './fixtures/aasFixtures'; import { createTestShellDescriptor } from './fixtures/aasregistryFixtures'; +import { assertApiFailure, assertApiResult } from './fixtures/assertionHelpers'; describe('AasService Integration Tests', () => { const aasRegistryConfig = new Configuration({ basePath: 'http://localhost:8084' }); @@ -52,7 +53,7 @@ describe('AasService Integration Tests', () => { shell: testShell, }); - expect(createResult.success).toBe(true); + assertApiResult(createResult); if (createResult.success) { expect(createResult.data.shell).toBeDefined(); expect(createResult.data.shell.id).toBe(testShell.id); @@ -71,14 +72,14 @@ describe('AasService Integration Tests', () => { const createResult = await aasService.createAas({ shell: testShell, }); - expect(createResult.success).toBe(true); + assertApiResult(createResult); // Then deregister const deregisterResult = await aasService.deleteAas({ aasIdentifier: testShell.id, }); - expect(deregisterResult.success).toBe(true); + assertApiResult(deregisterResult); }); test('should fail to deregister non-existent AAS', async () => { @@ -86,7 +87,7 @@ describe('AasService Integration Tests', () => { aasIdentifier: 'non-existent-id', }); - expect(deregisterResult.success).toBe(false); + assertApiFailure(deregisterResult); }); }); @@ -107,7 +108,7 @@ describe('AasService Integration Tests', () => { shell: testShell, }); - expect(updateResult.success).toBe(true); + assertApiResult(updateResult); if (updateResult.success) { expect(updateResult.data.shell).toBeDefined(); expect(updateResult.data.shell.id).toBe(testShell.id); @@ -134,7 +135,7 @@ describe('AasService Integration Tests', () => { aasIdentifier: testShell.id, }); - expect(endpointResult.success).toBe(true); + assertApiResult(endpointResult); if (endpointResult.success) { expect(endpointResult.data).toContain('/shells/'); expect(endpointResult.data).toContain('http://localhost:8081'); @@ -159,7 +160,7 @@ describe('AasService Integration Tests', () => { useRegistry: false, }); - expect(endpointResult.success).toBe(true); + assertApiResult(endpointResult); if (endpointResult.success) { expect(endpointResult.data).toContain('/shells/'); expect(endpointResult.data).toContain('http://localhost:8081'); @@ -184,7 +185,7 @@ describe('AasService Integration Tests', () => { aasIdentifier: testShell.id, }); - expect(endpointResult.success).toBe(true); + assertApiResult(endpointResult); if (endpointResult.success) { // Use endpoint to fetch AAS @@ -192,7 +193,7 @@ describe('AasService Integration Tests', () => { endpoint: endpointResult.data, }); - expect(shellResult.success).toBe(true); + assertApiResult(shellResult); if (shellResult.success) { expect(shellResult.data.shell).toBeDefined(); expect(shellResult.data.shell.id).toBe(testShell.id); @@ -210,7 +211,7 @@ describe('AasService Integration Tests', () => { endpoint: invalidEndpoint, }); - expect(result.success).toBe(false); + assertApiFailure(result); if (!result.success) { expect(result.error.errorType).toBe('InvalidEndpoint'); } @@ -228,7 +229,7 @@ describe('AasService Integration Tests', () => { const result = await aasService.getAasList({ preferRegistry: true }); - expect(result.success).toBe(true); + assertApiResult(result); if (result.success) { expect(result.data.source).toBe('registry'); expect(result.data.shells).toBeDefined(); @@ -253,7 +254,7 @@ describe('AasService Integration Tests', () => { const result = await aasService.getAasList({ preferRegistry: false }); - expect(result.success).toBe(true); + assertApiResult(result); if (result.success) { expect(result.data.source).toBe('repository'); expect(result.data.shells).toBeDefined(); @@ -275,7 +276,7 @@ describe('AasService Integration Tests', () => { const result = await aasService.getAasList({ limit: 1, preferRegistry: true }); - expect(result.success).toBe(true); + assertApiResult(result); if (result.success) { expect(result.data.source).toBe('registry'); // The limit parameter should restrict the result to at most 1 item @@ -302,7 +303,7 @@ describe('AasService Integration Tests', () => { useRegistryEndpoint: true, }); - expect(result.success).toBe(true); + assertApiResult(result); if (result.success) { expect(result.data.shell).toBeDefined(); expect(result.data.shell.id).toBe(testShell.id); @@ -329,7 +330,7 @@ describe('AasService Integration Tests', () => { useRegistryEndpoint: false, }); - expect(result.success).toBe(true); + assertApiResult(result); if (result.success) { expect(result.data.shell).toBeDefined(); expect(result.data.shell.id).toBe(testShell.id); @@ -346,7 +347,7 @@ describe('AasService Integration Tests', () => { useRegistryEndpoint: false, }); - expect(result.success).toBe(false); + assertApiFailure(result); }); }); @@ -368,7 +369,7 @@ describe('AasService Integration Tests', () => { // Try to get list with bad registry - should fall back to repository const result = await serviceWithBadRegistry.getAasList(); - expect(result.success).toBe(true); + assertApiResult(result); if (result.success) { expect(result.data.source).toBe('repository'); expect(result.data.shells).toBeDefined(); @@ -385,7 +386,7 @@ describe('AasService Integration Tests', () => { test('should work with only repository configuration', async () => { const result = await repoOnlyService.getAasList(); - expect(result.success).toBe(true); + assertApiResult(result); if (result.success) { expect(result.data.source).toBe('repository'); } @@ -398,7 +399,7 @@ describe('AasService Integration Tests', () => { test('should fail when no configuration is provided', async () => { const result = await emptyService.getAasList(); - expect(result.success).toBe(false); + assertApiFailure(result); if (!result.success) { expect(result.error.errorType).toBe('ConfigurationError'); } @@ -418,7 +419,7 @@ describe('AasService Integration Tests', () => { includeSubmodels: true, }); - expect(result.success).toBe(true); + assertApiResult(result); if (result.success) { expect(result.data.shells).toBeDefined(); expect(result.data.submodels).toBeDefined(); @@ -441,7 +442,7 @@ describe('AasService Integration Tests', () => { includeSubmodels: false, }); - expect(result.success).toBe(true); + assertApiResult(result); if (result.success) { expect(result.data.shells).toBeDefined(); expect(result.data.submodels).toBeUndefined(); @@ -464,7 +465,7 @@ describe('AasService Integration Tests', () => { includeSubmodels: true, }); - expect(result.success).toBe(true); + assertApiResult(result); if (result.success) { expect(result.data.shell).toBeDefined(); expect(result.data.submodels).toBeDefined(); @@ -486,7 +487,7 @@ describe('AasService Integration Tests', () => { aasIdentifier: testShell.id, }); - expect(endpointResult.success).toBe(true); + assertApiResult(endpointResult); if (endpointResult.success) { // Get by endpoint with submodels @@ -495,7 +496,7 @@ describe('AasService Integration Tests', () => { includeSubmodels: true, }); - expect(result.success).toBe(true); + assertApiResult(result); if (result.success) { expect(result.data.shell).toBeDefined(); expect(result.data.submodels).toBeDefined(); @@ -529,7 +530,7 @@ describe('AasService Integration Tests', () => { includeConceptDescriptions: true, }); - expect(result.success).toBe(true); + assertApiResult(result); if (result.success) { expect(result.data.shells.length).toBeGreaterThan(0); expect(result.data.submodels).toBeDefined(); @@ -554,7 +555,7 @@ describe('AasService Integration Tests', () => { includeConceptDescriptions: true, }); - expect(result.success).toBe(true); + assertApiResult(result); if (result.success) { expect(result.data.shell.id).toBe(testShell.id); expect(result.data.submodels).toBeDefined(); @@ -580,7 +581,7 @@ describe('AasService Integration Tests', () => { includeConceptDescriptions: true, }); - expect(result.success).toBe(true); + assertApiResult(result); if (result.success) { expect(result.data.shell.id).toBe(testShell.id); expect(result.data.submodels).toBeDefined(); @@ -601,7 +602,7 @@ describe('AasService Integration Tests', () => { // Create AAS const createResult = await aasServiceWithDiscovery.createAas({ shell: testShell }); - expect(createResult.success).toBe(true); + assertApiResult(createResult); // Register asset links (assuming the shell has asset information with specific asset IDs) const assetIds = [ @@ -620,7 +621,7 @@ describe('AasService Integration Tests', () => { // Find AAS by asset IDs const result = await aasServiceWithDiscovery.getAasByAssetId({ assetIds }); - expect(result.success).toBe(true); + assertApiResult(result); if (result.success) { expect(result.data.shells.length).toBeGreaterThan(0); expect(result.data.aasIds).toContain(testShell.id); @@ -641,7 +642,7 @@ describe('AasService Integration Tests', () => { const result = await aasServiceWithDiscovery.getAasByAssetId({ assetIds }); - expect(result.success).toBe(true); + assertApiResult(result); if (result.success) { expect(result.data.shells).toHaveLength(0); expect(result.data.aasIds).toHaveLength(0); @@ -675,7 +676,7 @@ describe('AasService Integration Tests', () => { // Find AAS by the shared asset ID const result = await aasServiceWithDiscovery.getAasByAssetId({ assetIds: [sharedAssetId] }); - expect(result.success).toBe(true); + assertApiResult(result); if (result.success) { expect(result.data.shells.length).toBeGreaterThanOrEqual(2); expect(result.data.aasIds).toContain(testShell1.id); @@ -700,7 +701,7 @@ describe('AasService Integration Tests', () => { const result = await aasService.getAasByAssetId({ assetIds }); - expect(result.success).toBe(false); + assertApiFailure(result); if (!result.success) { expect(result.error.errorType).toBe('ConfigurationError'); expect(result.error.message).toContain('Discovery service configuration not provided'); @@ -729,7 +730,7 @@ describe('AasService Integration Tests', () => { includeSubmodels: true, }); - expect(result.success).toBe(true); + assertApiResult(result); if (result.success) { expect(result.data.shells.length).toBeGreaterThan(0); // Submodels would be included if the AAS had any @@ -768,7 +769,7 @@ describe('AasService Integration Tests', () => { // Resolve reference const result = await serviceWithSubmodels.resolveReference({ reference }); - expect(result.success).toBe(true); + assertApiResult(result); if (result.success) { expect(result.data.aasEndpoint).toBeDefined(); expect(result.data.aasEndpoint).toContain('http://localhost:8081/shells/'); @@ -779,7 +780,7 @@ describe('AasService Integration Tests', () => { const shellByEndpoint = await serviceWithSubmodels.getAasByEndpoint({ endpoint: result.data.aasEndpoint!, }); - expect(shellByEndpoint.success).toBe(true); + assertApiResult(shellByEndpoint); if (shellByEndpoint.success) { expect(shellByEndpoint.data.shell.id).toBe(testShell.id); } @@ -799,7 +800,7 @@ describe('AasService Integration Tests', () => { const result = await serviceWithSubmodels.resolveReference({ reference }); // Should still return success with constructed endpoint (from repository config fallback) - expect(result.success).toBe(true); + assertApiResult(result); if (result.success) { // Endpoint is constructed from repository config even if AAS doesn't exist expect(result.data.aasEndpoint).toBeDefined(); @@ -809,7 +810,7 @@ describe('AasService Integration Tests', () => { const shellByEndpoint = await serviceWithSubmodels.getAasByEndpoint({ endpoint: result.data.aasEndpoint!, }); - expect(shellByEndpoint.success).toBe(false); + assertApiFailure(shellByEndpoint); } }); @@ -820,7 +821,7 @@ describe('AasService Integration Tests', () => { const result = await serviceWithSubmodels.resolveReference({ reference }); - expect(result.success).toBe(false); + assertApiFailure(result); if (!result.success) { expect(result.error.errorType).toBe('UnsupportedReferenceType'); } @@ -831,7 +832,7 @@ describe('AasService Integration Tests', () => { const result = await serviceWithSubmodels.resolveReference({ reference }); - expect(result.success).toBe(false); + assertApiFailure(result); if (!result.success) { expect(result.error.errorType).toBe('InvalidReference'); } @@ -851,7 +852,7 @@ describe('AasService Integration Tests', () => { // Resolve reference with useRegistry=false in getAasEndpointById const result = await serviceWithSubmodels.resolveReference({ reference }); - expect(result.success).toBe(true); + assertApiResult(result); if (result.success) { // Should construct endpoint from repository config expect(result.data.aasEndpoint).toBeDefined(); diff --git a/src/integration-tests/aasxFile.integration.test.ts b/src/integration-tests/aasxFile.integration.test.ts index 2530156a..6027939b 100644 --- a/src/integration-tests/aasxFile.integration.test.ts +++ b/src/integration-tests/aasxFile.integration.test.ts @@ -4,6 +4,7 @@ import { Configuration } from '../generated'; import { AasxFileService } from '../generated'; import { base64Encode } from '../lib/base64Url'; import { createTestShell } from './fixtures/aasxFileFixtures'; +import { assertApiFailure, assertApiResult } from './fixtures/assertionHelpers'; import { getIntegrationBasePath } from './testEngineConfig'; type StoredPackageDescription = AasxFileService.PackageDescription & { packageId: string }; @@ -33,10 +34,7 @@ describe('AASX File Server Integration Tests', () => { file: createPackageFile(), }); - expect(response.success).toBe(true); - if (!response.success) { - throw new Error('Failed to create AASX package fixture'); - } + assertApiResult(response, 'Create AASX package fixture'); expect(response.data.packageId).toBeDefined(); if (!response.data.packageId) { @@ -68,7 +66,7 @@ describe('AASX File Server Integration Tests', () => { configuration, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(Array.isArray(response.data.result)).toBe(true); @@ -87,7 +85,7 @@ describe('AASX File Server Integration Tests', () => { limit: -1, }); - expect(response.success).toBe(false); + assertApiFailure(response); if (!response.success) { expect(response.statusCode).toBe(400); expect(response.error.messages?.[0]?.code).toBe('400'); @@ -104,7 +102,7 @@ describe('AASX File Server Integration Tests', () => { cursor: unavailableCursor(), }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data.pagedResult).toEqual({}); @@ -126,7 +124,7 @@ describe('AASX File Server Integration Tests', () => { file: createPackageFile(), }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(201); expect(response.data.packageId).toBeDefined(); @@ -148,7 +146,7 @@ describe('AASX File Server Integration Tests', () => { file: new Blob([], { type: 'application/asset-administration-shell-package' }), }); - expect(response.success).toBe(false); + assertApiFailure(response); if (!response.success) { expect(response.statusCode).toBe(400); expect(response.error.messages?.[0]?.code).toBe('400'); @@ -171,7 +169,7 @@ describe('AASX File Server Integration Tests', () => { fileName, file, }); - expect(initialResponse.success).toBe(true); + assertApiResult(initialResponse); if (initialResponse.success && initialResponse.data.packageId) { createdPackageIds.push(initialResponse.data.packageId); } @@ -208,7 +206,7 @@ describe('AASX File Server Integration Tests', () => { packageId: packageDescription.packageId, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data.size).toBeGreaterThan(0); @@ -225,7 +223,7 @@ describe('AASX File Server Integration Tests', () => { packageId: undefined as unknown as string, }); - expect(response.success).toBe(false); + assertApiFailure(response); if (!response.success) { expect(response.statusCode).toBe(400); expect(response.error.messages?.[0]?.code).toBe('400'); @@ -242,7 +240,7 @@ describe('AASX File Server Integration Tests', () => { packageId: `non-existing-${uniqueSuffix()}`, }); - expect(response.success).toBe(false); + assertApiFailure(response); if (!response.success) { expect(response.statusCode).toBe(404); expect(response.error.messages?.[0]?.code).toBe('404'); @@ -267,7 +265,7 @@ describe('AASX File Server Integration Tests', () => { file: createPackageFile(), }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(201); createdPackageIds.push(packageId); @@ -291,7 +289,7 @@ describe('AASX File Server Integration Tests', () => { file: createPackageFile(), }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(204); expect(response.data).toBeUndefined(); @@ -310,7 +308,7 @@ describe('AASX File Server Integration Tests', () => { file: createPackageFile(), }); - expect(response.success).toBe(false); + assertApiFailure(response); if (!response.success) { expect(response.statusCode).toBe(400); expect(response.error.messages?.[0]?.code).toBe('400'); @@ -332,7 +330,7 @@ describe('AASX File Server Integration Tests', () => { }); createdPackageIds.splice(createdPackageIds.indexOf(packageDescription.packageId), 1); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(204); expect(response.data).toBeUndefined(); @@ -349,7 +347,7 @@ describe('AASX File Server Integration Tests', () => { packageId: undefined as unknown as string, }); - expect(response.success).toBe(false); + assertApiFailure(response); if (!response.success) { expect(response.statusCode).toBe(400); expect(response.error.messages?.[0]?.code).toBe('400'); @@ -366,7 +364,7 @@ describe('AASX File Server Integration Tests', () => { packageId: `non-existing-${uniqueSuffix()}`, }); - expect(response.success).toBe(false); + assertApiFailure(response); if (!response.success) { expect(response.statusCode).toBe(404); expect(response.error.messages?.[0]?.code).toBe('404'); @@ -382,7 +380,7 @@ describe('AASX File Server Integration Tests', () => { configuration, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data).toBeDefined(); @@ -401,7 +399,7 @@ describe('AASX File Server Integration Tests', () => { configuration, }); - expect(response.success).toBe(false); + assertApiFailure(response); if (!response.success) { expect(response.statusCode).toBe(400); expect(response.error.messages?.[0]?.code).toBe('400'); @@ -419,7 +417,7 @@ describe('AASX File Server Integration Tests', () => { configuration, }); - expect(response.success).toBe(false); + assertApiFailure(response); if (!response.success) { expect(response.statusCode).toBe(404); expect(response.error.messages?.[0]?.code).toBe('404'); diff --git a/src/integration-tests/conceptDescriptionRepo.integration.test.ts b/src/integration-tests/conceptDescriptionRepo.integration.test.ts index 1875a44b..45e79d48 100644 --- a/src/integration-tests/conceptDescriptionRepo.integration.test.ts +++ b/src/integration-tests/conceptDescriptionRepo.integration.test.ts @@ -1,6 +1,7 @@ import { ConceptDescriptionRepositoryClient } from '../clients/ConceptDescriptionRepositoryClient'; import { Configuration } from '../generated'; import { base64Encode } from '../lib/base64Url'; +import { assertApiFailure, assertApiResult } from './fixtures/assertionHelpers'; import { createDescription, createTestCD } from './fixtures/conceptDescriptionFixtures'; import { createPerTestCleanupRunner } from './fixtures/testCleanup'; import { getIntegrationBasePath } from './testEngineConfig'; @@ -50,7 +51,7 @@ describe('Concept Description Repository Integration Tests', () => { conceptDescription, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(201); expect(response.data).toEqual(conceptDescription); @@ -83,7 +84,7 @@ describe('Concept Description Repository Integration Tests', () => { configuration, conceptDescription, }); - expect(initialResponse.success).toBe(true); + assertApiResult(initialResponse); const duplicateResponse = await client.postConceptDescription({ configuration, @@ -108,14 +109,14 @@ describe('Concept Description Repository Integration Tests', () => { configuration, conceptDescription, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const response = await client.getConceptDescriptionById({ configuration, cdIdentifier: conceptDescription.id, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data).toEqual(conceptDescription); @@ -132,7 +133,7 @@ describe('Concept Description Repository Integration Tests', () => { cdIdentifier: undefined as unknown as string, }); - expect(response.success).toBe(false); + assertApiFailure(response); if (!response.success) { expect(response.statusCode).toBe(400); expect(response.error.messages?.[0]?.code).toBe('400'); @@ -149,7 +150,7 @@ describe('Concept Description Repository Integration Tests', () => { cdIdentifier: `https://example.com/ids/cd/non-existing-${uniqueSuffix()}`, }); - expect(response.success).toBe(false); + assertApiFailure(response); if (!response.success) { expect(response.statusCode).toBe(404); expect(response.error.messages?.[0]?.code).toBe('404'); @@ -166,13 +167,13 @@ describe('Concept Description Repository Integration Tests', () => { configuration, conceptDescription, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const response = await client.getAllConceptDescriptions({ configuration, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data.result.length).toBeGreaterThan(0); @@ -190,7 +191,7 @@ describe('Concept Description Repository Integration Tests', () => { limit: -1, }); - expect(response.success).toBe(false); + assertApiFailure(response); if (!response.success) { expect(response.statusCode).toBe(400); expect(response.error.messages?.[0]?.code).toBe('400'); @@ -207,7 +208,7 @@ describe('Concept Description Repository Integration Tests', () => { cursor: unavailableCursor(), }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data.pagedResult).toEqual({}); @@ -228,7 +229,7 @@ describe('Concept Description Repository Integration Tests', () => { conceptDescription, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(201); expect(response.data).toEqual(conceptDescription); @@ -244,7 +245,7 @@ describe('Concept Description Repository Integration Tests', () => { conceptDescription, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(201); expect(response.data).toEqual(conceptDescription); @@ -261,7 +262,7 @@ describe('Concept Description Repository Integration Tests', () => { configuration, conceptDescription, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const updatedConceptDescription = createUniqueConceptDescription(); updatedConceptDescription.id = conceptDescription.id; @@ -273,7 +274,7 @@ describe('Concept Description Repository Integration Tests', () => { conceptDescription: updatedConceptDescription, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(204); expect(response.data).toBeUndefined(); @@ -286,7 +287,7 @@ describe('Concept Description Repository Integration Tests', () => { configuration, conceptDescription, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const updatedConceptDescription = createUniqueConceptDescription(); updatedConceptDescription.id = conceptDescription.id; @@ -298,7 +299,7 @@ describe('Concept Description Repository Integration Tests', () => { conceptDescription: updatedConceptDescription, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(204); expect(response.data).toBeUndefined(); @@ -316,7 +317,7 @@ describe('Concept Description Repository Integration Tests', () => { conceptDescription: createUniqueConceptDescription(), }); - expect(response.success).toBe(false); + assertApiFailure(response); if (!response.success) { expect(response.statusCode).toBe(400); expect(response.error.messages?.[0]?.code).toBe('400'); @@ -333,14 +334,14 @@ describe('Concept Description Repository Integration Tests', () => { configuration, conceptDescription, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const response = await client.deleteConceptDescriptionById({ configuration, cdIdentifier: conceptDescription.id, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(204); expect(response.data).toBeUndefined(); @@ -357,7 +358,7 @@ describe('Concept Description Repository Integration Tests', () => { cdIdentifier: undefined as unknown as string, }); - expect(response.success).toBe(false); + assertApiFailure(response); if (!response.success) { expect(response.statusCode).toBe(400); expect(response.error.messages?.[0]?.code).toBe('400'); @@ -374,7 +375,7 @@ describe('Concept Description Repository Integration Tests', () => { cdIdentifier: `https://example.com/ids/cd/non-existing-${uniqueSuffix()}`, }); - expect(response.success).toBe(false); + assertApiFailure(response); if (!response.success) { expect(response.statusCode).toBe(404); expect(response.error.messages?.[0]?.code).toBe('404'); @@ -393,7 +394,7 @@ describe('Concept Description Repository Integration Tests', () => { includeConceptDescriptions: true, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data).toBeDefined(); @@ -413,7 +414,7 @@ describe('Concept Description Repository Integration Tests', () => { aasIds: [''], }); - expect(response.success).toBe(false); + assertApiFailure(response); if (!response.success) { expect(response.statusCode).toBe(400); expect(response.error.messages?.[0]?.code).toBe('400'); @@ -429,7 +430,7 @@ describe('Concept Description Repository Integration Tests', () => { configuration, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data).toBeDefined(); diff --git a/src/integration-tests/fixtures/assertionHelpers.ts b/src/integration-tests/fixtures/assertionHelpers.ts new file mode 100644 index 00000000..bade1683 --- /dev/null +++ b/src/integration-tests/fixtures/assertionHelpers.ts @@ -0,0 +1,149 @@ +type ApiErrorMessage = { + code?: unknown; + message?: unknown; +}; + +export type ApiResultLike = { + success: boolean; + statusCode?: number; + data?: unknown; + error?: unknown; +}; + +const MAX_FALLBACK_LENGTH = 400; + +function asNonEmptyString(value: unknown): string | undefined { + if (typeof value === 'string') { + const trimmed = value.trim(); + return trimmed.length > 0 ? trimmed : undefined; + } + + if (typeof value === 'number' || typeof value === 'boolean') { + return String(value); + } + + return undefined; +} + +function compactUnique(values: string[]): string[] { + return [...new Set(values.map((value) => value.trim()).filter(Boolean))]; +} + +function stringifyFallback(value: unknown): string { + try { + const serialized = JSON.stringify(value); + if (!serialized) { + return 'unstructured error payload'; + } + + return serialized.length > MAX_FALLBACK_LENGTH + ? `${serialized.slice(0, MAX_FALLBACK_LENGTH)}...` + : serialized; + } catch { + return 'unstructured error payload'; + } +} + +function extractMessages(error: unknown): ApiErrorMessage[] { + if (!error || typeof error !== 'object') { + const inlineMessage = asNonEmptyString(error); + return inlineMessage ? [{ message: inlineMessage }] : []; + } + + const payload = error as { messages?: unknown; code?: unknown; message?: unknown }; + if (Array.isArray(payload.messages)) { + return payload.messages + .map((entry) => { + if (entry && typeof entry === 'object') { + return entry as ApiErrorMessage; + } + + const inlineMessage = asNonEmptyString(entry); + return inlineMessage ? ({ message: inlineMessage } as ApiErrorMessage) : undefined; + }) + .filter((entry): entry is ApiErrorMessage => Boolean(entry)); + } + + if (payload.code !== undefined || payload.message !== undefined) { + return [payload]; + } + + return []; +} + +function summarizeError(error: unknown): { codes: string[]; messages: string[] } { + const messageEntries = extractMessages(error); + const codes = compactUnique( + messageEntries + .map((entry) => asNonEmptyString(entry.code)) + .filter((value): value is string => value !== undefined) + ); + const messages = compactUnique( + messageEntries + .map((entry) => asNonEmptyString(entry.message)) + .filter((value): value is string => value !== undefined) + ); + + if (codes.length > 0 || messages.length > 0) { + return { codes, messages }; + } + + return { + codes: [], + messages: [stringifyFallback(error)], + }; +} + +function formatFailureContext(response: ApiResultLike): string { + const { codes, messages } = summarizeError(response.error); + const status = response.statusCode ?? 'n/a'; + const codeSummary = codes.length > 0 ? codes.join(', ') : 'none'; + const messageSummary = messages.length > 0 ? messages.join(' | ') : 'none'; + return `status=${status}; errorCodes=${codeSummary}; errorMessages=${messageSummary}`; +} + +export function assertApiResult(response: ApiResultLike, context = 'API request'): void { + if (typeof response.success !== 'boolean') { + throw new Error(`${context} produced an invalid result: success flag is not a boolean.`); + } + + if (!response.success) { + throw new Error(`${context} failed: ${formatFailureContext(response)}`); + } + + if (response.error !== undefined) { + throw new Error(`${context} unexpectedly returned an error payload despite success.`); + } +} + +export function assertApiFailure(response: ApiResultLike, context = 'API request'): void { + if (typeof response.success !== 'boolean') { + throw new Error(`${context} produced an invalid result: success flag is not a boolean.`); + } + + if (response.success) { + throw new Error(`${context} unexpectedly succeeded while a failure was expected.`); + } + + // Keep failure assertion resilient even when some backends return sparse payloads. + if (response.error === undefined) { + throw new Error(`${context} failed but did not return an error payload. status=${response.statusCode ?? 'n/a'}`); + } +} + +export function assertApiFailureCode(response: ApiResultLike, expectedCode: string, context = 'API request'): void { + if (typeof response.success !== 'boolean') { + throw new Error(`${context} produced an invalid result: success flag is not a boolean.`); + } + + if (response.success) { + throw new Error(`${context} unexpectedly succeeded while expecting error code ${expectedCode}.`); + } + + const { codes } = summarizeError(response.error); + if (!codes.includes(expectedCode)) { + throw new Error( + `${context} failed with unexpected error codes. Expected ${expectedCode}; received ${codes.join(', ') || 'none'}. ${formatFailureContext(response)}` + ); + } +} diff --git a/src/integration-tests/submodelRegistry.integration.test.ts b/src/integration-tests/submodelRegistry.integration.test.ts index fd4f760f..11c51f58 100644 --- a/src/integration-tests/submodelRegistry.integration.test.ts +++ b/src/integration-tests/submodelRegistry.integration.test.ts @@ -2,6 +2,7 @@ import { SubmodelRegistryClient } from '../clients/SubmodelRegistryClient'; import { Configuration } from '../generated'; import { base64Encode } from '../lib/base64Url'; import { createDisplayName, createTestSubmodelDescriptor } from './fixtures/aasregistryFixtures'; +import { assertApiFailure, assertApiResult } from './fixtures/assertionHelpers'; import { createPerTestCleanupRunner } from './fixtures/testCleanup'; import { getIntegrationBasePath } from './testEngineConfig'; @@ -50,7 +51,7 @@ describe('Submodel Registry Integration Tests', () => { submodelDescriptor, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(201); expect(response.data).toBeDefined(); @@ -71,7 +72,7 @@ describe('Submodel Registry Integration Tests', () => { submodelDescriptor: invalidSubmodelDescriptor, }); - expect(response.success).toBe(false); + assertApiFailure(response); if (!response.success) { expect(response.statusCode).toBe(400); expect(response.error.messages?.[0]?.code).toBe('400'); @@ -89,7 +90,7 @@ describe('Submodel Registry Integration Tests', () => { configuration, submodelDescriptor, }); - expect(initialResponse.success).toBe(true); + assertApiResult(initialResponse); const duplicateResponse = await client.postSubmodelDescriptor({ configuration, @@ -114,14 +115,14 @@ describe('Submodel Registry Integration Tests', () => { configuration, submodelDescriptor, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const response = await client.getSubmodelDescriptorById({ configuration, submodelIdentifier: submodelDescriptor.id, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data).toBeDefined(); @@ -139,7 +140,7 @@ describe('Submodel Registry Integration Tests', () => { submodelIdentifier: undefined as unknown as string, }); - expect(response.success).toBe(false); + assertApiFailure(response); if (!response.success) { expect(response.statusCode).toBe(400); expect(response.error.messages?.[0]?.code).toBe('400'); @@ -157,7 +158,7 @@ describe('Submodel Registry Integration Tests', () => { submodelIdentifier: nonExistingId, }); - expect(response.success).toBe(false); + assertApiFailure(response); if (!response.success) { expect(response.statusCode).toBe(404); expect(response.error.messages?.[0]?.code).toBe('404'); @@ -189,13 +190,13 @@ describe('Submodel Registry Integration Tests', () => { configuration, submodelDescriptor, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const response = await client.getAllSubmodelDescriptors({ configuration, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data).toBeDefined(); @@ -214,7 +215,7 @@ describe('Submodel Registry Integration Tests', () => { limit: -1, }); - expect(response.success).toBe(false); + assertApiFailure(response); if (!response.success) { expect(response.statusCode).toBe(400); expect(response.error.messages?.[0]?.code).toBe('400'); @@ -231,7 +232,7 @@ describe('Submodel Registry Integration Tests', () => { cursor: unavailableCursor(), }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data.pagedResult).toEqual({}); @@ -248,7 +249,7 @@ describe('Submodel Registry Integration Tests', () => { configuration, }); - expect(response.success).toBe(false); + assertApiFailure(response); if (!response.success) { expect(response.statusCode).toBe(404); expect(response.error.messages?.[0]?.code).toBe('404'); @@ -268,7 +269,7 @@ describe('Submodel Registry Integration Tests', () => { submodelDescriptor, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(201); expect(response.data).toEqual(submodelDescriptor); @@ -285,7 +286,7 @@ describe('Submodel Registry Integration Tests', () => { configuration, submodelDescriptor, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const updatedSubmodelDescriptor = createUniqueSubmodelDescriptor(); updatedSubmodelDescriptor.id = submodelDescriptor.id; @@ -297,7 +298,7 @@ describe('Submodel Registry Integration Tests', () => { submodelDescriptor: updatedSubmodelDescriptor, }); - expect(updateResponse.success).toBe(true); + assertApiResult(updateResponse); if (updateResponse.success) { expect(updateResponse.statusCode).toBe(204); expect(updateResponse.data).toBeUndefined(); @@ -308,7 +309,7 @@ describe('Submodel Registry Integration Tests', () => { submodelIdentifier: submodelDescriptor.id, }); - expect(fetchResponse.success).toBe(true); + assertApiResult(fetchResponse); if (fetchResponse.success) { expect(fetchResponse.statusCode).toBe(200); expect(fetchResponse.data.displayName).toEqual(updatedSubmodelDescriptor.displayName); @@ -329,7 +330,7 @@ describe('Submodel Registry Integration Tests', () => { submodelDescriptor, }); - expect(response.success).toBe(false); + assertApiFailure(response); if (!response.success) { expect(response.statusCode).toBe(400); expect(response.error.messages?.[0]?.code).toBe('400'); @@ -346,14 +347,14 @@ describe('Submodel Registry Integration Tests', () => { configuration, submodelDescriptor, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const response = await client.deleteSubmodelDescriptorById({ configuration, submodelIdentifier: submodelDescriptor.id, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(204); expect(response.data).toBeUndefined(); @@ -372,7 +373,7 @@ describe('Submodel Registry Integration Tests', () => { submodelIdentifier: nonExistingId, }); - expect(response.success).toBe(false); + assertApiFailure(response); if (!response.success) { expect(response.statusCode).toBe(404); expect(response.error.messages?.[0]?.code).toBe('404'); @@ -389,7 +390,7 @@ describe('Submodel Registry Integration Tests', () => { submodelIdentifier: undefined as unknown as string, }); - expect(response.success).toBe(false); + assertApiFailure(response); if (!response.success) { expect(response.statusCode).toBe(400); expect(response.error.messages?.[0]?.code).toBe('400'); @@ -405,7 +406,7 @@ describe('Submodel Registry Integration Tests', () => { configuration, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data).toBeDefined(); diff --git a/src/integration-tests/submodelRepo.integration.test.ts b/src/integration-tests/submodelRepo.integration.test.ts index ee07e9e4..380464ca 100644 --- a/src/integration-tests/submodelRepo.integration.test.ts +++ b/src/integration-tests/submodelRepo.integration.test.ts @@ -1,6 +1,7 @@ import { SubmodelRepositoryClient } from '../clients/SubmodelRepositoryClient'; //import { Configuration } from '../generated'; import { Configuration } from '../generated'; +import { assertApiFailureCode, assertApiResult } from './fixtures/assertionHelpers'; import { createSubmodelRepositoryPayloadFixtures } from './fixtures/requestPayloadFixtures'; import { createAttachmentBlob, @@ -33,31 +34,6 @@ describe('Submodel Repository Integration Tests', () => { const uniqueSuffix = (): string => `${Date.now()}-${Math.random().toString(36).slice(2)}`; const { track } = createPerTestCleanupRunner(); - type ApiResultLike = { - success: boolean; - statusCode?: number; - data?: unknown; - error?: unknown; - }; - - function assertApiResult(response: ApiResultLike): void { - expect(typeof response.success).toBe('boolean'); - if (response.success) { - expect(response.error).toBeUndefined(); - } else { - expect(response.error).toBeDefined(); - } - } - - function assertApiFailureCode(response: ApiResultLike, expectedCode: string): void { - expect(response.success).toBe(false); - if (!response.success) { - const errorPayload = response.error as { messages?: Array<{ code?: string }> } | undefined; - const messageCodes = (errorPayload?.messages ?? []).map((message) => message.code); - expect(messageCodes).toContain(expectedCode); - } - } - function assertNonEmptyResult(result: unknown): void { if (Array.isArray(result)) { expect(result.length).toBeGreaterThan(0); @@ -91,7 +67,7 @@ describe('Submodel Repository Integration Tests', () => { submodelElement, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(201); } @@ -107,7 +83,7 @@ describe('Submodel Repository Integration Tests', () => { submodelElement: collectionElement, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(201); } @@ -123,7 +99,7 @@ describe('Submodel Repository Integration Tests', () => { submodelElement: fileSubmodelElement, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(201); } @@ -165,7 +141,7 @@ describe('Submodel Repository Integration Tests', () => { if (!response.success && response.error) { console.error('API Error:', JSON.stringify(response.error, null, 2)); } - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(201); expect(response.data).toBeDefined(); @@ -201,7 +177,7 @@ describe('Submodel Repository Integration Tests', () => { submodel: duplicateSubmodel, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); if (createResponse.success) { expect(createResponse.statusCode).toBe(201); } @@ -228,14 +204,14 @@ describe('Submodel Repository Integration Tests', () => { submodel: scopedSubmodel, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const response = await client.getSubmodelById({ configuration, submodelIdentifier: scopedSubmodel.id, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data).toBeDefined(); @@ -289,13 +265,13 @@ describe('Submodel Repository Integration Tests', () => { submodel: scopedSubmodel, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const response = await client.getAllSubmodels({ configuration, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data).toBeDefined(); @@ -331,7 +307,7 @@ describe('Submodel Repository Integration Tests', () => { configuration, submodel: scopedSubmodel, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const createdSubmodelElement = createNewSubmodelElement(); createdSubmodelElement.idShort = `testPropertyCreate-${uniqueSuffix()}`; @@ -346,7 +322,7 @@ describe('Submodel Repository Integration Tests', () => { if (!response.success && response.error) { console.error('API Error:', JSON.stringify(response.error, null, 2)); } - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(201); expect(response.data).toBeDefined(); @@ -364,7 +340,7 @@ describe('Submodel Repository Integration Tests', () => { configuration, submodel: scopedSubmodel, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const duplicateSubmodelElement = createNewSubmodelElement(); duplicateSubmodelElement.idShort = `dup-${uniqueSuffix()}`; @@ -375,7 +351,7 @@ describe('Submodel Repository Integration Tests', () => { submodelElement: duplicateSubmodelElement, }); - expect(createElementResponse.success).toBe(true); + assertApiResult(createElementResponse); if (createElementResponse.success) { expect(createElementResponse.statusCode).toBe(201); } @@ -441,7 +417,7 @@ describe('Submodel Repository Integration Tests', () => { submodel: putSubmodel, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(201); expect(response.data).toBeDefined(); @@ -458,7 +434,7 @@ describe('Submodel Repository Integration Tests', () => { configuration, submodel: scopedSubmodel, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const updatedProperty = createTestSubmodelElement(); updatedProperty.idShort = `updated-property-${uniqueSuffix()}`; @@ -480,7 +456,7 @@ describe('Submodel Repository Integration Tests', () => { submodel: updatedSubmodel, }); - expect(updateResponse.success).toBe(true); + assertApiResult(updateResponse); if (updateResponse.success) { expect(updateResponse.statusCode).toBe(204); } @@ -490,7 +466,7 @@ describe('Submodel Repository Integration Tests', () => { submodelIdentifier: scopedSubmodel.id, }); - expect(fetchResponse.success).toBe(true); + assertApiResult(fetchResponse); if (fetchResponse.success) { expect(fetchResponse.data).toBeDefined(); expect(fetchResponse.data.id).toEqual(updatedSubmodel.id); @@ -514,7 +490,7 @@ describe('Submodel Repository Integration Tests', () => { configuration, submodel: scopedSubmodel, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const patchedSubmodel = createTestSubmodel(); patchedSubmodel.id = scopedSubmodel.id; @@ -526,7 +502,7 @@ describe('Submodel Repository Integration Tests', () => { submodel: patchedSubmodel, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(204); } @@ -580,7 +556,7 @@ describe('Submodel Repository Integration Tests', () => { configuration, submodel: scopedSubmodel, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const valueOnlyElement = createTestSubmodelElement(); valueOnlyElement.idShort = `value-only-${uniqueSuffix()}`; @@ -594,7 +570,7 @@ describe('Submodel Repository Integration Tests', () => { }, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(204); } @@ -642,7 +618,7 @@ describe('Submodel Repository Integration Tests', () => { configuration, submodel: scopedSubmodel, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const seededElement = createTestSubmodelElement(); seededElement.idShort = `seeded-property-${uniqueSuffix()}`; @@ -653,7 +629,7 @@ describe('Submodel Repository Integration Tests', () => { submodelIdentifier: scopedSubmodel.id, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data).toBeDefined(); @@ -708,7 +684,7 @@ describe('Submodel Repository Integration Tests', () => { configuration, submodel: scopedSubmodel, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const seededElement = createTestSubmodelElement(); seededElement.idShort = `path-property-${uniqueSuffix()}`; @@ -720,7 +696,7 @@ describe('Submodel Repository Integration Tests', () => { idShortPath: seededElement.idShort!, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data).toBeDefined(); @@ -740,7 +716,7 @@ describe('Submodel Repository Integration Tests', () => { configuration, submodel: scopedSubmodel, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const response = await client.getSubmodelElementByPath({ configuration, @@ -781,7 +757,7 @@ describe('Submodel Repository Integration Tests', () => { configuration, submodel: scopedSubmodel, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const parentCollection = createTestSubmodelElementCollection(); parentCollection.idShort = `parentCollection-${uniqueSuffix()}`; @@ -801,7 +777,7 @@ describe('Submodel Repository Integration Tests', () => { if (!response.success && response.error) { console.error('API Error:', JSON.stringify(response.error, null, 2)); } - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(201); expect(response.data).toBeDefined(); @@ -819,7 +795,7 @@ describe('Submodel Repository Integration Tests', () => { configuration, submodel: scopedSubmodel, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const parentCollection = createTestSubmodelElementCollection(); parentCollection.idShort = `parentCollection-${uniqueSuffix()}`; @@ -835,7 +811,7 @@ describe('Submodel Repository Integration Tests', () => { submodelElement: nestedSubmodelElement, }); - expect(createElementResponse.success).toBe(true); + assertApiResult(createElementResponse); if (createElementResponse.success) { expect(createElementResponse.statusCode).toBe(201); } @@ -863,7 +839,7 @@ describe('Submodel Repository Integration Tests', () => { configuration, submodel: scopedSubmodel, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const nestedSubmodelElement = createNewSubmodelElement(); nestedSubmodelElement.idShort = `nested-${uniqueSuffix()}`; @@ -910,7 +886,7 @@ describe('Submodel Repository Integration Tests', () => { configuration, submodel: scopedSubmodel, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const seededElement = createTestSubmodelElement(); seededElement.idShort = `putByPath-${uniqueSuffix()}`; @@ -928,7 +904,7 @@ describe('Submodel Repository Integration Tests', () => { submodelElement: updatedSubmodelElement, }); - expect(updateResponse.success).toBe(true); + assertApiResult(updateResponse); if (updateResponse.success) { expect(updateResponse.statusCode).toBe(204); } @@ -939,7 +915,7 @@ describe('Submodel Repository Integration Tests', () => { idShortPath: seededElement.idShort!, }); - expect(fetchResponse.success).toBe(true); + assertApiResult(fetchResponse); if (fetchResponse.success) { expect(fetchResponse.data).toBeDefined(); expect(fetchResponse.data).toEqual(updatedSubmodelElement); @@ -956,7 +932,7 @@ describe('Submodel Repository Integration Tests', () => { configuration, submodel: scopedSubmodel, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const parentCollection = createTestSubmodelElementCollection(); parentCollection.idShort = `putParent-${uniqueSuffix()}`; @@ -972,7 +948,7 @@ describe('Submodel Repository Integration Tests', () => { submodelElement: createdElement, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(201); } @@ -1030,7 +1006,7 @@ describe('Submodel Repository Integration Tests', () => { configuration, submodel: scopedSubmodel, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const seededElement = createTestSubmodelElement(); seededElement.idShort = `patchByPath-${uniqueSuffix()}`; @@ -1046,7 +1022,7 @@ describe('Submodel Repository Integration Tests', () => { submodelElement: patchedSubmodelElement, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(204); } @@ -1080,7 +1056,7 @@ describe('Submodel Repository Integration Tests', () => { configuration, submodel: scopedSubmodel, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const response = await client.patchSubmodelElementByPath({ configuration, @@ -1106,14 +1082,14 @@ describe('Submodel Repository Integration Tests', () => { configuration, submodel: scopedSubmodel, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const response = await client.getSubmodelByIdMetadata({ configuration, submodelIdentifier: scopedSubmodel.id, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data).toBeDefined(); @@ -1158,7 +1134,7 @@ describe('Submodel Repository Integration Tests', () => { configuration, submodel: scopedSubmodel, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const seededElement = createTestSubmodelElement(); seededElement.idShort = `valueOnlySubmodel-${uniqueSuffix()}`; @@ -1169,7 +1145,7 @@ describe('Submodel Repository Integration Tests', () => { submodelIdentifier: scopedSubmodel.id, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data).toBeDefined(); @@ -1214,7 +1190,7 @@ describe('Submodel Repository Integration Tests', () => { configuration, submodel: scopedSubmodel, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const seededElement = createNewSubmodelElement(); seededElement.idShort = `valueOnlyByPath-${uniqueSuffix()}`; @@ -1226,7 +1202,7 @@ describe('Submodel Repository Integration Tests', () => { idShortPath: seededElement.idShort!, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); const newPropertyElement = seededElement as { value?: unknown }; @@ -1260,7 +1236,7 @@ describe('Submodel Repository Integration Tests', () => { configuration, submodel: scopedSubmodel, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const response = await client.getSubmodelElementByPathValueOnly({ configuration, @@ -1281,7 +1257,7 @@ describe('Submodel Repository Integration Tests', () => { configuration, submodel: scopedSubmodel, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const seededElement = createNewSubmodelElement(); seededElement.idShort = `valueOnlyPatch-${uniqueSuffix()}`; @@ -1298,7 +1274,7 @@ describe('Submodel Repository Integration Tests', () => { submodelElementValue: updatedPropertyValue, }); - expect(updateResponse.success).toBe(true); + assertApiResult(updateResponse); if (updateResponse.success) { expect(updateResponse.statusCode).toBe(204); } @@ -1309,7 +1285,7 @@ describe('Submodel Repository Integration Tests', () => { idShortPath: seededElement.idShort!, }); - expect(fetchResponse.success).toBe(true); + assertApiResult(fetchResponse); if (fetchResponse.success) { expect(fetchResponse.data).toBeDefined(); expect(fetchResponse.data).toEqual(updatedPropertyValue); @@ -1326,7 +1302,7 @@ describe('Submodel Repository Integration Tests', () => { configuration, submodel: scopedSubmodel, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const response = await client.patchSubmodelElementByPathValueOnly({ configuration, @@ -1363,13 +1339,13 @@ describe('Submodel Repository Integration Tests', () => { configuration, submodel: scopedSubmodel, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const response = await client.getAllSubmodelsMetadata({ configuration, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data.result).toBeDefined(); @@ -1401,13 +1377,13 @@ describe('Submodel Repository Integration Tests', () => { configuration, submodel: scopedSubmodel, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const response = await client.getAllSubmodelsValueOnly({ configuration, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data.result).toBeDefined(); @@ -1453,13 +1429,13 @@ describe('Submodel Repository Integration Tests', () => { configuration, submodel: scopedSubmodel, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const response = await client.getAllSubmodelsReference({ configuration, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data.result).toBeDefined(); @@ -1500,13 +1476,13 @@ describe('Submodel Repository Integration Tests', () => { configuration, submodel: scopedSubmodel, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const response = await client.getAllSubmodelsPath({ configuration, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data.result).toBeDefined(); @@ -1536,14 +1512,14 @@ describe('Submodel Repository Integration Tests', () => { configuration, submodel: scopedSubmodel, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const response = await client.getSubmodelByIdReference({ configuration, submodelIdentifier: scopedSubmodel.id, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data).toBeDefined(); @@ -1587,7 +1563,7 @@ describe('Submodel Repository Integration Tests', () => { configuration, submodel: scopedSubmodel, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const seededElement = createTestSubmodelElement(); seededElement.idShort = `pathRepresentation-${uniqueSuffix()}`; @@ -1598,7 +1574,7 @@ describe('Submodel Repository Integration Tests', () => { submodelIdentifier: scopedSubmodel.id, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data).toBeDefined(); @@ -1642,7 +1618,7 @@ describe('Submodel Repository Integration Tests', () => { configuration, submodel: scopedSubmodel, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const seededElement = createNewSubmodelElement(); seededElement.idShort = `metadataList-${uniqueSuffix()}`; @@ -1653,7 +1629,7 @@ describe('Submodel Repository Integration Tests', () => { submodelIdentifier: scopedSubmodel.id, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data.result).toBeDefined(); @@ -1697,7 +1673,7 @@ describe('Submodel Repository Integration Tests', () => { configuration, submodel: scopedSubmodel, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const seededElement = createNewSubmodelElement(); seededElement.idShort = `valueOnlyList-${uniqueSuffix()}`; @@ -1708,7 +1684,7 @@ describe('Submodel Repository Integration Tests', () => { submodelIdentifier: scopedSubmodel.id, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data.result).toBeDefined(); @@ -1752,7 +1728,7 @@ describe('Submodel Repository Integration Tests', () => { configuration, submodel: scopedSubmodel, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const seededElement = createNewSubmodelElement(); seededElement.idShort = `referenceList-${uniqueSuffix()}`; @@ -1763,7 +1739,7 @@ describe('Submodel Repository Integration Tests', () => { submodelIdentifier: scopedSubmodel.id, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data.result).toBeDefined(); @@ -1807,7 +1783,7 @@ describe('Submodel Repository Integration Tests', () => { configuration, submodel: scopedSubmodel, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const seededElement = createNewSubmodelElement(); seededElement.idShort = `pathList-${uniqueSuffix()}`; @@ -1818,7 +1794,7 @@ describe('Submodel Repository Integration Tests', () => { submodelIdentifier: scopedSubmodel.id, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data.result).toBeDefined(); @@ -1862,7 +1838,7 @@ describe('Submodel Repository Integration Tests', () => { configuration, submodel: scopedSubmodel, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const seededElement = createNewSubmodelElement(); seededElement.idShort = `metaByPath-${uniqueSuffix()}`; @@ -1874,7 +1850,7 @@ describe('Submodel Repository Integration Tests', () => { idShortPath: seededElement.idShort!, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data).toBeDefined(); @@ -1906,7 +1882,7 @@ describe('Submodel Repository Integration Tests', () => { configuration, submodel: scopedSubmodel, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const response = await client.getSubmodelElementByPathMetadata({ configuration, @@ -1927,7 +1903,7 @@ describe('Submodel Repository Integration Tests', () => { configuration, submodel: scopedSubmodel, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const seededElement = createNewSubmodelElement(); seededElement.idShort = `referenceByPath-${uniqueSuffix()}`; @@ -1939,7 +1915,7 @@ describe('Submodel Repository Integration Tests', () => { idShortPath: seededElement.idShort!, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data).toBeDefined(); @@ -1971,7 +1947,7 @@ describe('Submodel Repository Integration Tests', () => { configuration, submodel: scopedSubmodel, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const response = await client.getSubmodelElementByPathReference({ configuration, @@ -1992,7 +1968,7 @@ describe('Submodel Repository Integration Tests', () => { configuration, submodel: scopedSubmodel, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const seededElement = createNewSubmodelElement(); seededElement.idShort = `pathByPath-${uniqueSuffix()}`; @@ -2004,7 +1980,7 @@ describe('Submodel Repository Integration Tests', () => { idShortPath: seededElement.idShort!, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data).toBeDefined(); @@ -2036,7 +2012,7 @@ describe('Submodel Repository Integration Tests', () => { configuration, submodel: scopedSubmodel, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const response = await client.getSubmodelElementByPathPath({ configuration, @@ -2057,7 +2033,7 @@ describe('Submodel Repository Integration Tests', () => { includeConceptDescriptions: true, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.data).toBeDefined(); expect(response.data.size).toBeGreaterThan(0); @@ -2087,7 +2063,7 @@ describe('Submodel Repository Integration Tests', () => { configuration, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data).toBeDefined(); @@ -2140,7 +2116,7 @@ describe('Submodel Repository Integration Tests', () => { configuration, submodel: scopedSubmodel, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const scopedMetadataPatch = { ...submodelMetadataPatch, @@ -2154,7 +2130,7 @@ describe('Submodel Repository Integration Tests', () => { submodelMetadata: scopedMetadataPatch, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(204); } @@ -2210,7 +2186,7 @@ describe('Submodel Repository Integration Tests', () => { configuration, submodel: scopedSubmodel, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const seededElement = createNewSubmodelElement(); seededElement.idShort = `metadataPatch-${uniqueSuffix()}`; @@ -2223,7 +2199,7 @@ describe('Submodel Repository Integration Tests', () => { submodelElementMetadata: submodelElementMetadataPatch, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(204); } @@ -2254,7 +2230,7 @@ describe('Submodel Repository Integration Tests', () => { configuration, submodel: scopedSubmodel, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const response = await client.patchSubmodelElementByPathMetadata({ configuration, @@ -2276,7 +2252,7 @@ describe('Submodel Repository Integration Tests', () => { configuration, submodel: scopedSubmodel, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const attachmentIdShortPath = await seedFileSubmodelElement(scopedSubmodel.id); const attachmentBlob = createAttachmentBlob(attachmentPayload); @@ -2289,7 +2265,7 @@ describe('Submodel Repository Integration Tests', () => { file: attachmentBlob, }); - expect(response.success).toBe(true); + assertApiResult(response); if (!response.success) { console.error('API Error:', JSON.stringify(response.error, null, 2)); } @@ -2308,7 +2284,7 @@ describe('Submodel Repository Integration Tests', () => { configuration, submodel: scopedSubmodel, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const attachmentIdShortPath = await seedFileSubmodelElement(scopedSubmodel.id); const attachmentBlob = createAttachmentBlob(attachmentPayload); @@ -2319,7 +2295,7 @@ describe('Submodel Repository Integration Tests', () => { fileName: 'coverage-file.txt', file: attachmentBlob, }); - expect(uploadResponse.success).toBe(true); + assertApiResult(uploadResponse); const response = await client.getFileByPath({ configuration, @@ -2327,7 +2303,7 @@ describe('Submodel Repository Integration Tests', () => { idShortPath: attachmentIdShortPath, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); expect(response.data).toBeDefined(); @@ -2346,7 +2322,7 @@ describe('Submodel Repository Integration Tests', () => { configuration, submodel: scopedSubmodel, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const nonFileElement = createTestSubmodelElement(); nonFileElement.idShort = `nonFileElement-${uniqueSuffix()}`; @@ -2385,7 +2361,7 @@ describe('Submodel Repository Integration Tests', () => { configuration, submodel: scopedSubmodel, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const response = await client.putFileByPath({ configuration, @@ -2473,7 +2449,7 @@ describe('Submodel Repository Integration Tests', () => { operationRequestValueOnly, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); } @@ -2523,7 +2499,7 @@ describe('Submodel Repository Integration Tests', () => { operationRequest: createTestOperationRequest(), }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); } @@ -2572,7 +2548,7 @@ describe('Submodel Repository Integration Tests', () => { operationRequestValueOnly, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); } @@ -2622,7 +2598,7 @@ describe('Submodel Repository Integration Tests', () => { handleId: 'coverage-handle-id', }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); } @@ -2670,7 +2646,7 @@ describe('Submodel Repository Integration Tests', () => { handleId: 'coverage-handle-id', }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); } @@ -2718,7 +2694,7 @@ describe('Submodel Repository Integration Tests', () => { handleId: 'coverage-handle-id', }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(200); } @@ -2764,7 +2740,7 @@ describe('Submodel Repository Integration Tests', () => { configuration, submodel: scopedSubmodel, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const attachmentIdShortPath = await seedFileSubmodelElement(scopedSubmodel.id); const uploadResponse = await client.putFileByPath({ @@ -2774,7 +2750,7 @@ describe('Submodel Repository Integration Tests', () => { fileName: 'coverage-file.txt', file: createAttachmentBlob(attachmentPayload), }); - expect(uploadResponse.success).toBe(true); + assertApiResult(uploadResponse); const response = await client.deleteFileByPath({ configuration, @@ -2782,7 +2758,7 @@ describe('Submodel Repository Integration Tests', () => { idShortPath: attachmentIdShortPath, }); - expect(response.success).toBe(true); + assertApiResult(response); if (!response.success) { console.error('API Error:', JSON.stringify(response.error, null, 2)); } @@ -2815,7 +2791,7 @@ describe('Submodel Repository Integration Tests', () => { configuration, submodel: scopedSubmodel, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const response = await client.deleteFileByPath({ configuration, @@ -2836,7 +2812,7 @@ describe('Submodel Repository Integration Tests', () => { configuration, submodel: scopedSubmodel, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const attachmentIdShortPath = await seedFileSubmodelElement(scopedSubmodel.id); const uploadResponse = await client.putFileByPath({ @@ -2846,14 +2822,14 @@ describe('Submodel Repository Integration Tests', () => { fileName: 'coverage-file.txt', file: createAttachmentBlob(attachmentPayload), }); - expect(uploadResponse.success).toBe(true); + assertApiResult(uploadResponse); const deleteResponse = await client.deleteFileByPath({ configuration, submodelIdentifier: scopedSubmodel.id, idShortPath: attachmentIdShortPath, }); - expect(deleteResponse.success).toBe(true); + assertApiResult(deleteResponse); const response = await client.getFileByPath({ configuration, @@ -2874,7 +2850,7 @@ describe('Submodel Repository Integration Tests', () => { configuration, submodel: scopedSubmodel, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const seededElement = createTestSubmodelElement(); seededElement.idShort = `deleteElement-${uniqueSuffix()}`; @@ -2886,7 +2862,7 @@ describe('Submodel Repository Integration Tests', () => { idShortPath: seededElement.idShort ?? 'testProperty', }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(204); } @@ -2916,7 +2892,7 @@ describe('Submodel Repository Integration Tests', () => { configuration, submodel: scopedSubmodel, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const response = await client.deleteSubmodelElementByPath({ configuration, @@ -2937,14 +2913,14 @@ describe('Submodel Repository Integration Tests', () => { configuration, submodel: scopedSubmodel, }); - expect(createResponse.success).toBe(true); + assertApiResult(createResponse); const response = await client.deleteSubmodelById({ configuration, submodelIdentifier: scopedSubmodel.id, }); - expect(response.success).toBe(true); + assertApiResult(response); if (response.success) { expect(response.statusCode).toBe(204); } diff --git a/src/integration-tests/submodelService.integration.test.ts b/src/integration-tests/submodelService.integration.test.ts index df40db9f..50b1ceb4 100644 --- a/src/integration-tests/submodelService.integration.test.ts +++ b/src/integration-tests/submodelService.integration.test.ts @@ -2,6 +2,7 @@ import { Configuration } from '../generated'; import { base64Encode } from '../lib/base64Url'; import { SubmodelService } from '../services/SubmodelService'; import { createTestSubmodelDescriptor } from './fixtures/aasregistryFixtures'; +import { assertApiFailure, assertApiResult } from './fixtures/assertionHelpers'; import { createTestSubmodel } from './fixtures/submodelFixtures'; describe('SubmodelService Integration Tests', () => { @@ -43,7 +44,7 @@ describe('SubmodelService Integration Tests', () => { submodel: testSubmodel, }); - expect(createResult.success).toBe(true); + assertApiResult(createResult); if (createResult.success) { expect(createResult.data.submodel).toBeDefined(); expect(createResult.data.submodel.id).toBe(testSubmodel.id); @@ -62,14 +63,14 @@ describe('SubmodelService Integration Tests', () => { const createResult = await submodelService.createSubmodel({ submodel: testSubmodel, }); - expect(createResult.success).toBe(true); + assertApiResult(createResult); // Then deregister const deregisterResult = await submodelService.deleteSubmodel({ submodelIdentifier: testSubmodel.id, }); - expect(deregisterResult.success).toBe(true); + assertApiResult(deregisterResult); }); test('should fail to deregister non-existent Submodel', async () => { @@ -77,7 +78,7 @@ describe('SubmodelService Integration Tests', () => { submodelIdentifier: 'non-existent-id', }); - expect(deregisterResult.success).toBe(false); + assertApiFailure(deregisterResult); }); }); @@ -98,7 +99,7 @@ describe('SubmodelService Integration Tests', () => { submodel: testSubmodel, }); - expect(updateResult.success).toBe(true); + assertApiResult(updateResult); if (updateResult.success) { expect(updateResult.data.submodel).toBeDefined(); expect(updateResult.data.submodel.id).toBe(testSubmodel.id); @@ -125,7 +126,7 @@ describe('SubmodelService Integration Tests', () => { submodelIdentifier: testSubmodel.id, }); - expect(endpointResult.success).toBe(true); + assertApiResult(endpointResult); if (endpointResult.success) { expect(endpointResult.data).toContain('/submodels/'); expect(endpointResult.data).toContain('http://localhost:8082'); @@ -150,7 +151,7 @@ describe('SubmodelService Integration Tests', () => { useRegistry: false, }); - expect(endpointResult.success).toBe(true); + assertApiResult(endpointResult); if (endpointResult.success) { expect(endpointResult.data).toContain('/submodels/'); expect(endpointResult.data).toContain('http://localhost:8082'); @@ -175,7 +176,7 @@ describe('SubmodelService Integration Tests', () => { submodelIdentifier: testSubmodel.id, }); - expect(endpointResult.success).toBe(true); + assertApiResult(endpointResult); if (endpointResult.success) { // Use endpoint to fetch Submodel @@ -183,7 +184,7 @@ describe('SubmodelService Integration Tests', () => { endpoint: endpointResult.data, }); - expect(submodelResult.success).toBe(true); + assertApiResult(submodelResult); if (submodelResult.success) { expect(submodelResult.data.submodel).toBeDefined(); expect(submodelResult.data.submodel.id).toBe(testSubmodel.id); @@ -201,7 +202,7 @@ describe('SubmodelService Integration Tests', () => { endpoint: invalidEndpoint, }); - expect(result.success).toBe(false); + assertApiFailure(result); if (!result.success) { expect(result.error.errorType).toBe('InvalidEndpoint'); } @@ -219,7 +220,7 @@ describe('SubmodelService Integration Tests', () => { const result = await submodelService.getSubmodelList({ preferRegistry: true }); - expect(result.success).toBe(true); + assertApiResult(result); if (result.success) { expect(result.data.source).toBe('registry'); expect(result.data.submodels).toBeDefined(); @@ -244,7 +245,7 @@ describe('SubmodelService Integration Tests', () => { const result = await submodelService.getSubmodelList({ preferRegistry: false }); - expect(result.success).toBe(true); + assertApiResult(result); if (result.success) { expect(result.data.source).toBe('repository'); expect(result.data.submodels).toBeDefined(); @@ -266,7 +267,7 @@ describe('SubmodelService Integration Tests', () => { const result = await submodelService.getSubmodelList({ limit: 1, preferRegistry: true }); - expect(result.success).toBe(true); + assertApiResult(result); if (result.success) { expect(result.data.source).toBe('registry'); // The limit parameter should restrict the result to at most 1 item @@ -293,7 +294,7 @@ describe('SubmodelService Integration Tests', () => { useRegistryEndpoint: true, }); - expect(result.success).toBe(true); + assertApiResult(result); if (result.success) { expect(result.data.submodel).toBeDefined(); expect(result.data.submodel.id).toBe(testSubmodel.id); @@ -320,7 +321,7 @@ describe('SubmodelService Integration Tests', () => { useRegistryEndpoint: false, }); - expect(result.success).toBe(true); + assertApiResult(result); if (result.success) { expect(result.data.submodel).toBeDefined(); expect(result.data.submodel.id).toBe(testSubmodel.id); @@ -337,7 +338,7 @@ describe('SubmodelService Integration Tests', () => { useRegistryEndpoint: false, }); - expect(result.success).toBe(false); + assertApiFailure(result); }); }); @@ -359,7 +360,7 @@ describe('SubmodelService Integration Tests', () => { // Try to get list with bad registry - should fall back to repository const result = await serviceWithBadRegistry.getSubmodelList(); - expect(result.success).toBe(true); + assertApiResult(result); if (result.success) { expect(result.data.source).toBe('repository'); expect(result.data.submodels).toBeDefined(); @@ -376,7 +377,7 @@ describe('SubmodelService Integration Tests', () => { test('should work with only repository configuration', async () => { const result = await repoOnlyService.getSubmodelList(); - expect(result.success).toBe(true); + assertApiResult(result); if (result.success) { expect(result.data.source).toBe('repository'); } @@ -389,7 +390,7 @@ describe('SubmodelService Integration Tests', () => { test('should fail when no configuration is provided', async () => { const result = await emptyService.getSubmodelList(); - expect(result.success).toBe(false); + assertApiFailure(result); if (!result.success) { expect(result.error.errorType).toBe('ConfigurationError'); } @@ -418,7 +419,7 @@ describe('SubmodelService Integration Tests', () => { includeConceptDescriptions: true, }); - expect(result.success).toBe(true); + assertApiResult(result); if (result.success) { expect(result.data.submodels.length).toBeGreaterThan(0); expect(result.data.conceptDescriptions).toBeDefined(); @@ -445,7 +446,7 @@ describe('SubmodelService Integration Tests', () => { includeConceptDescriptions: true, }); - expect(result.success).toBe(true); + assertApiResult(result); if (result.success) { expect(result.data.submodel.id).toBe(testSubmodel.id); expect(result.data.conceptDescriptions).toBeDefined(); @@ -472,7 +473,7 @@ describe('SubmodelService Integration Tests', () => { includeConceptDescriptions: true, }); - expect(result.success).toBe(true); + assertApiResult(result); if (result.success) { expect(result.data.submodel.id).toBe(testSubmodel.id); expect(result.data.conceptDescriptions).toBeDefined(); From b183d8de0b8548ba8eb31a394e672de9e0b8d460 Mon Sep 17 00:00:00 2001 From: Aaron Zielstorff Date: Tue, 5 May 2026 22:09:41 +0200 Subject: [PATCH 2/5] Fixes formatting issues --- .../fixtures/assertionHelpers.ts | 298 +++++++++--------- 1 file changed, 149 insertions(+), 149 deletions(-) diff --git a/src/integration-tests/fixtures/assertionHelpers.ts b/src/integration-tests/fixtures/assertionHelpers.ts index bade1683..72a06235 100644 --- a/src/integration-tests/fixtures/assertionHelpers.ts +++ b/src/integration-tests/fixtures/assertionHelpers.ts @@ -1,149 +1,149 @@ -type ApiErrorMessage = { - code?: unknown; - message?: unknown; -}; - -export type ApiResultLike = { - success: boolean; - statusCode?: number; - data?: unknown; - error?: unknown; -}; - -const MAX_FALLBACK_LENGTH = 400; - -function asNonEmptyString(value: unknown): string | undefined { - if (typeof value === 'string') { - const trimmed = value.trim(); - return trimmed.length > 0 ? trimmed : undefined; - } - - if (typeof value === 'number' || typeof value === 'boolean') { - return String(value); - } - - return undefined; -} - -function compactUnique(values: string[]): string[] { - return [...new Set(values.map((value) => value.trim()).filter(Boolean))]; -} - -function stringifyFallback(value: unknown): string { - try { - const serialized = JSON.stringify(value); - if (!serialized) { - return 'unstructured error payload'; - } - - return serialized.length > MAX_FALLBACK_LENGTH - ? `${serialized.slice(0, MAX_FALLBACK_LENGTH)}...` - : serialized; - } catch { - return 'unstructured error payload'; - } -} - -function extractMessages(error: unknown): ApiErrorMessage[] { - if (!error || typeof error !== 'object') { - const inlineMessage = asNonEmptyString(error); - return inlineMessage ? [{ message: inlineMessage }] : []; - } - - const payload = error as { messages?: unknown; code?: unknown; message?: unknown }; - if (Array.isArray(payload.messages)) { - return payload.messages - .map((entry) => { - if (entry && typeof entry === 'object') { - return entry as ApiErrorMessage; - } - - const inlineMessage = asNonEmptyString(entry); - return inlineMessage ? ({ message: inlineMessage } as ApiErrorMessage) : undefined; - }) - .filter((entry): entry is ApiErrorMessage => Boolean(entry)); - } - - if (payload.code !== undefined || payload.message !== undefined) { - return [payload]; - } - - return []; -} - -function summarizeError(error: unknown): { codes: string[]; messages: string[] } { - const messageEntries = extractMessages(error); - const codes = compactUnique( - messageEntries - .map((entry) => asNonEmptyString(entry.code)) - .filter((value): value is string => value !== undefined) - ); - const messages = compactUnique( - messageEntries - .map((entry) => asNonEmptyString(entry.message)) - .filter((value): value is string => value !== undefined) - ); - - if (codes.length > 0 || messages.length > 0) { - return { codes, messages }; - } - - return { - codes: [], - messages: [stringifyFallback(error)], - }; -} - -function formatFailureContext(response: ApiResultLike): string { - const { codes, messages } = summarizeError(response.error); - const status = response.statusCode ?? 'n/a'; - const codeSummary = codes.length > 0 ? codes.join(', ') : 'none'; - const messageSummary = messages.length > 0 ? messages.join(' | ') : 'none'; - return `status=${status}; errorCodes=${codeSummary}; errorMessages=${messageSummary}`; -} - -export function assertApiResult(response: ApiResultLike, context = 'API request'): void { - if (typeof response.success !== 'boolean') { - throw new Error(`${context} produced an invalid result: success flag is not a boolean.`); - } - - if (!response.success) { - throw new Error(`${context} failed: ${formatFailureContext(response)}`); - } - - if (response.error !== undefined) { - throw new Error(`${context} unexpectedly returned an error payload despite success.`); - } -} - -export function assertApiFailure(response: ApiResultLike, context = 'API request'): void { - if (typeof response.success !== 'boolean') { - throw new Error(`${context} produced an invalid result: success flag is not a boolean.`); - } - - if (response.success) { - throw new Error(`${context} unexpectedly succeeded while a failure was expected.`); - } - - // Keep failure assertion resilient even when some backends return sparse payloads. - if (response.error === undefined) { - throw new Error(`${context} failed but did not return an error payload. status=${response.statusCode ?? 'n/a'}`); - } -} - -export function assertApiFailureCode(response: ApiResultLike, expectedCode: string, context = 'API request'): void { - if (typeof response.success !== 'boolean') { - throw new Error(`${context} produced an invalid result: success flag is not a boolean.`); - } - - if (response.success) { - throw new Error(`${context} unexpectedly succeeded while expecting error code ${expectedCode}.`); - } - - const { codes } = summarizeError(response.error); - if (!codes.includes(expectedCode)) { - throw new Error( - `${context} failed with unexpected error codes. Expected ${expectedCode}; received ${codes.join(', ') || 'none'}. ${formatFailureContext(response)}` - ); - } -} +type ApiErrorMessage = { + code?: unknown; + message?: unknown; +}; + +export type ApiResultLike = { + success: boolean; + statusCode?: number; + data?: unknown; + error?: unknown; +}; + +const MAX_FALLBACK_LENGTH = 400; + +function asNonEmptyString(value: unknown): string | undefined { + if (typeof value === 'string') { + const trimmed = value.trim(); + return trimmed.length > 0 ? trimmed : undefined; + } + + if (typeof value === 'number' || typeof value === 'boolean') { + return String(value); + } + + return undefined; +} + +function compactUnique(values: string[]): string[] { + return [...new Set(values.map((value) => value.trim()).filter(Boolean))]; +} + +function stringifyFallback(value: unknown): string { + try { + const serialized = JSON.stringify(value); + if (!serialized) { + return 'unstructured error payload'; + } + + return serialized.length > MAX_FALLBACK_LENGTH ? `${serialized.slice(0, MAX_FALLBACK_LENGTH)}...` : serialized; + } catch { + return 'unstructured error payload'; + } +} + +function extractMessages(error: unknown): ApiErrorMessage[] { + if (!error || typeof error !== 'object') { + const inlineMessage = asNonEmptyString(error); + return inlineMessage ? [{ message: inlineMessage }] : []; + } + + const payload = error as { messages?: unknown; code?: unknown; message?: unknown }; + if (Array.isArray(payload.messages)) { + return payload.messages + .map((entry) => { + if (entry && typeof entry === 'object') { + return entry as ApiErrorMessage; + } + + const inlineMessage = asNonEmptyString(entry); + return inlineMessage ? ({ message: inlineMessage } as ApiErrorMessage) : undefined; + }) + .filter((entry): entry is ApiErrorMessage => Boolean(entry)); + } + + if (payload.code !== undefined || payload.message !== undefined) { + return [payload]; + } + + return []; +} + +function summarizeError(error: unknown): { codes: string[]; messages: string[] } { + const messageEntries = extractMessages(error); + const codes = compactUnique( + messageEntries + .map((entry) => asNonEmptyString(entry.code)) + .filter((value): value is string => value !== undefined) + ); + const messages = compactUnique( + messageEntries + .map((entry) => asNonEmptyString(entry.message)) + .filter((value): value is string => value !== undefined) + ); + + if (codes.length > 0 || messages.length > 0) { + return { codes, messages }; + } + + return { + codes: [], + messages: [stringifyFallback(error)], + }; +} + +function formatFailureContext(response: ApiResultLike): string { + const { codes, messages } = summarizeError(response.error); + const status = response.statusCode ?? 'n/a'; + const codeSummary = codes.length > 0 ? codes.join(', ') : 'none'; + const messageSummary = messages.length > 0 ? messages.join(' | ') : 'none'; + return `status=${status}; errorCodes=${codeSummary}; errorMessages=${messageSummary}`; +} + +export function assertApiResult(response: ApiResultLike, context = 'API request'): void { + if (typeof response.success !== 'boolean') { + throw new Error(`${context} produced an invalid result: success flag is not a boolean.`); + } + + if (!response.success) { + throw new Error(`${context} failed: ${formatFailureContext(response)}`); + } + + if (response.error !== undefined) { + throw new Error(`${context} unexpectedly returned an error payload despite success.`); + } +} + +export function assertApiFailure(response: ApiResultLike, context = 'API request'): void { + if (typeof response.success !== 'boolean') { + throw new Error(`${context} produced an invalid result: success flag is not a boolean.`); + } + + if (response.success) { + throw new Error(`${context} unexpectedly succeeded while a failure was expected.`); + } + + // Keep failure assertion resilient even when some backends return sparse payloads. + if (response.error === undefined) { + throw new Error( + `${context} failed but did not return an error payload. status=${response.statusCode ?? 'n/a'}` + ); + } +} + +export function assertApiFailureCode(response: ApiResultLike, expectedCode: string, context = 'API request'): void { + if (typeof response.success !== 'boolean') { + throw new Error(`${context} produced an invalid result: success flag is not a boolean.`); + } + + if (response.success) { + throw new Error(`${context} unexpectedly succeeded while expecting error code ${expectedCode}.`); + } + + const { codes } = summarizeError(response.error); + if (!codes.includes(expectedCode)) { + throw new Error( + `${context} failed with unexpected error codes. Expected ${expectedCode}; received ${codes.join(', ') || 'none'}. ${formatFailureContext(response)}` + ); + } +} From 394eed1dad606601b93da64a56261c7a9851ca2f Mon Sep 17 00:00:00 2001 From: Aaron Zielstorff Date: Tue, 5 May 2026 22:15:47 +0200 Subject: [PATCH 3/5] fixes TS errors Co-authored-by: Copilot --- .../fixtures/assertionHelpers.ts | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/integration-tests/fixtures/assertionHelpers.ts b/src/integration-tests/fixtures/assertionHelpers.ts index 72a06235..5b931130 100644 --- a/src/integration-tests/fixtures/assertionHelpers.ts +++ b/src/integration-tests/fixtures/assertionHelpers.ts @@ -10,6 +10,20 @@ export type ApiResultLike = { error?: unknown; }; +type ApiSuccessResultLike = { + success: true; + statusCode?: number; + data: TData; + error?: unknown; +}; + +type ApiFailureResultLike = { + success: false; + statusCode?: number; + data?: unknown; + error: TError; +}; + const MAX_FALLBACK_LENGTH = 400; function asNonEmptyString(value: unknown): string | undefined { @@ -100,7 +114,10 @@ function formatFailureContext(response: ApiResultLike): string { return `status=${status}; errorCodes=${codeSummary}; errorMessages=${messageSummary}`; } -export function assertApiResult(response: ApiResultLike, context = 'API request'): void { +export function assertApiResult( + response: ApiResultLike & ({ data: TData } | { error: TError }), + context = 'API request' +): asserts response is ApiSuccessResultLike { if (typeof response.success !== 'boolean') { throw new Error(`${context} produced an invalid result: success flag is not a boolean.`); } @@ -114,7 +131,10 @@ export function assertApiResult(response: ApiResultLike, context = 'API request' } } -export function assertApiFailure(response: ApiResultLike, context = 'API request'): void { +export function assertApiFailure( + response: ApiResultLike & ({ data: TData } | { error: TError }), + context = 'API request' +): asserts response is ApiFailureResultLike { if (typeof response.success !== 'boolean') { throw new Error(`${context} produced an invalid result: success flag is not a boolean.`); } From 3226f40f1d7b006d503f420e499c25296a248a50 Mon Sep 17 00:00:00 2001 From: Aaron Zielstorff Date: Tue, 5 May 2026 22:32:12 +0200 Subject: [PATCH 4/5] Adds missing status assertions Co-authored-by: Copilot --- .../aasRepo.integration.test.ts | 94 ++++++++++++++++++- 1 file changed, 93 insertions(+), 1 deletion(-) diff --git a/src/integration-tests/aasRepo.integration.test.ts b/src/integration-tests/aasRepo.integration.test.ts index b8057774..0245d772 100644 --- a/src/integration-tests/aasRepo.integration.test.ts +++ b/src/integration-tests/aasRepo.integration.test.ts @@ -1661,6 +1661,10 @@ describe('AAS Repository Integration Tests', () => { } }); + /** + * @operation GetAllSubmodelElements_AasRepository + * @status 200 + */ test('should get all SubmodelElements through AAS repository superpath', async () => { const { shell, submodel } = await createScopedSuperpathFixture(); @@ -1672,6 +1676,9 @@ describe('AAS Repository Integration Tests', () => { try { assertApiResult(response); + if (response.success) { + expect(response.statusCode).toBe(200); + } } finally { await cleanupShell(shell.id); } @@ -1740,6 +1747,10 @@ describe('AAS Repository Integration Tests', () => { } }); + /** + * @operation PostSubmodelElement_AasRepository + * @status 201 + */ test('should post SubmodelElement through AAS repository superpath', async () => { const { shell, submodel } = await createScopedSuperpathFixture(); const element = createTestSubmodelElement(); @@ -1754,6 +1765,9 @@ describe('AAS Repository Integration Tests', () => { try { assertApiResult(response); + if (response.success) { + expect(response.statusCode).toBe(201); + } } finally { await cleanupShell(shell.id); } @@ -1867,6 +1881,10 @@ describe('AAS Repository Integration Tests', () => { } }); + /** + * @operation GetAllSubmodelElements-Metadata_AasRepository + * @status 200 + */ test('should get all SubmodelElements metadata through AAS repository superpath', async () => { const { shell, submodel } = await createScopedSuperpathFixture(); @@ -1878,6 +1896,9 @@ describe('AAS Repository Integration Tests', () => { try { assertApiResult(response); + if (response.success) { + expect(response.statusCode).toBe(200); + } } finally { await cleanupShell(shell.id); } @@ -1957,6 +1978,9 @@ describe('AAS Repository Integration Tests', () => { try { assertApiResult(response); + if (response.success) { + expect(response.statusCode).toBe(200); + } } finally { await cleanupShell(shell.id); } @@ -2036,6 +2060,9 @@ describe('AAS Repository Integration Tests', () => { try { assertApiResult(response); + if (response.success) { + expect(response.statusCode).toBe(200); + } } finally { await cleanupShell(shell.id); } @@ -2115,6 +2142,9 @@ describe('AAS Repository Integration Tests', () => { try { assertApiResult(response); + if (response.success) { + expect(response.statusCode).toBe(200); + } } finally { await cleanupShell(shell.id); } @@ -2195,6 +2225,9 @@ describe('AAS Repository Integration Tests', () => { try { assertApiResult(response); + if (response.success) { + expect(response.statusCode).toBe(200); + } } finally { await cleanupShell(shell.id); } @@ -2275,12 +2308,15 @@ describe('AAS Repository Integration Tests', () => { configuration, aasIdentifier: shell.id, submodelIdentifier: submodel.id, - idShortPath: 'testProperty', + idShortPath: 'parentCollection', submodelElement: element, }); try { assertApiResult(response); + if (response.success) { + expect(response.statusCode).toBe(201); + } } finally { await cleanupShell(shell.id); } @@ -2398,6 +2434,10 @@ describe('AAS Repository Integration Tests', () => { } }); + /** + * @operation PutSubmodelElementByPath_AasRepository + * @status 204 + */ test('should put SubmodelElement by path through AAS repository superpath', async () => { const { shell, submodel } = await createScopedSuperpathFixture(); const element = createTestSubmodelElement(); @@ -2413,6 +2453,9 @@ describe('AAS Repository Integration Tests', () => { try { assertApiResult(response); + if (response.success) { + expect(response.statusCode).toBe(204); + } } finally { await cleanupShell(shell.id); } @@ -2534,6 +2577,10 @@ describe('AAS Repository Integration Tests', () => { } }); + /** + * @operation PatchSubmodelElementValueByPath_AasRepository + * @status 204 + */ test('should patch SubmodelElement value by path through AAS repository superpath', async () => { const { shell, submodel } = await createScopedSuperpathFixture(); const element = createTestSubmodelElement(); @@ -2549,6 +2596,9 @@ describe('AAS Repository Integration Tests', () => { try { assertApiResult(response); + if (response.success) { + expect(response.statusCode).toBe(204); + } } finally { await cleanupShell(shell.id); } @@ -2630,6 +2680,10 @@ describe('AAS Repository Integration Tests', () => { } }); + /** + * @operation GetSubmodelElementByPath-Metadata_AasRepository + * @status 200 + */ test('should get SubmodelElement metadata by path through AAS repository superpath', async () => { const { shell, submodel } = await createScopedSuperpathFixture(); @@ -2642,6 +2696,9 @@ describe('AAS Repository Integration Tests', () => { try { assertApiResult(response); + if (response.success) { + expect(response.statusCode).toBe(200); + } } finally { await cleanupShell(shell.id); } @@ -2726,6 +2783,9 @@ describe('AAS Repository Integration Tests', () => { try { assertApiResult(response); + if (response.success) { + expect(response.statusCode).toBe(204); + } } finally { await cleanupShell(shell.id); } @@ -2812,6 +2872,9 @@ describe('AAS Repository Integration Tests', () => { try { assertApiResult(response); + if (response.success) { + expect(response.statusCode).toBe(200); + } } finally { await cleanupShell(shell.id); } @@ -2896,6 +2959,9 @@ describe('AAS Repository Integration Tests', () => { try { assertApiResult(response); + if (response.success) { + expect(response.statusCode).toBe(204); + } } finally { await cleanupShell(shell.id); } @@ -2982,6 +3048,9 @@ describe('AAS Repository Integration Tests', () => { try { assertApiResult(response); + if (response.success) { + expect(response.statusCode).toBe(200); + } } finally { await cleanupShell(shell.id); } @@ -3065,6 +3134,9 @@ describe('AAS Repository Integration Tests', () => { try { assertApiResult(response); + if (response.success) { + expect(response.statusCode).toBe(200); + } } finally { await cleanupShell(shell.id); } @@ -3240,6 +3312,9 @@ describe('AAS Repository Integration Tests', () => { try { assertApiFailureCode(response, '405'); + if (!response.success) { + expect(response.statusCode).toBe(405); + } } finally { await cleanupShell(shell.id); } @@ -3307,6 +3382,9 @@ describe('AAS Repository Integration Tests', () => { try { assertApiFailureCode(response, '404'); + if (!response.success) { + expect(response.statusCode).toBe(404); + } } finally { await cleanupShell(shell.id); } @@ -3760,6 +3838,10 @@ describe('AAS Repository Integration Tests', () => { } }); + /** + * @operation GetFileByPath_AasRepository + * @status 404 + */ test('should return not found when downloading a deleted file through AAS repository superpath', async () => { const { shell, submodel } = await createScopedSuperpathFixture(); @@ -3792,6 +3874,9 @@ describe('AAS Repository Integration Tests', () => { }); assertApiFailureCode(response, '404'); + if (!response.success) { + expect(response.statusCode).toBe(404); + } } finally { await cleanupShell(shell.id); } @@ -3815,6 +3900,10 @@ describe('AAS Repository Integration Tests', () => { } }); + /** + * @operation DeleteSubmodelElementByPath_AasRepository + * @status 204 + */ test('should delete SubmodelElement by path through AAS repository superpath', async () => { const { shell, submodel } = await createScopedSuperpathFixture(); @@ -3827,6 +3916,9 @@ describe('AAS Repository Integration Tests', () => { try { assertApiResult(response); + if (response.success) { + expect(response.statusCode).toBe(204); + } } finally { await cleanupShell(shell.id); } From 722bcf0fce4622d90d53e9ef5200ace494d2dc12 Mon Sep 17 00:00:00 2001 From: Aaron Zielstorff Date: Tue, 5 May 2026 22:37:09 +0200 Subject: [PATCH 5/5] Adds further status code assertions Co-authored-by: Copilot --- ...conceptDescriptionRepo.integration.test.ts | 8 + .../submodelRepo.integration.test.ts | 181 ++++++++++++++++++ 2 files changed, 189 insertions(+) diff --git a/src/integration-tests/conceptDescriptionRepo.integration.test.ts b/src/integration-tests/conceptDescriptionRepo.integration.test.ts index 45e79d48..964c158e 100644 --- a/src/integration-tests/conceptDescriptionRepo.integration.test.ts +++ b/src/integration-tests/conceptDescriptionRepo.integration.test.ts @@ -236,6 +236,10 @@ describe('Concept Description Repository Integration Tests', () => { } }); + /** + * @operation PutConceptDescriptionById + * @status 201 + */ test('should create a Concept Description through put by ID with current backend status', async () => { const conceptDescription = createUniqueConceptDescription(); @@ -281,6 +285,10 @@ describe('Concept Description Repository Integration Tests', () => { } }); + /** + * @operation PutConceptDescriptionById + * @status 204 + */ test('should update a Concept Description through put by ID with current backend status', async () => { const conceptDescription = createUniqueConceptDescription(); const createResponse = await client.postConceptDescription({ diff --git a/src/integration-tests/submodelRepo.integration.test.ts b/src/integration-tests/submodelRepo.integration.test.ts index 380464ca..90ceddbb 100644 --- a/src/integration-tests/submodelRepo.integration.test.ts +++ b/src/integration-tests/submodelRepo.integration.test.ts @@ -590,6 +590,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '400'); + if (!response.success) { + expect(response.statusCode).toBe(400); + } }); /** @@ -606,6 +609,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '404'); + if (!response.success) { + expect(response.statusCode).toBe(404); + } }); /** @@ -1109,6 +1115,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '400'); + if (!response.success) { + expect(response.statusCode).toBe(400); + } }); /** @@ -1122,6 +1131,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '404'); + if (!response.success) { + expect(response.statusCode).toBe(404); + } }); /** @@ -1165,6 +1177,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '400'); + if (!response.success) { + expect(response.statusCode).toBe(400); + } }); /** @@ -1178,6 +1193,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '404'); + if (!response.success) { + expect(response.statusCode).toBe(404); + } }); /** @@ -1224,6 +1242,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '400'); + if (!response.success) { + expect(response.statusCode).toBe(400); + } }); /** @@ -1245,6 +1266,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '404'); + if (!response.success) { + expect(response.statusCode).toBe(404); + } }); /** @@ -1312,6 +1336,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '404'); + if (!response.success) { + expect(response.statusCode).toBe(404); + } }); /** @@ -1327,6 +1354,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '400'); + if (!response.success) { + expect(response.statusCode).toBe(400); + } }); /** @@ -1365,6 +1395,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '400'); + if (!response.success) { + expect(response.statusCode).toBe(400); + } }); /** @@ -1417,6 +1450,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '404'); + if (!response.success) { + expect(response.statusCode).toBe(404); + } }); /** @@ -1500,6 +1536,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '400'); + if (!response.success) { + expect(response.statusCode).toBe(400); + } }); /** @@ -1538,6 +1577,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '400'); + if (!response.success) { + expect(response.statusCode).toBe(400); + } }); /** @@ -1551,6 +1593,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '404'); + if (!response.success) { + expect(response.statusCode).toBe(404); + } }); /** @@ -1593,6 +1638,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '400'); + if (!response.success) { + expect(response.statusCode).toBe(400); + } }); /** @@ -1606,6 +1654,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '404'); + if (!response.success) { + expect(response.statusCode).toBe(404); + } }); /** @@ -1648,6 +1699,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '400'); + if (!response.success) { + expect(response.statusCode).toBe(400); + } }); /** @@ -1661,6 +1715,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '404'); + if (!response.success) { + expect(response.statusCode).toBe(404); + } }); /** @@ -1703,6 +1760,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '400'); + if (!response.success) { + expect(response.statusCode).toBe(400); + } }); /** @@ -1716,6 +1776,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '404'); + if (!response.success) { + expect(response.statusCode).toBe(404); + } }); /** @@ -1758,6 +1821,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '400'); + if (!response.success) { + expect(response.statusCode).toBe(400); + } }); /** @@ -1771,6 +1837,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '404'); + if (!response.success) { + expect(response.statusCode).toBe(404); + } }); /** @@ -1813,6 +1882,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '400'); + if (!response.success) { + expect(response.statusCode).toBe(400); + } }); /** @@ -1826,6 +1898,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '404'); + if (!response.success) { + expect(response.statusCode).toBe(404); + } }); /** @@ -1870,6 +1945,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '400'); + if (!response.success) { + expect(response.statusCode).toBe(400); + } }); /** @@ -1891,6 +1969,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '404'); + if (!response.success) { + expect(response.statusCode).toBe(404); + } }); /** @@ -1935,6 +2016,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '400'); + if (!response.success) { + expect(response.statusCode).toBe(400); + } }); /** @@ -1956,6 +2040,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '404'); + if (!response.success) { + expect(response.statusCode).toBe(404); + } }); /** @@ -2000,6 +2087,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '400'); + if (!response.success) { + expect(response.statusCode).toBe(400); + } }); /** @@ -2021,6 +2111,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '404'); + if (!response.success) { + expect(response.statusCode).toBe(404); + } }); /** @@ -2035,6 +2128,7 @@ describe('Submodel Repository Integration Tests', () => { assertApiResult(response); if (response.success) { + expect(response.statusCode).toBe(200); expect(response.data).toBeDefined(); expect(response.data.size).toBeGreaterThan(0); } @@ -2052,6 +2146,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '400'); + if (!response.success) { + expect(response.statusCode).toBe(400); + } }); /** @@ -2153,6 +2250,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '400'); + if (!response.success) { + expect(response.statusCode).toBe(400); + } }); /** @@ -2218,6 +2318,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '400'); + if (!response.success) { + expect(response.statusCode).toBe(400); + } }); /** @@ -2240,6 +2343,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '404'); + if (!response.success) { + expect(response.statusCode).toBe(404); + } }); /** @@ -2335,6 +2441,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '405'); + if (!response.success) { + expect(response.statusCode).toBe(405); + } }); /** @@ -2349,6 +2458,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '400'); + if (!response.success) { + expect(response.statusCode).toBe(400); + } }); /** @@ -2372,6 +2484,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '404'); + if (!response.success) { + expect(response.statusCode).toBe(404); + } }); /** @@ -2389,6 +2504,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '400'); + if (!response.success) { + expect(response.statusCode).toBe(400); + } }); /** @@ -2404,6 +2522,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiResult(response); + if (response.success) { + expect(response.statusCode).toBe(200); + } }); /** @@ -2419,6 +2540,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '400'); + if (!response.success) { + expect(response.statusCode).toBe(400); + } }); /** @@ -2434,6 +2558,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '404'); + if (!response.success) { + expect(response.statusCode).toBe(404); + } }); /** @@ -2469,6 +2596,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '400'); + if (!response.success) { + expect(response.statusCode).toBe(400); + } }); /** @@ -2485,6 +2615,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '404'); + if (!response.success) { + expect(response.statusCode).toBe(404); + } }); /** @@ -2518,6 +2651,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '400'); + if (!response.success) { + expect(response.statusCode).toBe(400); + } }); /** @@ -2533,6 +2669,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '404'); + if (!response.success) { + expect(response.statusCode).toBe(404); + } }); /** @@ -2568,6 +2707,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '400'); + if (!response.success) { + expect(response.statusCode).toBe(400); + } }); /** @@ -2584,6 +2726,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '404'); + if (!response.success) { + expect(response.statusCode).toBe(404); + } }); /** @@ -2617,6 +2762,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '400'); + if (!response.success) { + expect(response.statusCode).toBe(400); + } }); /** @@ -2632,6 +2780,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '404'); + if (!response.success) { + expect(response.statusCode).toBe(404); + } }); /** @@ -2665,6 +2816,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '400'); + if (!response.success) { + expect(response.statusCode).toBe(400); + } }); /** @@ -2680,6 +2834,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '404'); + if (!response.success) { + expect(response.statusCode).toBe(404); + } }); /** @@ -2713,6 +2870,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '400'); + if (!response.success) { + expect(response.statusCode).toBe(400); + } }); /** @@ -2728,6 +2888,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '404'); + if (!response.success) { + expect(response.statusCode).toBe(404); + } }); /** @@ -2779,6 +2942,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '400'); + if (!response.success) { + expect(response.statusCode).toBe(400); + } }); /** @@ -2800,6 +2966,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '404'); + if (!response.success) { + expect(response.statusCode).toBe(404); + } }); /** @@ -2838,6 +3007,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '404'); + if (!response.success) { + expect(response.statusCode).toBe(404); + } }); /** @@ -2880,6 +3052,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '400'); + if (!response.success) { + expect(response.statusCode).toBe(400); + } }); /** @@ -2901,6 +3076,9 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '404'); + if (!response.success) { + expect(response.statusCode).toBe(404); + } }); /** @@ -2937,5 +3115,8 @@ describe('Submodel Repository Integration Tests', () => { }); assertApiFailureCode(response, '404'); + if (!response.success) { + expect(response.statusCode).toBe(404); + } }); });