test(plugins): exercise clawhub clawpack fixtures

This commit is contained in:
Vincent Koc
2026-05-02 08:57:24 -07:00
parent 43de6ae725
commit 437acb4184
5 changed files with 61 additions and 8 deletions

View File

@@ -11,6 +11,15 @@ const JSZip = requireFromApp("jszip");
const packageName = "@openclaw/kitchen-sink";
const pluginId = "openclaw-kitchen-sink-fixture";
const buildClawPackSummary = ({ sha256hash, manifestSha256, size }) => ({
available: true,
specVersion: 1,
format: "clawpack.zip",
sha256: sha256hash,
size,
manifestSha256,
});
const profiles = {
"kitchen-sink-plugin": {
version: "0.1.3",
@@ -87,7 +96,8 @@ export default definePluginEntry({
properties: {},
},
},
packageDetail(sha256hash) {
packageDetail(artifact) {
const clawpack = buildClawPackSummary(artifact);
const packageDetail = {
package: {
name: packageName,
@@ -121,6 +131,7 @@ export default definePluginEntry({
hasProvenance: false,
scanStatus: "passed",
},
clawpack,
},
};
return {
@@ -136,10 +147,11 @@ export default definePluginEntry({
createdAt: 0,
changelog: "Fixture package for kitchen-sink plugin prerelease CI.",
distTags: ["latest"],
sha256hash,
sha256hash: artifact.sha256hash,
compatibility: packageDetail.package.compatibility,
capabilities: packageDetail.package.capabilities,
verification: packageDetail.package.verification,
clawpack,
},
},
betaStatus: 404,
@@ -191,11 +203,12 @@ export default definePluginEntry({
properties: {},
},
},
packageDetail(sha256hash) {
packageDetail(artifact) {
const compatibility = {
pluginApiRange: ">=2026.4.26",
minGatewayVersion: "2026.4.26",
};
const clawpack = buildClawPackSummary(artifact);
return {
packageDetail: {
package: {
@@ -209,6 +222,7 @@ export default definePluginEntry({
createdAt: 0,
updatedAt: 0,
compatibility,
clawpack,
},
},
versionDetail: {
@@ -216,8 +230,9 @@ export default definePluginEntry({
version: this.version,
createdAt: 0,
changelog: "Kitchen-sink fixture package for Docker plugin E2E.",
sha256hash,
sha256hash: artifact.sha256hash,
compatibility,
clawpack,
},
},
};
@@ -237,13 +252,17 @@ async function main() {
date: new Date(0),
});
zip.file("package/index.js", fixture.indexJs, { date: new Date(0) });
zip.file("package/openclaw.plugin.json", `${JSON.stringify(fixture.manifest, null, 2)}\n`, {
date: new Date(0),
});
const manifestJson = `${JSON.stringify(fixture.manifest, null, 2)}\n`;
zip.file("package/openclaw.plugin.json", manifestJson, { date: new Date(0) });
const archive = await zip.generateAsync({ type: "nodebuffer", compression: "DEFLATE" });
const sha256hash = crypto.createHash("sha256").update(archive).digest("hex");
const { packageDetail, versionDetail, betaStatus } = fixture.packageDetail(sha256hash);
const manifestSha256 = crypto.createHash("sha256").update(manifestJson).digest("hex");
const { packageDetail, versionDetail, betaStatus } = fixture.packageDetail({
sha256hash,
manifestSha256,
size: archive.length,
});
const json = (response, value, status = 200) => {
response.writeHead(status, { "content-type": "application/json" });
@@ -283,6 +302,19 @@ async function main() {
response.end(archive);
return;
}
if (
url.pathname ===
`/api/v1/packages/${encodeURIComponent(packageName)}/versions/${fixture.version}/clawpack`
) {
response.writeHead(200, {
"content-type": "application/zip",
"content-length": String(archive.length),
"X-ClawHub-ClawPack-Sha256": sha256hash,
"X-ClawHub-ClawPack-Spec-Version": "1",
});
response.end(archive);
return;
}
response.writeHead(404, { "content-type": "text/plain" });
response.end(`not found: ${url.pathname}`);
});

View File

@@ -389,6 +389,14 @@ function assertInstalled() {
if (!record.version || !record.integrity || !record.resolvedAt) {
throw new Error(`missing ClawHub resolution metadata: ${JSON.stringify(record)}`);
}
if (
!record.clawpackSha256 ||
record.clawpackSpecVersion !== 1 ||
!record.clawpackManifestSha256 ||
typeof record.clawpackSize !== "number"
) {
throw new Error(`missing kitchen-sink ClawPack metadata: ${JSON.stringify(record)}`);
}
}
if (typeof record.installPath !== "string" || record.installPath.length === 0) {
throw new Error("missing kitchen-sink install path");

View File

@@ -534,6 +534,14 @@ function assertClawHubInstalled() {
if (typeof record.installPath !== "string" || record.installPath.length === 0) {
throw new Error(`missing ClawHub install path for ${pluginId}`);
}
if (
!record.clawpackSha256 ||
record.clawpackSpecVersion !== 1 ||
!record.clawpackManifestSha256 ||
typeof record.clawpackSize !== "number"
) {
throw new Error(`missing ClawHub ClawPack metadata for ${pluginId}: ${JSON.stringify(record)}`);
}
const installPath = record.installPath.replace(/^~(?=$|\/)/u, process.env.HOME);
const extensionsRoot = path.join(process.env.HOME, ".openclaw", "extensions");

View File

@@ -307,5 +307,6 @@ describe("docker build helper", () => {
expect(clawhub).toContain('plugins update "$CLAWHUB_PLUGIN_ID"');
expect(clawhub).toContain("clawhub:@openclaw/kitchen-sink");
expect(assertions).toContain("clawhub-updated");
expect(assertions).toContain("record.clawpackSha256");
});
});

View File

@@ -131,6 +131,7 @@ describe("scripts/lib/plugin-prerelease-test-plan.mjs", () => {
expect(assertionsScript).toContain("assertCutoverPreinstalled");
expect(assertionsScript).toContain("record.source !== source");
expect(assertionsScript).toContain("record.clawhubPackage !== packageName");
expect(assertionsScript).toContain("record.clawpackSha256");
expect(assertionsScript).toContain("assertClawHubExternalInstallContract");
expect(assertionsScript).toContain("expectedErrorMessages");
expect(assertionsScript).toContain(
@@ -140,6 +141,9 @@ describe("scripts/lib/plugin-prerelease-test-plan.mjs", () => {
expect(readFileSync("scripts/e2e/lib/clawhub-fixture-server.cjs", "utf8")).toContain(
'from "openclaw/plugin-sdk/plugin-entry"',
);
expect(readFileSync("scripts/e2e/lib/clawhub-fixture-server.cjs", "utf8")).toContain(
"X-ClawHub-ClawPack-Sha256",
);
expect(script).toContain("docker stats --no-stream");
expect(sweepScript).toContain("scan_logs_for_unexpected_errors");
});