Skip to content

Commit ca90492

Browse files
authored
test(e2e): add end-to-end payload decoder coverage (#3321)
* add payload coverage workflow and add encryption to codec server * test(e2e): add payload decoder tests covering all payload touchpoints Start payload-coverage-workflow fire-and-forget in global setup so the workflow remains running when tests execute, enabling signal and query interaction. Add payload-decoder.desktop.spec.ts covering: - Workflow input decoded via cluster codec - Memo payloads decoded - Search attributes decoded - Event history: WorkflowExecutionStarted, ActivityTaskScheduled, ActivityTaskCompleted, ActivityTaskFailed, StartChildWorkflowExecutionInitiated, ChildWorkflowExecutionCompleted - Query results (get-status, get-field) - Send signal and verify decoded payload in history - Call stack stack trace Use getByRole('textbox') within event-summary-row-expanded to access CodeMirror contentDOM directly, matching the pattern used by existing query and call-stack tests. * test(e2e): refactor payload-decoder spec to use page object model Add four page classes to encapsulate e2e test interactions: - WorkflowDetailPage: tab navigation and input/result/main locators - EventHistoryPage: feed toggle, event row expansion, and editor access - WorkflowQueryPage: query type selection, arg input, and result - SignalModalPage: signal modal open, signal selection, payload fill and submit Refactor payload-decoder.desktop.spec.ts to use these classes, removing all raw page.getByTestId/getByRole calls from the test body. Also upgrades @temporalio/* packages from 1.15.0 to 1.16.0. * change wf timeout back to 5 minutes * fix search attributes
1 parent 9146199 commit ca90492

23 files changed

Lines changed: 962 additions & 128 deletions

package.json

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,8 @@
7373
"stylelint": "stylelint \"src/**/*.{css,postcss,svelte}\"",
7474
"stylelint:fix": "stylelint --fix \"src/**/*.{css,postcss,svelte}\"",
7575
"generate:locales": "esno scripts/generate-locales.ts",
76-
"workflows": "esno scripts/workflows.ts",
76+
"e2e-workflows": "esno scripts/e2e-workflows.ts",
77+
"payload-coverage-workflow": "esno scripts/payload-coverage-workflow.ts",
7778
"audit:tailwind": "esno scripts/audit-tailwind-colors",
7879
"audit:holocene-props": "esno scripts/generate-holocene-props.ts",
7980
"validate:versions": "./scripts/validate-versions.sh"
@@ -145,13 +146,13 @@
145146
"@sveltejs/adapter-vercel": "^6.3.2",
146147
"@sveltejs/kit": "2.57.1",
147148
"@sveltejs/vite-plugin-svelte": "^6.2.4",
148-
"@temporalio/activity": "1.15.0",
149-
"@temporalio/client": "1.15.0",
150-
"@temporalio/common": "1.15.0",
151-
"@temporalio/proto": "1.15.0",
152-
"@temporalio/testing": "1.15.0",
153-
"@temporalio/worker": "1.15.0",
154-
"@temporalio/workflow": "1.15.0",
149+
"@temporalio/activity": "1.16.0",
150+
"@temporalio/client": "1.16.0",
151+
"@temporalio/common": "1.16.0",
152+
"@temporalio/proto": "1.16.0",
153+
"@temporalio/testing": "1.16.0",
154+
"@temporalio/worker": "1.16.0",
155+
"@temporalio/workflow": "1.16.0",
155156
"@types/base-64": "^1.0.0",
156157
"@types/cors": "^2.8.13",
157158
"@types/express": "^4.17.17",

pnpm-lock.yaml

Lines changed: 74 additions & 74 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { connect, startPayloadCoverageWorkflow } from '../temporal/client';
2+
import { runWorkerUntil } from '../temporal/workers';
3+
4+
async function main() {
5+
const client = await connect();
6+
const result = startPayloadCoverageWorkflow(client);
7+
await runWorkerUntil(result);
8+
}
9+
10+
main().catch((error) => {
11+
console.error(error);
12+
process.exit(1);
13+
});

src/lib/pages/workflow-query.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@
145145
<Option {value} {description}>{value}</Option>
146146
{/each}
147147
</Select>
148-
<div class="flex flex-col gap-1">
148+
<div data-testid="query-input" class="flex flex-col gap-1">
149149
<PayloadInput bind:input label={translate('workflows.query-arg')} />
150150
</div>
151151
<div class="flex w-full flex-wrap items-end justify-end gap-4">

temporal/PAYLOAD_COVERAGE.md

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# PayloadCoverageWorkflow — Design Notes
2+
3+
## Context
4+
5+
The `<Payload>` component in `src/lib/components/payload/payload.svelte` decodes and renders Temporal Payloads from event history. To test all display/decode paths in the UI, we need a Temporal workflow that exercises every event type that produces a Payload field. The workflow is added to the existing `temporal/` directory which already has a worker, client, codec, and 4 existing workflows.
6+
7+
## Files
8+
9+
- `temporal/activities/complex.ts` — new activity with rich input/output types
10+
- `temporal/activities/index.ts` — exports the new `complex` activity
11+
- `temporal/workflows.ts` — adds `PayloadCoverageChildWorkflow` and `PayloadCoverageWorkflow`
12+
- `temporal/client.ts` — adds `startPayloadCoverageWorkflow` helper for easy testing
13+
14+
## Payload-Producing Event Types Covered
15+
16+
| Event / Location | Payload Field |
17+
| ------------------------------------------- | -------------------------------------------------------------------------- |
18+
| `WorkflowExecutionStarted` | `input` — rich object with all JSON primitive types; `memo` — set at start |
19+
| `ActivityTaskScheduled` | `input` — complex object with nested arrays/objects |
20+
| `ActivityTaskCompleted` | `result` — complex return object |
21+
| `ActivityTaskFailed` | `failure.details` — from deliberately failing activity variant |
22+
| `ActivityTaskScheduled` (local) | inside `MarkerRecorded` details |
23+
| `ActivityTaskCompleted` (local) | inside `MarkerRecorded` details |
24+
| `WorkflowExecutionSignaled` | `input` — two signals with typed payloads |
25+
| `WorkflowExecutionUpdateAccepted/Completed` | `input` / `result` |
26+
| `UpsertWorkflowSearchAttributes` | search attribute value Payloads |
27+
| `StartChildWorkflowExecutionInitiated` | `input` |
28+
| `ChildWorkflowExecutionCompleted` | `result` |
29+
| `WorkflowExecutionCompleted` | `result` — aggregate result object |
30+
| Query `get-status` | runtime query response (visible in UI query tab) |
31+
| Query `get-field` | parameterized query response |
32+
33+
## Workflow Behavior
34+
35+
- **Starts and runs activities/child workflow immediately** — all Payload events are created on start
36+
- **Waits up to 5 minutes** for signals/queries/updates via `condition` — gives time for manual UI testing
37+
- **Auto-completes** after the timeout, so you also see `WorkflowExecutionCompleted` with result payload
38+
- **Failing activity** is wrapped in try/catch — workflow continues after `ActivityTaskFailed` is recorded
39+
40+
## Running It
41+
42+
```bash
43+
# Register custom search attributes (one-time, local dev server)
44+
temporal operator search-attribute create --name CustomKeywordField --type Keyword
45+
temporal operator search-attribute create --name CustomIntField --type Int
46+
```
47+
48+
Then call `startPayloadCoverageWorkflow(client)` from `client.ts`. The workflow starts at ID `payload-coverage-workflow`.
49+
50+
## Interacting During the 5-Minute Window
51+
52+
**Send a signal:**
53+
54+
```bash
55+
temporal workflow signal \
56+
--workflow-id payload-coverage-workflow \
57+
--name add-data \
58+
--input '{"key":"testKey","value":{"nested":true}}'
59+
60+
temporal workflow signal \
61+
--workflow-id payload-coverage-workflow \
62+
--name trigger \
63+
--input '["tagA","tagB"]'
64+
```
65+
66+
**Send an update:**
67+
68+
```bash
69+
temporal workflow update \
70+
--workflow-id payload-coverage-workflow \
71+
--name process-update \
72+
--input '{"operation":"transform","payload":{"x":1,"y":2}}'
73+
```
74+
75+
**Run a query:**
76+
77+
```bash
78+
temporal workflow query \
79+
--workflow-id payload-coverage-workflow \
80+
--type get-status
81+
82+
temporal workflow query \
83+
--workflow-id payload-coverage-workflow \
84+
--type get-field \
85+
--input '"stringField"'
86+
```

0 commit comments

Comments
 (0)