| 19 | */ |
| 20 | |
| 21 | export interface E2ECase { |
| 22 | name: string; |
| 23 | prompt: string; |
| 24 | sampleIntervalMs?: number; |
| 25 | maxWaitMs?: number; |
| 26 | screenshots?: number[]; |
| 27 | /** |
| 28 | * Optional follow-up turn that gets sent INTO the thread that this case's |
| 29 | * first prompt creates. Used to test thread-continuation without |
| 30 | * re-mentioning the bot. The follow-up has its own prompt + expectations |
| 31 | * and reuses the same sampleIntervalMs / maxWaitMs. |
| 32 | */ |
| 33 | followUp?: { |
| 34 | prompt: string; |
| 35 | expectations?: E2ECase["expectations"]; |
| 36 | }; |
| 37 | /** |
| 38 | * Mid-stream interrupt: send a second user message into the SAME thread |
| 39 | * `afterMs` after kicking off the first prompt. Used to verify that the |
| 40 | * in-flight bot reply is aborted, marked as interrupted in Slack, and |
| 41 | * the new turn produces a fresh reply. |
| 42 | */ |
| 43 | interrupt?: { |
| 44 | afterMs: number; |
| 45 | prompt: string; |
| 46 | /** Expectations applied to the interrupted FIRST reply. */ |
| 47 | firstExpectations?: E2ECase["expectations"]; |
| 48 | /** Expectations applied to the new (second) reply. */ |
| 49 | expectations?: E2ECase["expectations"]; |
| 50 | }; |
| 51 | expectations?: { |
| 52 | /** Bot's final response must contain these substrings (case-insensitive). */ |
| 53 | finalContains?: string[]; |
| 54 | /** Bot's final response must NOT contain these. */ |
| 55 | finalNotContains?: string[]; |
| 56 | /** Final mrkdwn must be balanced (no dangling brackets). */ |
| 57 | balancedBrackets?: boolean; |
| 58 | /** Minimum reply length in chars (catches truncation regressions). */ |
| 59 | minLength?: number; |
| 60 | /** |
| 61 | * Verifies the final text contains a monospace table whose rows all |
| 62 | * have the same line length — i.e. columns are aligned, not pipe-soup. |
| 63 | */ |
| 64 | monospaceAlignedTable?: boolean; |
| 65 | /** |
| 66 | * Counts how many distinct Slack messages this case produced (after |
| 67 | * the bot's parent message). Used to verify chunking-keeps-whole-block |
| 68 | * behaviour: a long fenced block should land in one message, not split. |
| 69 | */ |
| 70 | expectedChunkCount?: number; |
| 71 | /** |
| 72 | * Custom predicate run against the *full* set of bot replies in the |
| 73 | * thread (NOT just the first one). Useful for asserting properties |
| 74 | * across chunked output, e.g. "the fence opener appears at the start |
| 75 | * of exactly one message" or "no message text contains a dangling ```". |
| 76 | */ |
| 77 | /** |
| 78 | * Custom predicate. `replies` is the bot's per-message text array; |
nothing calls this directly
no outgoing calls
no test coverage detected