Skip to content

Commit b98a8fc

Browse files
committed
Refactor integration tests to fetch data from GitHub
Updated integration tests to fetch schema and probe metadata directly from the trodes_to_nwb GitHub repository, improving compatibility across environments and CI. Removed local file system dependencies and enhanced error handling for network issues. Increased Vitest test timeout to 15 seconds to accommodate slower CI environments. Updated snapshots to reflect new test logic.
1 parent 34f4fba commit b98a8fc

File tree

4 files changed

+53
-77
lines changed

4 files changed

+53
-77
lines changed

.github/workflows/test.yml

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,6 @@ jobs:
3131
- name: Run linter
3232
run: npm run lint
3333

34-
- name: Run unit tests
35-
run: npm test -- run unit
36-
37-
- name: Run integration tests
38-
run: npm run test:integration
39-
4034
- name: Run all tests with coverage
4135
run: npm run test:coverage -- run
4236

src/__tests__/integration/__snapshots__/schema-contracts.test.js.snap

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,25 +17,8 @@ exports[`BASELINE: Integration Contracts > Device Types Contract > documents all
1717
]
1818
`;
1919

20-
exports[`BASELINE: Integration Contracts > Device Types Contract > verifies device types exist in trodes_to_nwb (if available) > device-type-sync-status 1`] = `
21-
{
22-
"missingFromWebApp": [],
23-
"missingProbeFiles": [],
24-
"trodesCount": 12,
25-
"webAppCount": 12,
26-
}
27-
`;
28-
2920
exports[`BASELINE: Integration Contracts > Schema Hash > documents current schema version > schema-hash 1`] = `"a15136fd1086fde303e219350db6069e07225608dc8fda96e5be11db9dfe8e22"`;
3021

31-
exports[`BASELINE: Integration Contracts > Schema Hash > verifies schema sync with trodes_to_nwb (if available) > schema-sync-status 1`] = `
32-
{
33-
"inSync": true,
34-
"trodesHash": "a15136fd1086fde3",
35-
"webAppHash": "a15136fd1086fde3",
36-
}
37-
`;
38-
3922
exports[`BASELINE: Integration Contracts > YAML Generation Contract > documents YAML output format > schema-required-fields 1`] = `
4023
[
4124
"experimenter_name",

src/__tests__/integration/schema-contracts.test.js

Lines changed: 52 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@
1616

1717
import { describe, it, expect } from 'vitest';
1818
import crypto from 'crypto';
19-
import fs from 'fs';
20-
import path from 'path';
2119
import schema from '../../nwb_schema.json';
2220
import { 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
});

vitest.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export default defineConfig({
4141
},
4242
include: ['src/**/*.{test,spec}.{js,jsx}'],
4343
exclude: ['node_modules/', 'build/', 'dist/'],
44-
testTimeout: 10000,
44+
testTimeout: 15000, // Increased from 10000 for slower CI environments
4545
hookTimeout: 10000,
4646
},
4747
resolve: {

0 commit comments

Comments
 (0)