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

119 lines
4.5 KiB
TypeScript

import { describe, expect, it } from "vitest";
import {
exceptDevEnvironments,
filterOrphanedEnvironments,
onlyDevEnvironments,
sortEnvironments,
} from "~/utils/environmentSort";
describe("sortEnvironments", () => {
it("orders by environment type first (dev, staging, preview, prod)", () => {
const sorted = sortEnvironments([
{ type: "PRODUCTION" },
{ type: "PREVIEW" },
{ type: "DEVELOPMENT" },
{ type: "STAGING" },
]);
expect(sorted.map((e) => e.type)).toEqual(["DEVELOPMENT", "STAGING", "PREVIEW", "PRODUCTION"]);
});
it("sorts same-type rows by lastActivity desc when both have it", () => {
const older = new Date("2026-06-01T00:00:00Z");
const newer = new Date("2026-06-20T00:00:00Z");
const sorted = sortEnvironments([
{ type: "DEVELOPMENT", userName: "a", lastActivity: older },
{ type: "DEVELOPMENT", userName: "b", lastActivity: newer },
]);
// Most recently active branch first.
expect(sorted.map((e) => e.userName)).toEqual(["b", "a"]);
});
it("falls back to updatedAt desc when neither row has lastActivity", () => {
const older = new Date("2026-06-01T00:00:00Z");
const newer = new Date("2026-06-20T00:00:00Z");
const sorted = sortEnvironments([
{ type: "DEVELOPMENT", userName: "a", updatedAt: older },
{ type: "DEVELOPMENT", userName: "b", updatedAt: newer },
]);
// Most recently updated branch first.
expect(sorted.map((e) => e.userName)).toEqual(["b", "a"]);
});
it("uses a row's lastActivity over its own stale updatedAt", () => {
const staleUpdate = new Date("2026-06-01T00:00:00Z");
const recentActivity = new Date("2026-06-26T00:00:00Z");
const otherUpdate = new Date("2026-06-10T00:00:00Z");
// 'a' has a stale updatedAt but recent dev activity; 'b' has only a (more
// recent than a's update) updatedAt. If activity weren't preferred, a's
// stale 06-01 would lose to b's 06-10; instead a's 06-26 activity wins.
const sorted = sortEnvironments([
{ type: "DEVELOPMENT", userName: "b", updatedAt: otherUpdate },
{ type: "DEVELOPMENT", userName: "a", updatedAt: staleUpdate, lastActivity: recentActivity },
]);
expect(sorted.map((e) => e.userName)).toEqual(["a", "b"]);
});
it("orders rows with any timestamp ahead of rows with none", () => {
const sorted = sortEnvironments([
{ type: "DEVELOPMENT", userName: "no-timestamp" },
{ type: "DEVELOPMENT", userName: "has-update", updatedAt: new Date("2026-06-10T00:00:00Z") },
]);
expect(sorted.map((e) => e.userName)).toEqual(["has-update", "no-timestamp"]);
});
it("falls back to username order when lastActivity is absent (the ZSET-missing case)", () => {
// When the recency ZSET is missing/evicted, lastActivity is undefined for
// every branch, and the list must still render in a stable order.
const sorted = sortEnvironments([
{ type: "DEVELOPMENT", userName: "charlie" },
{ type: "DEVELOPMENT", userName: "alice" },
{ type: "DEVELOPMENT", userName: "bob" },
]);
expect(sorted.map((e) => e.userName)).toEqual(["alice", "bob", "charlie"]);
});
});
describe("filterOrphanedEnvironments", () => {
it("drops DEVELOPMENT envs with no owning org member", () => {
const result = filterOrphanedEnvironments([
{ type: "DEVELOPMENT", orgMemberId: "om_1" },
{ type: "DEVELOPMENT", orgMemberId: undefined },
{ type: "PRODUCTION" } as any,
]);
expect(result).toEqual([{ type: "DEVELOPMENT", orgMemberId: "om_1" }, { type: "PRODUCTION" }]);
});
it("keeps DEVELOPMENT envs whose orgMember relation is loaded", () => {
const result = filterOrphanedEnvironments([
{ type: "DEVELOPMENT", orgMember: { id: "om_1" } },
{ type: "DEVELOPMENT", orgMember: undefined } as any,
]);
expect(result).toEqual([{ type: "DEVELOPMENT", orgMember: { id: "om_1" } }]);
});
it("never filters non-development environments", () => {
const envs = [{ type: "PREVIEW" }, { type: "STAGING" }, { type: "PRODUCTION" }] as any[];
expect(filterOrphanedEnvironments(envs)).toEqual(envs);
});
});
describe("onlyDevEnvironments / exceptDevEnvironments", () => {
const envs = [{ type: "DEVELOPMENT" }, { type: "PREVIEW" }, { type: "PRODUCTION" }] as const;
it("partitions on the development type", () => {
expect(onlyDevEnvironments([...envs])).toEqual([{ type: "DEVELOPMENT" }]);
expect(exceptDevEnvironments([...envs])).toEqual([{ type: "PREVIEW" }, { type: "PRODUCTION" }]);
});
});