Skip to content

Commit

Permalink
chore: add vitest tests
Browse files Browse the repository at this point in the history
  • Loading branch information
sean-beard committed Feb 10, 2024
1 parent 5694eb5 commit abae606
Show file tree
Hide file tree
Showing 12 changed files with 1,220 additions and 183 deletions.
3 changes: 3 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,7 @@ ENTRYPOINT [ "/app/docker-entrypoint.js" ]
# Start the server by default, this can be overwritten at runtime
EXPOSE 3000
ENV DATABASE_URL="file:///data/ping_me_db.db"

RUN yarn astro preferences disable devToolbar

CMD [ "yarn", "run", "start" ]
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@
"seed": "npx ts-node --esm ./seed.ts",
"lint": "eslint --ext .ts,.tsx,.astro .",
"lint:fix": "yarn lint --fix",
"test": "vitest",
"typecheck": "tsc --noEmit"
},
"dependencies": {
"@astrojs/node": "^7.0.4",
"@fontsource/pacifico": "^5.0.8",
"@prisma/client": "4.16.2",
"@toast-ui/editor": "^3.2.2",
"astro": "^4.1.1",
"astro": "^4.1.2",
"astro-htmx": "^1.0.5",
"bcryptjs": "^2.4.3",
"cron-parser": "^4.9.0",
Expand All @@ -44,6 +45,7 @@
"eslint-plugin-prettier": "^5.0.0",
"prettier": "^3.0.0",
"prettier-plugin-astro": "^0.11.1",
"prisma": "^4.16.2"
"prisma": "^4.16.2",
"vitest": "^1.1.3"
}
}
1 change: 1 addition & 0 deletions src/env.d.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
/// <reference path="../.astro/types.d.ts" />
/// <reference types="astro/client" />
248 changes: 248 additions & 0 deletions src/repositories/PrismaReminderRepository.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,248 @@
import { describe, expect, it, vi } from "vitest";
import { PrismaReminderRepository } from "./PrismaReminderRepository";
import type { PrismaClient } from "@prisma/client";

