UNPKG

@rivetkit/core

Version:

260 lines (201 loc) 8.78 kB
import { describe, expect, test } from "vitest"; import type { DriverTestConfig } from "../mod"; import { setupDriverTest } from "../utils"; export function runActorHandleTests(driverTestConfig: DriverTestConfig) { describe("Actor Handle Tests", () => { describe("Access Methods", () => { test("should use .get() to access a actor", async (c) => { const { client } = await setupDriverTest(c, driverTestConfig); // Create actor first await client.counter.create(["test-get-handle"]); // Access using get const handle = client.counter.get(["test-get-handle"]); // Verify Action works const count = await handle.increment(5); expect(count).toBe(5); const retrievedCount = await handle.getCount(); expect(retrievedCount).toBe(5); }); test("should use .getForId() to access a actor by ID", async (c) => { const { client } = await setupDriverTest(c, driverTestConfig); // Create a actor first to get its ID const handle = client.counter.getOrCreate(["test-get-for-id-handle"]); await handle.increment(3); const actorId = await handle.resolve(); // Access using getForId const idHandle = client.counter.getForId(actorId); // Verify Action works and state is preserved const count = await idHandle.getCount(); expect(count).toBe(3); const newCount = await idHandle.increment(4); expect(newCount).toBe(7); }); test("should use .getOrCreate() to access or create a actor", async (c) => { const { client } = await setupDriverTest(c, driverTestConfig); // Access using getOrCreate - should create the actor const handle = client.counter.getOrCreate([ "test-get-or-create-handle", ]); // Verify Action works const count = await handle.increment(7); expect(count).toBe(7); // Get the same actor again - should retrieve existing actor const sameHandle = client.counter.getOrCreate([ "test-get-or-create-handle", ]); const retrievedCount = await sameHandle.getCount(); expect(retrievedCount).toBe(7); }); test("should use (await create()) to create and return a handle", async (c) => { const { client } = await setupDriverTest(c, driverTestConfig); // Create actor and get handle const handle = await client.counter.create(["test-create-handle"]); // Verify Action works const count = await handle.increment(9); expect(count).toBe(9); const retrievedCount = await handle.getCount(); expect(retrievedCount).toBe(9); }); }); describe("Action Functionality", () => { test("should call actions directly on the handle", async (c) => { const { client } = await setupDriverTest(c, driverTestConfig); const handle = client.counter.getOrCreate(["test-action-handle"]); // Call multiple actions in sequence const count1 = await handle.increment(3); expect(count1).toBe(3); const count2 = await handle.increment(5); expect(count2).toBe(8); const retrievedCount = await handle.getCount(); expect(retrievedCount).toBe(8); }); test("should handle independent handles to the same actor", async (c) => { const { client } = await setupDriverTest(c, driverTestConfig); // Create two handles to the same actor const handle1 = client.counter.getOrCreate(["test-multiple-handles"]); const handle2 = client.counter.get(["test-multiple-handles"]); // Call actions on both handles await handle1.increment(3); const count = await handle2.getCount(); // Verify both handles access the same state expect(count).toBe(3); const finalCount = await handle2.increment(4); expect(finalCount).toBe(7); const checkCount = await handle1.getCount(); expect(checkCount).toBe(7); }); test("should resolve a actor's ID", async (c) => { const { client } = await setupDriverTest(c, driverTestConfig); const handle = client.counter.getOrCreate(["test-resolve-id"]); // Call an action to ensure actor exists await handle.increment(1); // Resolve the ID const actorId = await handle.resolve(); // Verify we got a valid ID (string) expect(typeof actorId).toBe("string"); expect(actorId).not.toBe(""); // Verify we can use this ID to get the actor const idHandle = client.counter.getForId(actorId); const count = await idHandle.getCount(); expect(count).toBe(1); }); }); describe("Lifecycle Hooks", () => { test("should trigger lifecycle hooks on actor creation", async (c) => { const { client } = await setupDriverTest(c, driverTestConfig); // Get or create a new actor - this should trigger onStart const handle = client.counterWithLifecycle.getOrCreate([ "test-lifecycle-handle", ]); // Verify onStart was triggered const initialEvents = await handle.getEvents(); expect(initialEvents).toContain("onStart"); // Create a separate handle to the same actor const sameHandle = client.counterWithLifecycle.getOrCreate([ "test-lifecycle-handle", ]); // Verify events still include onStart but don't duplicate it // (onStart should only be called once when the actor is first created) const events = await sameHandle.getEvents(); expect(events).toContain("onStart"); expect(events.filter((e) => e === "onStart").length).toBe(1); }); test("should trigger lifecycle hooks for each Action call", async (c) => { const { client } = await setupDriverTest(c, driverTestConfig); // Create a normal handle to view events const viewHandle = client.counterWithLifecycle.getOrCreate([ "test-lifecycle-action", ]); // Initial state should only have onStart const initialEvents = await viewHandle.getEvents(); expect(initialEvents).toContain("onStart"); expect(initialEvents).not.toContain("onBeforeConnect"); expect(initialEvents).not.toContain("onConnect"); expect(initialEvents).not.toContain("onDisconnect"); // Create a handle with trackLifecycle enabled for testing Action calls const trackingHandle = client.counterWithLifecycle.getOrCreate( ["test-lifecycle-action"], { params: { trackLifecycle: true } }, ); // Make an Action call await trackingHandle.increment(5); // Check that it triggered the lifecycle hooks const eventsAfterAction = await viewHandle.getEvents(); // Should have onBeforeConnect, onConnect, and onDisconnect for the Action call expect(eventsAfterAction).toContain("onBeforeConnect"); expect(eventsAfterAction).toContain("onConnect"); expect(eventsAfterAction).toContain("onDisconnect"); // Each should have count 1 expect( eventsAfterAction.filter((e) => e === "onBeforeConnect").length, ).toBe(1); expect(eventsAfterAction.filter((e) => e === "onConnect").length).toBe( 1, ); expect( eventsAfterAction.filter((e) => e === "onDisconnect").length, ).toBe(1); // Make another Action call await trackingHandle.increment(10); // Check that it triggered another set of lifecycle hooks const eventsAfterSecondAction = await viewHandle.getEvents(); // Each hook should now have count 2 expect( eventsAfterSecondAction.filter((e) => e === "onBeforeConnect").length, ).toBe(2); expect( eventsAfterSecondAction.filter((e) => e === "onConnect").length, ).toBe(2); expect( eventsAfterSecondAction.filter((e) => e === "onDisconnect").length, ).toBe(2); }); test("should trigger lifecycle hooks for each Action call across multiple handles", async (c) => { const { client } = await setupDriverTest(c, driverTestConfig); // Create a normal handle to view events const viewHandle = client.counterWithLifecycle.getOrCreate([ "test-lifecycle-multi-handle", ]); // Create two tracking handles to the same actor const trackingHandle1 = client.counterWithLifecycle.getOrCreate( ["test-lifecycle-multi-handle"], { params: { trackLifecycle: true } }, ); const trackingHandle2 = client.counterWithLifecycle.getOrCreate( ["test-lifecycle-multi-handle"], { params: { trackLifecycle: true } }, ); // Make Action calls on both handles await trackingHandle1.increment(5); await trackingHandle2.increment(10); // Check lifecycle hooks const events = await viewHandle.getEvents(); // Should have 1 onStart, 2 each of onBeforeConnect, onConnect, and onDisconnect expect(events.filter((e) => e === "onStart").length).toBe(1); expect(events.filter((e) => e === "onBeforeConnect").length).toBe(2); expect(events.filter((e) => e === "onConnect").length).toBe(2); expect(events.filter((e) => e === "onDisconnect").length).toBe(2); }); }); }); }