mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-09-20 22:02:19 +03:00
fix(dashboard): make model auto-fetch order independent (#11805)
Obrigado! Validado em lote combinado (8 PRs, release/v3.8.51): - TDD claro: implementação antiga falhava 1/5 no caso "enabled-first mixed" (postava `/sync-models?mode=sync` incorretamente); implementação corrigida passa 5/5. - Avalia todas as conexões ativas antes de tratar o auto-fetch como habilitado, tornando o resultado independente da ordem de conexões API/DB. - `tests/unit/ui/use-provider-models-auto-fetch.test.tsx` — verde via vitest. - Gates estáticos do lote OK (incluindo confirmação de que o único erro de lint pré-existente no arquivo tocado apenas mudou de linha 130→137 por causa das linhas adicionadas por esta PR — sem regressão real).
This commit is contained in:
@@ -77,11 +77,18 @@ export function useProviderModels(providerId: string): UseProviderModelsResult {
|
||||
}>;
|
||||
};
|
||||
if (cancelled) return;
|
||||
const providerConn = connData.connections?.find(
|
||||
const providerConnections = connData.connections?.filter(
|
||||
(c) => (c.provider === providerId || c.id === providerId) && c.isActive !== false
|
||||
);
|
||||
const providerConn = providerConnections?.[0];
|
||||
|
||||
if (providerConn?.providerSpecificData?.autoFetchModels === true && !cancelled) {
|
||||
if (
|
||||
providerConn &&
|
||||
providerConnections.every(
|
||||
(connection) => connection.providerSpecificData?.autoFetchModels === true
|
||||
) &&
|
||||
!cancelled
|
||||
) {
|
||||
const syncRes = await fetch(
|
||||
`/api/providers/${encodeURIComponent(providerConn.id)}/sync-models?mode=sync`,
|
||||
{ method: "POST" }
|
||||
|
||||
@@ -6,9 +6,8 @@ vi.mock("next-intl", () => ({
|
||||
useTranslations: () => (key: string) => key,
|
||||
}));
|
||||
|
||||
const { useProviderModels } = await import(
|
||||
"@/app/(dashboard)/dashboard/providers/hooks/useProviderModels"
|
||||
);
|
||||
const { useProviderModels } =
|
||||
await import("@/app/(dashboard)/dashboard/providers/hooks/useProviderModels");
|
||||
|
||||
function createResponse(body: unknown, ok = true): Response {
|
||||
return {
|
||||
@@ -17,6 +16,15 @@ function createResponse(body: unknown, ok = true): Response {
|
||||
} as Response;
|
||||
}
|
||||
|
||||
function connection(id: string, autoFetchModels: boolean, isActive = true) {
|
||||
return {
|
||||
id,
|
||||
provider: "custom-provider",
|
||||
isActive,
|
||||
providerSpecificData: { autoFetchModels },
|
||||
};
|
||||
}
|
||||
|
||||
async function renderProviderModels(providerId = "custom-provider") {
|
||||
const container = document.createElement("div");
|
||||
document.body.appendChild(container);
|
||||
@@ -101,8 +109,71 @@ describe("useProviderModels upstream auto-fetch", () => {
|
||||
const mounted = await renderProviderModels();
|
||||
await flushQueuedSync();
|
||||
|
||||
expect(fetchMock).toHaveBeenCalledWith("/api/providers/connection-1/sync-models?mode=sync", {
|
||||
method: "POST",
|
||||
});
|
||||
mounted.unmount();
|
||||
});
|
||||
|
||||
it.each([
|
||||
[
|
||||
"enabled connection first",
|
||||
[connection("connection-on", true), connection("connection-off", false)],
|
||||
],
|
||||
[
|
||||
"disabled connection first",
|
||||
[connection("connection-off", false), connection("connection-on", true)],
|
||||
],
|
||||
])("does not synchronize a mixed provider when the %s", async (_name, connections) => {
|
||||
const fetchMock = vi.fn(async (input: string) => {
|
||||
if (input.startsWith("/api/v1/providers/")) {
|
||||
return createResponse({ data: [] });
|
||||
}
|
||||
if (input === "/api/providers") {
|
||||
return createResponse({ connections });
|
||||
}
|
||||
throw new Error(`Unexpected request: ${input}`);
|
||||
});
|
||||
vi.stubGlobal("fetch", fetchMock);
|
||||
|
||||
const mounted = await renderProviderModels();
|
||||
try {
|
||||
await flushQueuedSync();
|
||||
|
||||
expect(fetchMock).not.toHaveBeenCalledWith(
|
||||
expect.stringContaining("/sync-models?mode=sync"),
|
||||
expect.anything()
|
||||
);
|
||||
} finally {
|
||||
mounted.unmount();
|
||||
}
|
||||
});
|
||||
|
||||
it("ignores inactive opt-outs when every active connection is enabled", async () => {
|
||||
const fetchMock = vi.fn(async (input: string) => {
|
||||
if (input.startsWith("/api/v1/providers/")) {
|
||||
return createResponse({ data: [] });
|
||||
}
|
||||
if (input === "/api/providers") {
|
||||
return createResponse({
|
||||
connections: [
|
||||
connection("connection-inactive", false, false),
|
||||
connection("connection-active", true),
|
||||
],
|
||||
});
|
||||
}
|
||||
if (input === "/api/providers/connection-active/sync-models?mode=sync") {
|
||||
return createResponse({});
|
||||
}
|
||||
throw new Error(`Unexpected request: ${input}`);
|
||||
});
|
||||
vi.stubGlobal("fetch", fetchMock);
|
||||
|
||||
const mounted = await renderProviderModels();
|
||||
await flushQueuedSync();
|
||||
|
||||
expect(fetchMock).toHaveBeenCalledWith(
|
||||
"/api/providers/connection-1/sync-models?mode=sync",
|
||||
"/api/providers/connection-active/sync-models?mode=sync",
|
||||
{ method: "POST" }
|
||||
);
|
||||
mounted.unmount();
|
||||
|
||||
Reference in New Issue
Block a user