Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 14 additions & 6 deletions .github/scripts/ciScript.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,21 @@ module.exports = async ({ github, context, core }) => {
backendFiles.push(fileName);

const relative = fileName.replace('apps/backend/src/', '');
const baseName = relative
.split('/')
.pop()
?.replace(/\.(ts|tsx|js|jsx)$/, '');

if (baseName) {
backendTests.push(`src/__tests__/${baseName}.test.ts`);
if (relative.startsWith('__tests__/')) {
// Already a test file — use it directly. Without this guard the
// extension strip above turns logout.test.ts into logout.test and
// then appends .test.ts again, producing logout.test.test.ts.
backendTests.push(`src/${relative}`);
} else {
const baseName = relative
.split('/')
.pop()
?.replace(/\.(ts|tsx|js|jsx)$/, '');

if (baseName) {
backendTests.push(`src/__tests__/${baseName}.test.ts`);
}
}

} else if (fileName.startsWith('apps/mobile/')) {
Expand Down
11 changes: 6 additions & 5 deletions apps/backend/src/__tests__/analytics.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import Fastify, {
type FastifyInstance,
} from 'fastify';
import {
describe,
it,
Expand All @@ -7,13 +10,11 @@ import {
vi,
} from 'vitest';

import Fastify, {
type FastifyInstance,
} from 'fastify';

import { analyticsRoutes } from '../routes/analytics';

import type { PrismaClient } from '@prisma/client';

import { analyticsRoutes } from '../routes/analytics';

// ─── Shared mock data ────────────────────────────────────────────────────────

Expand All @@ -34,7 +35,7 @@ const prismaMock = {

// ─── App factory ─────────────────────────────────────────────────────────────

let mockJwtVerify = vi.fn();
const mockJwtVerify = vi.fn();

async function buildApp(): Promise<FastifyInstance> {
const app = Fastify({
Expand Down
9 changes: 7 additions & 2 deletions apps/backend/src/__tests__/app.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
process.env.NODE_ENV = 'test';

import { describe, it, expect } from 'vitest';

import { buildApp } from '../app';

process.env.NODE_ENV = 'test';
// validateEnv() runs inside buildApp() and exits if these are absent.
// Provide safe test-only fallbacks so CI doesn't need real secrets here.
process.env.JWT_SECRET ??= 'test-jwt-secret-not-for-production-xxxxxxxxxxxxxxxxxxxxxxx';
process.env.ENCRYPTION_KEY ??= 'a'.repeat(64);

describe('GET /health', () => {
it('should return status ok', async () => {
const app = await buildApp();
Expand Down
3 changes: 2 additions & 1 deletion apps/backend/src/__tests__/cards.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { describe, it, expect, beforeEach, vi } from 'vitest';
import Fastify from 'fastify';
import { describe, it, expect, beforeEach, vi } from 'vitest';

import { cardRoutes } from '../routes/cards.js';

const USER_ID = 'user-123';
Expand Down
8 changes: 5 additions & 3 deletions apps/backend/src/__tests__/event.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import Fastify, { type FastifyInstance } from 'fastify';
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
import Fastify, { FastifyInstance } from 'fastify';
import { PrismaClient } from '@prisma/client';

import { eventRoutes } from '../routes/event';

import type { PrismaClient } from '@prisma/client';

// ─── Shared mock data ────────────────────────────────────────────────────────

const MOCK_USER_ID = 'user-uuid-001';
Expand Down Expand Up @@ -64,7 +66,7 @@
//
// This mirrors the real app setup without touching a real DB or real JWT keys.

let mockJwtVerify = vi.fn();
const mockJwtVerify = vi.fn();

async function buildApp(): Promise<FastifyInstance> {
const app = Fastify({ logger: false });
Expand Down Expand Up @@ -138,7 +140,7 @@
prismaMock.event.findUnique.mockResolvedValue(null); // slug is free
prismaMock.event.create.mockResolvedValue(MOCK_EVENT);

const res = await createEvent(app, validBody);

Check failure on line 143 in apps/backend/src/__tests__/event.test.ts

View workflow job for this annotation

GitHub Actions / backend-ci

src/__tests__/event.test.ts > Events API > POST /api/events — create event > 201 — creates event and returns it for authenticated organizer

AssertionError: expected 500 to be 201 // Object.is equality - Expected + Received - 201 + 500 ❯ src/__tests__/event.test.ts:143:30

expect(res.statusCode).toBe(201);
const body = res.json();
Expand All @@ -163,34 +165,34 @@
expect(res.json()).toMatchObject({ error: 'Unauthorized' });
});

it('400 — rejects missing required fields (no dates, no location)', async () => {

Check failure on line 168 in apps/backend/src/__tests__/event.test.ts

View workflow job for this annotation

GitHub Actions / backend-ci

src/__tests__/event.test.ts > Events API > POST /api/events — create event > 400 — rejects missing required fields (no dates, no location)

AssertionError: expected 500 to be 400 // Object.is equality - Expected + Received - 400 + 500 ❯ src/__tests__/event.test.ts:168:30
const res = await createEvent(app, { name: 'Hello World' }); // missing dates + location
expect(res.statusCode).toBe(400);
});

it('400 — rejects missing location', async () => {
const { location: _omit, ...bodyWithoutLocation } = validBody;

Check failure on line 174 in apps/backend/src/__tests__/event.test.ts

View workflow job for this annotation

GitHub Actions / backend-ci

src/__tests__/event.test.ts > Events API > POST /api/events — create event > 400 — rejects missing location

AssertionError: expected 500 to be 400 // Object.is equality - Expected + Received - 400 + 500 ❯ src/__tests__/event.test.ts:174:30
const res = await createEvent(app, bodyWithoutLocation);
expect(res.statusCode).toBe(400);
});

it('400 — rejects location shorter than 2 characters', async () => {

Check failure on line 179 in apps/backend/src/__tests__/event.test.ts

View workflow job for this annotation

GitHub Actions / backend-ci

src/__tests__/event.test.ts > Events API > POST /api/events — create event > 400 — rejects location shorter than 2 characters

AssertionError: expected 500 to be 400 // Object.is equality - Expected + Received - 400 + 500 ❯ src/__tests__/event.test.ts:179:30
const res = await createEvent(app, { ...validBody, location: 'A' });
expect(res.statusCode).toBe(400);
});

it('400 — rejects location longer than 100 characters', async () => {

Check failure on line 184 in apps/backend/src/__tests__/event.test.ts

View workflow job for this annotation

GitHub Actions / backend-ci

src/__tests__/event.test.ts > Events API > POST /api/events — create event > 400 — rejects location longer than 100 characters

AssertionError: expected 500 to be 400 // Object.is equality - Expected + Received - 400 + 500 ❯ src/__tests__/event.test.ts:184:30
const res = await createEvent(app, { ...validBody, location: 'A'.repeat(101) });
expect(res.statusCode).toBe(400);
});

it('400 — rejects event name shorter than 3 characters', async () => {

Check failure on line 189 in apps/backend/src/__tests__/event.test.ts

View workflow job for this annotation

GitHub Actions / backend-ci

src/__tests__/event.test.ts > Events API > POST /api/events — create event > 400 — rejects event name shorter than 3 characters

AssertionError: expected 500 to be 400 // Object.is equality - Expected + Received - 400 + 500 ❯ src/__tests__/event.test.ts:189:30
const res = await createEvent(app, { ...validBody, name: 'Hi' });
expect(res.statusCode).toBe(400);
});

it('400 — rejects event name longer than 100 characters', async () => {
const longName = 'A'.repeat(101);

Check failure on line 195 in apps/backend/src/__tests__/event.test.ts

View workflow job for this annotation

GitHub Actions / backend-ci

src/__tests__/event.test.ts > Events API > POST /api/events — create event > 400 — rejects event name longer than 100 characters

AssertionError: expected 500 to be 400 // Object.is equality - Expected + Received - 400 + 500 ❯ src/__tests__/event.test.ts:195:30
const res = await createEvent(app, { ...validBody, name: longName });
expect(res.statusCode).toBe(400);
});
Expand All @@ -198,7 +200,7 @@
it('400 — rejects invalid date format', async () => {
const res = await createEvent(app, {
...validBody,
startDate: 'not-a-date',

Check failure on line 203 in apps/backend/src/__tests__/event.test.ts

View workflow job for this annotation

GitHub Actions / backend-ci

src/__tests__/event.test.ts > Events API > POST /api/events — create event > 400 — rejects invalid date format

AssertionError: expected 500 to be 400 // Object.is equality - Expected + Received - 400 + 500 ❯ src/__tests__/event.test.ts:203:30
});
expect(res.statusCode).toBe(400);
});
Expand All @@ -214,7 +216,7 @@
slug: 'devcard-conf-2025-ab12',
});

const res = await createEvent(app, validBody);

Check failure on line 219 in apps/backend/src/__tests__/event.test.ts

View workflow job for this annotation

GitHub Actions / backend-ci

src/__tests__/event.test.ts > Events API > POST /api/events — create event > 201 — generates a unique slug when the first candidate is taken

AssertionError: expected 500 to be 201 // Object.is equality - Expected + Received - 201 + 500 ❯ src/__tests__/event.test.ts:219:30

expect(res.statusCode).toBe(201);
// create was eventually called with a slug different from the base one
Expand Down
2 changes: 1 addition & 1 deletion apps/backend/src/__tests__/follow.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import Fastify, { FastifyInstance } from 'fastify';
import Fastify, { type FastifyInstance } from 'fastify';
import { describe, expect, it, vi, beforeAll, beforeEach, afterAll } from 'vitest';

import { followRoutes } from '../routes/follow.js';
Expand Down
Loading
Loading