Files
triggerdotdev--trigger.dev/apps/webapp/test/runsRepository.part4.test.ts
T
2026-07-13 13:32:57 +08:00

456 lines
13 KiB
TypeScript

import { describe, expect, vi } from "vitest";
// Mock the db prisma client
vi.mock("~/db.server", () => ({
prisma: {},
$replica: {},
}));
import { replicationContainerTest } from "@internal/testcontainers";
import { setTimeout } from "node:timers/promises";
import { RunsRepository } from "~/services/runsRepository/runsRepository.server";
import { setupClickhouseReplication } from "./utils/replicationUtils";
vi.setConfig({ testTimeout: 60_000 });
describe("RunsRepository (part 4/4)", () => {
replicationContainerTest(
"should filter runs by date range (from/to)",
async ({ clickhouseContainer, redisOptions, postgresContainer, prisma }) => {
const { clickhouse } = await setupClickhouseReplication({
prisma,
databaseUrl: postgresContainer.getConnectionUri(),
clickhouseUrl: clickhouseContainer.getConnectionUrl(),
redisOptions,
});
const organization = await prisma.organization.create({
data: {
title: "test",
slug: "test",
},
});
const project = await prisma.project.create({
data: {
name: "test",
slug: "test",
organizationId: organization.id,
externalRef: "test",
},
});
const runtimeEnvironment = await prisma.runtimeEnvironment.create({
data: {
slug: "test",
type: "DEVELOPMENT",
projectId: project.id,
organizationId: organization.id,
apiKey: "test",
pkApiKey: "test",
shortcode: "test",
},
});
const now = new Date();
const yesterday = new Date(now.getTime() - 24 * 60 * 60 * 1000);
const tomorrow = new Date(now.getTime() + 24 * 60 * 60 * 1000);
// Create runs with different creation dates
await prisma.taskRun.create({
data: {
friendlyId: "run_yesterday",
taskIdentifier: "my-task",
createdAt: yesterday,
payload: JSON.stringify({ foo: "bar" }),
traceId: "1234",
spanId: "1234",
queue: "test",
runtimeEnvironmentId: runtimeEnvironment.id,
projectId: project.id,
organizationId: organization.id,
environmentType: "DEVELOPMENT",
engine: "V2",
},
});
await prisma.taskRun.create({
data: {
friendlyId: "run_today",
taskIdentifier: "my-task",
createdAt: now,
payload: JSON.stringify({ foo: "bar" }),
traceId: "1235",
spanId: "1235",
queue: "test",
runtimeEnvironmentId: runtimeEnvironment.id,
projectId: project.id,
organizationId: organization.id,
environmentType: "DEVELOPMENT",
engine: "V2",
},
});
await prisma.taskRun.create({
data: {
friendlyId: "run_tomorrow",
taskIdentifier: "my-task",
createdAt: tomorrow,
payload: JSON.stringify({ foo: "bar" }),
traceId: "1236",
spanId: "1236",
queue: "test",
runtimeEnvironmentId: runtimeEnvironment.id,
projectId: project.id,
organizationId: organization.id,
environmentType: "DEVELOPMENT",
engine: "V2",
},
});
await setTimeout(1000);
const runsRepository = new RunsRepository({
prisma,
clickhouse,
});
// Test filtering by date range (from yesterday to today)
const { runs } = await runsRepository.listRuns({
page: { size: 10 },
projectId: project.id,
environmentId: runtimeEnvironment.id,
organizationId: organization.id,
from: yesterday.getTime(),
to: now.getTime(),
});
expect(runs).toHaveLength(2);
expect(runs.map((r) => r.friendlyId).sort()).toEqual(["run_today", "run_yesterday"]);
}
);
replicationContainerTest(
"should handle multiple filters combined",
async ({ clickhouseContainer, redisOptions, postgresContainer, prisma }) => {
const { clickhouse } = await setupClickhouseReplication({
prisma,
databaseUrl: postgresContainer.getConnectionUri(),
clickhouseUrl: clickhouseContainer.getConnectionUrl(),
redisOptions,
});
const organization = await prisma.organization.create({
data: {
title: "test",
slug: "test",
},
});
const project = await prisma.project.create({
data: {
name: "test",
slug: "test",
organizationId: organization.id,
externalRef: "test",
},
});
const runtimeEnvironment = await prisma.runtimeEnvironment.create({
data: {
slug: "test",
type: "DEVELOPMENT",
projectId: project.id,
organizationId: organization.id,
apiKey: "test",
pkApiKey: "test",
shortcode: "test",
},
});
// Create runs with different combinations of properties
await prisma.taskRun.create({
data: {
friendlyId: "run_match",
taskIdentifier: "task-1",
taskVersion: "1.0.0",
status: "COMPLETED_SUCCESSFULLY",
isTest: false,
runTags: ["urgent"],
payload: JSON.stringify({ foo: "bar" }),
traceId: "1234",
spanId: "1234",
queue: "test",
runtimeEnvironmentId: runtimeEnvironment.id,
projectId: project.id,
organizationId: organization.id,
environmentType: "DEVELOPMENT",
engine: "V2",
},
});
await prisma.taskRun.create({
data: {
friendlyId: "run_no_match_task",
taskIdentifier: "task-2", // Different task
taskVersion: "1.0.0",
status: "COMPLETED_SUCCESSFULLY",
isTest: false,
runTags: ["urgent"],
payload: JSON.stringify({ foo: "bar" }),
traceId: "1235",
spanId: "1235",
queue: "test",
runtimeEnvironmentId: runtimeEnvironment.id,
projectId: project.id,
organizationId: organization.id,
environmentType: "DEVELOPMENT",
engine: "V2",
},
});
await prisma.taskRun.create({
data: {
friendlyId: "run_no_match_status",
taskIdentifier: "task-1",
taskVersion: "1.0.0",
status: "PENDING", // Different status
isTest: false,
runTags: ["urgent"],
payload: JSON.stringify({ foo: "bar" }),
traceId: "1236",
spanId: "1236",
queue: "test",
runtimeEnvironmentId: runtimeEnvironment.id,
projectId: project.id,
organizationId: organization.id,
environmentType: "DEVELOPMENT",
engine: "V2",
},
});
await setTimeout(1000);
const runsRepository = new RunsRepository({
prisma,
clickhouse,
});
// Test combining multiple filters
const { runs } = await runsRepository.listRuns({
page: { size: 10 },
projectId: project.id,
environmentId: runtimeEnvironment.id,
organizationId: organization.id,
tasks: ["task-1"],
versions: ["1.0.0"],
statuses: ["COMPLETED_SUCCESSFULLY"],
isTest: false,
tags: ["urgent"],
});
expect(runs).toHaveLength(1);
expect(runs[0].friendlyId).toBe("run_match");
}
);
replicationContainerTest(
"should handle pagination correctly",
async ({ clickhouseContainer, redisOptions, postgresContainer, prisma }) => {
const { clickhouse } = await setupClickhouseReplication({
prisma,
databaseUrl: postgresContainer.getConnectionUri(),
clickhouseUrl: clickhouseContainer.getConnectionUrl(),
redisOptions,
});
const organization = await prisma.organization.create({
data: {
title: "test",
slug: "test",
},
});
const project = await prisma.project.create({
data: {
name: "test",
slug: "test",
organizationId: organization.id,
externalRef: "test",
},
});
const runtimeEnvironment = await prisma.runtimeEnvironment.create({
data: {
slug: "test",
type: "DEVELOPMENT",
projectId: project.id,
organizationId: organization.id,
apiKey: "test",
pkApiKey: "test",
shortcode: "test",
},
});
// Create multiple runs for pagination testing
const runs = [];
for (let i = 1; i <= 5; i++) {
const run = await prisma.taskRun.create({
data: {
friendlyId: `run_${i}`,
taskIdentifier: "my-task",
payload: JSON.stringify({ foo: "bar" }),
traceId: `123${i}`,
spanId: `123${i}`,
queue: "test",
runtimeEnvironmentId: runtimeEnvironment.id,
projectId: project.id,
organizationId: organization.id,
environmentType: "DEVELOPMENT",
engine: "V2",
},
});
runs.push(run);
}
await setTimeout(1000);
const runsRepository = new RunsRepository({
prisma,
clickhouse,
});
// Test first page
const firstPage = await runsRepository.listRuns({
page: { size: 2 },
projectId: project.id,
environmentId: runtimeEnvironment.id,
organizationId: organization.id,
});
expect(firstPage.runs).toHaveLength(2);
expect(firstPage.pagination.nextCursor).toBeTruthy();
expect(firstPage.pagination.previousCursor).toBe(null);
// Test next page using cursor
const secondPage = await runsRepository.listRuns({
page: {
size: 2,
cursor: firstPage.pagination.nextCursor!,
direction: "forward",
},
projectId: project.id,
environmentId: runtimeEnvironment.id,
organizationId: organization.id,
});
expect(secondPage.runs).toHaveLength(2);
expect(secondPage.pagination.nextCursor).toBeTruthy();
expect(secondPage.pagination.previousCursor).toBeTruthy();
}
);
replicationContainerTest(
"should count new runs with listRunIds",
async ({ clickhouseContainer, redisOptions, postgresContainer, prisma }) => {
const { clickhouse } = await setupClickhouseReplication({
prisma,
databaseUrl: postgresContainer.getConnectionUri(),
clickhouseUrl: clickhouseContainer.getConnectionUrl(),
redisOptions,
});
const organization = await prisma.organization.create({
data: {
title: "test",
slug: "test",
},
});
const project = await prisma.project.create({
data: {
name: "test",
slug: "test",
organizationId: organization.id,
externalRef: "test",
},
});
const runtimeEnvironment = await prisma.runtimeEnvironment.create({
data: {
slug: "test",
type: "DEVELOPMENT",
projectId: project.id,
organizationId: organization.id,
apiKey: "test",
pkApiKey: "test",
shortcode: "test",
},
});
const taskRun = await prisma.taskRun.create({
data: {
friendlyId: "run_has_new",
taskIdentifier: "my-task",
payload: JSON.stringify({ foo: "bar" }),
traceId: "1234",
spanId: "1234",
queue: "test",
runtimeEnvironmentId: runtimeEnvironment.id,
projectId: project.id,
organizationId: organization.id,
environmentType: "DEVELOPMENT",
engine: "V2",
},
});
await setTimeout(1000);
const runsRepository = new RunsRepository({
prisma,
clickhouse,
});
const baseOptions = {
projectId: project.id,
environmentId: runtimeEnvironment.id,
organizationId: organization.id,
};
const createdAtMs = taskRun.createdAt.getTime();
const newRunIdsBefore = await runsRepository.listRunIds({
...baseOptions,
from: createdAtMs - 1,
page: { size: 100 },
});
expect(newRunIdsBefore.runIds.length).toBeGreaterThanOrEqual(1);
const newRunIdsAfter = await runsRepository.listRunIds({
...baseOptions,
from: createdAtMs + 60_000,
page: { size: 100 },
});
expect(newRunIdsAfter.runIds).toHaveLength(0);
const fromBeforeRun = createdAtMs - 1;
const matchingTaskIds = await runsRepository.listRunIds({
...baseOptions,
from: fromBeforeRun,
tasks: ["my-task"],
page: { size: 100 },
});
expect(matchingTaskIds.runIds.length).toBeGreaterThanOrEqual(1);
const otherTaskIds = await runsRepository.listRunIds({
...baseOptions,
from: fromBeforeRun,
tasks: ["other-task"],
page: { size: 100 },
});
expect(otherTaskIds.runIds).toHaveLength(0);
}
);
});