test: cover skill query helpers

This commit is contained in:
yun-zhi-ztl 2026-03-17 11:54:16 +08:00
parent 9e916305f1
commit c8ba86e8a2
3 changed files with 66 additions and 14 deletions

View file

@ -0,0 +1,27 @@
import { describe, expect, it } from 'vitest'
import { buildSkillSearchUrl, shouldEnableNamespaceMemberCandidates } from './skill-query-helpers'
describe('buildSkillSearchUrl', () => {
it('normalizes the query and strips the namespace prefix', () => {
expect(buildSkillSearchUrl({
q: ' hello world ',
namespace: '@team-ai',
sort: 'relevance',
page: 2,
size: 12,
})).toBe('/api/web/skills?q=hello+world&namespace=team-ai&sort=relevance&page=2&size=12')
})
it('returns the base skills endpoint when no search params are provided', () => {
expect(buildSkillSearchUrl({})).toBe('/api/web/skills')
})
})
describe('shouldEnableNamespaceMemberCandidates', () => {
it('enables the query only when slug exists and search text has at least two non-space characters', () => {
expect(shouldEnableNamespaceMemberCandidates('team-ai', 'ab')).toBe(true)
expect(shouldEnableNamespaceMemberCandidates('team-ai', ' a ')).toBe(false)
expect(shouldEnableNamespaceMemberCandidates('', 'admin')).toBe(false)
expect(shouldEnableNamespaceMemberCandidates('team-ai', 'admin', false)).toBe(false)
})
})

View file

@ -0,0 +1,36 @@
import type { SearchParams } from '@/api/types'
import { WEB_API_PREFIX } from '@/api/client'
import { normalizeSearchQuery } from '@/shared/lib/search-query'
export function buildSkillSearchUrl(params: SearchParams) {
const queryParams = new URLSearchParams()
const normalizedQuery = normalizeSearchQuery(params.q ?? '')
if (normalizedQuery) {
queryParams.append('q', normalizedQuery)
}
if (params.namespace) {
const cleanNamespace = params.namespace.startsWith('@') ? params.namespace.slice(1) : params.namespace
queryParams.append('namespace', cleanNamespace)
}
if (params.sort) {
queryParams.append('sort', params.sort)
}
if (params.page !== undefined) {
queryParams.append('page', String(params.page))
}
if (params.size !== undefined) {
queryParams.append('size', String(params.size))
}
const queryString = queryParams.toString()
return queryString ? `${WEB_API_PREFIX}/skills?${queryString}` : `${WEB_API_PREFIX}/skills`
}
export function shouldEnableNamespaceMemberCandidates(slug: string, search: string, enabled = true) {
return enabled && !!slug && search.trim().length >= 2
}

View file

@ -2,23 +2,12 @@ import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
import type { SkillSummary, SkillDetail, SkillVersion, SkillVersionDetail, SkillFile, SearchParams, PagedResponse, PublishResult, Namespace, NamespaceMember, ManagedNamespace, CreateNamespaceRequest, NamespaceCandidateUser, NamespaceRole } from '@/api/types'
import { fetchJson, fetchText, getCsrfHeaders, meApi, namespaceApi, promotionApi, skillLifecycleApi, WEB_API_PREFIX } from '@/api/client'
import { appendNamespaceMember, replaceNamespaceMemberRole } from '@/shared/lib/namespace-member-cache'
import { normalizeSearchQuery } from '@/shared/lib/search-query'
import { buildSkillSearchUrl, shouldEnableNamespaceMemberCandidates } from './skill-query-helpers'
const PUBLISH_REQUEST_TIMEOUT_MS = 60_000
async function searchSkills(params: SearchParams): Promise<PagedResponse<SkillSummary>> {
const queryParams = new URLSearchParams()
const normalizedQuery = normalizeSearchQuery(params.q ?? '')
if (normalizedQuery) queryParams.append('q', normalizedQuery)
if (params.namespace) {
const cleanNamespace = params.namespace.startsWith('@') ? params.namespace.slice(1) : params.namespace
queryParams.append('namespace', cleanNamespace)
}
if (params.sort) queryParams.append('sort', params.sort)
if (params.page !== undefined) queryParams.append('page', String(params.page))
if (params.size !== undefined) queryParams.append('size', String(params.size))
return fetchJson<PagedResponse<SkillSummary>>(`${WEB_API_PREFIX}/skills?${queryParams.toString()}`)
return fetchJson<PagedResponse<SkillSummary>>(buildSkillSearchUrl(params))
}
async function getSkillDetail(namespace: string, slug: string): Promise<SkillDetail> {
@ -226,7 +215,7 @@ export function useNamespaceMemberCandidates(slug: string, search: string, enabl
return useQuery({
queryKey: ['namespaces', slug, 'member-candidates', search],
queryFn: () => searchNamespaceMemberCandidates({ slug, search }),
enabled: enabled && !!slug && search.trim().length >= 2,
enabled: shouldEnableNamespaceMemberCandidates(slug, search, enabled),
})
}