diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 32efdbe..4094dc9 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -8,6 +8,7 @@ on: jobs: test: runs-on: ubuntu-latest + timeout-minutes: 10 # Add a 10-minute timeout to prevent hanging steps: - uses: actions/checkout@v4 diff --git a/package.json b/package.json index 8bb65f3..bff0a0a 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "test:ui": "vitest --ui", "test:run": "vitest run", "test:coverage": "vitest run --coverage", - "test:ci": "vitest run --coverage --coverage.thresholds.lines=0 --coverage.thresholds.functions=0 --coverage.thresholds.branches=0 --coverage.thresholds.statements=0", + "test:ci": "vitest run --coverage --coverage.thresholds.lines=0 --coverage.thresholds.functions=0 --coverage.thresholds.branches=0 --coverage.thresholds.statements=0 --reporter=default --reporter=junit", "test:watch": "vitest watch", "test:unit": "vitest run tests/unit", "test:integration": "vitest run tests/integration", diff --git a/scripts/test-ci-no-coverage.sh b/scripts/test-ci-no-coverage.sh new file mode 100755 index 0000000..de47c54 --- /dev/null +++ b/scripts/test-ci-no-coverage.sh @@ -0,0 +1,7 @@ +#!/bin/bash +# Emergency script to run tests without coverage in CI if hanging persists + +echo "Running tests without coverage to diagnose hanging issue..." +FEATURE_TEST_COVERAGE=false vitest run --reporter=default --reporter=junit + +echo "Tests completed. If this works but regular test:ci hangs, the issue is coverage-related." \ No newline at end of file diff --git a/tests/setup/msw-setup.ts b/tests/setup/msw-setup.ts index 4e20c3e..90cb9bf 100644 --- a/tests/setup/msw-setup.ts +++ b/tests/setup/msw-setup.ts @@ -60,14 +60,26 @@ export function useHandlers(...handlers: RequestHandler[]) { * Utility to wait for a specific request to be made * Useful for testing async operations */ -export function waitForRequest(method: string, url: string | RegExp): Promise { - return new Promise((resolve) => { - server.events.on('request:match', ({ request }) => { +export function waitForRequest(method: string, url: string | RegExp, timeout = 5000): Promise { + return new Promise((resolve, reject) => { + let timeoutId: NodeJS.Timeout; + + const handler = ({ request }: { request: Request }) => { if (request.method === method && (typeof url === 'string' ? request.url === url : url.test(request.url))) { + clearTimeout(timeoutId); + server.events.removeListener('request:match', handler); resolve(request); } - }); + }; + + // Set timeout + timeoutId = setTimeout(() => { + server.events.removeListener('request:match', handler); + reject(new Error(`Timeout waiting for ${method} request to ${url}`)); + }, timeout); + + server.events.on('request:match', handler); }); } diff --git a/vitest.config.ts b/vitest.config.ts index 362bc6a..4e45cc6 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -21,17 +21,15 @@ export default defineConfig({ }, // Retry configuration retry: parseInt(process.env.TEST_RETRY_ATTEMPTS || '2', 10), - // Test reporter - reporters: process.env.CI ? ['default', 'json', 'junit', 'html'] : ['default'], + // Test reporter - reduce reporters in CI to prevent hanging + reporters: process.env.CI ? ['default', 'junit'] : ['default'], outputFile: { - json: './test-results/results.json', - junit: './test-results/junit.xml', - html: './test-results/html/index.html' + junit: './test-results/junit.xml' }, coverage: { provider: 'v8', enabled: process.env.FEATURE_TEST_COVERAGE !== 'false', - reporter: (process.env.COVERAGE_REPORTER || 'lcov,html,text-summary').split(','), + reporter: process.env.CI ? ['lcov', 'text-summary'] : (process.env.COVERAGE_REPORTER || 'lcov,html,text-summary').split(','), reportsDirectory: process.env.COVERAGE_DIR || './coverage', exclude: [ 'node_modules/', @@ -50,10 +48,16 @@ export default defineConfig({ functions: 80, branches: 75, statements: 80 - } + }, + // Add coverage-specific settings to prevent hanging + all: false, // Don't collect coverage for untested files + skipFull: true // Skip files with 100% coverage }, // Test isolation - isolate: true + isolate: true, + // Force exit after tests complete in CI to prevent hanging + forceRerunTriggers: ['**/tests/**/*.ts'], + teardownTimeout: 1000 }, resolve: { alias: {