describe(PrismaReminderRepository.name, () => {
const mockUserId = 1;
const mockFolderId = 2;
const mockSchedule = "* * * * *";
const mockReminderId = 10;

describe("getReminder", () => {
it("should get a reminder", async () => {
const client = {
$queryRawUnsafe: vi.fn().mockResolvedValue([
{
dueDate: new Date(),
schedule: mockSchedule,
},
]),
} as unknown as PrismaClient;

const reminderRepository = new PrismaReminderRepository(client);

const reminder = await reminderRepository.getReminder(
mockFolderId,
mockUserId,
);

expect(reminder).toEqual({
schedule: mockSchedule,
dueDate: expect.any(Date),
});
});

it("should return null if reminder is not found", async () => {
const client = {
$queryRawUnsafe: vi.fn().mockResolvedValue([]),
} as unknown as PrismaClient;

const reminderRepository = new PrismaReminderRepository(client);

const reminder = await reminderRepository.getReminder(
mockFolderId,
mockUserId,
);

expect(reminder).toBeNull();
});

it("should handle errors", async () => {
const consoleErrorSpy = vi.spyOn(console, "error");

const client = {
$queryRawUnsafe: vi.fn().mockRejectedValue(new Error("error")),
} as unknown as PrismaClient;

const reminderRepository = new PrismaReminderRepository(client);

const reminder = await reminderRepository.getReminder(
mockFolderId,
mockUserId,
);

expect(reminder).toBeNull();
expect(consoleErrorSpy).toBeCalledWith({
message: `Error getting reminder`,
userId: mockUserId,
folderId: mockFolderId,
error: new Error("error"),
});
});
});

describe("upsertReminder", () => {
const mockDueDate = new Date();

it("should upsert a reminder", async () => {
const client = {
$executeRawUnsafe: vi.fn().mockResolvedValue([]),
} as unknown as PrismaClient;

const reminderRepository = new PrismaReminderRepository(client);

const result = await reminderRepository.upsertReminder({
userId: mockUserId,
folderId: mockFolderId,
schedule: mockSchedule,
dueDate: mockDueDate,
});

expect(result).toBe(true);
});

it("should handle errors", async () => {
const consoleErrorSpy = vi.spyOn(console, "error");

const client = {
$executeRawUnsafe: vi.fn().mockRejectedValue(new Error("error")),
} as unknown as PrismaClient;

const reminderRepository = new PrismaReminderRepository(client);

const result = await reminderRepository.upsertReminder({
userId: mockUserId,
folderId: mockFolderId,
schedule: mockSchedule,
dueDate: mockDueDate,
});

expect(result).toBeNull();
expect(consoleErrorSpy).toBeCalledWith({
message: `Error upserting reminder`,
userId: mockUserId,
folderId: mockFolderId,
schedule: mockSchedule,
dueDate: mockDueDate,
error: new Error("error"),
});
});
});

describe("updateReminderDueDate", () => {
const mockDueDate = new Date();

it("should update a reminder due date", async () => {
const client = {
$executeRawUnsafe: vi.fn().mockResolvedValue([]),
} as unknown as PrismaClient;

const reminderRepository = new PrismaReminderRepository(client);

const result = await reminderRepository.updateReminderDueDate(
mockReminderId,
mockDueDate,
);

expect(result).toBe(true);
});

it("should handle errors", async () => {
const consoleErrorSpy = vi.spyOn(console, "error");

const client = {
$executeRawUnsafe: vi.fn().mockRejectedValue(new Error("error")),
} as unknown as PrismaClient;

const reminderRepository = new PrismaReminderRepository(client);

const result = await reminderRepository.updateReminderDueDate(
mockReminderId,
mockDueDate,
);

expect(result).toBeNull();
expect(consoleErrorSpy).toBeCalledWith({
message: `Error updating reminder due date`,
reminderId: mockReminderId,
dueDate: mockDueDate,
error: new Error("error"),
});
});
});

describe("markReminderAsCompleted", () => {
it("should mark a reminder as completed", async () => {
const client = {
reminder: {
update: vi.fn().mockResolvedValue([]),
},
} as unknown as PrismaClient;

const reminderRepository = new PrismaReminderRepository(client);

const result = await reminderRepository.markReminderAsCompleted(
mockReminderId,
);

expect(result).toBe(true);
});

it("should handle errors", async () => {
const consoleErrorSpy = vi.spyOn(console, "error");

const client = {
reminder: {
update: vi.fn().mockRejectedValue(new Error("error")),
},
} as unknown as PrismaClient;

const reminderRepository = new PrismaReminderRepository(client);

const result = await reminderRepository.markReminderAsCompleted(
mockReminderId,
);

expect(result).toBeNull();
expect(consoleErrorSpy).toBeCalledWith({
message: `Error marking reminder as completed`,
reminderId: mockReminderId,
error: new Error("error"),
});
});
});

describe("getReminders", () => {
it("should get reminders", async () => {
const mockReminders = [
{
id: mockReminderId,
dueDate: new Date(),
schedule: mockSchedule,
folderId: mockFolderId,
userId: mockUserId,
notificationsEnabled: 1,
},
];
const client = {
$queryRawUnsafe: vi.fn().mockResolvedValue(mockReminders),
} as unknown as PrismaClient;

const reminderRepository = new PrismaReminderRepository(client);

const result = await reminderRepository.getReminders();

expect(result).toEqual(mockReminders);
});

it("should handle errors", async () => {
const consoleErrorSpy = vi.spyOn(console, "error");

const client = {
$queryRawUnsafe: vi.fn().mockImplementation(() => {
throw new Error("error");
}),
} as unknown as PrismaClient;

const reminderRepository = new PrismaReminderRepository(client);

const result = await reminderRepository.getReminders();

expect(result).toBeNull();
expect(consoleErrorSpy).toBeCalledWith({
message: `Error getting due reminders`,
error: new Error("error"),
});
});
});
});
37 changes: 26 additions & 11 deletions src/repositories/PrismaReminderRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,12 @@ export class PrismaReminderRepository {

return rawReminders[0] ?? null;
} catch (error) {
console.error(
`Error getting notification preference for user ${userId} and folder ${folderId}`,
console.error({
message: "Error getting reminder",
userId,
folderId,
error,
);
});
return null;
}
}
Expand Down Expand Up @@ -71,18 +73,22 @@ export class PrismaReminderRepository {

return true;
} catch (error) {
console.error(
`Error upserting notification preference for user ${userId} and folder ${folderId}`,
console.error({
message: "Error upserting reminder",
userId,
folderId,
dueDate,
schedule,
error,
);
});
return null;
}
}

async updateReminderDueDate(
id: number,
dueDate: Date,
): Promise<DatabaseReminder | null> {
): Promise<boolean | null> {
try {
const formattedDate = this.getFormattedDate(dueDate);

Expand All @@ -94,9 +100,14 @@ export class PrismaReminderRepository {

await this.client.$executeRawUnsafe(sql);

return null;
return true;
} catch (error) {
console.error("Error updating reminder due date", error);
console.error({
message: "Error updating reminder due date",
reminderId: id,
dueDate,
error,
});
return null;
}
}
Expand All @@ -110,7 +121,11 @@ export class PrismaReminderRepository {

return true;
} catch (error) {
console.error("Error marking reminder as completed", error);
console.error({
message: "Error marking reminder as completed",
reminderId: id,
error,
});
return null;
}
}
Expand Down Expand Up @@ -139,7 +154,7 @@ export class PrismaReminderRepository {

return this.client.$queryRawUnsafe(sql);
} catch (error) {
console.error("Error getting due reminders", error);
console.error({ message: "Error getting due reminders", error });
return null;
}
}
Expand Down

0 comments on commit abae606

Please sign in to comment.