@@ -0,0 +1,76 @@
1+import { describe, it, expect, beforeAll } from "vitest";
2+import { execSync } from "child_process";
3+import { readdirSync, readFileSync } from "fs";
4+import { join } from "path";
5+
6+const casesDir = join(__dirname, "cases");
7+const outputDir = "output-compile-fail";
8+
9+function getSourceGlobs() {
10+ const raw = execSync("npx spago sources", {
11+ encoding: "utf-8",
12+ cwd: join(__dirname, ".."),
13+ stdio: ["pipe", "pipe", "pipe"],
14+ });
15+ return raw
16+ .split("\n")
17+ .filter((l) => l.trim() && !l.startsWith("test/"))
18+ .map((g) => `"${g}"`)
19+ .join(" ");
20+}
21+
22+let sourceGlobs;
23+
24+beforeAll(() => {
25+ sourceGlobs = getSourceGlobs();
26+ try {
27+ execSync(
28+ `npx purs compile --output ${outputDir} ${sourceGlobs}`,
29+ {
30+ cwd: join(__dirname, ".."),
31+ encoding: "utf-8",
32+ stdio: ["pipe", "pipe", "pipe"],
33+ }
34+ );
35+ } catch {
36+ // Warming cache - ignore errors
37+ }
38+}, 120_000);
39+
40+const cases = readdirSync(casesDir)
41+ .filter((f) => f.endsWith(".purs"))
42+ .sort();
43+
44+describe("Compile-fail tests", () => {
45+ for (const file of cases) {
46+ const filePath = join(casesDir, file);
47+ const firstLine = readFileSync(filePath, "utf-8").split("\n")[0];
48+ const expectMatch = firstLine.match(/^-- EXPECT:\s*(.+)/);
49+ const expectedSubstring = expectMatch ? expectMatch[1].trim() : null;
50+ const testName = file.replace(".purs", "");
51+
52+ it(testName, () => {
53+ let output = "";
54+ let exitCode = 0;
55+ try {
56+ execSync(
57+ `npx purs compile --output ${outputDir} ${sourceGlobs} "${filePath}"`,
58+ {
59+ cwd: join(__dirname, ".."),
60+ encoding: "utf-8",
61+ stdio: ["pipe", "pipe", "pipe"],
62+ }
63+ );
64+ } catch (err) {
65+ exitCode = err.status;
66+ output = (err.stdout || "") + (err.stderr || "");
67+ }
68+
69+ expect(exitCode, `Expected ${file} to fail compilation but it succeeded`).not.toBe(0);
70+
71+ if (expectedSubstring) {
72+ expect(output, `Expected error to contain "${expectedSubstring}"`).toContain(expectedSubstring);
73+ }
74+ }, 30_000);
75+ }
76+});