Test Cases
Create, generate, edit, organize, publish, and inspect individual tests.
| Method | Path | What it does |
|---|---|---|
| POST | /test-cases/ | Bulk-create test cases (generation optional via schedule flag) |
| POST | /test-case/ | Create a single test case and immediately queue generation |
| GET | /test-case/{test_case_id} | Get full test case detail including generated steps |
| DELETE | /test-case/{test_case_id} | Delete a test case and all its runs |
| GET | /test-case/state/{test_case_id} | Get just the generation state (cheap to poll) |
| PATCH | /test-case/{test_case_id}/edit | Partial update (only supplied fields are changed; schedule query flag controls regeneration) |
| PUT | /test-case/{test_case_id}/regenerate | Re-run generation |
| POST | /test-case/{test_case_id}/record-journey | Trigger journey recording |
| PUT | /test-case/{test_case_id}/append-description | Append text to the description and regenerate |
| PUT | /test-case/{test_case_id}/user-feedback | Submit step-level feedback to steer generation |
| DELETE | /test-case/cancel/{test_case_id} | Cancel queued generation |
| PATCH | /test-case/{test_case_id}/steps/{step_index} | Mark a step optional or mandatory |
| DELETE | /test-cases/{test_case_id}/steps/{test_step_index} | Delete a step |
| GET | /test-case/{test_case_id}/parameters | List a test case's parameters |
| PATCH | /test-cases/{test_case_id}/collections | Set which collections the test belongs to |
| POST | /test-cases/{test_case_id}/copy | Deep-copy a test within its suite |
| PUT | /test-cases/{test_case_id}/rename | Rename a test case |
| PUT | /test-cases/{test_case_id}/update-test-path | Move a test to a different folder path |
| PUT | /test-cases/{test_suite_id}/update-test-paths | Bulk-update folder paths |
| PUT | /test-cases/{test_case_id}/set-test-suite/{new_test_suite_id} | Move a test to another suite |
| PUT | /test-case/{test_case_id}/publish | Publish a test case at a public URL |
| GET | /test-case/{test_case_id}/slugs | List a test's published slugs |
| GET | /public/test-case/{slug_or_id} | Fetch a published test case (no auth required) |
Creating a test case
Minimum required fields are name, description, and test_suite_id.
curl -X POST "https://cj-backend.foreai.co/test-cases/" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"test_suite_id": "ddfa83cd-b43d-4b68-8931-42684931f58d",
"test_cases": [{
"name": "Login — happy path",
"description": "Step 1. Navigate to the login page. Expectation: login form is visible.\nStep 2. Enter username and password and click Sign in. Expectation: user is redirected to the dashboard.",
"website": "https://example.com",
"test_suite_id": "ddfa83cd-b43d-4b68-8931-42684931f58d",
"parameters": { "username": "jdoe", "password": "password123" }
}]
}'
["3f2504e0-4f89-11d3-9a0c-0305e82c3301"]
All TestCaseRequest fields
| Field | Required | Description |
|---|---|---|
name | Yes | Short identifier for the test |
description | Yes | Plain-language steps and expectations used to generate the test |
test_suite_id | Yes | Suite to add the test to |
website | No | Base URL the test runs against |
path | No | Folder path within the suite (e.g. checkout/guest/) |
parameters | No | Key/value pairs available as variables within the test |
shared_parameter_ids | No | UUIDs of suite-level shared parameters to attach |
asset_parameter_ids | No | UUIDs of asset parameters to attach |
browser_state_id | No | Pre-authenticated browser session to start from |
collection_ids | No | Collections to add this test to |
enable_proxies | No | Route through proxy (default true) |
proxy_id | No | Specific proxy UUID |
geolocation | No | { "latitude": 47.38, "longitude": 8.54 } |
accept_language | No | e.g. "de-CH,de;q=0.9" |
browser_type_override | No | chromium, firefox, webkit, msedge |
viewport_width / viewport_height | No | Browser viewport dimensions |
user_agent | No | Custom user-agent string |
mobile_app_asset_id | No | UUID of an uploaded .apk / .ipa (mobile tests only) |
test_module_id_for_setup | No | Test module to run as setup before this test |
is_flaky | No | Mark as known flaky (default false) |
Mobile testing — to test a mobile app instead of a website, omit website and set mobile_app_asset_id to the UUID of an uploaded .apk or .ipa asset. Upload the binary first via POST /assets/.
Polling generation state
After creating a test, poll until generation completes:
curl "https://cj-backend.foreai.co/test-case/state/<test_case_id>" \
-H "Authorization: Bearer <token>"
{ "state": "completed" }
States follow this path: pending → waiting_for_executor → running → completed. Stop polling when state is completed or a terminal error state (failed, resources_exceeded, error, executor_not_available). See Status enumerations for the full list.
TestCase response fields
Returned by GET /test-case/{test_case_id}:
| Field | Type | Description |
|---|---|---|
_id | UUID | Test case ID |
name | string | |
description | string | |
state | TestState | Generation lifecycle state |
website | string | URL under test |
test_suite_id | UUID | |
org_id | UUID | |
path | string | Folder path within the suite |
parameters | object | Key/value test parameters |
test_generation_steps | array | Generated steps with code, screenshots, and status |
latest_run_status | TestRunStatus | Status of the most recent run |
latest_run_time | datetime | |
is_flaky | boolean | Marked as known flaky |
is_public | boolean | Published via a public URL |
created_at / last_modified_at | datetime |
Editing a test case
PATCH /test-case/{test_case_id}/edit — all fields optional; omitting a field leaves it unchanged. Pass ?schedule=false to update metadata without triggering regeneration.
| Field | Type | Description |
|---|---|---|
name | string | |
description | string | |
path | string | Move to a different folder |
parameters | object | Replace parameter values |
shared_parameter_ids | UUID[] | |
asset_parameter_ids | UUID[] | |
browser_state_id | UUID | |
collection_ids | UUID[] | |
proxy_id | UUID | |
enable_proxies | boolean | |
browser_type_override | BrowserType | chromium, firefox, webkit, msedge |
viewport_width / viewport_height | integer | |
geolocation | object | { "latitude": 47.38, "longitude": 8.54 } |
accept_language | string | e.g. "de-CH,de;q=0.9" |