import { describe, expect, it } from "vitest";
import { parseIfHeader, positiveEtags, positiveLockTokens } from "@/worker/dav/if-header";
import { ifHeaderMatches } from "@/worker/dav/locks";
import type { FileLockRow } from "@/worker/db/file-dav-do/schema";
function activeLock(input: { token?: string; rootPath: string; depth?: "0" | "infinity" }): FileLockRow {
return {
token: input.token ?? "opaquelocktoken:abc",
rootNodeId: "node-1",
rootPath: input.rootPath,
ownerXml: '',
principalSubjectId: "subject-1",
scope: "exclusive",
depth: input.depth ?? "0",
createdAtMs: 1,
expiresAtMs: 2,
};
}
describe("WebDAV If header parser", () => {
it("parses untagged lock tokens and entity tags", () => {
const parsed = parseIfHeader('( ["etag-1"])');
expect(parsed.ok).toBe(true);
if (!parsed.ok) return;
expect(positiveLockTokens(parsed.header)).toEqual(["opaquelocktoken:abc"]);
expect(positiveEtags(parsed.header)).toEqual(['"etag-1"']);
});
it("parses tagged lists and Not conditions without treating prefixes as text hacks", () => {
const parsed = parseIfHeader(" (Not ) ()");
expect(parsed.ok).toBe(true);
if (!parsed.ok) return;
expect(parsed.header.lists[0]?.resourceHref).toBe("/files/a.txt");
expect(parsed.header.lists[0]?.conditions[0]).toMatchObject({ not: true, kind: "lock-token" });
expect(positiveLockTokens(parsed.header)).toEqual(["opaquelocktoken:def"]);
});
it("matches absolute tagged lock roots against descendant writes", () => {
const parsed = parseIfHeader(" ()");
expect(parsed.ok).toBe(true);
if (!parsed.ok) return;
expect(
ifHeaderMatches({
header: parsed.header,
targetHref: "/files/locked/child.txt",
targetEtag: null,
locks: [activeLock({ rootPath: "/files/locked/", depth: "infinity" })],
}),
).toBe(true);
});
it("honors Not conditions for entity tags", () => {
const parsed = parseIfHeader('(Not ["other-etag"])');
expect(parsed.ok).toBe(true);
if (!parsed.ok) return;
expect(
ifHeaderMatches({
header: parsed.header,
targetHref: "/files/a.txt",
targetEtag: '"etag-1"',
locks: [],
}),
).toBe(true);
});
});