1+ import Database from 'better-sqlite3'
2+ import { sql } from 'drizzle-orm'
3+ import { type BetterSQLite3Database , drizzle } from 'drizzle-orm/better-sqlite3'
4+ import { migrate } from 'drizzle-orm/better-sqlite3/migrator'
5+ import { afterEach , beforeEach } from 'vitest'
6+ import * as schema from '../drizzle/schema'
7+
8+ /**
9+ * Global test database instance
10+ * Each test gets a fresh in-memory database
11+ */
12+ export let testDb : BetterSQLite3Database < typeof schema >
13+ export let sqlite : any
14+
15+ /**
16+ * Create a fresh in-memory SQLite database with schema
17+ */
18+ export function createTestDatabase ( ) {
19+ // Create in-memory SQLite database
20+ sqlite = new Database ( ':memory:' )
21+ testDb = drizzle ( sqlite , { schema } )
22+
23+ // Create all tables from schema
24+ sqlite . exec ( `
25+ CREATE TABLE IF NOT EXISTS Users (
26+ UserID INTEGER PRIMARY KEY AUTOINCREMENT,
27+ Username TEXT NOT NULL UNIQUE,
28+ Name TEXT NOT NULL DEFAULT '',
29+ Email TEXT NOT NULL UNIQUE,
30+ ImageURL TEXT,
31+ Description TEXT,
32+ IsAdmin INTEGER NOT NULL DEFAULT 0,
33+ Intrestets TEXT NOT NULL DEFAULT '[]',
34+ CreatedAt TEXT DEFAULT CURRENT_TIMESTAMP
35+ );
36+
37+ CREATE TABLE IF NOT EXISTS Sessions (
38+ SessionID INTEGER PRIMARY KEY AUTOINCREMENT,
39+ UserID INTEGER NOT NULL REFERENCES Users(UserID),
40+ SessionToken TEXT NOT NULL UNIQUE,
41+ CreatedAt TEXT DEFAULT CURRENT_TIMESTAMP,
42+ ExpiresAt TEXT
43+ );
44+
45+ CREATE TABLE IF NOT EXISTS Events (
46+ EventID INTEGER PRIMARY KEY AUTOINCREMENT,
47+ Name TEXT NOT NULL,
48+ Description TEXT NOT NULL,
49+ Location TEXT NOT NULL,
50+ ImageURL TEXT,
51+ Coordinates TEXT NOT NULL,
52+ Date TEXT NOT NULL,
53+ StartTime TEXT NOT NULL,
54+ PlaceId INTEGER,
55+ EndTime TEXT NOT NULL,
56+ Tags TEXT NOT NULL,
57+ CreatedAt TEXT DEFAULT CURRENT_TIMESTAMP,
58+ UserID INTEGER NOT NULL REFERENCES Users(UserID)
59+ );
60+
61+ CREATE TABLE IF NOT EXISTS Requests (
62+ RequestID INTEGER PRIMARY KEY AUTOINCREMENT,
63+ EventID INTEGER NOT NULL REFERENCES Events(EventID),
64+ UserID INTEGER NOT NULL REFERENCES Users(UserID),
65+ Status TEXT NOT NULL DEFAULT 'pending',
66+ Background TEXT,
67+ Experience TEXT,
68+ WhyJoin TEXT,
69+ CreatedAt TEXT DEFAULT CURRENT_TIMESTAMP
70+ );
71+
72+ CREATE TABLE IF NOT EXISTS Places (
73+ PlaceID INTEGER PRIMARY KEY AUTOINCREMENT,
74+ Name TEXT NOT NULL,
75+ Address TEXT NOT NULL,
76+ ImageURL TEXT,
77+ Description TEXT NOT NULL,
78+ Tags TEXT,
79+ Rating INTEGER NOT NULL DEFAULT 0,
80+ WifiSpeed INTEGER,
81+ HasQuietEnvironment INTEGER,
82+ Price TEXT,
83+ Coordinates TEXT,
84+ Category TEXT,
85+ IsPublic INTEGER NOT NULL DEFAULT 1,
86+ CreatedAt TEXT DEFAULT CURRENT_TIMESTAMP,
87+ UserID INTEGER NOT NULL REFERENCES Users(UserID)
88+ );
89+ ` )
90+
91+ return testDb ;
92+ }
93+
94+ /**
95+ * Clean up database after test
96+ */
97+ export function cleanupTestDatabase ( ) {
98+ if ( sqlite ) {
99+ sqlite . close ( )
100+ }
101+ }
102+
103+ /**
104+ * Setup: Create fresh database before each test
105+ */
106+ beforeEach ( ( ) => {
107+ createTestDatabase ( )
108+ } )
109+
110+ /**
111+ * Teardown: Clean up database after each test
112+ */
113+ afterEach ( ( ) => {
114+ cleanupTestDatabase ( )
115+ } )
116+
117+ /**
118+ * Helper: Get current timestamp in SQLite format
119+ */
120+ export function getCurrentTimestamp ( ) : string {
121+ return new Date ( ) . toISOString ( )
122+ }
123+
124+ /**
125+ * Helper: Get future date (for events)
126+ */
127+ export function getFutureDate ( daysAhead = 7 ) : string {
128+ const date = new Date ( )
129+ date . setDate ( date . getDate ( ) + daysAhead )
130+ return date . toISOString ( ) . split ( 'T' ) [ 0 ]
131+ }
132+
133+ /**
134+ * Helper: Get past date (for testing validation)
135+ */
136+ export function getPastDate ( daysAgo = 7 ) : string {
137+ const date = new Date ( )
138+ date . setDate ( date . getDate ( ) - daysAgo )
139+ return date . toISOString ( ) . split ( 'T' ) [ 0 ]
140+ }
141+
142+ /**
143+ * Helper: Get future time
144+ */
145+ export function getFutureTime ( ) : string {
146+ return '18:00'
147+ }
148+
149+ /**
150+ * Helper: Clear all tables (useful for specific test setups)
151+ */
152+ export function clearAllTables ( ) {
153+ const statements = [
154+ 'DELETE FROM Requests' ,
155+ 'DELETE FROM Events' ,
156+ 'DELETE FROM Sessions' ,
157+ 'DELETE FROM Places' ,
158+ 'DELETE FROM Users'
159+ ] ;
160+
161+ statements . forEach ( sql => sqlite . exec ( sql + ';' ) ) ;
162+ }
0 commit comments