zynagent-first application framework

Back to the API reference

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;
};