| 1 | import { vi } from 'vitest'
|
| 2 |
|
| 3 | // The database project truncates and repopulates a real database on every run.
|
| 4 | // The container's ambient DATABASE_URL points at orbit_dev, so a vitest
|
| 5 | // invocation that skips the npm scripts' dotenv wrapper would silently wipe the
|
| 6 | // development database. Only a database named like the test one is safe to run
|
| 7 | // against, so anything not ending in `_test` is refused.
|
| 8 | const TEST_DATABASE_SUFFIX = '_test'
|
| 9 |
|
| 10 | const databaseNameOf = (url: string | undefined): string => {
|
| 11 | if (!url) return '(unset)'
|
| 12 |
|
| 13 | try {
|
| 14 | return new URL(url).pathname.replace(/^\//, '') || '(none)'
|
| 15 | } catch {
|
| 16 | return '(unparseable)'
|
| 17 | }
|
| 18 | }
|
| 19 |
|
| 20 | const database = databaseNameOf(process.env.DATABASE_URL)
|
| 21 |
|
| 22 | if (!database.endsWith(TEST_DATABASE_SUFFIX)) {
|
| 23 | throw new Error(
|
| 24 | `Refusing to run against "${database}": the database project only runs ` +
|
| 25 | `against a database ending in "${TEST_DATABASE_SUFFIX}" (e.g. ` +
|
| 26 | 'orbit_test). Use `npm test` or `npm run test:coverage`, which load ' +
|
| 27 | '.env.test.',
|
| 28 | )
|
| 29 | }
|
| 30 |
|
| 31 | // Mock the barrel export used by controllers and most services. `getQueue`
|
| 32 | // returns a stable per-name mock so specs can assert on scheduled jobs via
|
| 33 | // `recordedJobs` from ./mocks/queue
|
| 34 | vi.mock('@app/lib/queue', async () => {
|
| 35 | const { getQueueMock } = await import('./mocks/queue')
|
| 36 |
|
| 37 | return {
|
| 38 | bootWorkers: vi.fn(),
|
| 39 | closeAllWorkers: vi.fn(),
|
| 40 | closeAllQueues: vi.fn(),
|
| 41 | scheduleInsights: vi.fn(),
|
| 42 | getQueue: (name: string) => getQueueMock(name),
|
| 43 | MailJobName: {
|
| 44 | WelcomeEmail: 'mail:welcome',
|
| 45 | PasswordReset: 'mail:password-reset',
|
| 46 | ActivateAccountEmail: 'mail:activate-account',
|
| 47 | },
|
| 48 | }
|
| 49 | })
|
| 50 |
|
| 51 | // syncMedicineReminderJobs imports getQueue directly from QueueRegistry
|
| 52 | vi.mock('@app/lib/queue/QueueRegistry', async () => {
|
| 53 | const { getQueueMock } = await import('./mocks/queue')
|
| 54 |
|
| 55 | return {
|
| 56 | getQueue: (name: string) => getQueueMock(name),
|
| 57 | closeAllQueues: vi.fn(),
|
| 58 | }
|
| 59 | })
|
| 60 |
|
| 61 | // avatar.ts constructs multer-s3 at import time and requires S3_BUCKET env var.
|
| 62 | // The replacement is a no-op middleware unless a spec stages a file through
|
| 63 | // setUploadedFile (see ./mocks/avatar)
|
| 64 | vi.mock('@app/services/avatar', async () => {
|
| 65 | const { avatarMulterMock } = await import('./mocks/avatar')
|
| 66 |
|
| 67 | return { default: avatarMulterMock }
|
| 68 | })
|
| 69 |
|
| 70 | // The avatar controller deletes the previous object through the S3 client
|
| 71 | vi.mock('@app/lib/s3', () => ({
|
| 72 | default: { send: vi.fn().mockResolvedValue({}) },
|
| 73 | }))
|