Merge public-gh/master into paperclip-company-import-export
This commit is contained in:
29
server/src/__tests__/documents.test.ts
Normal file
29
server/src/__tests__/documents.test.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { extractLegacyPlanBody } from "../services/documents.js";
|
||||
|
||||
describe("extractLegacyPlanBody", () => {
|
||||
it("returns null when no plan block exists", () => {
|
||||
expect(extractLegacyPlanBody("hello world")).toBeNull();
|
||||
});
|
||||
|
||||
it("extracts plan body from legacy issue descriptions", () => {
|
||||
expect(
|
||||
extractLegacyPlanBody(`
|
||||
intro
|
||||
|
||||
<plan>
|
||||
|
||||
# Plan
|
||||
|
||||
- one
|
||||
- two
|
||||
|
||||
</plan>
|
||||
`),
|
||||
).toBe("# Plan\n\n- one\n- two");
|
||||
});
|
||||
|
||||
it("ignores empty plan blocks", () => {
|
||||
expect(extractLegacyPlanBody("<plan> </plan>")).toBeNull();
|
||||
});
|
||||
});
|
||||
68
server/src/__tests__/plugin-dev-watcher.test.ts
Normal file
68
server/src/__tests__/plugin-dev-watcher.test.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import { resolvePluginWatchTargets } from "../services/plugin-dev-watcher.js";
|
||||
|
||||
const tempDirs: string[] = [];
|
||||
|
||||
afterEach(() => {
|
||||
while (tempDirs.length > 0) {
|
||||
const dir = tempDirs.pop();
|
||||
if (dir) rmSync(dir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
function makeTempPluginDir(): string {
|
||||
const dir = mkdtempSync(path.join(os.tmpdir(), "paperclip-plugin-watch-"));
|
||||
tempDirs.push(dir);
|
||||
return dir;
|
||||
}
|
||||
|
||||
describe("resolvePluginWatchTargets", () => {
|
||||
it("watches package metadata plus concrete declared runtime files", () => {
|
||||
const pluginDir = makeTempPluginDir();
|
||||
mkdirSync(path.join(pluginDir, "dist", "ui"), { recursive: true });
|
||||
writeFileSync(
|
||||
path.join(pluginDir, "package.json"),
|
||||
JSON.stringify({
|
||||
name: "@acme/example",
|
||||
paperclipPlugin: {
|
||||
manifest: "./dist/manifest.js",
|
||||
worker: "./dist/worker.js",
|
||||
ui: "./dist/ui",
|
||||
},
|
||||
}),
|
||||
);
|
||||
writeFileSync(path.join(pluginDir, "dist", "manifest.js"), "export default {};\n");
|
||||
writeFileSync(path.join(pluginDir, "dist", "worker.js"), "export default {};\n");
|
||||
writeFileSync(path.join(pluginDir, "dist", "ui", "index.js"), "export default {};\n");
|
||||
writeFileSync(path.join(pluginDir, "dist", "ui", "index.css"), "body {}\n");
|
||||
|
||||
const targets = resolvePluginWatchTargets(pluginDir);
|
||||
|
||||
expect(targets).toEqual([
|
||||
{ path: path.join(pluginDir, "dist", "manifest.js"), recursive: false, kind: "file" },
|
||||
{ path: path.join(pluginDir, "dist", "ui", "index.css"), recursive: false, kind: "file" },
|
||||
{ path: path.join(pluginDir, "dist", "ui", "index.js"), recursive: false, kind: "file" },
|
||||
{ path: path.join(pluginDir, "dist", "worker.js"), recursive: false, kind: "file" },
|
||||
{ path: path.join(pluginDir, "package.json"), recursive: false, kind: "file" },
|
||||
]);
|
||||
});
|
||||
|
||||
it("falls back to dist when package metadata does not declare entrypoints", () => {
|
||||
const pluginDir = makeTempPluginDir();
|
||||
mkdirSync(path.join(pluginDir, "dist", "nested"), { recursive: true });
|
||||
writeFileSync(path.join(pluginDir, "package.json"), JSON.stringify({ name: "@acme/example" }));
|
||||
writeFileSync(path.join(pluginDir, "dist", "manifest.js"), "export default {};\n");
|
||||
writeFileSync(path.join(pluginDir, "dist", "nested", "chunk.js"), "export default {};\n");
|
||||
|
||||
const targets = resolvePluginWatchTargets(pluginDir);
|
||||
|
||||
expect(targets).toEqual([
|
||||
{ path: path.join(pluginDir, "package.json"), recursive: false, kind: "file" },
|
||||
{ path: path.join(pluginDir, "dist", "manifest.js"), recursive: false, kind: "file" },
|
||||
{ path: path.join(pluginDir, "dist", "nested", "chunk.js"), recursive: false, kind: "file" },
|
||||
]);
|
||||
});
|
||||
});
|
||||
43
server/src/__tests__/plugin-worker-manager.test.ts
Normal file
43
server/src/__tests__/plugin-worker-manager.test.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { appendStderrExcerpt, formatWorkerFailureMessage } from "../services/plugin-worker-manager.js";
|
||||
|
||||
describe("plugin-worker-manager stderr failure context", () => {
|
||||
it("appends worker stderr context to failure messages", () => {
|
||||
expect(
|
||||
formatWorkerFailureMessage(
|
||||
"Worker process exited (code=1, signal=null)",
|
||||
"TypeError: Unknown file extension \".ts\"",
|
||||
),
|
||||
).toBe(
|
||||
"Worker process exited (code=1, signal=null)\n\nWorker stderr:\nTypeError: Unknown file extension \".ts\"",
|
||||
);
|
||||
});
|
||||
|
||||
it("does not duplicate stderr that is already present", () => {
|
||||
const message = [
|
||||
"Worker process exited (code=1, signal=null)",
|
||||
"",
|
||||
"Worker stderr:",
|
||||
"TypeError: Unknown file extension \".ts\"",
|
||||
].join("\n");
|
||||
|
||||
expect(
|
||||
formatWorkerFailureMessage(message, "TypeError: Unknown file extension \".ts\""),
|
||||
).toBe(message);
|
||||
});
|
||||
|
||||
it("keeps only the latest stderr excerpt", () => {
|
||||
let excerpt = "";
|
||||
excerpt = appendStderrExcerpt(excerpt, "first line");
|
||||
excerpt = appendStderrExcerpt(excerpt, "second line");
|
||||
|
||||
expect(excerpt).toContain("first line");
|
||||
expect(excerpt).toContain("second line");
|
||||
|
||||
excerpt = appendStderrExcerpt(excerpt, "x".repeat(9_000));
|
||||
|
||||
expect(excerpt).not.toContain("first line");
|
||||
expect(excerpt).not.toContain("second line");
|
||||
expect(excerpt.length).toBeLessThanOrEqual(8_000);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user