src / __tests__ / searchCriteria.test.ts
import { describe, expect, it } from "vitest";
import {
buildSearchCriteria,
normalizeSearchUids,
paginateNewestFirst,
} from "../searchCriteria";
describe("buildSearchCriteria", () => {
it("uses all when no filters are populated", () => {
expect(buildSearchCriteria({})).toEqual({ all: true });
});
it("uses ImapFlow object criteria", () => {
const since = new Date(2026, 7, 1);
const before = new Date(2026, 7, 5);
expect(
buildSearchCriteria({
query: "invoice",
from: "sender@example.com",
to: "me@example.com",
subject: "August",
since,
before,
unseen: true,
}),
).toEqual({
text: "invoice",
from: "sender@example.com",
to: "me@example.com",
subject: "August",
since,
before,
seen: false,
});
});
});
describe("normalizeSearchUids", () => {
it("turns false into an empty result", () => {
expect(normalizeSearchUids(false)).toEqual([]);
});
it("accepts ordinary UID arrays", () => {
expect(normalizeSearchUids([1, 2, 3])).toEqual([1, 2, 3]);
});
it("accepts ESEARCH-like all results", () => {
expect(normalizeSearchUids({ all: [4, 5] })).toEqual([4, 5]);
});
it("removes invalid values and duplicate UIDs", () => {
expect(normalizeSearchUids([1, 1, 0, -1, 2.5, "3", 4])).toEqual([1, 4]);
});
});
describe("paginateNewestFirst", () => {
it("reverses without mutating the input and pages deterministically", () => {
const input = [10, 11, 12, 13, 14];
const result = paginateNewestFirst(input, 1, 2);
expect(input).toEqual([10, 11, 12, 13, 14]);
expect(result).toEqual({
page: [13, 12],
total: 5,
offset: 1,
hasMore: true,
});
});
it("reports no further page at the end", () => {
expect(paginateNewestFirst([1, 2], 0, 10)).toEqual({
page: [2, 1],
total: 2,
offset: 0,
hasMore: false,
});
});
});
src / __tests__ / searchCriteria.test.ts
import { describe, expect, it } from "vitest";
import {
buildSearchCriteria,
normalizeSearchUids,
paginateNewestFirst,
} from "../searchCriteria";
describe("buildSearchCriteria", () => {
it("uses all when no filters are populated", () => {
expect(buildSearchCriteria({})).toEqual({ all: true });
});
it("uses ImapFlow object criteria", () => {
const since = new Date(2026, 7, 1);
const before = new Date(2026, 7, 5);
expect(
buildSearchCriteria({
query: "invoice",
from: "sender@example.com",
to: "me@example.com",
subject: "August",
since,
before,
unseen: true,
}),
).toEqual({
text: "invoice",
from: "sender@example.com",
to: "me@example.com",
subject: "August",
since,
before,
seen: false,
});
});
});
describe("normalizeSearchUids", () => {
it("turns false into an empty result", () => {
expect(normalizeSearchUids(false)).toEqual([]);
});
it("accepts ordinary UID arrays", () => {
expect(normalizeSearchUids([1, 2, 3])).toEqual([1, 2, 3]);
});
it("accepts ESEARCH-like all results", () => {
expect(normalizeSearchUids({ all: [4, 5] })).toEqual([4, 5]);
});
it("removes invalid values and duplicate UIDs", () => {
expect(normalizeSearchUids([1, 1, 0, -1, 2.5, "3", 4])).toEqual([1, 4]);
});
});
describe("paginateNewestFirst", () => {
it("reverses without mutating the input and pages deterministically", () => {
const input = [10, 11, 12, 13, 14];
const result = paginateNewestFirst(input, 1, 2);
expect(input).toEqual([10, 11, 12, 13, 14]);
expect(result).toEqual({
page: [13, 12],
total: 5,
offset: 1,
hasMore: true,
});
});
it("reports no further page at the end", () => {
expect(paginateNewestFirst([1, 2], 0, 10)).toEqual({
page: [2, 1],
total: 2,
offset: 0,
hasMore: false,
});
});
});