Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions src/test/factories/createTestArchive.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import type { Archive } from "@permanentorg/sdk";

interface TestArchiveOverrides {
id?: number;
slug?: string;
name?: string;
createdAt?: Date;
updatedAt?: Date;
}

export const createTestArchive = (
overrides: TestArchiveOverrides = {},
): Archive => ({
id: overrides.id ?? 1,
slug: overrides.slug ?? "test-archive",
name: overrides.name ?? "Test Archive",
createdAt: overrides.createdAt ?? new Date("2024-01-15T12:00:00Z"),
updatedAt: overrides.updatedAt ?? new Date("2024-01-15T12:00:00Z"),
});
31 changes: 31 additions & 0 deletions src/test/factories/createTestArchiveRecord.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { ArchiveRecordType, Status } from "@permanentorg/sdk";
import { createTestFile } from "./createTestFile";
import type { ArchiveRecord, File } from "@permanentorg/sdk";

interface TestArchiveRecordOverrides {
id?: number;
fileSystemId?: number;
displayDate?: Date | null;
type?: ArchiveRecordType;
displayName?: string;
files?: File[];
fileSystemCompatibleName?: string;
status?: Status;
createdAt?: Date;
updatedAt?: Date;
}

export const createTestArchiveRecord = (
overrides: TestArchiveRecordOverrides = {},
): ArchiveRecord => ({
id: overrides.id ?? 1,
fileSystemId: overrides.fileSystemId ?? 1,
displayDate: overrides.displayDate ?? null,
type: overrides.type ?? ArchiveRecordType.Unknown,
displayName: overrides.displayName ?? "Test Record",
files: overrides.files ?? [createTestFile()],
fileSystemCompatibleName: overrides.fileSystemCompatibleName ?? "test-record",
status: overrides.status ?? Status.Ok,
createdAt: overrides.createdAt ?? new Date("2024-01-15T12:00:00Z"),
updatedAt: overrides.updatedAt ?? new Date("2024-01-15T12:00:00Z"),
});
2 changes: 2 additions & 0 deletions src/test/factories/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
export * from "./createTestArchive";
export * from "./createTestArchiveRecord";
export * from "./createTestAttributes";
export * from "./createTestFile";
export * from "./createTestFileEntry";
Expand Down
246 changes: 119 additions & 127 deletions src/utils/deduplicateFileEntries.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,143 +2,135 @@ import { createTestFileEntry } from "../test/factories";
import { deduplicateFileEntries } from "./deduplicateFileEntries";

