Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 64891bd260 | |||
| f460729d8d |
@@ -178,9 +178,6 @@ vi.mock("../db/index.js", () => {
|
|||||||
const staff = new Proxy({ _name: "staff" }, { get: (t, p) => p === "_name" ? "staff" : {} });
|
const staff = new Proxy({ _name: "staff" }, { get: (t, p) => p === "_name" ? "staff" : {} });
|
||||||
const services = new Proxy({ _name: "services" }, { get: (t, p) => p === "_name" ? "services" : {} });
|
const services = new Proxy({ _name: "services" }, { get: (t, p) => p === "_name" ? "services" : {} });
|
||||||
|
|
||||||
// Tracks { [tableName]: { [alias]: SQLExpression } } for the current select() call
|
|
||||||
let selectedColumns: Record<string, Record<string, unknown>> = {};
|
|
||||||
|
|
||||||
function makeChainable(rows: unknown[]) {
|
function makeChainable(rows: unknown[]) {
|
||||||
const arr = rows as unknown[];
|
const arr = rows as unknown[];
|
||||||
return new Proxy(arr, {
|
return new Proxy(arr, {
|
||||||
@@ -191,67 +188,25 @@ vi.mock("../db/index.js", () => {
|
|||||||
if (prop === Symbol.iterator) {
|
if (prop === Symbol.iterator) {
|
||||||
return function* () { for (const v of target) yield v; };
|
return function* () { for (const v of target) yield v; };
|
||||||
}
|
}
|
||||||
if (prop === Symbol.asyncIterator) {
|
|
||||||
return async function* () { for (const v of target) yield v; };
|
|
||||||
}
|
|
||||||
// @ts-expect-error proxy
|
// @ts-expect-error proxy
|
||||||
return target[prop];
|
return target[prop];
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// sql mock: returns an object with .as() so drizzle's select() can alias it
|
|
||||||
function sqlMock(_strings: TemplateStringsArray, ..._params: unknown[]) {
|
|
||||||
const queryString = _strings[0];
|
|
||||||
const asFn = (alias: string) => ({
|
|
||||||
sql: { queryChunks: [_strings[0]] },
|
|
||||||
fieldAlias: alias,
|
|
||||||
getSQL() { return this.sql; },
|
|
||||||
});
|
|
||||||
return { queryChunks: [queryString], as: asFn };
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
getDb: () => ({
|
getDb: () => ({
|
||||||
select: (cols?: Record<string, unknown>) => {
|
select: () => ({
|
||||||
selectedColumns = {};
|
from: (table: unknown) => {
|
||||||
if (cols) {
|
const name = (table as { _name?: string })._name;
|
||||||
// Inspect cols to find sql-aliased expressions and their aliases
|
if (name === "pets") return makeChainable(mock.pets);
|
||||||
for (const [alias, expr] of Object.entries(cols)) {
|
if (name === "appointments") return makeChainable(mock.appointments);
|
||||||
if (expr && typeof expr === "object" && "as" in expr && typeof (expr as Record<string, unknown>).as === "function") {
|
if (name === "groomingVisitLogs") return makeChainable(mock.groomingLogs);
|
||||||
const aliased = (expr as { as: (a: string) => { fieldAlias: string; sql: unknown } }).as(alias);
|
if (name === "staff") return makeChainable(mock.staffMembers);
|
||||||
// Detect count(*) queries
|
if (name === "services") return makeChainable(mock.services);
|
||||||
if (typeof aliased.sql === "object" && aliased.sql !== null && "queryChunks" in (aliased.sql as Record<string, unknown>) && String((aliased.sql as { queryChunks?: unknown[] }).queryChunks).includes("count")) {
|
return makeChainable([]);
|
||||||
// Store count query intent — we'll resolve it in from()
|
},
|
||||||
if (!selectedColumns["appointments"]) selectedColumns["appointments"] = {};
|
}),
|
||||||
selectedColumns["appointments"][alias] = { _isCountQuery: true };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
from: (table: unknown) => {
|
|
||||||
const name = (table as { _name?: string })._name;
|
|
||||||
const tableCols = selectedColumns[name] || {};
|
|
||||||
// If this table has a count query, return computed count result
|
|
||||||
const countQueryEntry = Object.entries(tableCols).find(([, v]) =>
|
|
||||||
typeof v === "object" && v !== null && "_isCountQuery" in v
|
|
||||||
);
|
|
||||||
if (countQueryEntry) {
|
|
||||||
const [countAlias] = countQueryEntry;
|
|
||||||
const count = (name === "appointments" ? mock.appointments : [])
|
|
||||||
.filter((row: Record<string, unknown>) => row.status === "completed").length;
|
|
||||||
return makeChainable([{ [countAlias]: count }]);
|
|
||||||
}
|
|
||||||
if (name === "pets") return makeChainable(mock.pets);
|
|
||||||
if (name === "appointments") return makeChainable(mock.appointments);
|
|
||||||
if (name === "groomingVisitLogs") return makeChainable(mock.groomingLogs);
|
|
||||||
if (name === "staff") return makeChainable(mock.staffMembers);
|
|
||||||
if (name === "services") return makeChainable(mock.services);
|
|
||||||
return makeChainable([]);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
insert: () => ({ values: () => ({ returning: () => [{}] }) }),
|
insert: () => ({ values: () => ({ returning: () => [{}] }) }),
|
||||||
update: () => ({ set: () => ({ where: () => ({ returning: () => [{}] }) }) }),
|
update: () => ({ set: () => ({ where: () => ({ returning: () => [{}] }) }) }),
|
||||||
delete: () => ({ where: () => ({ returning: () => [{}] }) }),
|
delete: () => ({ where: () => ({ returning: () => [{}] }) }),
|
||||||
@@ -267,7 +222,7 @@ vi.mock("../db/index.js", () => {
|
|||||||
exists: vi.fn(() => true),
|
exists: vi.fn(() => true),
|
||||||
gte: vi.fn((a: unknown, b: unknown) => ({ col: a, val: b })),
|
gte: vi.fn((a: unknown, b: unknown) => ({ col: a, val: b })),
|
||||||
or: vi.fn((a: unknown, b: unknown) => [a, b]),
|
or: vi.fn((a: unknown, b: unknown) => [a, b]),
|
||||||
sql: sqlMock,
|
sql: vi.fn((str: string) => str),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user