Configuration
Learn how to configure Probitas scenarios, steps, and clients. This guide covers
all available options and common configuration patterns.
Project Configuration
Configure Probitas CLI defaults in your deno.json or deno.jsonc file under
the probitas section:
{
"imports": {
"probitas": "jsr:@probitas/probitas@^0"
},
"probitas": {
"reporter": "list",
"includes": ["**/*.probitas.ts"],
"excludes": [],
"selectors": ["!tag:slow"],
"maxConcurrency": 4,
"maxFailures": 5
}
}
| Option |
Description |
Default |
reporter |
Output reporter: dot, list, json, tap |
"list" |
includes |
Glob patterns for scenario file discovery |
["**/*.probitas.ts"] |
excludes |
Glob patterns to exclude from discovery |
[] |
selectors |
Default selectors for filtering scenarios |
[] |
maxConcurrency |
Maximum parallel scenario execution |
unlimited |
maxFailures |
Stop after this many failures |
unlimited |
Selectors
Selectors filter which scenarios to run. The format is [!][type:]value:
| Type |
Description |
Example |
tag |
Match by scenario tag |
tag:api |
name |
Match by scenario name (default) |
Login or name:Login |
! |
Negation prefix |
!tag:slow |
Multiple selectors use OR logic. Comma-separated values within a selector use
AND logic:
{
"probitas": {
"selectors": ["tag:api,!tag:slow"]
}
}
This runs scenarios with api tag AND without slow tag.
CLI Override
Command-line options override deno.json settings:
# Override reporter
probitas run --reporter dot
# Override concurrency
probitas run --max-concurrency 1
# Add selectors (combined with config selectors)
probitas run -s tag:smoke
Scenario Options
Configure scenarios using the options parameter of scenario().
scenario("My Test", {
tags: ["api", "integration"],
stepOptions: {
timeout: 60000,
retry: { maxAttempts: 3, backoff: "exponential" },
},
});
| Option |
Description |
Default |
tags |
Tags for filtering scenarios during runs |
[] |
stepOptions.timeout |
Default timeout for all steps (ms) |
30000 |
stepOptions.retry.maxAttempts |
Default max retry attempts for steps |
1 |
stepOptions.retry.backoff |
Backoff strategy: "linear" or "exponential" |
"linear" |
Use tags to categorize and filter scenarios:
scenario("API Integration", {
tags: ["api", "integration", "slow"],
});
Run scenarios by tag using selectors:
# Run only "api" tagged scenarios
probitas run -s tag:api
# Exclude "slow" scenarios
probitas run -s "!tag:slow"
# Combine filters (AND logic)
probitas run -s "tag:api,!tag:slow"
Step Options
Override scenario defaults for individual steps:
scenario("Mixed Timeouts")
.step("Quick check", async (ctx) => {
// Must complete in 1 second
}, { timeout: 1000 })
.step("Slow operation", async (ctx) => {
// Can take up to 60 seconds
}, { timeout: 60000 })
.step("Flaky external call", async (ctx) => {
// Retry up to 5 times with exponential backoff
}, {
retry: { maxAttempts: 5, backoff: "exponential" },
})
.build();
| Option |
Description |
timeout |
Step timeout in milliseconds |
retry.maxAttempts |
Maximum retry attempts for this step |
retry.backoff |
Backoff strategy for this step |
Timeout Behavior
When a step times out:
- The step's
ctx.signal is aborted
- The step fails with
TimeoutError
- Retry logic applies if configured
- Cleanup hooks still execute
.step("Cancellable operation", async (ctx) => {
// Pass signal to cancellable operations
const response = await fetch(url, { signal: ctx.signal });
return response.json();
}, { timeout: 5000 })
Retry Configuration
Configure automatic retries for flaky operations.
| Option |
Description |
Default |
maxAttempts |
Maximum number of attempts |
1 |
backoff |
"linear" or "exponential" |
— |
initialDelay |
First retry delay (ms) |
1000 |
maxDelay |
Maximum delay between retries (ms) |
30000 |
retryOn |
Custom predicate for retry decisions |
— |
Backoff Strategies
| Strategy |
Delay Pattern |
"linear" |
1s, 2s, 3s, 4s... |
"exponential" |
1s, 2s, 4s, 8s... |
Custom Retry Logic
const res = await http.get("/endpoint", {
retry: {
maxAttempts: 3,
backoff: "exponential",
initialDelay: 500,
maxDelay: 10000,
retryOn: (error) => {
// Only retry on network errors
return error.kind === "connection" || error.kind === "timeout";
},
},
});
Client Configurations
HTTP Client
client.http.createHttpClient({
url: "http://localhost:8080",
headers: { "Content-Type": "application/json" },
throwOnError: true,
timeout: 10000,
});
| Option |
Description |
Default |
url |
Base URL for all requests (required) |
— |
headers |
Default headers for all requests |
{} |
throwOnError |
Throw on 4xx/5xx responses |
true |
timeout |
Request timeout (ms) |
— |
redirect |
"follow", "manual", or "error" |
"follow" |
PostgreSQL Client
client.sql.postgres.createPostgresClient({
url: {
host: "localhost",
port: 5432,
database: "testdb",
user: "testuser",
password: "testpass",
},
pool: { min: 1, max: 10 },
});
| Option |
Description |
Default |
url |
Connection string or config object |
— |
pool.min |
Minimum pool connections |
0 |
pool.max |
Maximum pool connections |
10 |
pool.idleTimeout |
Idle connection timeout (ms) |
30000 |
Connection can also be a URL string:
client.sql.postgres.createPostgresClient({
url: "postgres://user:pass@localhost:5432/mydb",
});
gRPC Client
client.grpc.createGrpcClient({
url: "localhost:50051",
metadata: { authorization: "Bearer token" },
tls: { insecure: false },
});
| Option |
Description |
Default |
url |
Server address (host:port) |
— |
metadata |
Default metadata for all calls |
{} |
tls |
TLS configuration |
— |
schema |
Proto schema source |
"reflection" |
GraphQL Client
client.graphql.createGraphqlClient({
url: "http://localhost:4000/graphql",
headers: { Authorization: "Bearer token" },
wsUrl: "ws://localhost:4000/graphql",
});
| Option |
Description |
Default |
url |
GraphQL HTTP endpoint (required) |
— |
headers |
Default headers |
{} |
wsUrl |
WebSocket endpoint for subscriptions |
— |
throwOnError |
Throw on GraphQL errors |
true |
Redis Client
client.redis.createRedisClient({
url: "redis://localhost:6379",
});
| Option |
Description |
Default |
url |
Redis connection URL (redis://host:port) |
"redis://localhost:6379" |
MongoDB Client
client.mongodb.createMongoClient({
uri: "mongodb://localhost:27017",
database: "testdb",
});
| Option |
Description |
Default |
uri |
MongoDB connection URI |
— |
database |
Default database name |
— |
RabbitMQ Client
client.rabbitmq.createRabbitMqClient({
url: "amqp://guest:guest@localhost:5672",
});
| Option |
Description |
Default |
url |
AMQP connection URL |
"amqp://localhost" |
SQS Client
client.sqs.createSqsClient({
endpoint: "http://localhost:4566",
region: "us-east-1",
credentials: {
accessKeyId: "test",
secretAccessKey: "test",
},
});
| Option |
Description |
Default |
endpoint |
SQS endpoint URL |
— |
region |
AWS region |
— |
credentials |
AWS access key and secret |
— |
Environment Variables
Probitas respects these environment variables:
| Variable |
Purpose |
NO_COLOR |
Disable colored output |
Using Environment Variables
scenario("Production Test")
.resource("http", () =>
client.http.createHttpClient({
url: Deno.env.get("API_URL") ?? "http://localhost:8080",
headers: {
Authorization: `Bearer ${Deno.env.get("API_TOKEN")}`,
},
}))
.resource("pg", () =>
client.sql.postgres.createPostgresClient({
url: Deno.env.get("DATABASE_URL") ??
"postgres://user:pass@localhost/testdb",
}))
.build();
Configuration Patterns
Environment-Aware Configuration
const isProduction = Deno.env.get("ENV") === "production";
scenario("API Test")
.resource("http", () =>
client.http.createHttpClient({
url: isProduction ? "https://api.example.com" : "http://localhost:8080",
timeout: isProduction ? 30000 : 5000,
retry: isProduction
? { maxAttempts: 3, backoff: "exponential" }
: undefined,
}))
.build();
Shared Configuration
// config.ts
export const httpDefaults = {
timeout: 10000,
headers: { "Content-Type": "application/json" },
};
export const dbDefaults = {
timeout: 10000,
pool: { min: 1, max: 5 },
};
// scenario.ts
import { dbDefaults, httpDefaults } from "./config.ts";
scenario("Test")
.resource("http", () =>
client.http.createHttpClient({
url: "http://localhost:8080",
...httpDefaults,
}))
.resource("pg", () =>
client.sql.postgres.createPostgresClient({
url: "postgres://...",
...dbDefaults,
}))
.build();
Resource Factory Pattern
// factories.ts
export function createApiClient(url?: string) {
return client.http.createHttpClient({
url: url ?? Deno.env.get("API_URL") ?? "http://localhost:8080",
timeout: 10000,
retry: { maxAttempts: 2 },
});
}
export function createTestDatabase() {
return client.sql.postgres.createPostgresClient({
url: {
host: Deno.env.get("DB_HOST") ?? "localhost",
port: Number(Deno.env.get("DB_PORT") ?? 5432),
database: "testdb",
user: "testuser",
password: "testpass",
},
});
}
// scenario.ts
import { createApiClient, createTestDatabase } from "./factories.ts";
scenario("Test")
.resource("http", createApiClient)
.resource("pg", createTestDatabase)
.build();
Conditional Resources
import { Skip } from "probitas";
scenario("Conditional Features")
.resource("http", () => createHttpClient(...))
.resource("redis", () => {
const redisUrl = Deno.env.get("REDIS_URL");
if (!redisUrl) {
throw new Skip("Redis not configured");
}
return client.redis.createRedisClient({
url: redisUrl,
});
})
.build();