From c2bcc743cb1857b5c2927b2df2483ed5c7fa818f Mon Sep 17 00:00:00 2001 From: Chris R Date: Thu, 22 Dec 2022 16:04:24 +0000 Subject: [PATCH] Feat: allow access to the Durable Object's instance from inside a test (#385) * feat: added `getMiniflareDurableObjectInstance()` to test environments This allows access to the Durable Object instance for direct manipulation and testing * Update durableobjects.module.spec.js Co-authored-by: MrBBot --- packages/durable-objects/src/plugin.ts | 9 +++++++++ .../test/fixtures/durableobjects.module.spec.js | 14 ++++++++++++++ packages/shared-test-environment/src/globals.ts | 12 ++++++++++++ .../modules/durableobjects.module.spec.js | 15 ++++++++++++++- 4 files changed, 49 insertions(+), 1 deletion(-) diff --git a/packages/durable-objects/src/plugin.ts b/packages/durable-objects/src/plugin.ts index 1dc69bc04..84972184c 100644 --- a/packages/durable-objects/src/plugin.ts +++ b/packages/durable-objects/src/plugin.ts @@ -15,6 +15,7 @@ import { import { AlarmStore } from "./alarms"; import { DurableObjectError } from "./error"; import { + DurableObject, DurableObjectConstructor, DurableObjectFactory, DurableObjectId, @@ -207,6 +208,14 @@ export class DurableObjectsPlugin return state; } + async getInstance( + storage: StorageFactory, + id: DurableObjectId + ): Promise { + const state = await this.getObject(storage, id); + return state[kInstance] as DurableObject; + } + getNamespace( storage: StorageFactory, objectName: string diff --git a/packages/jest-environment-miniflare/test/fixtures/durableobjects.module.spec.js b/packages/jest-environment-miniflare/test/fixtures/durableobjects.module.spec.js index 8e929e235..e5e617619 100644 --- a/packages/jest-environment-miniflare/test/fixtures/durableobjects.module.spec.js +++ b/packages/jest-environment-miniflare/test/fixtures/durableobjects.module.spec.js @@ -1,3 +1,4 @@ +import { jest } from "@jest/globals"; import { DurableObjectId } from "@miniflare/durable-objects"; beforeAll(async () => { @@ -67,3 +68,16 @@ test("Durable Objects list", async () => { new DurableObjectId("TEST_OBJECT", id2.toString()) ); }); + +test("Access to Durable Object instance", async () => { + const env = getMiniflareBindings(); + const id = env.TEST_OBJECT.idFromName("test"); + const stub = env.TEST_OBJECT.get(id); + const instance = await getMiniflareDurableObjectInstance(id); + const fetch = jest.spyOn(instance, "fetch"); + + await stub.fetch(new Request("https://object/")); + + expect(instance.constructor.name).toBe("TestObject"); + expect(fetch).toHaveBeenCalled(); +}); diff --git a/packages/shared-test-environment/src/globals.ts b/packages/shared-test-environment/src/globals.ts index 395ab24b3..6834a86b8 100644 --- a/packages/shared-test-environment/src/globals.ts +++ b/packages/shared-test-environment/src/globals.ts @@ -5,6 +5,7 @@ import { kWaitUntil, } from "@miniflare/core"; import { + DurableObject, DurableObjectId, DurableObjectState, DurableObjectStorage, @@ -32,6 +33,9 @@ declare global { function getMiniflareDurableObjectState( id: DurableObjectId ): Promise; + function getMiniflareDurableObjectInstance( + id: DurableObjectId + ): Promise; function runWithMiniflareDurableObjectGates( state: DurableObjectState, closure: () => Awaitable @@ -56,6 +60,9 @@ export interface MiniflareEnvironmentUtilities { getMiniflareDurableObjectState( id: DurableObjectId ): Promise; + getMiniflareDurableObjectInstance( + id: DurableObjectId + ): Promise; runWithMiniflareDurableObjectGates( state: DurableObjectState, closure: () => Awaitable @@ -91,6 +98,11 @@ export async function createMiniflareEnvironmentUtilities( const storage = plugin.getStorage(factory, id); return new DurableObjectState(id, storage); }, + async getMiniflareDurableObjectInstance(id: DurableObjectId) { + const plugin = (await mf.getPlugins()).DurableObjectsPlugin; + const factory = mf.getPluginStorage("DurableObjectsPlugin"); + return await plugin.getInstance(factory, id); + }, runWithMiniflareDurableObjectGates( state: DurableObjectState, closure: () => Awaitable diff --git a/packages/vitest-environment-miniflare/test/fixtures/modules/durableobjects.module.spec.js b/packages/vitest-environment-miniflare/test/fixtures/modules/durableobjects.module.spec.js index 1e79d28d1..c78cdd26d 100644 --- a/packages/vitest-environment-miniflare/test/fixtures/modules/durableobjects.module.spec.js +++ b/packages/vitest-environment-miniflare/test/fixtures/modules/durableobjects.module.spec.js @@ -1,5 +1,5 @@ import { DurableObjectId } from "@miniflare/durable-objects"; -import { beforeAll, expect, test } from "vitest"; +import { beforeAll, expect, test, vi } from "vitest"; setupMiniflareIsolatedStorage(); beforeAll(async () => { @@ -69,3 +69,16 @@ test("Durable Objects list", async () => { new DurableObjectId("TEST_OBJECT", id2.toString()) ); }); + +test("Access to Durable Object instance", async () => { + const env = getMiniflareBindings(); + const id = env.TEST_OBJECT.idFromName("test"); + const stub = env.TEST_OBJECT.get(id); + const instance = await getMiniflareDurableObjectInstance(id); + const fetch = vi.spyOn(instance, "fetch"); + + await stub.fetch(new Request("https://object/")); + + expect(instance.constructor.name).toBe("TestObject"); + expect(fetch).toHaveBeenCalled(); +});