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
86import { exec } from 'node:child_process' ;
97import { promisify } from 'node:util' ;
108import { join , dirname } from 'node:path' ;
119import { fileURLToPath } from 'node:url' ;
12- import { existsSync , mkdirSync } from 'node:fs' ;
10+ import { existsSync , mkdirSync , statSync } from 'node:fs' ;
1311
1412const execAsync = promisify ( exec ) ;
1513
@@ -21,82 +19,53 @@ const ARTIFACTS_DIR = join(__dirname, 'fixtures', 'artifacts');
2119
2220const 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-
2822async 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
5651async 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
0 commit comments