测试沙盒插件

本页内容

@emdash-cms/plugin-test 构建沙盒插件并在 workerd 中运行其测试。测试使用 EmDash 的生产 Cloudflare 沙盒包装器和 PluginBridge,以及由 @cloudflare/vitest-plugin 提供的本地 D1 和 Worker Loader 绑定。

使用 emdash-plugin init 创建的项目包含此设置。现有插件项目可以将测试主机安装为开发依赖:

pnpm add -D @emdash-cms/plugin-test vitest

如果项目限制依赖项的构建脚本,请允许 workerd 安装其平台二进制文件。生成的 pnpm 策略包含此条目:

allowBuilds:
  workerd: true

配置 Vitest

将 EmDash 测试插件添加到项目的 Vitest 配置中:

import { emdashPluginTest } from "@emdash-cms/plugin-test/config";
import { defineConfig } from "vitest/config";

export default defineConfig({
	plugins: [emdashPluginTest()],
});

emdashPluginTest() 在 Vitest 启动前运行插件构建。它读取生成的运行时和清单,创建一个隔离的 D1 数据库和 Worker Loader 绑定,并导出 Cloudflare 部署使用的相同 PluginBridge。当 Vitest 配置位于插件目录之外时,传入 { dir: "./packages/gallery" }

测试路由

在每个测试中创建和销毁主机。销毁会停止插件并重置其测试绑定:

import { afterEach, describe, expect, it } from "vitest";

import { createPluginTestHost, type PluginTestHost } from "@emdash-cms/plugin-test";

let host: PluginTestHost | undefined;

afterEach(async () => {
	await host?.dispose();
	host = undefined;
});

describe("health route", () => {
	it("identifies the plugin", async () => {
		host = await createPluginTestHost();

		await expect(host.invokeRoute("health")).resolves.toEqual({
			ok: true,
			plugin: "save-log",
		});
	});
});

invokeRoute() 接受输入值和可选的请求属性。默认请求是对插件路由的 POST,带有空的头部和请求元数据。

测试钩子和存储

使用从 EmDash 接收的事件形式调用钩子。存储和 KV 读取器检查通过桥接写入的状态:

host = await createPluginTestHost();

await host.invokeHook("content:afterSave", {
	collection: "posts",
	content: { id: "post-1", title: "First post" },
});

const events = await host.storage("events").list();
expect(events).toHaveLength(1);
expect(events[0]?.data).toMatchObject({
	collection: "posts",
	contentId: "post-1",
});

存储调用仍然强制执行 emdash-plugin.jsonc 中声明的集合。内容、媒体、用户、电子邮件和网络调用仍然强制执行插件声明的能力和允许的主机。

填充内容

在调用读取站点内容的路由或钩子之前,创建集合并填充条目:

host = await createPluginTestHost();
await host.createCollection({
	slug: "posts",
	label: "Posts",
	fields: [{ slug: "title", label: "Title", type: "string" }],
});
await host.seedContent("posts", [{ title: "First" }, { title: "Second" }]);

await expect(host.invokeRoute("post-count")).resolves.toEqual({ count: 2 });

集合和条目使用 D1 上的真实 EmDash 模式注册表和内容存储库。

测试边界

主机涵盖构建的插件、隔离边界、远程过程调用序列化、D1 行为、能力检查、钩子、路由、KV 和声明的存储。它不渲染 EmDash 管理应用程序,也不重现 Cloudflare 部署的 CPU、内存和子请求限制。使用一次性 EmDash 站点进行浏览器之旅,并在 Cloudflare 预览或预发布部署上验证对限制敏感的行为。

对于 Block Kit 处理程序,调用插件的 admin 路由并断言返回的块文档。使用 Block Playground 或浏览器之旅来验证渲染的布局和交互。