Skip to content

Commit 0ef2ab4

Browse files
committed
refactor: fix vitest globalsetup
1 parent 769a860 commit 0ef2ab4

3 files changed

Lines changed: 31 additions & 62 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
],
99
"scripts": {
1010
"build": "turbo run build --log-prefix=none",
11-
"test": "turbo run test --filter=@openzeppelin/compact-tools-cli --log-prefix=none",
11+
"test": "turbo run test --log-prefix=none",
1212
"fmt-and-lint": "biome check . --changed",
1313
"fmt-and-lint:fix": "biome check . --changed --write",
1414
"fmt-and-lint:ci": "biome ci . --changed --no-errors-on-unmatched",

packages/simulator/test/setup.ts

Lines changed: 29 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
1-
#!/usr/bin/env node
2-
31
/**
42
* Test setup script that compiles sample contracts before running tests.
5-
* This ensures test artifacts are generated dynamically rather than being hardcoded.
3+
* Runs once before all tests via Vitest's globalSetup.
64
*/
75

86
import { exec } from 'node:child_process';
97
import { promisify } from 'node:util';
108
import { join, dirname } from 'node:path';
119
import { fileURLToPath } from 'node:url';
12-
import { existsSync, mkdirSync } from 'node:fs';
10+
import { existsSync, mkdirSync, statSync } from 'node:fs';
1311

1412
const execAsync = promisify(exec);
1513

@@ -21,82 +19,53 @@ const ARTIFACTS_DIR = join(__dirname, 'fixtures', 'artifacts');
2119

2220
const CONTRACT_FILES = ['Simple.compact', 'Witness.compact', 'SampleZOwnable.compact'];
2321

24-
// Singleton pattern to ensure setup only runs once across all test workers
25-
let setupPromise: Promise<void> | null = null;
26-
let setupComplete = false;
27-
2822
async function compileContract(contractFile: string): Promise<void> {
2923
const inputPath = join(SAMPLE_CONTRACTS_DIR, contractFile);
3024
const contractName = contractFile.replace('.compact', '');
3125
const outputDir = join(ARTIFACTS_DIR, contractName);
26+
const contractArtifact = join(outputDir, 'contract', 'index.cjs');
27+
28+
// Skip if artifact already exists and is newer than source
29+
if (existsSync(contractArtifact) && existsSync(inputPath)) {
30+
const artifactTime = statSync(contractArtifact).mtime;
31+
const sourceTime = statSync(inputPath).mtime;
32+
if (artifactTime >= sourceTime) {
33+
console.log(`✓ ${contractFile} (already compiled)`);
34+
return; // Already compiled and up to date
35+
}
36+
}
3237

3338
if (!existsSync(inputPath)) {
3439
throw new Error(`Contract file not found: ${inputPath}`);
3540
}
3641

3742
// Ensure output directory and keys subdirectory exist
38-
// compact compile requires the keys directory to exist
3943
mkdirSync(outputDir, { recursive: true });
4044
mkdirSync(join(outputDir, 'keys'), { recursive: true });
4145

42-
try {
43-
const command = `compact compile --skip-zk "${inputPath}" "${outputDir}"`;
44-
const { stderr } = await execAsync(command);
45-
46-
if (stderr && !stderr.includes('warning')) {
47-
console.log(`Warning for ${contractFile}: ${stderr}`);
48-
}
49-
console.log(`✓ Compiled ${contractFile}`);
50-
} catch (error: unknown) {
51-
const message = error instanceof Error ? error.message : String(error);
52-
throw new Error(`Failed to compile ${contractFile}: ${message}`);
53-
}
46+
const command = `compact compile --skip-zk "${inputPath}" "${outputDir}"`;
47+
await execAsync(command);
48+
console.log(`✓ Compiled ${contractFile}`);
5449
}
5550

5651
async function setup(): Promise<void> {
57-
// If setup is already complete, return immediately
58-
if (setupComplete) {
59-
return;
60-
}
61-
62-
// If setup is in progress, wait for it
63-
if (setupPromise) {
64-
return setupPromise;
65-
}
66-
67-
// Start setup
68-
setupPromise = (async () => {
69-
console.log('🔨 Compiling sample contracts for tests...\n');
52+
console.log('🔨 Compiling sample contracts for tests...\n');
7053

71-
// Ensure artifacts directory exists
72-
mkdirSync(ARTIFACTS_DIR, { recursive: true });
54+
mkdirSync(ARTIFACTS_DIR, { recursive: true });
7355

74-
// Compile each contract
75-
for (const contractFile of CONTRACT_FILES) {
76-
await compileContract(contractFile);
77-
}
78-
79-
console.log('\n✅ Test artifacts compiled successfully!\n');
80-
setupComplete = true;
81-
})();
56+
// Compile each contract sequentially
57+
for (const contractFile of CONTRACT_FILES) {
58+
await compileContract(contractFile);
59+
}
60+
}
8261

62+
// Export setup function for Vitest's globalSetup
63+
export default async function globalSetup(): Promise<void> {
8364
try {
84-
await setupPromise;
65+
await setup();
8566
} catch (error) {
86-
// Reset promise on error so it can be retried
87-
setupPromise = null;
88-
throw error;
67+
console.log(`❌ Setup failed: ${error}`);
68+
process.exit(1);
8969
}
90-
}
91-
92-
// Always run setup when this file is loaded by vitest
93-
// Vitest's `setupFiles` loads (imports) this module, so execute on import.
94-
// The singleton pattern ensures it only runs once even with parallel workers.
95-
await setup().catch((error) => {
96-
console.log(`❌ Setup failed: ${error}`);
97-
process.exit(1);
98-
});
99-
100-
// Export default function as well (useful if needed elsewhere)
101-
export default setup;
70+
};
10271

packages/simulator/vitest.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,6 @@ export default defineConfig({
66
environment: 'node',
77
include: ['test/**/*.test.ts'],
88
reporters: 'verbose',
9-
setupFiles: ['./test/setup.ts'],
9+
globalSetup: ['./test/setup.ts'],
1010
},
1111
});

0 commit comments

Comments
 (0)