1616
1717import { describe , it , expect } from 'vitest' ;
1818import crypto from 'crypto' ;
19- import fs from 'fs' ;
20- import path from 'path' ;
2119import schema from '../../nwb_schema.json' ;
2220import { deviceTypes } from '../../valueList' ;
2321
@@ -33,22 +31,22 @@ describe('BASELINE: Integration Contracts', () => {
3331 expect ( hash ) . toMatchSnapshot ( 'schema-hash' ) ;
3432 } ) ;
3533
36- it ( 'verifies schema sync with trodes_to_nwb (if available )' , ( ) => {
37- // This test gracefully degrades if trodes_to_nwb repo is not available
38- // Useful for CI environments where Python package may not be checked out
34+ it ( 'verifies schema sync with trodes_to_nwb (from GitHub )' , async ( ) => {
35+ // Fetch schema from GitHub main branch to verify synchronization
36+ // This works in any environment (local, CI, contributor machines)
3937
40- const trodesSchemaPath = path . join (
41- '/Users/edeno/Documents/GitHub/trodes_to_nwb' ,
42- 'src/trodes_to_nwb/nwb_schema.json'
43- ) ;
44-
45- if ( ! fs . existsSync ( trodesSchemaPath ) ) {
46- console . log ( '⚠️ trodes_to_nwb not found at expected location, skipping sync check' ) ;
47- return ;
48- }
38+ const TRODES_SCHEMA_URL = 'https://raw.githubusercontent.com/LorenFrankLab/trodes_to_nwb/main/src/trodes_to_nwb/nwb_schema.json' ;
4939
5040 try {
51- const trodesSchema = JSON . parse ( fs . readFileSync ( trodesSchemaPath , 'utf-8' ) ) ;
41+ const response = await fetch ( TRODES_SCHEMA_URL ) ;
42+
43+ if ( ! response . ok ) {
44+ console . warn ( `⚠️ Could not fetch trodes_to_nwb schema from GitHub (${ response . status } )` ) ;
45+ console . warn ( ' Skipping sync check' ) ;
46+ return ;
47+ }
48+
49+ const trodesSchema = await response . json ( ) ;
5250
5351 const webAppHash = crypto
5452 . createHash ( 'sha256' )
@@ -64,19 +62,19 @@ describe('BASELINE: Integration Contracts', () => {
6462 console . log ( `📊 trodes_to_nwb: ${ trodesHash . substring ( 0 , 16 ) } ...` ) ;
6563
6664 if ( webAppHash !== trodesHash ) {
67- console . warn ( '⚠️ SCHEMA MISMATCH DETECTED - This is a P0 bug!' ) ;
68- console . warn ( ' Schemas must be synchronized between repositories' ) ;
65+ console . error ( '❌ SCHEMA MISMATCH DETECTED - This is a P0 bug!' ) ;
66+ console . error ( ' Schemas must be synchronized between repositories' ) ;
67+ console . error ( ` Web app: ${ webAppHash } ` ) ;
68+ console . error ( ` trodes_to_nwb: ${ trodesHash } ` ) ;
69+ console . error ( ` Compare: https://github.com/LorenFrankLab/trodes_to_nwb/blob/main/src/trodes_to_nwb/nwb_schema.json` ) ;
6970 }
7071
71- // Document current sync state
72- expect ( {
73- inSync : webAppHash === trodesHash ,
74- webAppHash : webAppHash . substring ( 0 , 16 ) ,
75- trodesHash : trodesHash . substring ( 0 , 16 ) ,
76- } ) . toMatchSnapshot ( 'schema-sync-status' ) ;
72+ // Verify synchronization (fail test if mismatch)
73+ expect ( webAppHash ) . toBe ( trodesHash ) ;
7774 } catch ( error ) {
78- console . log ( `⚠️ Error reading trodes_to_nwb schema: ${ error . message } ` ) ;
79- // Don't fail test if we can't read the file
75+ console . warn ( `⚠️ Error fetching trodes_to_nwb schema: ${ error . message } ` ) ;
76+ console . warn ( ' Skipping sync check (network issue?)' ) ;
77+ // Don't fail test if network error - gracefully degrade
8078 }
8179 } ) ;
8280 } ) ;
@@ -103,25 +101,25 @@ describe('BASELINE: Integration Contracts', () => {
103101 } ) ;
104102 } ) ;
105103
106- it ( 'verifies device types exist in trodes_to_nwb (if available )' , ( ) => {
107- // This test checks that device types have corresponding probe metadata files
108- // Gracefully degrades if trodes_to_nwb repo is not available
104+ it ( 'verifies device types exist in trodes_to_nwb (from GitHub )' , async ( ) => {
105+ // Fetch probe metadata directory from GitHub to verify device types exist
106+ // This works in any environment (local, CI, contributor machines)
109107
110- const probeMetadataDir = path . join (
111- '/Users/edeno/Documents/GitHub/trodes_to_nwb' ,
112- 'src/trodes_to_nwb/device_metadata/probe_metadata'
113- ) ;
114-
115- if ( ! fs . existsSync ( probeMetadataDir ) ) {
116- console . log ( '⚠️ trodes_to_nwb probe_metadata not found, skipping device type check' ) ;
117- return ;
118- }
108+ const PROBE_METADATA_API_URL = 'https://api.github.com/repos/LorenFrankLab/trodes_to_nwb/contents/src/trodes_to_nwb/device_metadata/probe_metadata' ;
119109
120110 try {
121- const probeFiles = fs
122- . readdirSync ( probeMetadataDir )
123- . filter ( f => f . endsWith ( '.yml' ) )
124- . map ( f => f . replace ( '.yml' , '' ) )
111+ const response = await fetch ( PROBE_METADATA_API_URL ) ;
112+
113+ if ( ! response . ok ) {
114+ console . warn ( `⚠️ Could not fetch probe metadata from GitHub (${ response . status } )` ) ;
115+ console . warn ( ' Skipping device type check' ) ;
116+ return ;
117+ }
118+
119+ const files = await response . json ( ) ;
120+ const probeFiles = files
121+ . filter ( f => f . name . endsWith ( '.yml' ) )
122+ . map ( f => f . name . replace ( '.yml' , '' ) )
125123 . sort ( ) ;
126124
127125 const webAppTypes = deviceTypes ( ) . sort ( ) ;
@@ -136,23 +134,24 @@ describe('BASELINE: Integration Contracts', () => {
136134 missingFromWebApp . forEach ( probe => console . warn ( ` - ${ probe } ` ) ) ;
137135 }
138136
139- // Check which device types don't have probe files (more critical )
137+ // Check which device types don't have probe files (CRITICAL )
140138 const missingProbeFiles = webAppTypes . filter ( type => ! probeFiles . includes ( type ) ) ;
141139 if ( missingProbeFiles . length > 0 ) {
142- console . warn ( `⚠️ Device types in web app but NO probe file in trodes_to_nwb:` ) ;
143- missingProbeFiles . forEach ( type => console . warn ( ` - ${ type } ` ) ) ;
140+ console . error ( `❌ Device types in web app but NO probe file in trodes_to_nwb:` ) ;
141+ missingProbeFiles . forEach ( type => console . error ( ` - ${ type } ` ) ) ;
142+ console . error ( ` View probe files: https://github.com/LorenFrankLab/trodes_to_nwb/tree/main/src/trodes_to_nwb/device_metadata/probe_metadata` ) ;
143+ // Fail test - web app has device types without probe files (DATA LOSS RISK)
144+ throw new Error ( `Missing probe files for: ${ missingProbeFiles . join ( ', ' ) } ` ) ;
144145 }
145146
146- // Document current state
147- expect ( {
148- webAppCount : webAppTypes . length ,
149- trodesCount : probeFiles . length ,
150- missingFromWebApp,
151- missingProbeFiles,
152- } ) . toMatchSnapshot ( 'device-type-sync-status' ) ;
147+ console . log ( '✅ All web app device types have corresponding probe files' ) ;
153148 } catch ( error ) {
154- console . log ( `⚠️ Error checking probe metadata: ${ error . message } ` ) ;
155- // Don't fail test if we can't read the directory
149+ if ( error . message . includes ( 'Missing probe files' ) ) {
150+ throw error ; // Re-throw validation errors
151+ }
152+ console . warn ( `⚠️ Error fetching probe metadata: ${ error . message } ` ) ;
153+ console . warn ( ' Skipping device type check (network issue?)' ) ;
154+ // Don't fail test if network error - gracefully degrade
156155 }
157156 } ) ;
158157 } ) ;
0 commit comments