use clap::Subcommand;
#[derive(Subcommand)]
pub enum DocsCommands {
#[command(name = "")]
Overview,
}
pub fn get_docs_overview() -> &'static str {
r#"CHECKMATE - API Testing Framework
==================================
Checkmate is a YAML-based API testing framework with Clove query assertions.
COMMAND STRUCTURE
-----------------
cm test run <specs> Run test specifications
cm test validate <specs> Validate specs without running
cm test list <specs> List tests in spec files
cm diff run <specs> Run API diff comparisons
cm diff list <specs> List diff definitions
cm docs This documentation
cm doc <category> Category-specific documentation
cm onboard Quick-start guide for AI agents
cm clove <cmd> Clove query language operations
TEST SPECIFICATION FORMAT
-------------------------
Test specs are YAML files with this structure:
name: "Suite Name"
env:
base_url: "http://localhost:8080"
timeout_ms: 5000
requests:
my_request:
body: { field: value }
headers: { Authorization: "Bearer ${TOKEN}" }
extract: # Extract values from response
my_var: "$[response_field]"
tests:
my_test:
endpoint: /api/v1/endpoint
requests: [my_request]
assertions:
- query: "$[field]"
expect: value
diffs:
my_diff:
setup: # Optional auth/login
- request: login
endpoint: /auth/login
endpoints:
- name: v1 # Named or simple strings
path: /api/v1/data
- name: v2
path: /api/v2/data
method: GET
requests:
- common_request # Sent to all endpoints
- name: v1_only # Scoped to specific endpoints
scope: [v1]
assertions:
- query: "$[additions]"
expect: 0
ASSERTIONS
----------
Checkmate uses Clove queries for assertions:
Exact match: { query: "$[status]", expect: "ok" }
Comparisons: { query: "$[count]", expect_gt: 0 }
Type checks: { query: "$[data]", expect_type: object }
Existence: { query: "$[field]?", expect: true }
Regex: { query: "$[id]", expect_match: "^[a-f0-9]+$" }
PREVIOUS RESPONSE (@prev)
-------------------------
Compare against previous response in multi-request tests:
tests:
counter_test:
requests: [req, req, req]
skip_first: true
assertions:
- query: "$[counter]"
expect_gt: "@prev[counter]"
ENVIRONMENT VARIABLES
---------------------
Use ${VAR} or ${VAR:-default} syntax in any string value — base URLs,
endpoints, headers, query params, and request bodies:
env:
base_url: "${BASE_URL:-http://localhost:8080}"
requests:
auth_request:
headers:
Authorization: "Bearer ${API_TOKEN}"
body:
env: "${ENV:-development}"
VARIABLE EXTRACTION ({{var}})
-----------------------------
Extract values from responses and inject into subsequent requests:
requests:
login:
body: { username: "${USER}", password: "${PASS}" }
extract:
token: "$[access_token]"
protected:
headers:
Authorization: "Bearer {{token}}"
DOCUMENTATION CATEGORIES
------------------------
Run `cm doc <category>` for detailed information:
assertions All assertion types and examples
requests Request definition, inheritance, and extraction
env Environment variables and configuration
scopes Scope references ($, @prev, @env)
diff API version comparison (cm diff)
examples Complete test spec examples
cli CLI commands and options
QUICK START
-----------
Run `cm onboard` for a quick-start guide optimized for AI agents.
"#
}
pub fn get_doc_category(category: &str) -> Result<&'static str, String> {
match category.to_lowercase().as_str() {
"assertions" | "assert" => Ok(get_assertions_doc()),
"requests" | "request" | "req" => Ok(get_requests_doc()),
"env" | "environment" | "vars" => Ok(get_env_doc()),
"scopes" | "scope" | "refs" => Ok(get_scopes_doc()),
"examples" | "example" => Ok(get_examples_doc()),
"diff" | "diffs" => Ok(get_diff_doc()),
"cli" | "commands" | "cmd" => Ok(get_cli_doc()),
_ => Err(format!(
"Unknown category: '{}'\n\nAvailable categories:\n assertions, requests, env, scopes, diff, examples, cli",
category
)),
}
}
fn get_assertions_doc() -> &'static str {
r#"ASSERTIONS
==========
Assertions validate API responses using Clove queries.
EXACT MATCH
-----------
Match a specific value:
- query: "$[status]"
expect: "success"
- query: "$[count]"
expect: 42
- query: "$[enabled]"
expect: true
COMPARISONS
-----------
Numeric comparisons:
- query: "$[count]"
expect_gt: 0 # Greater than
- query: "$[score]"
expect_lt: 100 # Less than
- query: "$[value]"
expect_gte: 1 # Greater than or equal
- query: "$[risk]"
expect_lte: 0.5 # Less than or equal
Compare against previous response:
- query: "$[counter]"
expect_gt: "@prev[counter]"
TYPE CHECKS
-----------
Verify value types:
- query: "$[data]"
expect_type: object
- query: "$[items]"
expect_type: array
- query: "$[count]"
expect_type: integer
- query: "$[price]"
expect_type: number # Matches integer or float
- query: "$[name]"
expect_type: string
- query: "$[enabled]"
expect_type: boolean
- query: "$[deleted]"
expect_type: null
EXISTENCE
---------
Check if fields exist:
- query: "$[data]?"
expect: true # Field must exist
- query: "$[error]?"
expect: false # Field must not exist
REGEX PATTERNS
--------------
Match string patterns:
- query: "$[id]"
expect_match: "^[a-f0-9-]{36}$" # UUID format
- query: "$[email]"
expect_match: ".*@.*\\..*" # Basic email
CUSTOM MESSAGES
---------------
Add context to failures:
- query: "$[status]"
expect: "active"
message: "User should be active after registration"
CLOVE METHODS IN QUERIES
------------------------
Use Clove methods for complex assertions:
- query: "$[items].length()"
expect_gte: 1
- query: "$[tags].contains('important')"
expect: true
- query: "$[scores].max()"
expect_lte: 100
- query: "$[events][-1][type]" # Last element
expect: "completed"
"#
}
fn get_requests_doc() -> &'static str {
r#"REQUESTS
========
Requests are reusable templates referenced by tests.
BASIC REQUEST
-------------
requests:
simple_request:
body:
name: "John Doe"
email: "john@example.com"
HEADERS
-------
requests:
auth_request:
headers:
Authorization: "Bearer ${TOKEN}"
Content-Type: application/json
body:
data: value
QUERY PARAMETERS
----------------
requests:
search_request:
query_params:
q: "search term"
page: "1"
limit: "10"
body: {}
INHERITANCE
-----------
Requests can extend other requests:
requests:
base_user:
headers:
Content-Type: application/json
body:
role: "user"
admin_user:
extends: base_user
body:
role: "admin" # Overrides parent
permissions: ["all"] # Added field
Child inherits:
- All parent headers (child overrides if same key)
- All parent query_params (child overrides if same key)
- Parent body is replaced if child has body
USING IN TESTS
--------------
tests:
my_test:
endpoint: /api/v1/users
method: POST
requests: [base_user, admin_user] # Execute in sequence
assertions:
- query: "$[id]?"
expect: true
VARIABLE EXTRACTION
-------------------
Extract values from response bodies for use in subsequent requests:
requests:
login:
body:
username: "${USER}"
password: "${PASS}"
extract:
auth_token: "$[token]" # Clove query on response body
user_id: "$[user][id]" # Nested field access
protected_call:
headers:
Authorization: "Bearer {{auth_token}}"
body:
user: "{{user_id}}"
extract: maps variable names to Clove queries. After a request executes,
each query runs against the response body and stores the result.
Use {{var}} syntax to inject extracted values (distinct from ${VAR} env vars).
Variables persist across all requests within a test/diff run.
HTTP METHODS
------------
Supported methods: GET, POST, PUT, PATCH, DELETE
tests:
get_test:
endpoint: /api/v1/users/123
method: GET
requests: [empty_request]
delete_test:
endpoint: /api/v1/users/123
method: DELETE
requests: [auth_request]
"#
}
fn get_env_doc() -> &'static str {
r#"ENVIRONMENT CONFIGURATION
=========================
SPEC-LEVEL ENV
--------------
Define environment settings at the spec level:
env:
base_url: "http://localhost:8080"
timeout_ms: 5000
ENVIRONMENT VARIABLES
---------------------
Use ${VAR} syntax to reference environment variables:
env:
base_url: "${BASE_URL}"
api_key: "${API_KEY}"
DEFAULT VALUES
--------------
Use ${VAR:-default} for fallback values:
env:
base_url: "${BASE_URL:-http://localhost:8080}"
timeout_ms: "${TIMEOUT:-5000}"
VARIABLES IN REQUESTS
---------------------
Environment variables work in any string value — headers, endpoints,
query parameters (keys and values), and request bodies:
requests:
auth_request:
headers:
Authorization: "Bearer ${API_TOKEN}"
X-Client-Id: "${CLIENT_ID:-default-client}"
query_params:
env: "${ENV:-production}"
body:
environment: "${ENV:-development}"
nested:
api_key: "${API_KEY}" # Works in nested JSON too
tests:
dynamic_endpoint:
endpoint: /api/${API_VERSION}/users # Works in endpoints
requests: [auth_request]
EXTRACTED VARIABLES ({{var}})
-----------------------------
Use extract to capture values from responses for use in later requests:
requests:
login:
body: { user: "${USER}", pass: "${PASS}" }
extract:
token: "$[access_token]" # Clove query on response
user_id: "$[user][id]"
get_profile:
headers:
Authorization: "Bearer {{token}}"
query_params:
id: "{{user_id}}"
{{var}} is expanded after ${VAR}, so both can be combined.
Extracted values persist across requests within a test run.
RUNNING WITH ENV VARS
---------------------
Set variables when running tests:
BASE_URL=http://staging:8080 cm test run tests/*.yaml
# Or export them
export API_TOKEN="secret-token"
cm test run tests/*.yaml
TIMEOUT CONFIGURATION
---------------------
Timeouts can be set at multiple levels:
# Spec-level default (milliseconds)
env:
timeout_ms: 10000
# Per-test override
tests:
slow_test:
endpoint: /api/slow
timeout_ms: 30000 # 30 seconds for this test
requests: [req]
assertions: []
HTTP STATUS EXPECTATIONS
------------------------
Default expected status is 200. Override per test:
tests:
error_test:
endpoint: /api/invalid
expect_status: 422
requests: [invalid_request]
assertions:
- query: "$[error]?"
expect: true
"#
}
fn get_scopes_doc() -> &'static str {
r#"SCOPE REFERENCES
================
Checkmate uses Clove's scope system for data access.
ROOT SCOPE ($)
--------------
Access current response data:
$ # Entire response
$[field] # Top-level field
$[nested][path] # Nested access
$[array][0] # Array index
$[array][-1] # Last element (negative index)
PREVIOUS RESPONSE (@prev)
-------------------------
In multi-request tests, compare with previous response:
tests:
counter_test:
requests: [req, req, req, req]
skip_first: true # Don't assert on first (baseline)
assertions:
# Current counter > previous counter
- query: "$[metrics][count]"
expect_gt: "@prev[metrics][count]"
How @prev works:
1. First request: no @prev available
2. Second request: @prev = first response
3. Third request: @prev = second response
4. And so on...
Use skip_first: true when first request establishes baseline.
CLOVE LAMBDA SCOPE (@)
----------------------
In Clove queries, @ refers to lambda context:
# Filter array where item.active is true
$[users].filter(@[active] == true)
# Map to extract names
$[users].map(@[name])
# Find first matching
$[events].find(@[type] == "error")
COMBINING SCOPES
----------------
Complex assertions can combine scopes:
assertions:
# Check current array length grew
- query: "$[items].length()"
expect_gt: "@prev[items].length()"
# Current max score > previous max
- query: "$[scores].max()"
expect_gt: "@prev[scores].max()"
# Verify specific nested value increased
- query: "$[metrics][purchase_volume][by_ip][current]"
expect_gt: "@prev[metrics][purchase_volume][by_ip][current]"
"#
}
fn get_examples_doc() -> &'static str {
r#"COMPLETE EXAMPLES
=================
BASIC API TEST
--------------
name: "User API Tests"
env:
base_url: "${BASE_URL:-http://localhost:8080}"
requests:
create_user:
body:
name: "Test User"
email: "test@example.com"
tests:
create_user_success:
description: "Creating a user returns the new user"
endpoint: /api/v1/users
method: POST
requests: [create_user]
assertions:
- query: "$[id]?"
expect: true
- query: "$[name]"
expect: "Test User"
AUTHENTICATION TEST
-------------------
requests:
login:
body:
username: "${TEST_USER}"
password: "${TEST_PASS}"
tests:
login_success:
endpoint: /api/v1/auth/login
requests: [login]
assertions:
- query: "$[token]?"
expect: true
- query: "$[token]"
expect_type: string
ERROR HANDLING TEST
-------------------
requests:
invalid_data:
body:
email: "not-an-email"
tests:
validation_error:
endpoint: /api/v1/users
requests: [invalid_data]
expect_status: 422
assertions:
- query: "$[error]?"
expect: true
- query: "$[errors]"
expect_type: array
COUNTER/RATE TRACKING TEST
--------------------------
requests:
order:
body:
item: "ticket"
quantity: 1
tests:
counter_increments:
description: "Order counter increases with each request"
endpoint: /api/v1/orders
requests: [order, order, order, order]
skip_first: true
fail_fast: true
assertions:
- query: "$[metrics][order_count]"
expect_gt: "@prev[metrics][order_count]"
FRAUD DETECTION API TEST
------------------------
name: "Fraud Detection Tests"
env:
base_url: "http://localhost:80"
requests:
check_order:
body:
name: "John Doe"
email: "john@example.com"
ip: "192.168.1.100"
user_agent: "Mozilla/5.0"
tests:
response_structure:
endpoint: /api/v1/check-order
requests: [check_order]
assertions:
- query: "$[doc][cm][decision]?"
expect: true
- query: "$[doc][cm][decision][blocked]"
expect_type: boolean
not_blocked_initially:
endpoint: /api/v1/check-order
requests: [check_order]
assertions:
- query: "$[doc][cm][decision][blocked]"
expect: false
purchase_counters_increment:
endpoint: /api/v1/check-order
requests: [check_order, check_order, check_order]
skip_first: true
assertions:
- query: "$[doc][securely][metrics][purchase_volume][by_ip][by_minutes][1][current]"
expect_gt: "@prev[doc][securely][metrics][purchase_volume][by_ip][by_minutes][1][current]"
"#
}
fn get_diff_doc() -> &'static str {
r#"API DIFF COMPARISON
===================
Compare API responses across different endpoints (e.g., API versions).
YAML SYNTAX
-----------
Add a `diffs` section alongside `tests` in any spec file:
diffs:
version_comparison:
description: "Compare v1 vs v2"
method: GET
endpoints:
- /api/v1/users
- /api/v2/users
requests: [auth_request] # Optional, same request sent to each
assertions:
- query: "$[additions]"
expect: 0
message: "No new fields expected"
ENDPOINTS
---------
Unlike tests (single endpoint), diffs take a list of endpoints.
Responses are compared as sequential pairs:
[/v1, /v2, /v3] → compares v1↔v2, then v2↔v3
NAMED ENDPOINTS
---------------
Give endpoints a name for use with scoped requests and assertions:
endpoints:
- name: v1
path: /api/v1/users
- name: v2
path: /api/v2/users
Simple strings and named objects can be mixed:
endpoints:
- /api/v1/users # name defaults to the path
- name: v2
path: /api/v2/users
SETUP (Authentication)
----------------------
Run pre-diff setup steps such as login/auth. Setup requests execute once
before endpoint iteration, and extracted variables persist into diff requests:
requests:
login:
body: { username: "${USER}", password: "${PASS}" }
extract:
token: "$[access_token]"
get_data:
headers:
Authorization: "Bearer {{token}}"
diffs:
authed_compare:
setup:
- request: login
endpoint: /auth/login # Own endpoint, not from the endpoints list
method: POST # Defaults to POST
endpoints:
- /api/v1/data
- /api/v2/data
requests: [get_data]
If a setup step fails, the entire diff case is marked as Error.
SCOPED REQUESTS
---------------
Different API versions often need different request payloads. Scope a
request to specific endpoints by name:
requests:
common:
headers: { Accept: application/json }
v1_call:
body: { format: "legacy" }
v2_call:
body: { format: "modern" }
diffs:
version_compare:
endpoints:
- name: v1
path: /api/v1/data
- name: v2
path: /api/v2/data
requests:
- common # Sent to all endpoints
- name: v1_call
scope: [v1] # Only sent to v1
- name: v2_call
scope: [v2] # Only sent to v2
Unscoped (simple string) requests are sent to every endpoint.
If no requests apply to an endpoint after scoping, an empty request is used.
SCOPED ASSERTIONS
-----------------
When comparing 3+ endpoints, scope assertions to specific pairs:
diffs:
three_way:
endpoints:
- name: v1
path: /api/v1/data
- name: v2
path: /api/v2/data
- name: v3
path: /api/v3/data
assertions:
- query: "$[removals]" # Applies to all pairs (v1↔v2, v2↔v3)
expect: 0
- query: "$[additions]"
expect: 0
scope: [v1, v2] # Only for the v1↔v2 pair
A scoped assertion runs only when both endpoints in the pair are listed.
DIFF RESULT DOCUMENT
--------------------
Assertions evaluate against a structured diff result:
{
"base_endpoint": "v1",
"target_endpoint": "v2",
"changes": [
{ "change_type": "added", "path": "metadata.version", "to": "2.0" },
{ "change_type": "removed", "path": "legacy_id", "from": 42 },
{ "change_type": "type_changed", "path": "count",
"from": "string", "to": "integer" },
{ "change_type": "value_changed", "path": "name",
"from": "old", "to": "new" }
],
"additions": 1,
"removals": 1,
"type_changes": 1,
"value_changes": 0,
"base_response": { ... },
"target_response": { ... }
}
ASSERTION QUERIES ON DIFF
-------------------------
The diff result has summary counts and a `changes` array.
Summary counts (top-level integers):
- query: "$[additions]"
expect: 0
- query: "$[removals]"
expect: 0
message: "No fields should be removed in v2"
- query: "$[type_changes]"
expect: 0
The `changes` field is an array of objects, each with:
change_type "added", "removed", "type_changed", or "value_changed"
path Dot-separated path string (e.g. "user.profile.bio")
from Previous value (null for additions)
to New value (null for removals)
Use array methods to query changes (direct key traversal won't work):
# Total number of changes
- query: "$[changes].length()"
expect_lte: 5
# No removals in the changes array
- query: "$[changes].filter(@[change_type] == 'removed').length()"
expect: 0
message: "No fields should be removed"
# No changes under a specific path prefix
- query: "$[changes].filter(@[path].startswith('auth')).length()"
expect: 0
message: "Auth fields must not change between versions"
# Check that a specific field was added
- query: "$[changes].any(@[change_type] == 'added' && @[path] == 'metadata.version')"
expect: true
# Ensure no type changes occurred anywhere
- query: "$[changes].filter(@[change_type] == 'type_changed').length()"
expect: 0
DIFF HISTORY
------------
Diff runs are recorded to .checkmate/runs/runs.jsonl alongside test runs.
View with `cm history`. Diff runs show with a [diff] tag and include a
summary of additions, removals, value changes, and type changes.
OUTPUT MODES
-----------
TTY (terminal): Colored structural diff with summary
Non-TTY (piped): Structured JSON diff result
RUNNING
-------
cm diff run # Run all diffs in .checkmate/tests/
cm diff run spec.yaml # Run diffs in specific file
cm diff run spec.yaml --diff name # Run specific diff by name
cm diff list # List available diffs
EXAMPLE
-------
name: "API Migration Check"
env:
base_url: "${BASE_URL}"
requests:
login:
body: { user: "${USER}", pass: "${PASS}" }
extract:
token: "$[access_token]"
auth_get:
headers:
Authorization: "Bearer {{token}}"
diffs:
user_endpoint:
description: "Ensure v2 is backwards compatible"
setup:
- request: login
endpoint: /auth/login
method: GET
requests: [auth_get]
endpoints:
- name: v1
path: /api/v1/users
- name: v2
path: /api/v2/users
assertions:
- query: "$[removals]"
expect: 0
message: "No fields should be removed"
- query: "$[type_changes]"
expect: 0
message: "No type changes allowed"
"#
}
fn get_cli_doc() -> &'static str {
r#"CLI COMMANDS
============
TEST EXECUTION
--------------
cm test run <specs...>
Run one or more test specification files
Options:
--test, -t <name> Run only the specified test
--verbose, -v Show detailed output
Examples:
cm test run tests/api.yaml
cm test run tests/*.yaml --verbose
cm test run tests/auth.yaml -t login_success
TEST VALIDATION
---------------
cm test validate <specs...>
Validate test specs without executing
Examples:
cm test validate tests/api.yaml
cm test validate tests/*.yaml
TEST LISTING
------------
cm test list <specs...>
List all tests in specification files
Examples:
cm test list tests/api.yaml
API DIFF COMPARISON
-------------------
cm diff run <specs...>
Run diff comparisons defined in spec files
Options:
--diff, -d <name> Run only the specified diff
--verbose, -v Show detailed output
Examples:
cm diff run tests/api.yaml
cm diff run tests/*.yaml --verbose
cm diff run tests/api.yaml -d version_check
cm diff list <specs...>
List all diffs in specification files
DOCUMENTATION
-------------
cm docs
Show documentation overview
cm doc <category>
Show category-specific documentation
Categories: assertions, requests, env, scopes, diff, examples, cli
cm onboard
Quick-start guide for AI agents
CLOVE QUERY LANGUAGE
--------------------
cm clove check <query> [--input <json>]
Evaluate a Clove query
cm clove docs
Clove language documentation
cm clove doc <category>
Clove category documentation
cm clove onboard
Clove quick-start guide
EXIT CODES
----------
0 All tests passed / command succeeded
1 One or more tests failed / command failed
OUTPUT FORMAT
-------------
Test results are output as JSON:
{
"suite": "Test Suite Name",
"timestamp": "2024-01-15T10:30:00Z",
"duration_ms": 1234,
"summary": {
"total": 5,
"passed": 4,
"failed": 1,
"skipped": 0,
"errors": 0
},
"tests": [...]
}
ENVIRONMENT VARIABLES
---------------------
BASE_URL Default base URL for API requests
Any variable can be referenced in specs with ${VAR}
"#
}
pub fn get_onboarding_content() -> &'static str {
r#"CHECKMATE ONBOARDING FOR AI AGENTS
===================================
You are working with Checkmate, a YAML-based API testing framework.
QUICK REFERENCE
---------------
Run tests: cm test run tests/spec.yaml --verbose
Run diffs: cm diff run tests/spec.yaml --verbose
Validate: cm test validate tests/spec.yaml
List tests: cm test list tests/spec.yaml
Full docs: cm docs
Category: cm doc assertions
MINIMAL TEST SPEC
-----------------
```yaml
env:
base_url: "http://localhost:8080"
requests:
my_request:
body:
field: value
tests:
my_test:
endpoint: /api/endpoint
requests: [my_request]
assertions:
- query: "$[field]"
expect: value
```
ASSERTION PATTERNS
------------------
```yaml
# Exact value
- query: "$[status]"
expect: "ok"
# Comparison
- query: "$[count]"
expect_gt: 0
# Type check
- query: "$[data]"
expect_type: object
# Existence
- query: "$[field]?"
expect: true
# Against previous response
- query: "$[counter]"
expect_gt: "@prev[counter]"
```
MULTI-REQUEST WITH @prev
------------------------
```yaml
tests:
counter_test:
endpoint: /api/increment
requests: [req, req, req, req] # 4 requests
skip_first: true # Skip assertion on first
assertions:
- query: "$[count]"
expect_gt: "@prev[count]" # Each > previous
```
WORKFLOW FOR API TESTING
------------------------
1. Examine API response structure (curl or test a simple query)
2. Create request definitions with required fields
3. Write test cases with appropriate assertions
4. Run with --verbose to debug
5. Use @prev for stateful/counter tests
COMMON QUERIES
--------------
$[field] Top-level field
$[nested][path] Nested access
$[array][0] First element
$[array][-1] Last element
$[items].length() Array length
$[values].max() Maximum value
$[data].keys() Object keys
$[field]? Existence check
ERROR HANDLING
--------------
```yaml
tests:
expect_error:
endpoint: /api/invalid
expect_status: 422 # Expect specific HTTP status
requests: [bad_request]
assertions:
- query: "$[error]"
expect_type: string
```
VARIABLE EXTRACTION
-------------------
```yaml
requests:
login:
body: { user: "${USER}", pass: "${PASS}" }
extract:
token: "$[access_token]"
protected:
headers:
Authorization: "Bearer {{token}}"
```
API DIFF COMPARISON
-------------------
```yaml
diffs:
version_check:
setup: # Optional login/auth
- request: login
endpoint: /auth/login
endpoints:
- name: v1 # Named endpoints for scoping
path: /api/v1/data
- name: v2
path: /api/v2/data
method: GET
requests:
- common_request # Unscoped = sent to all
- name: v1_only
scope: [v1] # Scoped = only this endpoint
assertions:
- query: "$[removals]"
expect: 0
- query: "$[additions]"
expect: 0
scope: [v1, v2] # Assertion scope (for 3+ endpoints)
```
For detailed documentation on any topic:
cm doc assertions - All assertion types
cm doc requests - Request definitions and extraction
cm doc scopes - $, @prev, @ references
cm doc diff - API version comparison
cm doc examples - Complete test specs
"#
}
pub fn run_docs() -> Result<(), Box<dyn std::error::Error>> {
print!("{}", get_docs_overview());
Ok(())
}
pub fn run_doc(category: &str) -> Result<(), Box<dyn std::error::Error>> {
match get_doc_category(category) {
Ok(content) => {
print!("{}", content);
Ok(())
}
Err(msg) => {
eprintln!("{}", msg);
std::process::exit(1);
}
}
}
pub fn run_onboard() -> Result<(), Box<dyn std::error::Error>> {
print!("{}", get_onboarding_content());
Ok(())
}