rallly/apps/web/tests/house-keeping.spec.ts
2025-03-28 10:10:46 +00:00

297 lines
9.7 KiB
TypeScript

import { expect, test } from "@playwright/test";
import { prisma } from "@rallly/database";
import dayjs from "dayjs";
/**
* This test suite tests the house-keeping API endpoints:
* 1. delete-inactive-polls: Marks inactive polls as deleted
* 2. remove-deleted-polls: Permanently removes polls that have been marked as deleted for more than 7 days
*/
test.describe("House-keeping API", () => {
// Store created poll IDs for cleanup
const createdPollIds: string[] = [];
const createdUserIds: string[] = [];
// API Secret for authentication
const API_SECRET = process.env.API_SECRET;
test.beforeAll(async () => {
// Clean up any existing test data
await cleanup();
});
test.afterAll(async () => {
// Clean up test data
await cleanup();
});
async function cleanup() {
// Delete test users - related polls will be deleted automatically due to cascade
if (createdUserIds.length > 0) {
await prisma.user.deleteMany({
where: {
id: {
in: createdUserIds,
},
},
});
createdUserIds.length = 0;
}
// Delete polls that don't have a user (not covered by cascade delete)
if (createdPollIds.length > 0) {
await prisma.poll.deleteMany({
where: {
id: {
in: createdPollIds,
},
userId: null,
},
});
createdPollIds.length = 0;
}
}
test("should mark inactive polls as deleted for users without active subscriptions", async ({
request,
baseURL,
}) => {
// Create test users
const regularUser = await prisma.user.create({
data: {
name: "Regular User",
email: "regular-user@example.com",
},
});
createdUserIds.push(regularUser.id);
const proUser = await prisma.user.create({
data: {
name: "Pro User",
email: "pro-user@example.com",
subscription: {
create: {
id: "sub_test_pro",
priceId: "price_test",
amount: 1000,
status: "active",
active: true,
currency: "USD",
interval: "month",
periodStart: new Date(),
periodEnd: dayjs().add(30, "day").toDate(),
},
},
},
});
createdUserIds.push(proUser.id);
// Create test polls
// 1. Old poll from regular user (should be marked as deleted)
const oldPollRegularUser = await prisma.poll.create({
data: {
id: "old-poll-regular-user",
title: "Old Poll Regular User",
participantUrlId: "old-poll-regular-user-participant",
adminUrlId: "old-poll-regular-user-admin",
userId: regularUser.id,
touchedAt: dayjs().subtract(35, "day").toDate(), // 35 days old
},
});
createdPollIds.push(oldPollRegularUser.id);
// 2. Old poll from pro user (should NOT be marked as deleted)
const oldPollProUser = await prisma.poll.create({
data: {
id: "old-poll-pro-user",
title: "Old Poll Pro User",
participantUrlId: "old-poll-pro-user-participant",
adminUrlId: "old-poll-pro-user-admin",
userId: proUser.id,
touchedAt: dayjs().subtract(35, "day").toDate(), // 35 days old
},
});
createdPollIds.push(oldPollProUser.id);
// 3. Recent poll from regular user (should NOT be marked as deleted)
const recentPollRegularUser = await prisma.poll.create({
data: {
id: "recent-poll-regular-user",
title: "Recent Poll Regular User",
participantUrlId: "recent-poll-regular-user-participant",
adminUrlId: "recent-poll-regular-user-admin",
userId: regularUser.id,
touchedAt: dayjs().subtract(15, "day").toDate(), // 15 days old
},
});
createdPollIds.push(recentPollRegularUser.id);
// 4. Old poll with future options from regular user (should NOT be marked as deleted)
const oldPollWithFutureOptions = await prisma.poll.create({
data: {
id: "old-poll-with-future-options",
title: "Old Poll With Future Options",
participantUrlId: "old-poll-with-future-options-participant",
adminUrlId: "old-poll-with-future-options-admin",
userId: regularUser.id,
touchedAt: dayjs().subtract(35, "day").toDate(), // 35 days old
options: {
create: {
startTime: dayjs().add(10, "day").toDate(), // Future date
duration: 60,
},
},
},
});
createdPollIds.push(oldPollWithFutureOptions.id);
// 5. Old poll without a user (should be marked as deleted)
const oldPollNoUser = await prisma.poll.create({
data: {
id: "old-poll-no-user",
title: "Old Poll No User",
participantUrlId: "old-poll-no-user-participant",
adminUrlId: "old-poll-no-user-admin",
touchedAt: dayjs().subtract(35, "day").toDate(), // 35 days old
},
});
createdPollIds.push(oldPollNoUser.id);
// 6. Old poll with recent views from regular user (should NOT be marked as deleted)
const oldPollWithRecentViews = await prisma.poll.create({
data: {
id: "old-poll-with-recent-views",
title: "Old Poll With Recent Views",
participantUrlId: "old-poll-with-recent-views-participant",
adminUrlId: "old-poll-with-recent-views-admin",
userId: regularUser.id,
touchedAt: dayjs().subtract(35, "day").toDate(), // 35 days old
views: {
create: {
viewedAt: dayjs().subtract(15, "day").toDate(), // Viewed 15 days ago
},
},
},
});
createdPollIds.push(oldPollWithRecentViews.id);
// Call the delete-inactive-polls endpoint
const response = await request.post(
`${baseURL}/api/house-keeping/delete-inactive-polls`,
{
headers: {
Authorization: `Bearer ${API_SECRET}`,
},
},
);
expect(response.ok()).toBeTruthy();
const responseData = await response.json();
expect(responseData.success).toBeTruthy();
// We expect 2 polls to be marked as deleted:
// - Old poll from regular user
// - Old poll without a user
expect(responseData.summary.markedDeleted).toBe(2);
// Verify the state of each poll
const updatedOldPollRegularUser = await prisma.poll.findUnique({
where: { id: oldPollRegularUser.id },
});
expect(updatedOldPollRegularUser?.deleted).toBe(true);
expect(updatedOldPollRegularUser?.deletedAt).not.toBeNull();
const updatedOldPollProUser = await prisma.poll.findUnique({
where: { id: oldPollProUser.id },
});
expect(updatedOldPollProUser?.deleted).toBe(false);
expect(updatedOldPollProUser?.deletedAt).toBeNull();
const updatedRecentPollRegularUser = await prisma.poll.findUnique({
where: { id: recentPollRegularUser.id },
});
expect(updatedRecentPollRegularUser?.deleted).toBe(false);
expect(updatedRecentPollRegularUser?.deletedAt).toBeNull();
const updatedOldPollWithFutureOptions = await prisma.poll.findUnique({
where: { id: oldPollWithFutureOptions.id },
});
expect(updatedOldPollWithFutureOptions?.deleted).toBe(false);
expect(updatedOldPollWithFutureOptions?.deletedAt).toBeNull();
const updatedOldPollNoUser = await prisma.poll.findUnique({
where: { id: oldPollNoUser.id },
});
expect(updatedOldPollNoUser?.deleted).toBe(true);
expect(updatedOldPollNoUser?.deletedAt).not.toBeNull();
const updatedOldPollWithRecentViews = await prisma.poll.findUnique({
where: { id: oldPollWithRecentViews.id },
});
expect(updatedOldPollWithRecentViews?.deleted).toBe(false);
expect(updatedOldPollWithRecentViews?.deletedAt).toBeNull();
});
test("should permanently remove polls that have been marked as deleted for more than 7 days", async ({
request,
baseURL,
}) => {
// Create a poll that was marked as deleted more than 7 days ago
const oldDeletedPoll = await prisma.poll.create({
data: {
id: "old-deleted-poll",
title: "Old Deleted Poll",
participantUrlId: "old-deleted-poll-participant",
adminUrlId: "old-deleted-poll-admin",
deleted: true,
deletedAt: dayjs().subtract(8, "day").toDate(), // Deleted 8 days ago
},
});
createdPollIds.push(oldDeletedPoll.id);
// Create a poll that was marked as deleted less than 7 days ago
const recentDeletedPoll = await prisma.poll.create({
data: {
id: "recent-deleted-poll",
title: "Recent Deleted Poll",
participantUrlId: "recent-deleted-poll-participant",
adminUrlId: "recent-deleted-poll-admin",
deleted: true,
deletedAt: dayjs().subtract(3, "day").toDate(), // Deleted 3 days ago
},
});
createdPollIds.push(recentDeletedPoll.id);
// Call the remove-deleted-polls endpoint
const response = await request.post(
`${baseURL}/api/house-keeping/remove-deleted-polls`,
{
headers: {
Authorization: `Bearer ${API_SECRET}`,
},
data: {}, // Empty JSON body
},
);
expect(response.ok()).toBeTruthy();
const responseData = await response.json();
expect(responseData.success).toBeTruthy();
// We expect 1 poll to be permanently deleted
expect(responseData.summary.deleted.polls).toBe(1);
// Verify that the old deleted poll is gone
const checkOldDeletedPoll = await prisma.poll.findUnique({
where: { id: oldDeletedPoll.id },
});
expect(checkOldDeletedPoll).toBeNull();
// Verify that the recent deleted poll still exists
const checkRecentDeletedPoll = await prisma.poll.findUnique({
where: { id: recentDeletedPoll.id },
});
expect(checkRecentDeletedPoll).not.toBeNull();
expect(checkRecentDeletedPoll?.deleted).toBe(true);
});
});