import * as crypto from "node:crypto"; import { defineSliceMachinePlugin, SliceMachineHookTypes, SliceMachinePlugin, SliceMachinePluginOptions, } from "@slicemachine/plugin-kit"; import { expect } from "vitest"; const sha1 = (data: crypto.BinaryLike): string => { return crypto.createHash("sha1").update(data).digest("hex"); }; const REQUIRED_ADAPTER_HOOKS: SliceMachineHookTypes[] = [ "slice:create", "slice:read", "slice:update", "slice:rename", "slice:delete", "slice:asset:update", "slice:asset:read", "slice:asset:delete", "slice-library:read", "custom-type:create", "custom-type:read", "custom-type:update", "custom-type:rename", "custom-type:delete", "custom-type:asset:update", "custom-type:asset:read", "custom-type:asset:delete", "custom-type-library:read", ]; type CreateTestPluginArgs = Partial> & { __autofillRequiredAdapterHooks?: boolean; }; export const createTestPlugin = < TPluginOptions extends SliceMachinePluginOptions, >({ setup, __autofillRequiredAdapterHooks = true, ...plugin }: CreateTestPluginArgs = {}): SliceMachinePlugin => { const state = expect.getState(); return defineSliceMachinePlugin({ ...plugin, meta: { ...plugin.meta, name: plugin.meta?.name ?? // eslint-disable-next-line @typescript-eslint/no-non-null-assertion `test-plugin-${sha1(state.currentTestName!)}`, }, setup: async ({ hook, ...restSetupArgs }) => { const hookedTypes: string[] = []; const spiedOnHook = ((type, ...restHookArgs) => { hookedTypes.push(type); return hook(type, ...restHookArgs); }) as typeof hook; await setup?.({ hook: spiedOnHook, ...restSetupArgs }); if (__autofillRequiredAdapterHooks) { for (const hookType of REQUIRED_ADAPTER_HOOKS) { if (!hookedTypes.includes(hookType)) { hook(hookType, () => { throw new Error("not implemented"); }); } } } }, }); };