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
12 changes: 7 additions & 5 deletions packages/backend/src/__tests__/climb-queries.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import type { ParsedBoardRouteParameters, ClimbSearchParams } from '../db/querie
import { getSizeEdges } from '../db/queries/util/product-sizes-data.js';

describe('Climb Query Functions', () => {
// Use valid size_id for kilter (7 = 12x14 Commercial)
// See packages/backend/src/db/queries/util/product-sizes-data.ts for valid IDs
const testParams: ParsedBoardRouteParameters = {
board_name: 'kilter',
layout_id: 1,
size_id: 1,
size_id: 7,
set_ids: [1, 2],
angle: 40,
};
Expand Down Expand Up @@ -231,7 +233,7 @@ describe('Climb Query Functions', () => {
const result = await getClimbByUuid({
board_name: 'kilter',
layout_id: 1,
size_id: 1,
size_id: 7, // Valid kilter size_id
angle: 40,
climb_uuid: 'non-existent-uuid-12345',
});
Expand All @@ -240,16 +242,16 @@ describe('Climb Query Functions', () => {
});

it('should handle different board names', async () => {
// Test with kilter
// Test with kilter (size_id 7 = 12x14 Commercial)
const kilterResult = await getClimbByUuid({
board_name: 'kilter',
layout_id: 1,
size_id: 1,
size_id: 7,
angle: 40,
climb_uuid: 'test-uuid',
});

// Test with tension
// Test with tension (size_id 1 = Full Wall)
const tensionResult = await getClimbByUuid({
board_name: 'tension',
layout_id: 1,
Expand Down
113 changes: 104 additions & 9 deletions packages/backend/src/__tests__/setup.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { beforeAll, beforeEach, afterAll } from 'vitest';
import { drizzle } from 'drizzle-orm/postgres-js';
import postgres from 'postgres';
import { sql } from 'drizzle-orm';
import * as schema from '../db/schema.js';
import { db as sharedDb } from '../db/client.js';
import { roomManager } from '../services/room-manager.js';

const TEST_DB_NAME = 'boardsesh_backend_test';
Expand All @@ -13,7 +12,6 @@ const connectionString =
const baseConnectionString = connectionString.replace(/\/[^/]+$/, '/postgres');

let migrationClient: ReturnType<typeof postgres>;
let db: ReturnType<typeof drizzle>;

// SQL to create only the tables needed for backend tests
const createTablesSQL = `
Expand All @@ -22,6 +20,12 @@ const createTablesSQL = `
DROP TABLE IF EXISTS "board_session_clients" CASCADE;
DROP TABLE IF EXISTS "board_sessions" CASCADE;
DROP TABLE IF EXISTS "users" CASCADE;
DROP TABLE IF EXISTS "kilter_climbs" CASCADE;
DROP TABLE IF EXISTS "kilter_climb_stats" CASCADE;
DROP TABLE IF EXISTS "kilter_difficulty_grades" CASCADE;
DROP TABLE IF EXISTS "tension_climbs" CASCADE;
DROP TABLE IF EXISTS "tension_climb_stats" CASCADE;
DROP TABLE IF EXISTS "tension_difficulty_grades" CASCADE;

-- Create users table (minimal, needed for FK reference)
CREATE TABLE IF NOT EXISTS "users" (
Expand Down Expand Up @@ -68,7 +72,89 @@ const createTablesSQL = `
"updated_at" timestamp DEFAULT now() NOT NULL
);

-- Create indexes
-- Create kilter tables for climb query tests
CREATE TABLE IF NOT EXISTS "kilter_climbs" (
"uuid" text PRIMARY KEY NOT NULL,
"layout_id" integer,
"setter_id" integer,
"setter_username" text,
"name" text,
"description" text,
"hsm" integer,
"edge_left" integer,
"edge_right" integer,
"edge_bottom" integer,
"edge_top" integer,
"frames_count" integer DEFAULT 1,
"frames_pace" integer,
"frames" text,
"is_draft" boolean DEFAULT false,
"is_listed" boolean DEFAULT true,
"created_at" text
);

CREATE TABLE IF NOT EXISTS "kilter_climb_stats" (
"climb_uuid" text NOT NULL,
"angle" integer NOT NULL,
"display_difficulty" double precision,
"benchmark_difficulty" double precision,
"ascensionist_count" bigint,
"difficulty_average" double precision,
"quality_average" double precision,
"fa_username" text,
"fa_at" timestamp,
PRIMARY KEY ("climb_uuid", "angle")
);

CREATE TABLE IF NOT EXISTS "kilter_difficulty_grades" (
"difficulty" integer PRIMARY KEY NOT NULL,
"boulder_name" text,
"route_name" text,
"is_listed" boolean DEFAULT true
);

-- Create tension tables for climb query tests
CREATE TABLE IF NOT EXISTS "tension_climbs" (
"uuid" text PRIMARY KEY NOT NULL,
"layout_id" integer,
"setter_id" integer,
"setter_username" text,
"name" text,
"description" text,
"hsm" integer,
"edge_left" integer,
"edge_right" integer,
"edge_bottom" integer,
"edge_top" integer,
"frames_count" integer DEFAULT 1,
"frames_pace" integer,
"frames" text,
"is_draft" boolean DEFAULT false,
"is_listed" boolean DEFAULT true,
"created_at" text
);

CREATE TABLE IF NOT EXISTS "tension_climb_stats" (
"climb_uuid" text NOT NULL,
"angle" integer NOT NULL,
"display_difficulty" double precision,
"benchmark_difficulty" double precision,
"ascensionist_count" bigint,
"difficulty_average" double precision,
"quality_average" double precision,
"fa_username" text,
"fa_at" timestamp,
PRIMARY KEY ("climb_uuid", "angle")
);

CREATE TABLE IF NOT EXISTS "tension_difficulty_grades" (
"difficulty" integer PRIMARY KEY NOT NULL,
"boulder_name" text,
"route_name" text,
"is_listed" boolean DEFAULT true
);

-- Create indexes for board_sessions
CREATE INDEX IF NOT EXISTS "board_sessions_location_idx" ON "board_sessions" ("latitude", "longitude");
CREATE INDEX IF NOT EXISTS "board_sessions_discoverable_idx" ON "board_sessions" ("discoverable");
CREATE INDEX IF NOT EXISTS "board_sessions_user_idx" ON "board_sessions" ("created_by_user_id");
Expand Down Expand Up @@ -100,9 +186,8 @@ beforeAll(async () => {
await adminClient.end();
}

// Now connect to the test database
// Now connect to the test database for schema creation
migrationClient = postgres(connectionString, { max: 1, onnotice: () => {} });
db = drizzle(migrationClient, { schema });

// Create tables directly (backend tests only need session tables)
await migrationClient.unsafe(createTablesSQL);
Expand All @@ -113,9 +198,19 @@ beforeEach(async () => {
roomManager.reset();

// Clear all tables in correct order (respect foreign keys)
await db.execute(sql`TRUNCATE TABLE board_session_queues CASCADE`);
await db.execute(sql`TRUNCATE TABLE board_session_clients CASCADE`);
await db.execute(sql`TRUNCATE TABLE board_sessions CASCADE`);
// Use sharedDb (same instance as roomManager) to ensure consistency
await sharedDb.execute(sql`TRUNCATE TABLE board_session_queues CASCADE`);
await sharedDb.execute(sql`TRUNCATE TABLE board_session_clients CASCADE`);
await sharedDb.execute(sql`TRUNCATE TABLE board_sessions CASCADE`);
await sharedDb.execute(sql`TRUNCATE TABLE users CASCADE`);

// Create test users that are referenced by tests
// The session-persistence tests use 'user-123' for discoverable sessions
await sharedDb.execute(sql`
INSERT INTO users (id, email, name)
VALUES ('user-123', 'test@example.com', 'Test User')
ON CONFLICT (id) DO NOTHING
`);
});

afterAll(async () => {
Expand Down
Loading