From 126933ba73e073be7a8d4d27cedb167f5e89f25b Mon Sep 17 00:00:00 2001 From: Dallin Romney Date: Fri, 31 Jul 2026 14:56:20 +0800 Subject: [PATCH] fix(qa): exceed Slack table aggregate limit in fallback probe (#116447) --- .../live-transports/slack/slack-live.invalid-blocks.ts | 10 +++++++++- .../live-transports/slack/slack-live.runtime.test.ts | 10 ++++++---- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/extensions/qa-lab/src/live-transports/slack/slack-live.invalid-blocks.ts b/extensions/qa-lab/src/live-transports/slack/slack-live.invalid-blocks.ts index 0a032b980c58..2c50c56cf8e3 100644 --- a/extensions/qa-lab/src/live-transports/slack/slack-live.invalid-blocks.ts +++ b/extensions/qa-lab/src/live-transports/slack/slack-live.invalid-blocks.ts @@ -8,7 +8,10 @@ import { function buildSlackInvalidBlocksTableRow(index: number) { const rowId = String(index).padStart(3, "0"); - return [`row-${rowId}`, `value-${rowId}`] as const; + // Cross both independently documented native-table limits. Slack has + // accepted the over-row-limit shape alone, so the probe also exceeds the + // 10,000-character aggregate cell contract. + return [`row-${rowId}`, `value-${rowId}-${"x".repeat(96)}`] as const; } export function buildSlackInvalidBlocksTableProbe() { @@ -32,8 +35,13 @@ export function buildSlackInvalidBlocksTableProbe() { SLACK_QA_INVALID_TABLE_HEADERS.join("\t"), ...dataRows.map((row) => row.join("\t")), ].join("\n"); + const cellCharacterCount = [...SLACK_QA_INVALID_TABLE_HEADERS, ...dataRows.flat()].reduce( + (total, value) => total + Array.from(value).length, + 0, + ); return { block, + cellCharacterCount, dataRowCount: dataRows.length, fallbackText, firstRowText: buildSlackInvalidBlocksTableRow(1).join("\t"), diff --git a/extensions/qa-lab/src/live-transports/slack/slack-live.runtime.test.ts b/extensions/qa-lab/src/live-transports/slack/slack-live.runtime.test.ts index 3d8c067f9c87..59d8254eefbf 100644 --- a/extensions/qa-lab/src/live-transports/slack/slack-live.runtime.test.ts +++ b/extensions/qa-lab/src/live-transports/slack/slack-live.runtime.test.ts @@ -1001,13 +1001,15 @@ describe("Slack live QA runtime helpers", () => { { type: "raw_text", text: "Row" }, { type: "raw_text", text: "Value" }, ]); - expect(probe.firstRowText).toBe("row-001\tvalue-001"); - expect(probe.finalRowText).toBe("row-101\tvalue-101"); + expect(probe.cellCharacterCount).toBeGreaterThan(10_000); + expect(probe.firstRowText).toMatch(/^row-001\tvalue-001-x{96}$/u); + expect(probe.finalRowText).toMatch(/^row-101\tvalue-101-x{96}$/u); expect(probe.fallbackText.split("\n")).toContain(probe.firstRowText); expect(probe.fallbackText.split("\n")).toContain(probe.finalRowText); }); it("proves the public Slack send path stores one complete formatting-disabled fallback", async () => { + const probe = testing.buildSlackInvalidBlocksTableProbe(); const invalidBlocksError = Object.assign(new Error("An API error occurred: invalid_blocks"), { code: "slack_webapi_platform_error", data: { error: "invalid_blocks", ok: false }, @@ -1068,8 +1070,8 @@ describe("Slack live QA runtime helpers", () => { expect(fallbackRequest).toMatchObject({ mrkdwn: false }); const fallbackText = typeof fallbackRequest?.text === "string" ? fallbackRequest.text : ""; expect(fallbackText).toBe(nativeRequest?.text); - expect(fallbackText.split("\n")).toContain("row-001\tvalue-001"); - expect(fallbackText.split("\n")).toContain("row-101\tvalue-101"); + expect(fallbackText.split("\n")).toContain(probe.firstRowText); + expect(fallbackText.split("\n")).toContain(probe.finalRowText); expect(result.message).toMatchObject({ text: fallbackText, ts: "2.000000",