From f3c231932e3ced6505e014e5c60dea1ca6100a96 Mon Sep 17 00:00:00 2001 From: Alex Luong Date: Thu, 28 May 2026 20:33:40 +0700 Subject: [PATCH 1/3] test(spec-sdk): fix paginator response shape (response.result.models) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Speakeasy CLI 1.741.7 → 1.753.0 (commit 3f311e0d, 2026-03-13) changed the generated TS SDK return type for list operations from the flat paginated body to a PageIterator wrapper: ListEventsResponse now wraps the body in `result`, so callers access `response.result.models` instead of `response.models`. The shape change was a side-effect of the Speakeasy version bump and wasn't surfaced in the SDK regen PR changelog (which only flagged the unrelated `request` query-param restyle). Tests in spec-sdk-tests/tests/{events,tenants}.test.ts still used the pre-bump accessor and failed to compile against the current SDK. Co-Authored-By: Claude Opus 4.7 (1M context) --- spec-sdk-tests/tests/events.test.ts | 8 ++++---- spec-sdk-tests/tests/tenants.test.ts | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/spec-sdk-tests/tests/events.test.ts b/spec-sdk-tests/tests/events.test.ts index 4868fb1d9..b101e3cb9 100644 --- a/spec-sdk-tests/tests/events.test.ts +++ b/spec-sdk-tests/tests/events.test.ts @@ -168,7 +168,7 @@ describe('Events (PR #491)', () => { limit: 5, }); expect(response).to.not.be.undefined; - expect(response?.models).to.be.an('array'); + expect(response?.result?.models).to.be.an('array'); }); it('should list events by tenant', async function () { @@ -191,7 +191,7 @@ describe('Events (PR #491)', () => { const response = await sdk.events.list({ tenantId: client.getTenantId(), }); - return response?.models || []; + return response?.result?.models || []; }, 30000, 5000 @@ -209,7 +209,7 @@ describe('Events (PR #491)', () => { const response = await sdk.events.list({ tenantId: client.getTenantId(), }); - const events = response?.models || []; + const events = response?.result?.models || []; if (events.length === 0) { console.warn('No events found - skipping single event test'); @@ -253,7 +253,7 @@ describe('Events (PR #491)', () => { destinationId: destinationId, eventId, }); - return response?.models ?? []; + return response?.result?.models ?? []; }, 45000, 5000 diff --git a/spec-sdk-tests/tests/tenants.test.ts b/spec-sdk-tests/tests/tenants.test.ts index cb04cef57..c44c2f41d 100644 --- a/spec-sdk-tests/tests/tenants.test.ts +++ b/spec-sdk-tests/tests/tenants.test.ts @@ -19,8 +19,8 @@ describe('Tenants - List with request object', () => { const result = await sdk.tenants.list({ limit: 5 }); expect(result).to.not.be.undefined; - expect(result?.models).to.be.an('array'); - (result?.models ?? []).forEach((t: { id?: string }, i: number) => { + expect(result?.result?.models).to.be.an('array'); + (result?.result?.models ?? []).forEach((t: { id?: string }, i: number) => { expect(t, `tenant[${i}]`).to.be.an('object'); if (t.id != null) expect(t.id, `tenant[${i}].id`).to.be.a('string'); }); From 53ade0de669fcc1b413b48e5ed661cf9d2b6431a Mon Sep 17 00:00:00 2001 From: Alex Luong Date: Thu, 28 May 2026 21:30:12 +0700 Subject: [PATCH 2/3] test(spec-sdk): assert event.data is exposed when include=event.data Co-Authored-By: Claude Opus 4.7 (1M context) --- spec-sdk-tests/tests/events.test.ts | 34 +++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/spec-sdk-tests/tests/events.test.ts b/spec-sdk-tests/tests/events.test.ts index b101e3cb9..fe6e08324 100644 --- a/spec-sdk-tests/tests/events.test.ts +++ b/spec-sdk-tests/tests/events.test.ts @@ -265,5 +265,39 @@ describe('Events (PR #491)', () => { expect(attempt.status).to.equal('success', 'Delivery to mock.hookdeck.com should succeed'); console.log(`Event ${eventId} generated attempt; status: ${attempt.status}`); }); + + it('listAttempts with include=event.data should expose event.data on the parsed attempt', async function () { + this.timeout(60000); + + const sdk: Outpost = client.getSDK(); + + const payload = { marker: `include-event-data-${Date.now()}` }; + const publishResponse = await sdk.publish({ + tenantId: client.getTenantId(), + topic: TEST_TOPICS[0], + data: payload, + }); + const eventId = publishResponse.id; + + const attempts = await pollForAttempts( + async () => { + const response = await sdk.destinations.listAttempts({ + tenantId: client.getTenantId(), + destinationId: destinationId, + eventId, + include: ['event.data', 'response_data'], + }); + return response?.result?.models ?? []; + }, + 45000, + 5000 + ); + + expect(attempts.length).to.be.at.least(1, 'Expected at least one attempt'); + const attempt = attempts[0]; + expect(attempt.responseData, 'response_data should be populated when include=response_data').to.exist; + expect(attempt.event, 'event should be populated when include=event.data').to.exist; + expect((attempt.event as { data?: unknown }).data, 'event.data should be populated when include=event.data').to.deep.equal(payload); + }); }); }); From 6dd579a078b7d73f3f5d5f7b790b5a06701011a7 Mon Sep 17 00:00:00 2001 From: Alex Luong Date: Thu, 28 May 2026 22:39:43 +0700 Subject: [PATCH 3/3] fix(spec): order EventFull before EventSummary in Attempt.event oneOf MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Speakeasy's TS generator emits zod unions in declaration order. The non-strict EventSummary matched first and silently stripped event.data from the parsed attempt — losing the payload added by include=event.data. Declaring EventFull first lets it match when data is present, with EventSummary as the fallback. Co-Authored-By: Claude Opus 4.7 (1M context) --- docs/apis/openapi.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/apis/openapi.yaml b/docs/apis/openapi.yaml index 0832890e4..c3c6915fd 100644 --- a/docs/apis/openapi.yaml +++ b/docs/apis/openapi.yaml @@ -2535,8 +2535,8 @@ components: event: nullable: true oneOf: - - $ref: "#/components/schemas/EventSummary" - $ref: "#/components/schemas/EventFull" + - $ref: "#/components/schemas/EventSummary" description: The associated event object. Only present when include=event or include=event.data. destination: nullable: true