// vite.config.ts import path from 'path'; // import fs from 'fs'; // Unused when nginx handles SSL import { defineConfig } from 'vitest/config'; import react from '@vitejs/plugin-react'; import { sentryVitePlugin } from '@sentry/vite-plugin'; // HTTPS configuration for local development (optional, disabled when using nginx proxy) // const httpsConfig = (() => { // const keyPath = '/app/certs/localhost.key'; // const certPath = '/app/certs/localhost.crt'; // if (fs.existsSync(keyPath) && fs.existsSync(certPath)) { // return { // key: fs.readFileSync(keyPath), // cert: fs.readFileSync(certPath), // }; // } // return undefined; // })(); // Ensure NODE_ENV is set to 'test' for all Vitest runs. process.env.NODE_ENV = 'test'; process.on('unhandledRejection', (reason, promise) => { console.error('Unhandled Rejection at:', promise, 'reason:', reason); }); /** * Determines if we should enable Sentry source map uploads. * Only enabled during production builds with the required environment variables. */ const shouldUploadSourceMaps = process.env.VITE_SENTRY_DSN && process.env.SENTRY_AUTH_TOKEN && process.env.NODE_ENV !== 'test'; /** * This is the main configuration file for Vite and the Vitest 'unit' test project. * When running `vitest`, it is orchestrated by `vitest.workspace.ts`, which * separates the unit and integration test environments. */ export default defineConfig({ // Vite-specific configuration for the dev server, build, etc. // This is inherited by all Vitest projects. build: { // Generate source maps for production builds (hidden = not referenced in built files) // The Sentry plugin will upload them and then delete them sourcemap: shouldUploadSourceMaps ? 'hidden' : false, }, plugins: [ react(), // Conditionally add Sentry plugin for production builds with source map upload ...(shouldUploadSourceMaps ? [ sentryVitePlugin({ // URL of the Bugsink instance (Sentry-compatible) url: process.env.SENTRY_URL, // Org and project are required by the API but Bugsink ignores them org: 'flyer-crawler', project: 'flyer-crawler-frontend', // Auth token from environment variable authToken: process.env.SENTRY_AUTH_TOKEN, sourcemaps: { // Delete source maps after upload to prevent public exposure filesToDeleteAfterUpload: ['./dist/**/*.map'], }, // Disable telemetry to Sentry telemetry: false, }), ] : []), ], server: { port: 5173, // Internal port, nginx proxies on 3000 host: '0.0.0.0', // https: httpsConfig, // Disabled - nginx handles SSL }, resolve: { alias: { // Use __dirname for a more robust path resolution '@': path.resolve(__dirname, './src'), // This alias ensures that any import of 'services/logger' is resolved // to the browser-safe client version during the Vite build process. // Server-side code should explicitly import 'services/logger.server'. 'services/logger': path.resolve(__dirname, './src/services/logger.client.ts'), // Alias zxing-wasm/reader to a mock to prevent Vite import analysis errors // The actual module uses WebAssembly which doesn't work in jsdom 'zxing-wasm/reader': path.resolve(__dirname, './src/tests/mocks/zxing-wasm-reader.mock.ts'), }, }, // Vitest-specific configuration for the 'unit' test project. test: { // Name this project 'unit' to distinguish it in the workspace. name: 'unit', // By default, Vitest does not suppress console logs. // The onConsoleLog hook is only needed if you want to conditionally filter specific logs. // Keeping the default behavior is often safer to avoid missing important warnings. environment: 'jsdom', // Configure dependencies handling for test environment deps: { // Inline the zxing-wasm module to prevent import resolution errors // The module uses dynamic imports and WASM which don't work in jsdom optimizer: { web: { exclude: ['zxing-wasm'], }, }, }, // Configure server dependencies server: { deps: { // Tell Vitest to not try to resolve these external modules external: ['zxing-wasm', 'zxing-wasm/reader'], }, }, globals: true, // tsconfig is auto-detected, so the explicit property is not needed and causes an error. globalSetup: './src/tests/setup/global-setup.ts', // The globalApiMock MUST come first to ensure it's applied before other mocks that might depend on it. setupFiles: [ './src/tests/setup/global.ts', './src/tests/setup/globalApiMock.ts', './src/tests/setup/tests-setup-unit.ts', ], // Explicitly include only test files. // We remove 'src/vite-env.d.ts' which was causing it to be run as a test. include: ['src/**/*.test.{ts,tsx}'], // Exclude integration tests and other non-test files from the unit test runner. exclude: [ '**/node_modules/**', '**/dist/**', 'src/tests/integration/**', // Exclude the entire integration test directory '**/*.e2e.test.ts', ], // Disable file parallelism to run tests sequentially (replaces --no-threads) fileParallelism: false, coverage: { provider: 'v8', reporter: [ // Add maxCols to suggest a wider output for the text summary. ['text', { maxCols: 200 }], 'html', 'json', ], // hanging-process reporter helps identify tests that do not exit properly - comes at a high cost tho //reporter: ['verbose', 'html', 'json', 'hanging-process'], reportsDirectory: './.coverage/unit', clean: true, reportOnFailure: true, // This ensures the report generates even if tests fail include: ['src/**/*.{ts,tsx}'], // Refine exclusions to be more comprehensive // By excluding scripts, setup files, and type definitions, we get a more accurate // picture of the test coverage for the actual application logic. exclude: [ 'src/index.tsx', // Application entry point 'src/main.tsx', // A common alternative entry point name 'src/types.ts', 'src/tests/**', // Exclude all test setup and helper files 'src/vitest.setup.ts', // Global test setup config 'src/**/*.test.{ts,tsx}', // Exclude test files themselves 'src/**/*.stories.{ts,tsx}', // Exclude Storybook stories 'src/**/*.d.ts', // Exclude type definition files 'src/components/icons/**', // Exclude icon components if they are simple wrappers 'src/db/seed.ts', // Database seeding script 'src/db/seed_admin_account.ts', // Database seeding script 'src/db/backup_user.ts', // Database backup script ], }, }, });