camunda / camunda/api-test-generator
Positive suite doesn't enumerate enum values on optional sort/filter fields — server-side bugs at valid enum values invisible
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 0
- Forks
- 3
- Avg merge
- 13h 41m
- Merged PRs (30d)
- 23
Description
Summary
Positive-path tests don't enumerate enum values for optional sort/filter body fields (and similar enum-typed query/body parameters). Server-side semantic bugs that fire on a valid enum value but not others slip through both suites today.
Canonical example: camunda/camunda#50945 — POST /process-definitions/statistics/process-instances returns 500 when the request body contains:
{ "sort": [{ "field": "processDefinitionId", "order": "DESC" }] }
processDefinitionId is one of three documented valid enum values for ProcessDefinitionInstanceStatisticsQuerySortRequest.field:
{
"field": {
"type": "string",
"enum": [
"processDefinitionId",
"activeInstancesWithIncidentCount",
"activeInstancesWithoutIncidentCount"
]
}
}
The other two values return 200; only processDefinitionId 500s. Per-enum-value semantic bugs of this shape are exactly what a generated suite should catch.
Why neither current suite catches this
Positive suite (path-analyser/dist/generated-tests/getProcessDefinitionInstanceStatistics.feature.spec.ts)
One test, feature-1 - base (1), sends an empty body {} and expects 200. Optional fields are never populated; enum values are never explored.
Negative suite (request-validation/generated/processdefinitions-validation-api-tests.spec.ts)
Has an Enum violation sort.0.field (#1) test that sends 'processDefinitionId_INVALID' to confirm the server returns 400. By design the negative suite covers invalid requests — a request with a valid enum value that triggers a 500 is out of scope.
So there's a coverage gap between "empty body → 200" (positive) and "malformed body → 400" (negative): valid bodies that exercise specific enum values.
Proposed fix: enum-value variant generation
Extend the variant generator to enumerate enum values on optional body/query/path fields, producing one test per enum value per ordering-relevant axis. Concretely, for the canonical example:
test.each([
'processDefinitionId',
'activeInstancesWithIncidentCount',
'activeInstancesWithoutIncidentCount',
])('getProcessDefinitionInstanceStatistics - sort by %s returns 200', async (field) => {
// POST with { sort: [{ field, order: 'ASC' }] }, assert 200, validate response shape
});
The path-analyser already emits .variant.spec.ts files for oneOf discriminator variants (see e.g. getProcessDefinitionInstanceVersionStatistics.variant.spec.ts). This is structurally identical: enumerate finite alternatives at one axis, hold the rest minimal.
Scope and budget
- Axes to vary:
sort[].field,filter.*enum fields, top-level enum body/query parameters, andorder(ASC/DESC) when paired with sort. - Combinations: vary one axis at a time (the natural extension of "base" — not a cartesian product). For
sort, that's N enum values × 2 orders, scoped per endpoint. - Budget: cap variants per endpoint (suggest 12) with deterministic enumeration ordered by the spec's enum declaration. Fallback to "base only" if the budget would be exceeded.
- Determinism: enumeration follows OpenAPI declaration order so output is byte-stable under the existing
TEST_SEED=snapshot-baselinediscipline.
Files likely touched
- path-analyser/src/scenarioGenerator.ts — add an enum-axis variant strategy alongside the existing
oneOf-variant strategy. - path-analyser/src/codegen/emitter.ts — emit
.variant.spec.tswithtest.eachshape. tests/fixtures/planner/— Layer-2 fixture: hand-built minimalOperationGraphwith an enum-typed sort field; assert the planner emits one variant per enum value.tests/regression/bundled-spec-invariants.test.ts— Layer-3 invariant: every endpoint with an optional sort field has at least one variant per enum value (or is in a documented exclusion list).
Acceptance criteria
- Layer-1 fixture —
path-analyser/src/scenarioGenerator.tsemits one variant per enum value when an optional body field hastype: string+enum: [...]. - Layer-2 fixture — minimal
OperationGraphwith sort-enum and filter-enum fields produces the expected variant fan-out. - Layer-3 invariant —
getProcessDefinitionInstanceStatistics(and structurally similar endpoints —searchProcessInstances,searchUserTasks, etc.) emit a.variant.spec.tsfile with onetest.eachrow per declared sort field. - Regression artefact — a manually-run variant suite on a snapshot build (or local Camunda) reproduces the 500 for
processDefinitionIdfrom #50945, demonstrating the test class would have caught the bug. - Budget honoured — no endpoint emits more than the configured cap; overflow falls back to
feature-Nbase test plus a documented partial-variant exclusion noted inpath-analyser/domain-semantics.jsonor equivalent. - Determinism preserved —
TEST_SEED=snapshot-baseline npm run testsuite:generateis byte-stable across runs (existing CI guard).
Out of scope
- Cartesian-product exploration across multiple enum axes. Single-axis variants only; multi-axis combinations are a separate (much larger) issue.
- Numeric-range or string-pattern variant exploration (separate test class — boundary/property-based testing).
- Negative-suite changes —
request-validationalready covers enum violations.
References
- Bug surfaced this gap: camunda/camunda#50945
- Existing variant generation pattern:
path-analyser/dist/generated-tests/*.variant.spec.ts - Layered test strategy this would extend: CONTRIBUTING.md
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with path-analyser/src/scenarioGenerator.ts and the existing oneOf variant strategy, then inspect path-analyser/src/codegen/emitter.ts and the generated .variant.spec.ts examples. Use the planner fixtures and bundled-spec invariants tests to define enum-axis fan-out, budget, and determinism. Done means the listed acceptance layers pass, including TEST_SEED=snapshot-baseline npm run testsuite:generate and the regression variant for getProcessDefinitionInstanceStatistics.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- openapi, typescript
- Domain
- testing-qa, tooling
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 48/100