···
-
import { Database } from "bun:sqlite";
import { afterEach, beforeEach, expect, test } from "bun:test";
-
import { unlinkSync } from "node:fs";
-
const TEST_DB = "test-classes.db";
-
db = new Database(TEST_DB);
-
// Create minimal schema for testing
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
-
email TEXT UNIQUE NOT NULL,
-
role TEXT NOT NULL DEFAULT 'user',
-
created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now'))
-
course_code TEXT NOT NULL,
-
professor TEXT NOT NULL,
-
semester TEXT NOT NULL,
-
archived BOOLEAN DEFAULT 0,
-
created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now'))
-
CREATE TABLE class_members (
-
class_id TEXT NOT NULL,
-
user_id INTEGER NOT NULL,
-
enrolled_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
-
PRIMARY KEY (class_id, user_id),
-
FOREIGN KEY (class_id) REFERENCES classes(id) ON DELETE CASCADE,
-
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
-
CREATE TABLE meeting_times (
-
class_id TEXT NOT NULL,
-
created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
-
FOREIGN KEY (class_id) REFERENCES classes(id) ON DELETE CASCADE
-
CREATE TABLE transcriptions (
-
user_id INTEGER NOT NULL,
-
filename TEXT NOT NULL,
-
original_filename TEXT NOT NULL,
-
status TEXT NOT NULL DEFAULT 'pending',
-
progress INTEGER NOT NULL DEFAULT 0,
-
created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
-
updated_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
-
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
-
FOREIGN KEY (class_id) REFERENCES classes(id) ON DELETE CASCADE,
-
FOREIGN KEY (meeting_time_id) REFERENCES meeting_times(id) ON DELETE SET NULL
test("creates a class with all required fields", () => {
-
const cls = createClass({
···
test("enrolls user in class", () => {
-
db.run("INSERT INTO users (email, password_hash) VALUES (?, ?)", [
-
.query<{ id: number }, []>("SELECT last_insert_rowid() as id")
-
if (!userId) throw new Error("Failed to create user");
-
const cls = createClass({
···
const isEnrolled = isUserEnrolledInClass(userId, cls.id);
expect(isEnrolled).toBe(true);
test("gets classes for enrolled user", () => {
-
db.run("INSERT INTO users (email, password_hash) VALUES (?, ?)", [
-
.query<{ id: number }, []>("SELECT last_insert_rowid() as id")
-
if (!userId) throw new Error("Failed to create user");
-
const cls1 = createClass({
···
-
const _cls2 = createClass({
···
// Enroll user in only one class
enrollUserInClass(userId, cls1.id);
-
// Get classes for user
const classes = getClassesForUser(userId, false);
expect(classes.length).toBe(1);
expect(classes[0]?.id).toBe(cls1.id);
-
// Admin should see all
const allClasses = getClassesForUser(userId, true);
-
expect(allClasses.length).toBe(2);
test("creates and retrieves meeting times", () => {
-
const cls = createClass({
···
-
const _meeting1 = createMeetingTime(cls.id, "Monday Lecture");
-
const _meeting2 = createMeetingTime(cls.id, "Wednesday Lab");
const meetings = getMeetingTimesForClass(cls.id);
expect(meetings.length).toBe(2);
···
import { afterEach, beforeEach, expect, test } from "bun:test";
+
import db from "../db/schema";
+
// Track created resources for cleanup
+
let createdUserIds: number[] = [];
+
let createdClassIds: string[] = [];
+
// Clean up classes (cascades to members and meeting times)
+
for (const classId of createdClassIds) {
+
// May already be deleted
+
for (const userId of createdUserIds) {
+
db.run("DELETE FROM users WHERE id = ?", [userId]);
+
// May already be deleted
+
function createTestUser(email: string): number {
+
db.run("INSERT INTO users (email, password_hash) VALUES (?, ?)", [
+
.query<{ id: number }, []>("SELECT last_insert_rowid() as id")
+
if (!userId) throw new Error("Failed to create user");
+
createdUserIds.push(userId);
+
function createTestClass(data: {
+
const cls = createClass(data);
+
createdClassIds.push(cls.id);
test("creates a class with all required fields", () => {
+
const cls = createTestClass({
···
test("enrolls user in class", () => {
+
const userId = createTestUser("test@example.com");
+
const cls = createTestClass({
···
const isEnrolled = isUserEnrolledInClass(userId, cls.id);
expect(isEnrolled).toBe(true);
+
removeUserFromClass(userId, cls.id);
test("gets classes for enrolled user", () => {
+
const userId = createTestUser("test@example.com");
+
const cls1 = createTestClass({
···
+
const cls2 = createTestClass({
···
// Enroll user in only one class
enrollUserInClass(userId, cls1.id);
+
// Get classes for user (non-admin)
const classes = getClassesForUser(userId, false);
expect(classes.length).toBe(1);
expect(classes[0]?.id).toBe(cls1.id);
+
// Admin should see all classes (not just the 2 test classes, but all in DB)
const allClasses = getClassesForUser(userId, true);
+
expect(allClasses.length).toBeGreaterThanOrEqual(2);
+
expect(allClasses.some((c) => c.id === cls1.id)).toBe(true);
+
expect(allClasses.some((c) => c.id === cls2.id)).toBe(true);
+
removeUserFromClass(userId, cls1.id);
test("creates and retrieves meeting times", () => {
+
const cls = createTestClass({
···
+
createMeetingTime(cls.id, "Monday Lecture");
+
createMeetingTime(cls.id, "Wednesday Lab");
const meetings = getMeetingTimesForClass(cls.id);
expect(meetings.length).toBe(2);