describe("deduplicateFileEntries", () => {
describe("when given an empty array", () => {
it("should return an empty array", () => {
const result = deduplicateFileEntries([]);
expect(result).toEqual([]);
});
test("should return an empty array when given an empty array", () => {
const result = deduplicateFileEntries([]);
expect(result).toEqual([]);
});

describe("when given entries with unique filenames", () => {
it("should return all entries for a single entry", () => {
const entries = [createTestFileEntry({ filename: "file1.txt" })];
test("should return all entries for a single entry", () => {
const entries = [createTestFileEntry({ filename: "file1.txt" })];

const result = deduplicateFileEntries(entries);
const result = deduplicateFileEntries(entries);

expect(result).toHaveLength(1);
expect(result[0].filename).toBe("file1.txt");
});
expect(result).toHaveLength(1);
expect(result[0].filename).toBe("file1.txt");
});

test("should return all entries when all are unique", () => {
const entries = [
createTestFileEntry({ filename: "file1.txt" }),
createTestFileEntry({ filename: "file2.txt" }),
createTestFileEntry({ filename: "file3.txt" }),
];

const result = deduplicateFileEntries(entries);

expect(result).toHaveLength(3);
expect(result.map((e) => e.filename)).toEqual([
"file1.txt",
"file2.txt",
"file3.txt",
]);
});

test("should keep only the first occurrence of a duplicate", () => {
const first = createTestFileEntry({ filename: "file.txt" });
const duplicate = createTestFileEntry({ filename: "file.txt" });
const entries = [first, duplicate];

const result = deduplicateFileEntries(entries);

it("should return all entries when all are unique", () => {
const entries = [
createTestFileEntry({ filename: "file1.txt" }),
createTestFileEntry({ filename: "file2.txt" }),
createTestFileEntry({ filename: "file3.txt" }),
];
expect(result).toHaveLength(1);
expect(result[0]).toBe(first);
});

test("should remove multiple duplicates of the same filename", () => {
const entries = [
createTestFileEntry({ filename: "file.txt" }),
createTestFileEntry({ filename: "file.txt" }),
createTestFileEntry({ filename: "file.txt" }),
];

const result = deduplicateFileEntries(entries);
const result = deduplicateFileEntries(entries);

expect(result).toHaveLength(3);
expect(result.map((e) => e.filename)).toEqual([
"file1.txt",
"file2.txt",
"file3.txt",
]);
});
expect(result).toHaveLength(1);
expect(result[0].filename).toBe("file.txt");
});

describe("when given entries with duplicate filenames", () => {
it("should keep only the first occurrence of a duplicate", () => {
const first = createTestFileEntry({ filename: "file.txt" });
const duplicate = createTestFileEntry({ filename: "file.txt" });
const entries = [first, duplicate];

const result = deduplicateFileEntries(entries);

expect(result).toHaveLength(1);
expect(result[0]).toBe(first);
});

it("should remove multiple duplicates of the same filename", () => {
const entries = [
createTestFileEntry({ filename: "file.txt" }),
createTestFileEntry({ filename: "file.txt" }),
createTestFileEntry({ filename: "file.txt" }),
];

const result = deduplicateFileEntries(entries);

expect(result).toHaveLength(1);
expect(result[0].filename).toBe("file.txt");
});

it("should handle mixed unique and duplicate entries", () => {
const entries = [
createTestFileEntry({ filename: "file1.txt" }),
createTestFileEntry({ filename: "file2.txt" }),
createTestFileEntry({ filename: "file1.txt" }),
createTestFileEntry({ filename: "file3.txt" }),
createTestFileEntry({ filename: "file2.txt" }),
];

const result = deduplicateFileEntries(entries);

expect(result).toHaveLength(3);
expect(result.map((e) => e.filename)).toEqual([
"file1.txt",
"file2.txt",
"file3.txt",
]);
});

it("should preserve original order of first occurrences", () => {
const entries = [
createTestFileEntry({ filename: "zebra.txt" }),
createTestFileEntry({ filename: "apple.txt" }),
createTestFileEntry({ filename: "zebra.txt" }),
createTestFileEntry({ filename: "mango.txt" }),
createTestFileEntry({ filename: "apple.txt" }),
];

const result = deduplicateFileEntries(entries);

expect(result.map((e) => e.filename)).toEqual([
"zebra.txt",
"apple.txt",
"mango.txt",
]);
});
test("should handle mixed unique and duplicate entries", () => {
const entries = [
createTestFileEntry({ filename: "file1.txt" }),
createTestFileEntry({ filename: "file2.txt" }),
createTestFileEntry({ filename: "file1.txt" }),
createTestFileEntry({ filename: "file3.txt" }),
createTestFileEntry({ filename: "file2.txt" }),
];

const result = deduplicateFileEntries(entries);

expect(result).toHaveLength(3);
expect(result.map((e) => e.filename)).toEqual([
"file1.txt",
"file2.txt",
"file3.txt",
]);
});

describe("edge cases", () => {
it("should treat filenames as case-sensitive", () => {
const entries = [
createTestFileEntry({ filename: "File.txt" }),
createTestFileEntry({ filename: "file.txt" }),
createTestFileEntry({ filename: "FILE.txt" }),
];

const result = deduplicateFileEntries(entries);

expect(result).toHaveLength(3);
});

it("should handle filenames with special characters", () => {
const entries = [
createTestFileEntry({ filename: "file (1).txt" }),
createTestFileEntry({ filename: "file (1).txt" }),
createTestFileEntry({ filename: "file (2).txt" }),
];

const result = deduplicateFileEntries(entries);

expect(result).toHaveLength(2);
expect(result.map((e) => e.filename)).toEqual([
"file (1).txt",
"file (2).txt",
]);
});

it("should handle empty string filenames", () => {
const entries = [
createTestFileEntry({ filename: "" }),
createTestFileEntry({ filename: "" }),
];

const result = deduplicateFileEntries(entries);

expect(result).toHaveLength(1);
expect(result[0].filename).toBe("");
});
test("should preserve original order of first occurrences", () => {
const entries = [
createTestFileEntry({ filename: "zebra.txt" }),
createTestFileEntry({ filename: "apple.txt" }),
createTestFileEntry({ filename: "zebra.txt" }),
createTestFileEntry({ filename: "mango.txt" }),
createTestFileEntry({ filename: "apple.txt" }),
];

const result = deduplicateFileEntries(entries);

expect(result.map((e) => e.filename)).toEqual([
"zebra.txt",
"apple.txt",
"mango.txt",
]);
});

test("should treat filenames as case-sensitive", () => {
const entries = [
createTestFileEntry({ filename: "File.txt" }),
createTestFileEntry({ filename: "file.txt" }),
createTestFileEntry({ filename: "FILE.txt" }),
];

const result = deduplicateFileEntries(entries);

expect(result).toHaveLength(3);
});

test("should handle filenames with special characters", () => {
const entries = [
createTestFileEntry({ filename: "file (1).txt" }),
createTestFileEntry({ filename: "file (1).txt" }),
createTestFileEntry({ filename: "file (2).txt" }),
];

const result = deduplicateFileEntries(entries);

expect(result).toHaveLength(2);
expect(result.map((e) => e.filename)).toEqual([
"file (1).txt",
"file (2).txt",
]);
});

test("should handle empty string filenames", () => {
const entries = [
createTestFileEntry({ filename: "" }),
createTestFileEntry({ filename: "" }),
];

const result = deduplicateFileEntries(entries);

expect(result).toHaveLength(1);
expect(result[0].filename).toBe("");
});
});
46 changes: 46 additions & 0 deletions src/utils/generateAttributesForArchive.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { createTestArchive, DIRECTORY_MODE } from "../test/factories";
import { generateAttributesForArchive } from "./generateAttributesForArchive";

describe("generateAttributesForArchive", () => {
test("should set mode to directory with full permissions", () => {
const archive = createTestArchive();

const result = generateAttributesForArchive(archive);

expect(result.mode).toBe(DIRECTORY_MODE);
});

test("should set size to 0", () => {
const archive = createTestArchive();

const result = generateAttributesForArchive(archive);

expect(result.size).toBe(0);
});

test("should convert updatedAt to unix timestamp for mtime", () => {
const updatedAt = new Date("2024-06-15T10:30:00Z");
const archive = createTestArchive({ updatedAt });

const result = generateAttributesForArchive(archive);

expect(result.mtime).toBe(updatedAt.getTime() / 1000);
});

test("should set atime to 0", () => {
const archive = createTestArchive();

const result = generateAttributesForArchive(archive);

expect(result.atime).toBe(0);
});

test("should set uid and gid to 0", () => {
const archive = createTestArchive();

const result = generateAttributesForArchive(archive);

expect(result.uid).toBe(0);
expect(result.gid).toBe(0);
});
});
Loading