Files
OmniRoute/tests/unit/connection-status-filter-active-2526.test.ts
Diego Rodrigues de Sa e Souza c46d35bcb4 fix(dashboard): hide disabled provider connections from combo builder (#6984)
* fix(dashboard): hide disabled provider connections from combo builder

The combos page's fetchData() only filtered available connections by
testStatus ("active"/"success"), so a connection the user had
explicitly disabled (isActive: false) could still show up in the
combo builder if it carried a stale testStatus from before it was
disabled.

Add filterActiveConnections() in src/shared/utils/connectionStatus.ts
and apply it ahead of the existing testStatus filter.

Co-authored-by: itolstov <attid0@gmail.com>
Inspired-by: https://github.com/decolua/9router/pull/2526

* chore(changelog): fragment for #6984

* fix(combos): keep combos page within frozen size cap

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

* fix(combos): extract filterUsableConnections to shrink the combos god-file

The combos page only filtered provider connections on testStatus, so a
connection the user had explicitly disabled survived with a stale
"active"/"success" status. The isActive + testStatus gate now lives in
the shared connectionStatus util as filterUsableConnections(), which the
page calls in a single line.

This keeps src/app/(dashboard)/dashboard/combos/page.tsx BELOW its frozen
file-size cap (4653 vs 4655 congelado — the file shrinks by 2 lines vs the
release tip) without touching config/quality/file-size-baseline.json, as
the gate asks ("modularize/extraia (DRY) para encolher").

The regression test now exercises filterUsableConnections directly instead
of hand-mirroring the page's filter chain, so it guards the real code path.

Co-authored-by: diegosouzapw <diegosouza.pw@gmail.com>

* fix(combos): drop nullish entries in filterActiveConnections

`connection?.isActive !== false` evaluated to true for null/undefined
entries, so nullish elements survived the filter. Callers read properties
off the result — filterUsableConnections() reads `connection.testStatus`
— which would throw "TypeError: Cannot read properties of null".

Guard with an explicit truthiness check. Covered by a test that fails
against the previous predicate.

Reported-by: gemini-code-assist
Co-authored-by: diegosouzapw <diegosouza.pw@gmail.com>

---------

Co-authored-by: itolstov <attid0@gmail.com>
2026-07-17 10:39:18 -03:00

63 lines
2.7 KiB
TypeScript

import { test } from "node:test";
import assert from "node:assert/strict";
import { filterActiveConnections, filterUsableConnections } from "@/shared/utils/connectionStatus";
// Ported from decolua/9router#2526 — the combos builder listed provider
// connections the user had explicitly disabled, because the page only
// filtered on the connection's last `testStatus` and ignored `isActive`.
// A disabled connection can still carry a stale "active"/"success"
// testStatus from before it was disabled.
test("filterActiveConnections excludes explicitly disabled connections", () => {
const active = { id: "active", isActive: true };
const legacyActive = { id: "legacy" }; // no isActive field -> treated as active
const disabled = { id: "disabled", isActive: false };
assert.deepEqual(filterActiveConnections([active, disabled, legacyActive]), [
active,
legacyActive,
]);
});
test("filterActiveConnections returns an empty list for invalid input", () => {
assert.deepEqual(filterActiveConnections(undefined), []);
assert.deepEqual(filterActiveConnections(null), []);
});
test("filterActiveConnections drops nullish entries instead of passing them through", () => {
// A nullish element must not survive: callers read properties off the
// result (e.g. `connection.testStatus`) and would throw a TypeError.
const active = { id: "active", isActive: true };
assert.deepEqual(filterActiveConnections([null, active, undefined]), [active]);
assert.doesNotThrow(() => filterUsableConnections([null, undefined]));
assert.deepEqual(filterUsableConnections([null, { id: "ok", testStatus: "active" }]), [
{ id: "ok", testStatus: "active" },
]);
});
test("filterUsableConnections applies the isActive gate before the testStatus gate", () => {
// Regression for the exact bug: a disabled connection with a stale
// "active" testStatus must NOT survive the combined filter that
// src/app/(dashboard)/dashboard/combos/page.tsx fetchData() calls.
const connections = [
{ id: "healthy", isActive: true, testStatus: "active" },
{ id: "healthy-success", isActive: true, testStatus: "success" },
{ id: "disabled-but-stale-status", isActive: false, testStatus: "active" },
{ id: "disabled-success-status", isActive: false, testStatus: "success" },
{ id: "enabled-not-tested", isActive: true, testStatus: "untested" },
{ id: "legacy-no-isActive", testStatus: "active" },
];
assert.deepEqual(
filterUsableConnections(connections).map((c) => c.id),
["healthy", "healthy-success", "legacy-no-isActive"]
);
});
test("filterUsableConnections returns an empty list for invalid input", () => {
assert.deepEqual(filterUsableConnections(undefined), []);
assert.deepEqual(filterUsableConnections(null), []);
});