UNPKG

@beignet/core

Version:

Core framework primitives for Beignet

1,148 lines 38.4 kB
import type { MemoryIdempotencyEntry, MemoryIdempotencyStore } from "../idempotency/index.js"; import type { MemoryMailDelivery, NormalizedMailMessage } from "../mail/index.js"; import type { MemoryNotificationDelivery } from "../notifications/index.js"; import type { DrainOutboxResult, OutboxErrorInfo, OutboxMessage, OutboxMessageKind, OutboxMessageStatus } from "../outbox/index.js"; import type { ProviderInstrumentationEventInput, ProviderInstrumentationPort } from "../providers/index.js"; import type { ScheduleDef, ScheduleRunnerPort, ScheduleRunOptions } from "../schedules/index.js"; import { type ActivityActor, type ActivityMetadata, type ActivityMetadataValue, type ActivityResource, type ActivityTenant, type AuditLogEntry, type AuditOutcome } from "./audit.js"; import type { EventBusPort, JobDef, JobDispatcherPort } from "./events.js"; import { type CreateGateOptions, type GateDecision, type GatePort, type PolicyContextFromDefinitions, type PolicyDefinition, type PolicyMapFromDefinitions, type PolicySubjectArgs } from "./policy.js"; import type { StorageObject, StoragePort, StorageVisibility } from "./storage.js"; /** * A recorded event entry from the recording event bus. */ export interface RecordedEvent { name: string; payload: unknown; } /** * Expected fields for a recorded event assertion. */ export interface RecordedEventExpectation { /** * Expected event name. */ name?: string; /** * Expected event payload. Object values are matched as partial objects. */ payload?: unknown; } /** * Create a recording event bus for testing. * * This bus records all published events for later assertion, * but does not support subscription (throws if called). * * @example * ```ts * const { bus, events } = createRecordingEventBus(); * * // Inject bus into your use case * await createUser({ ports: { eventBus: bus } }); * * // Assert on recorded events * expect(events).toHaveLength(1); * expect(events[0].name).toBe("user.registered"); * expect(events[0].payload).toEqual({ userId: "123", email: "test@example.com" }); * ``` */ export declare function createRecordingEventBus(): { bus: EventBusPort; events: RecordedEvent[]; }; /** * A job dispatch captured by `createRecordingJobDispatcher(...)`. */ export interface RecordedJobDispatch { /** * Dispatched job name. */ name: string; /** * Job definition supplied to the dispatcher. */ job: JobDef; /** * Payload supplied to the dispatcher. */ payload: unknown; } /** * Expected fields for a recorded job dispatch assertion. */ export interface RecordedJobDispatchExpectation { /** * Expected job name. */ name?: string; /** * Expected job payload. Object values are matched as partial objects. */ payload?: unknown; } /** * Create a recording job dispatcher for tests. * * The dispatcher records dispatch intent without running the job handler. Use * this when a use case or listener should enqueue work but the test does not * need to execute that work inline. * * @returns A job dispatcher plus its captured dispatches. */ export declare function createRecordingJobDispatcher(): { jobs: JobDispatcherPort; dispatchedJobs: RecordedJobDispatch[]; }; /** * A schedule run captured by `createRecordingScheduleRunner(...)`. */ export interface RecordedScheduleRun { /** * Schedule name. */ name: string; /** * Schedule definition supplied to the runner. */ schedule: ScheduleDef; /** * Payload supplied to the runner, when present. */ payload?: unknown; /** * Run ID supplied by the provider or test, when present. */ id?: string; /** * Provider or app source label, when present. */ source?: string; /** * Scheduled timestamp supplied to the runner, when present. */ scheduledAt?: ScheduleRunOptions["scheduledAt"]; /** * Triggered timestamp supplied to the runner, when present. */ triggeredAt?: ScheduleRunOptions["triggeredAt"]; } /** * Expected fields for a recorded schedule run assertion. */ export interface RecordedScheduleRunExpectation { /** * Expected schedule name. */ name?: string; /** * Expected schedule payload. Object values are matched as partial objects. */ payload?: unknown; /** * Expected run ID. */ id?: string; /** * Expected source label. */ source?: string; } /** * Expected fields for a provider instrumentation event assertion. */ export interface ProviderInstrumentationEventExpectation { /** * Expected instrumentation event type. */ type?: ProviderInstrumentationEventInput["type"]; /** * Expected event ID. */ id?: string; /** * Expected ISO timestamp. */ timestamp?: string; /** * Expected request correlation ID. */ requestId?: string; /** * Expected trace ID. */ traceId?: string; /** * Expected span ID. */ spanId?: string; /** * Expected parent span ID. */ parentSpanId?: string; /** * Expected traceparent header value. */ traceparent?: string; /** * Expected watcher name. */ watcher?: string; /** * Expected provider name. Matches `providerName` on provider lifecycle events * and `details.providerName` on provider instrumentation events. */ providerName?: string; /** * Expected structured details. Object values are matched as partial objects. */ details?: unknown; /** * Expected request method. */ method?: string; /** * Expected request path. */ path?: string; /** * Expected contract name. */ contractName?: string; /** * Expected status. This matches request status codes as well as job, outbox, * and schedule status strings. */ status?: unknown; /** * Expected duration in milliseconds. */ durationMs?: number; /** * Expected human-readable summary. */ summary?: string; /** * Expected error message. */ message?: string; /** * Expected stack trace. */ stack?: string; /** * Expected use-case name on error events. */ useCaseName?: string; /** * Expected use-case or custom event name. */ name?: string; /** * Expected use-case kind. */ kind?: "command" | "query"; /** * Expected use-case phase. */ phase?: "start" | "end" | "error"; /** * Expected error summary. */ error?: string; /** * Expected event bus event name. */ eventName?: string; /** * Expected job name. */ jobName?: string; /** * Expected outbox message ID. */ messageId?: string; /** * Expected outbox message kind. */ messageKind?: "event" | "job"; /** * Expected outbox message name. */ messageName?: string; /** * Expected schedule name. */ scheduleName?: string; /** * Expected schedule cron expression. */ cron?: string; /** * Expected schedule time zone. */ timezone?: string; /** * Expected provider lifecycle action. */ action?: "setup" | "start" | "stop"; /** * Expected custom event label. */ label?: string; } /** * Source accepted by provider instrumentation assertion helpers. */ export type ProviderInstrumentationAssertionSource = readonly ProviderInstrumentationEventInput[] | { /** * Recorded provider instrumentation events. */ readonly events: readonly ProviderInstrumentationEventInput[]; }; /** * Create a recording schedule runner for tests. * * The runner records schedule run intent without executing the schedule * handler. Use `createInlineScheduleRunner(...)` when the test should run the * handler. * * @returns A schedule runner plus its captured runs. */ export declare function createRecordingScheduleRunner(): { runner: ScheduleRunnerPort; runs: RecordedScheduleRun[]; }; /** * Create a provider instrumentation port for tests. * * The port records every event and can optionally disable specific watchers. * Use the returned `events` array with provider instrumentation assertion * helpers. * * @returns A provider instrumentation port plus its captured events. */ export declare function createRecordingProviderInstrumentation(options?: { enabledWatchers?: readonly string[]; disabledWatchers?: readonly string[]; }): { instrumentation: ProviderInstrumentationPort; events: ProviderInstrumentationEventInput[]; }; /** * Options for creating a test user actor. */ export interface CreateTestUserActorOptions extends Omit<ActivityActor, "type" | "id" | "metadata"> { /** * Optional role stored as `actor.metadata.role`. */ role?: string; /** * Additional redaction-safe actor metadata. */ metadata?: ActivityMetadata; } /** * Options for creating a test actor that represents impersonated user access. */ export interface CreateTestImpersonatedUserActorOptions extends CreateTestUserActorOptions { /** * Stable ID for the actor performing the impersonation. */ impersonatorId: string; } /** * Options for creating a test tenant. */ export type CreateTestTenantOptions = Omit<ActivityTenant, "id">; /** * Context fields commonly shared by Beignet tests that exercise audit, * authorization, route hooks, and use cases. */ export interface TestActivityContext { /** * Actor under test. */ actor: ActivityActor; /** * Tenant/account/workspace scope under test. */ tenant?: ActivityTenant; /** * Stable request ID for assertions. */ requestId: string; /** * Optional trace ID for assertions. */ traceId?: string; } /** * Options for creating a test activity context. */ export interface CreateTestActivityContextOptions { /** * Actor under test. * * @default createTestUserActor() */ actor?: ActivityActor; /** * Tenant under test. Pass `null` to omit tenant context. * * @default createTestTenant() */ tenant?: ActivityTenant | null; /** * Request ID to expose on the context. * * @default "test-request" */ requestId?: string; /** * Trace ID to expose on the context. * * @default "test-trace" */ traceId?: string; } /** * Create a predictable user actor for tests. * * Use this when authorization or audit assertions need a stable actor shape * without repeating the `ActivityActor` object in every test. * * @param id - Stable user ID for the test actor. * @param options - Optional display name, role, and metadata. * @returns A user actor with `type: "user"`. */ export declare function createTestUserActor(id?: string, options?: CreateTestUserActorOptions): ActivityActor; /** * Create a predictable user actor for tests that exercise impersonation. * * The returned actor remains the effective user, with `metadata.impersonatorId` * recording who initiated the impersonated access. * * @param id - Stable user ID being impersonated. * @param options - Impersonator ID plus optional display name, role, and metadata. * @returns A user actor with impersonation metadata. */ export declare function createTestImpersonatedUserActor(id: string, options: CreateTestImpersonatedUserActorOptions): ActivityActor; /** * Create a predictable anonymous actor for tests. * * @param options - Optional display name or metadata. * @returns An anonymous actor with `type: "anonymous"`. */ export declare function createTestAnonymousActor(options?: Omit<ActivityActor, "type">): ActivityActor; /** * Create a predictable service actor for tests. * * @param id - Stable service ID. * @param options - Optional display name or metadata. * @returns A service actor with `type: "service"`. */ export declare function createTestServiceActor(id?: string, options?: Omit<ActivityActor, "type" | "id">): ActivityActor; /** * Create a predictable system actor for tests. * * @param id - Stable system actor ID. * @param options - Optional display name or metadata. * @returns A system actor with `type: "system"`. */ export declare function createTestSystemActor(id?: string, options?: Omit<ActivityActor, "type" | "id">): ActivityActor; /** * Create a predictable tenant for tests. * * @param id - Stable tenant ID. * @param options - Optional slug or metadata. * @returns A tenant descriptor. */ export declare function createTestTenant(id?: string, options?: CreateTestTenantOptions): ActivityTenant; /** * Create the activity fields commonly copied onto app test contexts. * * @param options - Optional actor, tenant, request ID, and trace ID overrides. * @returns Stable activity context fields for a test. */ export declare function createTestActivityContext(options?: CreateTestActivityContextOptions): TestActivityContext; /** * Expected audit fields used by audit assertion helpers. */ export interface AuditLogEntryExpectation { /** * Expected action name. */ action?: string; /** * Expected actor fields. */ actor?: Partial<ActivityActor>; /** * Convenience matcher for `entry.actor.id`. */ actorId?: string; /** * Convenience matcher for `entry.actor.type`. */ actorType?: ActivityActor["type"]; /** * Expected tenant fields. */ tenant?: Partial<ActivityTenant>; /** * Convenience matcher for `entry.tenant.id`. */ tenantId?: string; /** * Expected resource fields. */ resource?: Partial<ActivityResource>; /** * Convenience matcher for `entry.resource.id`. */ resourceId?: string; /** * Convenience matcher for `entry.resource.type`. */ resourceType?: string; /** * Expected audit outcome. */ outcome?: AuditOutcome; /** * Convenience matcher for `entry.metadata.severity`. */ severity?: ActivityMetadataValue; /** * Expected request ID. */ requestId?: string; /** * Expected trace ID. */ traceId?: string; /** * Expected metadata fields. Object values are matched as partial objects. */ metadata?: ActivityMetadata; } /** * Expected mail delivery fields used by mail assertion helpers. */ export interface MailDeliveryExpectation { /** * Expected memory delivery ID. */ id?: string; /** * Expected subject. */ subject?: string; /** * Expected recipients. */ to?: NormalizedMailMessage["to"]; /** * Expected sender. */ from?: NormalizedMailMessage["from"]; /** * Expected text body. */ text?: string; /** * Expected HTML body. */ html?: string; /** * Expected message headers. */ headers?: Record<string, string>; /** * Expected normalized message fields. */ message?: Partial<NormalizedMailMessage>; } /** * Expected notification delivery fields used by notification assertion helpers. */ export interface NotificationDeliveryExpectation { /** * Expected memory delivery ID. */ id?: string; /** * Expected notification name. */ notificationName?: string; /** * Expected parsed payload. Object values are matched as partial objects. */ payload?: unknown; /** * Expected selected channels. */ channels?: readonly string[]; /** * Expected delivery metadata. Object values are matched as partial objects. */ metadata?: Record<string, unknown>; } /** * Expected storage object fields used by storage assertion helpers. */ export interface StorageObjectExpectation { /** * Object key to look up. */ key: string; /** * Expected size in bytes. */ size?: number; /** * Expected content type. */ contentType?: string; /** * Expected cache-control value. */ cacheControl?: string; /** * Expected storage metadata. */ metadata?: Record<string, string>; /** * Expected visibility. */ visibility?: StorageVisibility; /** * Expected text body. Cannot be combined with `bytes`. */ text?: string; /** * Expected object bytes. Cannot be combined with `text`. */ bytes?: Uint8Array; } /** * Source accepted by outbox message assertion helpers. * * Use a `MemoryOutboxPort` or a snapshot returned by a test adapter. Durable * SQL adapters should expose app-owned snapshots rather than widening the * production `OutboxPort` read surface. */ export type OutboxMessageAssertionSource = readonly OutboxMessage[] | { /** * Current outbox message snapshots. */ readonly messages: readonly OutboxMessage[]; }; /** * Expected outbox message fields used by outbox assertion helpers. */ export interface OutboxMessageExpectation { /** * Expected message ID. */ id?: string; /** * Expected message kind. */ kind?: OutboxMessageKind; /** * Expected event or job name. */ name?: string; /** * Expected JSON payload. Object values are matched as partial objects. */ payload?: unknown; /** * Expected delivery status. */ status?: OutboxMessageStatus; /** * Expected claim attempt count. */ attempts?: number; /** * Expected maximum delivery attempts. */ maxAttempts?: number; /** * Expected delivery timestamp. */ deliveredAt?: Date | null; /** * Expected serialized delivery error. Object values are matched as partial * objects. Pass `null` to assert no error has been recorded. */ lastError?: Partial<OutboxErrorInfo> | null; } /** * Expected fields for one outbox drain result assertion. */ export interface OutboxDrainResultExpectation { /** * Expected claimed count. */ claimed?: number; /** * Expected delivered count. */ delivered?: number; /** * Expected retried count. */ retried?: number; /** * Expected dead-lettered count. */ deadLettered?: number; } /** * Source accepted by idempotency entry assertion helpers. * * Use a `MemoryIdempotencyStore` or a snapshot array from an app-owned adapter. * Durable SQL adapters should expose app-owned snapshots rather than widening * the production `IdempotencyPort` read surface. */ export type IdempotencyEntryAssertionSource = readonly MemoryIdempotencyEntry[] | Pick<MemoryIdempotencyStore, "entries">; /** * Expected idempotency entry fields used by idempotency assertion helpers. */ export interface IdempotencyEntryExpectation { /** * Expected operation namespace. */ namespace?: string; /** * Expected client-provided idempotency key. */ key?: string; /** * Expected normalized scope key. */ scopeKey?: string; /** * Expected request fingerprint. */ fingerprint?: string; /** * Expected reservation status. */ status?: MemoryIdempotencyEntry["status"]; /** * Expected replay result. Object values are matched as partial objects. */ result?: unknown; /** * Expected reservation timestamp. */ reservedAt?: Date; /** * Expected completion timestamp. */ completedAt?: Date; /** * Expected expiration timestamp, or `null` when no expiration is set. */ expiresAt?: Date | null; } /** * Find the first audit entry matching the expected fields. * * @param entries - Audit entries captured by a memory or fake audit port. * @param expectation - Partial audit fields to match. * @returns The first matching entry, or `undefined`. */ export declare function findAuditEntry(entries: readonly AuditLogEntry[], expectation: AuditLogEntryExpectation): AuditLogEntry | undefined; /** * Assert that an audit entry exists and return the matching entry. * * The helper throws a plain `Error`, so it works with Bun, Vitest, Jest, and * other test runners. * * @param entries - Audit entries captured by a memory or fake audit port. * @param expectation - Partial audit fields to match. * @returns The matching audit entry. * @throws Error when no entry matches. */ export declare function assertAuditEntry(entries: readonly AuditLogEntry[], expectation: AuditLogEntryExpectation): AuditLogEntry; /** * Assert that no audit entry matches the expected fields. * * @param entries - Audit entries captured by a memory or fake audit port. * @param expectation - Partial audit fields to reject. * @throws Error when a matching entry exists. */ export declare function assertNoAuditEntry(entries: readonly AuditLogEntry[], expectation: AuditLogEntryExpectation): void; /** * Find the first recorded event matching the expected fields. * * @param events - Events captured by `createRecordingEventBus(...)`. * @param expectation - Partial event fields to match. * @returns The first matching event, or `undefined`. */ export declare function findRecordedEvent(events: readonly RecordedEvent[], expectation: RecordedEventExpectation): RecordedEvent | undefined; /** * Assert that a recorded event exists and return the matching event. * * @param events - Events captured by `createRecordingEventBus(...)`. * @param expectation - Partial event fields to match. * @returns The matching event. * @throws Error when no event matches. */ export declare function assertRecordedEvent(events: readonly RecordedEvent[], expectation: RecordedEventExpectation): RecordedEvent; /** * Assert that no recorded event matches the expected fields. * * @param events - Events captured by `createRecordingEventBus(...)`. * @param expectation - Partial event fields to reject. * @throws Error when a matching event exists. */ export declare function assertNoRecordedEvent(events: readonly RecordedEvent[], expectation: RecordedEventExpectation): void; /** * Find the first recorded job dispatch matching the expected fields. * * @param jobs - Job dispatches captured by `createRecordingJobDispatcher(...)`. * @param expectation - Partial job fields to match. * @returns The first matching dispatch, or `undefined`. */ export declare function findDispatchedJob(jobs: readonly RecordedJobDispatch[], expectation: RecordedJobDispatchExpectation): RecordedJobDispatch | undefined; /** * Assert that a job was dispatched and return the matching dispatch. * * @param jobs - Job dispatches captured by `createRecordingJobDispatcher(...)`. * @param expectation - Partial job fields to match. * @returns The matching dispatch. * @throws Error when no dispatch matches. */ export declare function assertDispatchedJob(jobs: readonly RecordedJobDispatch[], expectation: RecordedJobDispatchExpectation): RecordedJobDispatch; /** * Assert that no job dispatch matches the expected fields. * * @param jobs - Job dispatches captured by `createRecordingJobDispatcher(...)`. * @param expectation - Partial job fields to reject. * @throws Error when a matching dispatch exists. */ export declare function assertNoDispatchedJob(jobs: readonly RecordedJobDispatch[], expectation: RecordedJobDispatchExpectation): void; /** * Find the first recorded schedule run matching the expected fields. * * @param runs - Runs captured by `createRecordingScheduleRunner(...)`. * @param expectation - Partial schedule fields to match. * @returns The first matching schedule run, or `undefined`. */ export declare function findScheduleRun(runs: readonly RecordedScheduleRun[], expectation: RecordedScheduleRunExpectation): RecordedScheduleRun | undefined; /** * Find the first provider instrumentation event matching the expected fields. * * @param source - Recording instrumentation result or event snapshot array. * @param expectation - Partial event fields to match. * @returns The first matching event, or `undefined`. */ export declare function findProviderInstrumentationEvent(source: ProviderInstrumentationAssertionSource, expectation: ProviderInstrumentationEventExpectation): ProviderInstrumentationEventInput | undefined; /** * Assert that a provider instrumentation event exists and return it. * * @param source - Recording instrumentation result or event snapshot array. * @param expectation - Partial event fields to match. * @returns The matching event. * @throws Error when no event matches. */ export declare function assertProviderInstrumentationEvent(source: ProviderInstrumentationAssertionSource, expectation: ProviderInstrumentationEventExpectation): ProviderInstrumentationEventInput; /** * Assert that no provider instrumentation event matches the expected fields. * * @param source - Recording instrumentation result or event snapshot array. * @param expectation - Partial event fields to reject. * @throws Error when a matching event exists. */ export declare function assertNoProviderInstrumentationEvent(source: ProviderInstrumentationAssertionSource, expectation: ProviderInstrumentationEventExpectation): void; /** * Assert that a schedule run was recorded and return the matching run. * * @param runs - Runs captured by `createRecordingScheduleRunner(...)`. * @param expectation - Partial schedule fields to match. * @returns The matching schedule run. * @throws Error when no run matches. */ export declare function assertScheduleRun(runs: readonly RecordedScheduleRun[], expectation: RecordedScheduleRunExpectation): RecordedScheduleRun; /** * Assert that no schedule run matches the expected fields. * * @param runs - Runs captured by `createRecordingScheduleRunner(...)`. * @param expectation - Partial schedule fields to reject. * @throws Error when a matching run exists. */ export declare function assertNoScheduleRun(runs: readonly RecordedScheduleRun[], expectation: RecordedScheduleRunExpectation): void; /** * Find the first mail delivery matching the expected fields. * * @param deliveries - Deliveries captured by `createMemoryMailer(...)`. * @param expectation - Partial delivery or message fields to match. * @returns The first matching delivery, or `undefined`. */ export declare function findMailDelivery(deliveries: readonly MemoryMailDelivery[], expectation: MailDeliveryExpectation): MemoryMailDelivery | undefined; /** * Assert that a mail delivery exists and return the matching delivery. * * @param deliveries - Deliveries captured by `createMemoryMailer(...)`. * @param expectation - Partial delivery or message fields to match. * @returns The matching delivery. * @throws Error when no delivery matches. */ export declare function assertMailDelivery(deliveries: readonly MemoryMailDelivery[], expectation: MailDeliveryExpectation): MemoryMailDelivery; /** * Assert that no mail delivery matches the expected fields. * * @param deliveries - Deliveries captured by `createMemoryMailer(...)`. * @param expectation - Partial delivery or message fields to reject. * @throws Error when a matching delivery exists. */ export declare function assertNoMailDelivery(deliveries: readonly MemoryMailDelivery[], expectation: MailDeliveryExpectation): void; /** * Find the first notification delivery matching the expected fields. * * @param deliveries - Deliveries captured by `createMemoryNotificationPort(...)`. * @param expectation - Partial delivery fields to match. * @returns The first matching delivery, or `undefined`. */ export declare function findNotificationDelivery(deliveries: readonly MemoryNotificationDelivery[], expectation: NotificationDeliveryExpectation): MemoryNotificationDelivery | undefined; /** * Assert that a notification delivery exists and return the matching delivery. * * @param deliveries - Deliveries captured by `createMemoryNotificationPort(...)`. * @param expectation - Partial delivery fields to match. * @returns The matching delivery. * @throws Error when no delivery matches. */ export declare function assertNotificationDelivery(deliveries: readonly MemoryNotificationDelivery[], expectation: NotificationDeliveryExpectation): MemoryNotificationDelivery; /** * Assert that no notification delivery matches the expected fields. * * @param deliveries - Deliveries captured by `createMemoryNotificationPort(...)`. * @param expectation - Partial delivery fields to reject. * @throws Error when a matching delivery exists. */ export declare function assertNoNotificationDelivery(deliveries: readonly MemoryNotificationDelivery[], expectation: NotificationDeliveryExpectation): void; /** * Assert that a storage object exists and optionally matches metadata/body * expectations. * * This helper works against any `StoragePort`, not only memory storage. * * @param storage - Storage port under test. * @param expectation - Object key and expected fields. * @returns The matching object metadata. * @throws Error when the object is missing or does not match. */ export declare function assertStorageObject(storage: StoragePort, expectation: StorageObjectExpectation): Promise<StorageObject>; /** * Assert that a storage object does not exist. * * @param storage - Storage port under test. * @param key - Object key expected to be absent. * @throws Error when the object exists. */ export declare function assertNoStorageObject(storage: StoragePort, key: string): Promise<void>; /** * Find the first outbox message matching expected fields. * * @param source - Memory outbox or message snapshot array. * @param expectation - Partial message fields to match. * @returns The first matching message, or `undefined`. */ export declare function findOutboxMessage(source: OutboxMessageAssertionSource, expectation: OutboxMessageExpectation): OutboxMessage | undefined; /** * Find the first idempotency entry matching expected fields. * * @param source - Memory idempotency store or entry snapshot array. * @param expectation - Partial entry fields to match. * @returns The first matching entry, or `undefined`. */ export declare function findIdempotencyEntry(source: IdempotencyEntryAssertionSource, expectation: IdempotencyEntryExpectation): MemoryIdempotencyEntry | undefined; /** * Assert that an idempotency entry exists and return it. * * @param source - Memory idempotency store or entry snapshot array. * @param expectation - Partial entry fields to match. * @returns The matching entry. * @throws Error when no entry matches. */ export declare function assertIdempotencyEntry(source: IdempotencyEntryAssertionSource, expectation: IdempotencyEntryExpectation): MemoryIdempotencyEntry; /** * Assert that no idempotency entry matches expected fields. * * @param source - Memory idempotency store or entry snapshot array. * @param expectation - Partial entry fields to reject. * @throws Error when a matching entry exists. */ export declare function assertNoIdempotencyEntry(source: IdempotencyEntryAssertionSource, expectation: IdempotencyEntryExpectation): void; /** * Assert that a matching idempotency entry is still in progress. * * @param source - Memory idempotency store or entry snapshot array. * @param expectation - Entry fields to match. * @returns The matching in-progress entry. */ export declare function assertIdempotencyInProgress(source: IdempotencyEntryAssertionSource, expectation?: Omit<IdempotencyEntryExpectation, "status">): MemoryIdempotencyEntry; /** * Assert that a matching idempotency entry completed. * * @param source - Memory idempotency store or entry snapshot array. * @param expectation - Entry fields to match. * @returns The matching completed entry. */ export declare function assertIdempotencyCompleted(source: IdempotencyEntryAssertionSource, expectation?: Omit<IdempotencyEntryExpectation, "status">): MemoryIdempotencyEntry; /** * Assert that an outbox message exists and return it. * * @param source - Memory outbox or message snapshot array. * @param expectation - Partial message fields to match. * @returns The matching message. * @throws Error when no message matches. */ export declare function assertOutboxMessage(source: OutboxMessageAssertionSource, expectation: OutboxMessageExpectation): OutboxMessage; /** * Assert that no outbox message matches expected fields. * * @param source - Memory outbox or message snapshot array. * @param expectation - Partial message fields to reject. * @throws Error when a matching message exists. */ export declare function assertNoOutboxMessage(source: OutboxMessageAssertionSource, expectation: OutboxMessageExpectation): void; /** * Assert that an outbox message is pending. * * @param source - Memory outbox or message snapshot array. * @param expectation - Message fields to match. * @returns The matching pending message. */ export declare function assertOutboxPending(source: OutboxMessageAssertionSource, expectation?: Omit<OutboxMessageExpectation, "status">): OutboxMessage; /** * Assert that an outbox message was delivered. * * @param source - Memory outbox or message snapshot array. * @param expectation - Message fields to match. * @returns The matching delivered message. */ export declare function assertOutboxDelivered(source: OutboxMessageAssertionSource, expectation?: Omit<OutboxMessageExpectation, "status">): OutboxMessage; /** * Assert that an outbox message is pending after at least one failed attempt. * * Use this for retry-scheduled assertions after `drainOutbox(...)` returns a * retried count. * * @param source - Memory outbox or message snapshot array. * @param expectation - Message fields to match. * @returns The matching retry-scheduled message. */ export declare function assertOutboxRetryScheduled(source: OutboxMessageAssertionSource, expectation?: Omit<OutboxMessageExpectation, "status">): OutboxMessage; /** * Assert that an outbox message was dead-lettered. * * @param source - Memory outbox or message snapshot array. * @param expectation - Message fields to match. * @returns The matching dead-lettered message. */ export declare function assertOutboxDeadLettered(source: OutboxMessageAssertionSource, expectation?: Omit<OutboxMessageExpectation, "status">): OutboxMessage; /** * Assert that a drain result matches expected counts. * * @param result - Result returned by `drainOutbox(...)`. * @param expectation - Partial count expectation. * @throws Error when any supplied count differs. */ export declare function assertOutboxDrainResult(result: DrainOutboxResult, expectation: OutboxDrainResultExpectation): void; /** * Expected outcome for one policy matrix case. */ export type PolicyMatrixExpectation = "allow" | "deny"; type PolicyMatrixSubject<TResolver> = PolicySubjectArgs<TResolver> extends [subject: infer Subject] ? { subject: Subject; } : { subject?: never; }; /** * One typed authorization matrix case for a policy ability. */ export type PolicyMatrixCase<TContext, TPolicies extends readonly PolicyDefinition[] = readonly PolicyDefinition[]> = { [TAbility in keyof PolicyMapFromDefinitions<TPolicies> & string]: { name: string; ctx: TContext; ability: TAbility; expected: PolicyMatrixExpectation; reason?: string; code?: string; } & PolicyMatrixSubject<PolicyMapFromDefinitions<TPolicies>[TAbility]>; }[keyof PolicyMapFromDefinitions<TPolicies> & string]; /** * Untyped policy matrix case used internally for failure reporting. */ export type UntypedPolicyMatrixCase<TContext> = { name: string; ctx: TContext; ability: string; subject?: unknown; expected: PolicyMatrixExpectation; reason?: string; code?: string; }; /** * Result for one evaluated policy matrix case. */ export type PolicyMatrixResult<TContext, TPolicies extends readonly PolicyDefinition[] = readonly PolicyDefinition[]> = { case: PolicyMatrixCase<TContext, TPolicies>; decision: GateDecision; passed: boolean; message?: string; }; /** * Test helper for evaluating authorization policies. */ export type PolicyTester<TContext, TPolicies extends readonly PolicyDefinition[]> = { /** * Gate created from the same policies, useful for direct assertions. */ gate: GatePort<TContext, TPolicies>; /** * Evaluate cases and return structured pass/fail results. */ evaluateMatrix(cases: readonly PolicyMatrixCase<TContext, TPolicies>[]): Promise<PolicyMatrixResult<TContext, TPolicies>[]>; /** * Evaluate cases and throw a combined assertion error when any fail. */ assertMatrix(cases: readonly PolicyMatrixCase<TContext, TPolicies>[]): Promise<void>; }; /** * Create a policy tester from the same options used by `createGate(...)`. * * Use this for table-driven authorization tests that document who can perform * each ability against which subject. * * @param options - Policy definitions and optional denial mapper. * @returns A policy tester with a gate plus matrix helpers. */ export declare function createPolicyTester<const TPolicies extends readonly PolicyDefinition[]>(options: CreateGateOptions<PolicyContextFromDefinitions<TPolicies>, TPolicies>): PolicyTester<PolicyContextFromDefinitions<TPolicies>, TPolicies>; /** * Evaluate a table of policy cases without throwing. * * @param gate - Gate under test. * @param cases - Matrix cases to evaluate. * @returns Structured result for each case. */ export declare function evaluatePolicyMatrix<TContext, TPolicies extends readonly PolicyDefinition[]>(gate: GatePort<TContext, TPolicies>, cases: readonly PolicyMatrixCase<TContext, TPolicies>[]): Promise<PolicyMatrixResult<TContext, TPolicies>[]>; /** * Assert that all policy matrix cases pass. * * @param gate - Gate under test. * @param cases - Matrix cases to evaluate. * @throws Combined error listing every failed case. */ export declare function assertPolicyMatrix<TContext, TPolicies extends readonly PolicyDefinition[]>(gate: GatePort<TContext, TPolicies>, cases: readonly PolicyMatrixCase<TContext, TPolicies>[]): Promise<void>; export {}; //# sourceMappingURL=testing.d.ts.map