# Tests Explorer

Explore and analyze test metrics.

The Tests Explorer provides aggregated metrics for tests within a project, including execution counts, failure rates, flakiness rates, and duration statistics.

Outcome strings are defined in the `RecordedTestOutcome` schema (see **components/schemas**). That schema explains how each value maps to `metrics` on `GET /tests/{projectId}` (`ignored`, `failures`, etc.).

Narrative context for the dashboard is here: [Test result statuses — Tests Explorer & REST API](https://docs.currents.dev/dashboard/test-suite-performance-explorer/tests-explorer#test-result-statuses).

## Get tests explorer

> Get aggregated test metrics for a project within a date range. Outcomes use the \`RecordedTestOutcome\` schema (see components/schemas). For narrative context, see the \[Test result statuses]\(<https://docs.currents.dev/dashboard/test-suite-performance-explorer/tests-explorer#test-result-statuses>) section on the Test Explorer documentation page.

```json
{"openapi":"3.0.2","info":{"title":"Currents REST API","version":"1.0.0"},"tags":[{"name":"Tests Explorer","description":"Explore and analyze test metrics.\n\nThe Tests Explorer provides aggregated metrics for tests within a project,\nincluding execution counts, failure rates, flakiness rates, and duration statistics.\n\nOutcome strings are defined in the `RecordedTestOutcome` schema (see **components/schemas**). That schema explains how each value maps to `metrics` on `GET /tests/{projectId}` (`ignored`, `failures`, etc.).\n\nNarrative context for the dashboard is here:\n[Test result statuses — Tests Explorer & REST API](https://docs.currents.dev/dashboard/test-suite-performance-explorer/tests-explorer#test-result-statuses)."}],"servers":[{"url":"https://api.currents.dev/v1","description":"Production API"},{"url":"https://api-staging.currents.dev/v1","description":"Staging API"},{"url":"http://localhost:4000/v1","description":"Local development"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"API key authentication using Bearer token"}},"parameters":{"ProjectIdPath":{"name":"projectId","in":"path","required":true,"description":"The project ID","schema":{"type":"string"}},"DateStartQuery":{"name":"date_start","in":"query","required":true,"description":"Start date in ISO 8601 format","schema":{"type":"string","format":"date-time"}},"DateEndQuery":{"name":"date_end","in":"query","required":true,"description":"End date in ISO 8601 format","schema":{"type":"string","format":"date-time"}},"PageQuery":{"name":"page","in":"query","required":false,"description":"Page number (0-indexed)","schema":{"type":"integer","minimum":0,"default":0}},"TestsExplorerLimitQuery":{"name":"limit","in":"query","required":false,"description":"Maximum number of items to return (default: 50, max: 50)","schema":{"type":"integer","minimum":1,"maximum":50,"default":50}},"TagsQuery":{"name":"tags[]","in":"query","required":false,"description":"Filter by tags (can be specified multiple times using bracket notation, e.g., tags[]=value1&tags[]=value2)","schema":{"type":"array","items":{"type":"string"}},"style":"form","explode":true},"BranchesQuery":{"name":"branches[]","in":"query","required":false,"description":"Filter by git branch. Use trailing `*` for prefix match (e.g. `release/*`). Max 250 characters per value.","schema":{"type":"array","items":{"$ref":"#/components/schemas/BranchFilterQueryValue"}},"style":"form","explode":true},"GroupsQuery":{"name":"groups[]","in":"query","required":false,"description":"Filter by groups (can be specified multiple times using bracket notation, e.g., groups[]=group1&groups[]=group2)","schema":{"type":"array","items":{"type":"string"}},"style":"form","explode":true},"AuthorsQuery":{"name":"authors[]","in":"query","required":false,"description":"Filter by git authors (can be specified multiple times using bracket notation, e.g., authors[]=author1&authors[]=author2)","schema":{"type":"array","items":{"type":"string"}},"style":"form","explode":true},"SortDirectionQuery":{"name":"dir","in":"query","required":false,"description":"Sort direction: `desc` (default) or `asc`.","schema":{"type":"string","enum":["asc","desc"],"default":"desc"}}},"schemas":{"BranchFilterQueryValue":{"description":"Branch filter value: an exact branch name, or a trailing `*` for prefix match (e.g. `release/*`). Max 250 characters.","oneOf":[{"type":"string","description":"Exact branch name (must not contain `*` or spaces).","pattern":"^[!-)+-~]+$","maxLength":250},{"type":"string","description":"Prefix match: branch prefix followed by `*`.","pattern":"^[!-)+-~]+\\*$","maxLength":250}]},"RecordedTestOutcome":{"type":"string","description":"Final per-test outcome stored in Currents.\n\n- **passed** — Runner reported success.\n- **failed** — Runner reported failure (assertions, errors, timeouts, etc.).\n- **pending** — Intentional skip or disabled test (e.g. `test.skip()` / `it.skip()`). In **Tests Explorer** (`GET /tests/{projectId}`) this increments `metrics.ignored` and does **not** increment `metrics.failures`.\n- **skipped** — Runner reported a skip without a normal pass/fail (often interrupted or never executed as pass/fail). In **Tests Explorer** this increments `metrics.failures` together with `failed` (there is no separate `skipped` counter in that response). On **run and spec** payloads, `stats.skipped` is still reported separately from `stats.failures` and `stats.pending`.","enum":["passed","failed","pending","skipped"]},"TestsExplorerMetricSettings":{"type":"object","additionalProperties":false,"description":"Per-metric outcome filters for Tests Explorer (`metric_settings` query parameter).","properties":{"executions":{"type":"array","items":{"$ref":"#/components/schemas/RecordedTestOutcome"}},"avgDuration":{"type":"array","items":{"$ref":"#/components/schemas/RecordedTestOutcome"}},"flakinessRate":{"type":"array","items":{"$ref":"#/components/schemas/RecordedTestOutcome"}},"failureRate":{"type":"array","items":{"$ref":"#/components/schemas/RecordedTestOutcome"}}}},"TestsExplorerResponse":{"type":"object","required":["status","data"],"properties":{"status":{"type":"string","enum":["OK"]},"data":{"type":"object","properties":{"list":{"type":"array","items":{"$ref":"#/components/schemas/TestExplorerItem"}},"count":{"type":"integer"},"total":{"type":"integer"},"nextPage":{"oneOf":[{"type":"integer"},{"type":"boolean"}]}}}}},"TestExplorerItem":{"type":"object","properties":{"title":{"type":"string","description":"Test title"},"signature":{"type":"string","description":"Unique test signature"},"spec":{"type":"string","description":"Spec file path"},"metrics":{"type":"object","description":"Aggregates for the query window. Outcomes follow `RecordedTestOutcome` (see components/schemas): `pending` → `ignored`; `failed` and `skipped` → `failures`.","properties":{"executions":{"type":"integer","description":"Number of executions in the window matching the executions status filter."},"passes":{"type":"integer","description":"Executions with outcome `passed`."},"failures":{"type":"integer","description":"Executions with outcome `failed` or `skipped` (no separate skipped counter)."},"ignored":{"type":"integer","description":"Executions with outcome `pending` (intentional skip; “Ignored” in the dashboard)."},"flaky":{"type":"integer","description":"Executions flagged flaky within the flakiness-rate status filter."},"flakinessRate":{"type":"number","description":"Flaky executions ÷ flakiness denominator (0–1)."},"failureRate":{"type":"number","description":"Failed+skipped executions ÷ failure-rate denominator (0–1)."},"avgDurationMs":{"type":"number","description":"Mean duration in ms over the avg-duration status filter."},"flakinessVolume":{"type":"number","description":"Flakiness impact: rate × flakiness-denominator executions (rounded)."},"failureVolume":{"type":"number","description":"Failure impact: rate × failure-rate denominator executions (rounded)."},"durationVolume":{"type":"number","description":"Duration impact: avg duration × executions used for duration (rounded)."}}},"latestTag":{"type":"array","items":{"type":"string"},"nullable":true},"lastSeen":{"type":"string","format":"date-time","nullable":true}}},"ErrorResponse":{"type":"object","required":["status","error"],"properties":{"status":{"type":"string","enum":["FAILED"]},"error":{"type":"string","description":"Error message"}}}},"responses":{"BadRequest":{"description":"Invalid request parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"Unauthorized":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"NotFound":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"paths":{"/tests/{projectId}":{"get":{"summary":"Get tests explorer","description":"Get aggregated test metrics for a project within a date range. Outcomes use the `RecordedTestOutcome` schema (see components/schemas). For narrative context, see the [Test result statuses](https://docs.currents.dev/dashboard/test-suite-performance-explorer/tests-explorer#test-result-statuses) section on the Test Explorer documentation page.","operationId":"getTestsExplorer","tags":["Tests Explorer"],"parameters":[{"$ref":"#/components/parameters/ProjectIdPath"},{"$ref":"#/components/parameters/DateStartQuery"},{"$ref":"#/components/parameters/DateEndQuery"},{"$ref":"#/components/parameters/PageQuery"},{"$ref":"#/components/parameters/TestsExplorerLimitQuery"},{"$ref":"#/components/parameters/TagsQuery"},{"$ref":"#/components/parameters/BranchesQuery"},{"$ref":"#/components/parameters/GroupsQuery"},{"$ref":"#/components/parameters/AuthorsQuery"},{"name":"order","in":"query","required":false,"description":"Field to order results by","schema":{"type":"string","enum":["failures","passes","flakiness","flakinessXSamples","failRateXSamples","duration","durationDelta","flakinessRateDelta","failureRateDelta","durationXSamples","executions","title"],"default":"title"}},{"$ref":"#/components/parameters/SortDirectionQuery"},{"name":"spec","in":"query","required":false,"description":"Filter tests by spec file name (partial match)","schema":{"type":"string"}},{"name":"title","in":"query","required":false,"description":"Filter tests by title (partial match)","schema":{"type":"string"}},{"name":"min_executions","in":"query","required":false,"description":"Minimum number of executions to include","schema":{"type":"integer","minimum":1}},{"name":"test_state[]","in":"query","required":false,"description":"Restrict default **executions** and **avg duration** slices (unless `metric_settings` overrides). Each value is a `RecordedTestOutcome` (see components/schemas). Example: `test_state[]=passed&test_state[]=failed`.","schema":{"type":"array","items":{"$ref":"#/components/schemas/RecordedTestOutcome"}},"style":"form","explode":true},{"name":"metric_settings","in":"query","required":false,"description":"Overrides which outcomes feed each metric. Keys: `executions`, `avgDuration`, `flakinessRate`, `failureRate` — each value is an array of `RecordedTestOutcome`. Omitted keys use defaults. Pass as a JSON value (same encoding as `content: application/json` for this parameter).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestsExplorerMetricSettings"}}}},{"name":"annotations","in":"query","required":false,"description":"Filter by test annotations. The parameter value must be a JSON-stringified array of objects: `[{ \"type\": \"string\", \"description\": \"string\" | [\"string\"] or null }]`. description is optional; omit or set to null to match any value for that annotation.","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestsExplorerResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}}}}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.currents.dev/api/resources/tests-explorer.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
