Skip to content

Commit a4540bb

Browse files
Fixed tests failing due to rolling dates
Allowing column descriptors to be injected through the column filter store class
1 parent 9cf718f commit a4540bb

File tree

2 files changed

+74
-40
lines changed

2 files changed

+74
-40
lines changed

vuu-ui/packages/vuu-utils/src/filters/filter-utils.ts

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,11 @@ import {
2828
TimeString,
2929
toCalendarDate,
3030
} from "../date";
31-
import { isDateTimeDataValue, toColumnDescriptor } from "../column-utils";
31+
import {
32+
isDateTimeDataValue,
33+
isTimeDataValue,
34+
toColumnDescriptor,
35+
} from "../column-utils";
3236

3337
const singleValueFilterOps = new Set<SingleValueFilterClauseOp>([
3438
"=",
@@ -213,7 +217,7 @@ const convertValueToUIFormat = (
213217
column: ColumnDescriptor,
214218
value: ColumnFilterValue,
215219
): ColumnFilterValue => {
216-
if (isValidTimeString(value)) {
220+
if (isTimeDataValue(column)) {
217221
return asTimeString(value, false);
218222
} else if (isDateTimeDataValue(column)) {
219223
return toCalendarDate(new Date(value as number)).toString();
@@ -260,9 +264,19 @@ export class ColumnFilterStore extends EventEmitter<ColumnFilterStoreEvents> {
260264
#filters = new Map<string, ColumnFilterDescriptor>();
261265
#values = new Map<string, ColumnFilterValue>();
262266

263-
constructor(query: VuuFilter = { filter: "" }) {
267+
constructor(
268+
query: VuuFilter = { filter: "" },
269+
columnDescriptors: ColumnDescriptor[] = [],
270+
) {
264271
super();
265272
this.filter = query;
273+
this.loadColumnDescriptors(columnDescriptors);
274+
}
275+
276+
private loadColumnDescriptors(columnDescriptors: ColumnDescriptor[]) {
277+
columnDescriptors.forEach((descriptor) => {
278+
this.#columns.set(descriptor.name, descriptor);
279+
});
266280
}
267281

268282
addFilter(

vuu-ui/packages/vuu-utils/test/filters/columnFilterStore.test.ts

Lines changed: 57 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { describe, expect, it, vi } from "vitest";
22
import { ColumnFilterStore } from "../../src/filters/filter-utils";
33
import { toColumnDescriptor } from "../../src/column-utils";
4+
import { ColumnDescriptor } from "@vuu-ui/vuu-table-types";
45

56
vi.mock("@vuu-ui/vuu-filter-parser", () => ({
67
...vi.importActual("@vuu-ui/vuu-filter-parser"),
@@ -32,84 +33,108 @@ vi.mock("@vuu-ui/vuu-filter-parser", () => ({
3233
},
3334
}));
3435

36+
vi.mock("../../src/date/date-utils", async () => {
37+
const actual = await vi.importActual<
38+
typeof import("../../src/date/date-utils")
39+
>("../../src/date/date-utils");
40+
return {
41+
...actual,
42+
Time: (timeString: string) => ({
43+
asDate: vi.fn(() => {
44+
const d = new Date("2025-05-15");
45+
d.setHours(Number(timeString.split(":")[0]));
46+
d.setMinutes(Number(timeString.split(":")[1]));
47+
d.setSeconds(Number(timeString.split(":")[2]));
48+
return d;
49+
}),
50+
toString: () => timeString,
51+
}),
52+
};
53+
});
54+
3555
describe("ColumnFilterStore", () => {
56+
const lastUpdateDescriptor: ColumnDescriptor = {
57+
name: "lastUpdate",
58+
serverDataType: "long",
59+
type: "time",
60+
};
61+
const priceDescriptor: ColumnDescriptor = toColumnDescriptor(
62+
"price",
63+
"double",
64+
);
65+
const ricDescriptor: ColumnDescriptor = toColumnDescriptor("ric");
66+
3667
it("adds a filter to the store", () => {
3768
const store = new ColumnFilterStore();
38-
store.addFilter(toColumnDescriptor("ric"), "=", "AAOQ.OQ");
69+
store.addFilter(ricDescriptor, "=", "AAOQ.OQ");
3970
expect(store.filter).toEqual({ filter: 'ric = "AAOQ.OQ"' });
4071
});
4172

4273
it("removes a filter from the store", () => {
4374
const store = new ColumnFilterStore();
44-
const column = toColumnDescriptor("ric");
45-
store.addFilter(column, "=", "AAOQ.OQ");
46-
store.removeFilter(column);
75+
store.addFilter(ricDescriptor, "=", "AAOQ.OQ");
76+
store.removeFilter(ricDescriptor);
4777
expect(store.filter).toEqual({ filter: "" });
4878
});
4979

5080
it("resets all filters", () => {
5181
const store = new ColumnFilterStore();
52-
store.addFilter(toColumnDescriptor("ric"), "=", "AAOQ.OQ");
53-
store.addFilter(toColumnDescriptor("price"), ">", 100);
82+
store.addFilter(ricDescriptor, "=", "AAOQ.OQ");
83+
store.addFilter(priceDescriptor, ">", 100);
5484
store.resetFilters();
5585
expect(store.filter).toEqual({ filter: "" });
5686
});
5787

5888
it("handles multiple filters with AND", () => {
5989
const store = new ColumnFilterStore();
60-
store.addFilter(toColumnDescriptor("ric"), "=", "AAOQ.OQ");
61-
store.addFilter(toColumnDescriptor("price", "double"), ">", 100);
90+
store.addFilter(ricDescriptor, "=", "AAOQ.OQ");
91+
store.addFilter(priceDescriptor, ">", 100);
6292
expect(store.filter).toEqual({ filter: 'ric = "AAOQ.OQ" and price > 100' });
6393
});
6494

6595
it("handles between operator for numeric columns", () => {
6696
const store = new ColumnFilterStore();
67-
store.addFilter(toColumnDescriptor("price"), "between", ["10", "20"]);
97+
store.addFilter(priceDescriptor, "between", ["10", "20"]);
6898
expect(store.filter).toEqual({ filter: "price >= 10 and price <= 20" });
6999
});
70100

71101
it("handles time filter with single value", () => {
72102
const store = new ColumnFilterStore();
73-
store.addFilter(
74-
{ name: "lastUpdate", serverDataType: "long", type: "time" },
75-
"=",
76-
"12:34:56",
77-
);
78-
expect(store.filter).toEqual({ filter: "lastUpdate = 1757244896000" });
103+
store.addFilter(lastUpdateDescriptor, "=", "12:34:56");
104+
expect(store.filter).toEqual({ filter: "lastUpdate = 1747308896000" });
79105
expect(store.columnValues.get("lastUpdate")).toBe("12:34:56");
80106
});
81107

82108
it("handles between operator for time columns", () => {
83109
const store = new ColumnFilterStore();
84-
store.addFilter(
85-
{ name: "lastUpdate", serverDataType: "long", type: "time" },
86-
"between",
87-
["09:00:00", "10:00:00"],
88-
);
110+
store.addFilter(lastUpdateDescriptor, "between", ["09:00:00", "10:00:00"]);
89111
expect(store.filter).toEqual({
90-
filter: "lastUpdate >= 1757232000000 and lastUpdate <= 1757235600000",
112+
filter: "lastUpdate >= 1747296000000 and lastUpdate <= 1747299600000",
91113
});
92114
});
93115

94116
it("loads filter from query string for text field", () => {
95-
const store = new ColumnFilterStore();
117+
const store = new ColumnFilterStore({ filter: "" }, [
118+
ricDescriptor,
119+
priceDescriptor,
120+
]);
96121
store.filter = { filter: 'ric = "AAOQ.OQ" and price > 100' };
97122
expect(store.filter).toEqual({ filter: 'ric = "AAOQ.OQ" and price > 100' });
98123
});
99124

100125
it("loads filter from query string for time range", () => {
101-
const store = new ColumnFilterStore();
126+
const store = new ColumnFilterStore({ filter: "" }, [lastUpdateDescriptor]);
102127
store.filter = {
103128
filter: 'lastUpdate >= "09:00:00" and lastUpdate <= "10:00:00"',
104129
};
105130
expect(store.filter).toEqual({
106-
filter: "lastUpdate >= 1757232000000 and lastUpdate <= 1757235600000",
131+
filter: "lastUpdate >= 1747296000000 and lastUpdate <= 1747299600000",
107132
});
108133
});
109134

110135
it("set filter clears previous filters", () => {
111136
const store = new ColumnFilterStore();
112-
store.addFilter(toColumnDescriptor("ric"), "=", "AAOQ.OQ");
137+
store.addFilter(ricDescriptor, "=", "AAOQ.OQ");
113138
store.filter = { filter: "price > 100" };
114139
expect(store.filter).toEqual({ filter: "price > 100" });
115140
});
@@ -118,17 +143,16 @@ describe("ColumnFilterStore", () => {
118143
const store = new ColumnFilterStore();
119144
const onChange = vi.fn();
120145
store.on("onChange", onChange);
121-
store.addFilter(toColumnDescriptor("ric"), "=", "AAOQ.OQ");
146+
store.addFilter(ricDescriptor, "=", "AAOQ.OQ");
122147
expect(onChange).toHaveBeenCalledWith({ filter: 'ric = "AAOQ.OQ"' });
123148
});
124149

125150
it("emits onChange when filter is removed", () => {
126151
const store = new ColumnFilterStore();
127-
const column = toColumnDescriptor("ric");
128152
const onChange = vi.fn();
129153
store.on("onChange", onChange);
130-
store.addFilter(column, "=", "AAOQ.OQ");
131-
store.removeFilter(column);
154+
store.addFilter(ricDescriptor, "=", "AAOQ.OQ");
155+
store.removeFilter(ricDescriptor);
132156
expect(onChange).toHaveBeenCalledWith({ filter: "" });
133157
});
134158

@@ -142,13 +166,9 @@ describe("ColumnFilterStore", () => {
142166

143167
it("returns correct columnValues after adding filters", () => {
144168
const store = new ColumnFilterStore();
145-
store.addFilter(toColumnDescriptor("ric"), "=", "AAOQ.OQ");
146-
store.addFilter(toColumnDescriptor("price"), "between", ["10", "20"]);
147-
store.addFilter(
148-
{ name: "lastUpdate", serverDataType: "long", type: "time" },
149-
"between",
150-
["09:00:00", "10:00:00"],
151-
);
169+
store.addFilter(ricDescriptor, "=", "AAOQ.OQ");
170+
store.addFilter(priceDescriptor, "between", ["10", "20"]);
171+
store.addFilter(lastUpdateDescriptor, "between", ["09:00:00", "10:00:00"]);
152172
const values = store.columnValues;
153173
expect(values.get("ric")).toBe("AAOQ.OQ");
154174
expect(values.get("price")).toEqual(["10", "20"]);
@@ -158,7 +178,7 @@ describe("ColumnFilterStore", () => {
158178

159179
it("returns empty columnValues after reset", () => {
160180
const store = new ColumnFilterStore();
161-
store.addFilter(toColumnDescriptor("ric"), "=", "AAOQ.OQ");
181+
store.addFilter(ricDescriptor, "=", "AAOQ.OQ");
162182
store.resetFilters();
163183
expect(store.columnValues.size).toBe(0);
164184
});

0 commit comments

Comments
 (0)