Skip to content

progalaxyelabs/stonescriptphp-api-tester

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

@progalaxyelabs/stonescriptphp-api-tester

API test infrastructure for StoneScriptPHP projects — coverage validation and test execution.

Zero npm dependencies. Uses only Node.js built-ins.

Installation

npm install @progalaxyelabs/stonescriptphp-api-tester

Or use directly via npx:

npx @progalaxyelabs/stonescriptphp-api-tester validate
npx @progalaxyelabs/stonescriptphp-api-tester run --flow=smoke

Commands

api-tester validate

Static analysis — cross-references your testplan.json against routes.php and the generated TypeScript api-client to find coverage gaps.

api-tester validate [options]

Options:

Option Default Description
--testplan=<path> ./api/tests/testplan.json Path to testplan.json
--client=<path> ./api/client/src/index.ts Path to api-client index.ts
--routes=<path> ./api/src/config/routes.php Path to routes.php
--verbose Show all matches, not just failures
--json Output as JSON (for CI pipelines)

Coverage checks performed:

  1. API Client -> Testplan (MUST be 100%): Every endpoint in the TypeScript client must appear in testplan.json
  2. Routes.php -> Testplan (MUST be 100%): Every route in routes.php must appear in testplan.json
  3. Testplan -> API Client (informational): Shows testplan endpoints not in api-client (expected for untyped routes)
  4. Graph Coverage (MUST be 100%): Every endpoint ID must appear in at least one graph edge
  5. Flow Coverage (SHOULD be 100%): Every endpoint ID should appear in at least one flow

Exit codes: 0 = all mandatory checks pass, 1 = coverage gaps found.

api-tester run

Runtime test execution — sends real HTTP requests following flows defined in testplan.json.

api-tester run [options]

Options:

Option Default Description
--testplan=<path> ./api/tests/testplan.json Path to testplan.json
--base-url=<url> http://localhost:3000 Base URL for API
--flow=<name> Flow name to run, or all for all flows
--endpoint=<id> Run a single endpoint by ID (for debugging)
--dry-run Print what would happen without making HTTP calls
--verbose Show request/response bodies
--token=<token> Pre-obtained auth token (skip login)
--email=<email> Email for login step
--password=<pass> Password for login step
--platform=<name> Platform name for auth login

Examples:

# Run the smoke flow
api-tester run --flow=smoke --base-url=http://localhost:3011

# Run all flows with auth credentials
api-tester run --flow=all --email=test@example.com --password=TestPass1 --platform=myapp

# Debug a single endpoint
api-tester run --endpoint=15 --verbose --base-url=http://localhost:3011

# Dry run — see what would execute without making requests
api-tester run --flow=mvp --dry-run

# Use a pre-obtained token
api-tester run --flow=smoke --token=eyJhbG...

testplan.json Format

The testplan is a JSON file that describes your API surface, how endpoints relate to each other, and how to test them.

{
  "meta": {
    "version": "1.0",
    "total_endpoints": 128,
    "api_base": "http://localhost:3011"
  },
  "endpoints": [
    {
      "id": 1,
      "method": "GET",
      "path": "/health",
      "name": "system.health",
      "group": "system",
      "auth_required": false,
      "in_api_client": false,
      "implementation_status": "implemented-untyped",
      "sample_request": null,
      "expected_status": 200,
      "response_shape": ["status", "service", "timestamp"]
    },
    {
      "id": 89,
      "method": "POST",
      "path": "/invoices",
      "name": "invoices.create",
      "group": "invoices",
      "auth_required": true,
      "in_api_client": true,
      "implementation_status": "implemented-typed",
      "sample_request": {
        "invoice_number": "INV-{{timestamp}}",
        "invoice_date": "2026-01-15",
        "distributor_id": "{{distributor_id}}",
        "items": []
      },
      "expected_status": 200,
      "response_shape": ["invoice_id"]
    }
  ],
  "graph": [
    {
      "from": 89,
      "to": 29,
      "carry": {
        "invoice_id": "response.data.invoice_id"
      },
      "note": "Create invoice, then fetch it by ID"
    }
  ],
  "flows": {
    "smoke": [1, 2, 3],
    "mvp": [14, 107, 105, 89, 91]
  }
}

Endpoint fields

Field Type Description
id number Unique endpoint identifier (referenced in graph/flows)
method string HTTP method: GET, POST, PUT, DELETE
path string URL path with :param placeholders
name string Dot-notation name (e.g., invoices.create)
group string Logical group for organization
auth_required boolean Whether the endpoint requires a JWT
in_api_client boolean Whether this endpoint is in the TypeScript api-client
implementation_status string implemented-typed, implemented-untyped, or missing
sample_request object/null Request body template with {{placeholder}} support
expected_status number Expected HTTP status code
response_shape string[] Array of field names expected in response data

Graph edges

Graph edges define data dependencies between endpoints. When endpoint from succeeds, values are extracted from its response and carried to subsequent steps.

The carry object maps variable names to dot-notation paths into the response:

{
  "from": 89,
  "to": 29,
  "carry": {
    "invoice_id": "response.data.invoice_id"
  }
}

After step 89 (POST /invoices), the invoice_id is extracted from the response and used to resolve :id in step 29 (GET /invoices/:id).

Flows

Flows are named sequences of endpoint IDs executed in order. Each flow represents a business workflow (e.g., create distributor -> create item -> create invoice -> create bill).

Placeholders

sample_request fields support {{placeholder}} syntax:

Placeholder Resolves to
{{timestamp}} Current Unix timestamp
{{email}} Generated test email
{{any_carried_key}} Value carried from a previous step

Path parameters (:id, :slug) are resolved from carried data automatically.

StoneScriptPHP Awareness

The runner understands the StoneScriptPHP response format:

{"status": "ok", "message": "", "data": { ... }}

When validating response_shape, the runner checks body.data (not the wrapper) if the response has status: "ok". This matches how StoneScriptPHP wraps all responses via res_ok() and res_error().

Requirements

  • Node.js >= 18.0.0 (uses native fetch)
  • Zero npm dependencies

License

MIT

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors