feat: add filter and sort controller
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
import { describe, expect, test } from "vitest";
|
||||
|
||||
import { applyFilterAndSort } from "../src/content/market/filter-sort-controller";
|
||||
import type { MarketRecord } from "../src/content/market/types";
|
||||
|
||||
const baseRecords: MarketRecord[] = [
|
||||
{
|
||||
authorId: "a",
|
||||
authorName: "Alpha",
|
||||
status: "success",
|
||||
rates: {
|
||||
singleVideoAfterSearchRate: "0.02% - 0.1%",
|
||||
personalVideoAfterSearchRate: "0.03% - 0.2%"
|
||||
}
|
||||
},
|
||||
{
|
||||
authorId: "b",
|
||||
authorName: "Beta",
|
||||
status: "success",
|
||||
rates: {
|
||||
singleVideoAfterSearchRate: "0.5% - 1%",
|
||||
personalVideoAfterSearchRate: "0.01% - 0.1%"
|
||||
}
|
||||
},
|
||||
{
|
||||
authorId: "c",
|
||||
authorName: "Gamma",
|
||||
status: "failed",
|
||||
failureReason: "request-failed"
|
||||
}
|
||||
];
|
||||
|
||||
describe("filter-sort-controller", () => {
|
||||
test("passes only when the lower bound meets the single-rate threshold", () => {
|
||||
const result = applyFilterAndSort(baseRecords, {
|
||||
filters: {
|
||||
singleVideoAfterSearchRateMin: 0.1
|
||||
}
|
||||
});
|
||||
|
||||
expect(result.map((record) => record.authorId)).toEqual(["b"]);
|
||||
});
|
||||
|
||||
test("passes only when the lower bound meets the personal-rate threshold", () => {
|
||||
const result = applyFilterAndSort(baseRecords, {
|
||||
filters: {
|
||||
personalVideoAfterSearchRateMin: 0.02
|
||||
}
|
||||
});
|
||||
|
||||
expect(result.map((record) => record.authorId)).toEqual(["a"]);
|
||||
});
|
||||
|
||||
test("sorts by single-rate descending using the lower bound", () => {
|
||||
const result = applyFilterAndSort(baseRecords, {
|
||||
sort: {
|
||||
direction: "desc",
|
||||
field: "singleVideoAfterSearchRate"
|
||||
}
|
||||
});
|
||||
|
||||
expect(result.map((record) => record.authorId)).toEqual(["b", "a", "c"]);
|
||||
});
|
||||
|
||||
test("sorts by personal-rate ascending using the lower bound", () => {
|
||||
const result = applyFilterAndSort(baseRecords, {
|
||||
sort: {
|
||||
direction: "asc",
|
||||
field: "personalVideoAfterSearchRate"
|
||||
}
|
||||
});
|
||||
|
||||
expect(result.map((record) => record.authorId)).toEqual(["b", "a", "c"]);
|
||||
});
|
||||
|
||||
test("keeps failed and missing rows at the end", () => {
|
||||
const result = applyFilterAndSort(
|
||||
[
|
||||
...baseRecords,
|
||||
{
|
||||
authorId: "d",
|
||||
authorName: "Delta",
|
||||
status: "missing"
|
||||
}
|
||||
],
|
||||
{
|
||||
sort: {
|
||||
direction: "desc",
|
||||
field: "singleVideoAfterSearchRate"
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
expect(result.slice(-2).map((record) => record.authorId)).toEqual(["c", "d"]);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user