zyn.testing#
pub const testing = struct {
/// Configuration for a managed test application.
pub const StartOptions = struct {};
/// Result of one synchronous background-job attempt.
pub const JobOutcome = enum {
completed,
retrying,
failed,
discarded,
lease_lost,
};
/// Observable details from one synchronous background-job attempt.
pub const JobAttempt = struct {
job: []const u8,
outcome: JobOutcome,
attempt: u16,
error_name: ?[]const u8,
};
/// Selection behavior for one synchronous background-job attempt.
pub const PerformOptions = struct {
include_scheduled: bool = false,
};
/// Selection and attempt bound for synchronous background-job execution.
pub const PerformReadyOptions = struct {
limit: u32 = 100,
include_scheduled: bool = false,
};
/// PostgreSQL-time override for recurring schedule materialization.
pub const EnqueueRecurringOptions = struct {
at: i64,
};
/// Attempt outcomes accumulated by `Jobs.perform_ready`.
pub const JobSummary = struct {
attempts: u32 = 0,
completed: u32 = 0,
retrying: u32 = 0,
failed: u32 = 0,
discarded: u32 = 0,
lease_lost: u32 = 0,
has_more: bool = false,
};
/// Current rows grouped by durable queue state.
pub const JobStatus = struct {
pending: u64,
running: u64,
completed: u64,
failed: u64,
discarded: u64,
};
/// Recorded outcome from managed notification delivery.
pub const Delivery = NotificationDelivery;
/// Notification state exposed by managed delivery helpers.
pub const Status = NotificationStatus;
/// Managed notification delivery with recorded outcomes for assertions.
pub const Notifications = struct {
/// Persists and executes one notification inline and returns its outcome.
pub fn deliver_now(
self: *testing,
comptime selected_notification: []const u8,
args: anytype,
) !Delivery;
/// Persists one notification for synchronous worker execution in this test.
pub fn deliver_later(
self: *testing,
comptime selected_notification: []const u8,
args: anytype,
) !Delivery;
};
/// Synchronous access to the managed application's background-job queue.
pub const Jobs = struct {
/// Persists one typed immediate or scheduled job in the fixture database.
pub fn enqueue(
self: *testing,
comptime selected_job: []const u8,
args: anytype,
options: JobEnqueueOptions,
) !void;
/// Synchronizes recurring definitions and enqueues due occurrences without running them.
pub fn enqueue_recurring(
self: *testing,
options: EnqueueRecurringOptions,
) !u32;
/// Executes at most one eligible background-job attempt synchronously.
pub fn perform_one(self: *testing, options: PerformOptions) !?JobAttempt;
/// Executes eligible attempts synchronously until none remain or the limit is reached.
pub fn perform_ready(self: *testing, options: PerformReadyOptions) !JobSummary;
/// Returns current row counts for the fixture queue.
pub fn status(self: *testing) !JobStatus;
};
/// Headers and an optional body sent by `Application.request`.
pub const RequestOptions = struct {
headers: []const std.http.Header = &.{},
body: ?[]const u8 = null,
};
/// An owned test HTTP response.
pub const Response = struct {
status: std.http.Status,
headers: []const std.http.Header,
body: []const u8,
/// Releases the response headers and body.
pub fn deinit(self: *@This()) void;
/// Returns the first response header with an ASCII-case-insensitive name.
pub fn header(self: *const @This(), name: []const u8) ?[]const u8;
};
/// A database-backed application and its loopback HTTP server.
pub const Application = struct {
/// The direct database pool for this test.
db: *Database,
/// Direct access to this test's isolated storage.
storage: Storage,
/// Direct access to notification delivery and capture.
notifications: testing.Notifications,
/// This test's independent, disposable PostgreSQL cache.
cache: *binding.Cache,
/// Fixture-owned directory containing captured email messages.
email_capture_path: []const u8,
/// Synchronous access to this test's background-job queue.
jobs: testing.Jobs,
/// The loopback port serving the application.
port: u16,
/// Stops the server, closes its database pools, and drops its database.
/// All request, job, and direct `port` operations must finish first.
pub fn deinit(self: *Application) void;
/// Sends one HTTP request without following redirects.
pub fn request(
self: *Application,
method: anytype,
path: []const u8,
options: RequestOptions,
) !testing.Response;
};
/// Returns whether the current process is an isolated `zyn test` child.
pub fn available() bool;
/// Starts an application with a fresh test database on an ephemeral loopback port.
pub fn start(io: Io, gpa: std.mem.Allocator, options: StartOptions) !Application;
};