/** * Schema-aware test factories for scope plugin actions. * * Creates typed test inputs matching action input schemas. * No API calls, no gRPC — just data construction. * * Usage: * import { createTestInput, createTestNotification } from "@nullplatform/plugin/testing"; * * const input = createTestInput(schema, "create-scope", { * scope: { id: "123", slug: "my-app", nrn: "..." }, * application: { id: "100", slug: "my-app" }, * }); */ import type { Notification } from "../scope/index"; import type { NpJSONSchema } from "../schema"; import type { FromExtendedSchema } from "json-schema-to-ts"; import type { NpKeywords } from "../schema"; // ─── Test notification factory ─────────────────────────────────────── const DEFAULT_NOTIFICATION: Notification = { id: "test-action-id", slug: "", action: "service:action:create", type: "custom", name: "", status: "pending", parameters: {}, tags: { organization_id: "1", organization: "test-org", account_id: "2", account: "test-account", namespace_id: "3", namespace: "test-namespace", application_id: "4", application: "test-app", scope_id: "5", scope: "test-scope", }, entity_nrn: "organization=1:account=2:namespace=3:application=4:scope=5", specification: { id: "test-spec-id", slug: "" }, service: { id: "test-service-id", slug: "test-scope", attributes: {}, specification: { id: "test-scope-spec-id", slug: "test-scope-type" }, dimensions: { environment: "test" }, }, results: {}, user: { id: 1, email: "test@nullplatform.io" }, link: null, }; interface NotificationOverrides extends Partial { scope_id?: string; deployment_id?: string; } /** * Create a test notification payload matching the platform's structure. * Useful for E2E tests that send raw payloads via executeStreaming(). */ export function createTestNotification( actionSlug: string, overrides?: NotificationOverrides ): { notification: Notification } { // Extract convenience fields so they don't leak into the notification object const { scope_id, deployment_id, ...notificationOverrides } = overrides ?? {}; const scopeId = scope_id ?? overrides?.tags?.scope_id ?? "test-scope-id"; const deploymentIdVal = deployment_id ?? undefined; const parameters: Record = { scope_id: scopeId, ...notificationOverrides?.parameters, }; if (deploymentIdVal) { parameters.deployment_id = deploymentIdVal; } const tags = { ...DEFAULT_NOTIFICATION.tags, scope_id: scopeId, ...notificationOverrides?.tags, }; const notification: Notification = { ...DEFAULT_NOTIFICATION, slug: actionSlug, name: actionSlug, specification: { id: "test-spec-id", slug: actionSlug }, ...notificationOverrides, // parameters and tags are computed after spreading overrides // to ensure scope_id/deployment_id are always included parameters, tags, }; return { notification }; } /** * Create a test notification as a Buffer payload (for executeStreaming). */ export function createTestPayload( actionSlug: string, overrides?: NotificationOverrides ): Buffer { return Buffer.from( JSON.stringify(createTestNotification(actionSlug, overrides)) ); } // ─── Typed action input factory ────────────────────────────────────── /** * Create a typed test input for an action. * * Pass the action's input schema to get compile-time type checking. * * Usage: * const input = createTestInput(myAction.input, { * scope: { id: "123", slug: "my-app", nrn: "organization=1:..." }, * application: { id: "100", slug: "my-application" }, * }); */ export function createTestInput( _inputSchema: S, input: FromExtendedSchema ): FromExtendedSchema { return input; }