From 899d19881f176d69e138091a3e2847ff3bdffdfa Mon Sep 17 00:00:00 2001 From: Austin Liu <193228693+Dingding-leo@users.noreply.github.com> Date: Tue, 28 Jul 2026 00:00:39 +0930 Subject: [PATCH] Train 1D: merge via --admin on .113 validation Squash merge from local merge-train (Hard Rule owner-approved). Tip 029cdf4215cf465f0e1716ac9f84a84692b1e881 validated on 192.168.0.113: 26631/26653 pass. --- .../dashboard/providers/providerPageUtils.ts | 6 ++--- src/shared/utils/turkishText.ts | 16 +++++++++++ tests/unit/turkishText.test.ts | 27 +++++++++++++++++++ 3 files changed, 46 insertions(+), 3 deletions(-) diff --git a/src/app/(dashboard)/dashboard/providers/providerPageUtils.ts b/src/app/(dashboard)/dashboard/providers/providerPageUtils.ts index 31f1abf806..72fe8f163c 100644 --- a/src/app/(dashboard)/dashboard/providers/providerPageUtils.ts +++ b/src/app/(dashboard)/dashboard/providers/providerPageUtils.ts @@ -13,7 +13,7 @@ import { } from "@/shared/constants/providers"; import { getModelsByProviderId } from "@/shared/constants/models"; import { providerHasServiceKind } from "@/lib/providers/serviceKindIndex"; -import { compareTr, matchesSearch } from "@/shared/utils/turkishText"; +import { compareTr, matchesAnyToken, matchesSearch } from "@/shared/utils/turkishText"; import { fetchWithTimeout } from "@/shared/utils/fetchTimeout"; import type { ProviderDisplayMode } from "./providerPageStorage"; import { isFeaturedProviderId } from "./featuredProviders"; @@ -342,8 +342,8 @@ export function filterConfiguredProviderEntries( filtered = filtered.filter((entry) => { const provider = entry.provider as Record; return ( - matchesSearch(String(provider.name || ""), searchQuery) || - matchesSearch(entry.providerId, searchQuery) + matchesAnyToken(String(provider.name || ""), searchQuery) || + matchesAnyToken(entry.providerId, searchQuery) ); }); } diff --git a/src/shared/utils/turkishText.ts b/src/shared/utils/turkishText.ts index 6c73b1ec3d..af55400ed6 100644 --- a/src/shared/utils/turkishText.ts +++ b/src/shared/utils/turkishText.ts @@ -47,6 +47,22 @@ export function matchesSearch( return normalizeForSearch(text).includes(q); } +/** + * Checks if `text` matches any whitespace-separated token in `query`. + * Returns `true` if `query` is empty or if any token is found in `text`. + */ +export function matchesAnyToken( + text: string | null | undefined, + query: string | null | undefined +): boolean { + const q = normalizeForSearch(query); + if (!q) return true; + const tokens = q.split(/\s+/).filter(Boolean); + if (tokens.length === 0) return true; + const normText = normalizeForSearch(text); + return tokens.some((token) => normText.includes(token)); +} + const trCollator = new Intl.Collator("tr", { sensitivity: "base", numeric: true, diff --git a/tests/unit/turkishText.test.ts b/tests/unit/turkishText.test.ts index 280f39594d..9d42db99cf 100644 --- a/tests/unit/turkishText.test.ts +++ b/tests/unit/turkishText.test.ts @@ -3,6 +3,7 @@ import assert from "node:assert/strict"; import { normalizeForSearch, matchesSearch, + matchesAnyToken, compareTr, } from "../../src/shared/utils/turkishText.ts"; @@ -73,3 +74,29 @@ test("compareTr: null/undefined argümanları güvenli (?? '' guard)", () => { assert.equal(compareTr("a", null) > 0, true); assert.equal(compareTr(null, undefined), 0); }); + +test("matchesAnyToken: tek token eşleşmesi", () => { + assert.equal(matchesAnyToken("pollinations", "pollinations sambanova"), true); +}); + +test("matchesAnyToken: birden fazla token'dan biri eşleşir", () => { + assert.equal(matchesAnyToken("sambanova", "pollinations sambanova huggingface"), true); +}); + +test("matchesAnyToken: hiçbir token eşleşmez", () => { + assert.equal(matchesAnyToken("openai", "pollinations sambanova"), false); +}); + +test("matchesAnyToken: Türkçe ve aksan duyarsız çoklu token eşleşmesi", () => { + assert.equal(matchesAnyToken("İstanbul Provider", "ankara istanbul"), true); +}); + +test("matchesAnyToken: boş veya yalnızca boşluk sorgusu her şeyi eşler", () => { + assert.equal(matchesAnyToken("herhangi", ""), true); + assert.equal(matchesAnyToken("herhangi", " "), true); +}); + +test("matchesAnyToken: null/undefined text/query güvenli", () => { + assert.equal(matchesAnyToken(null, "test"), false); + assert.equal(matchesAnyToken("test", null), true); +});