fix(frontend): expose namespace picker value

Signed-off-by: dongmucat <1127093059@qq.com>
This commit is contained in:
dongmucat 2026-07-27 18:02:07 +08:00
parent 9149227206
commit 1d216e73f0
4 changed files with 31 additions and 8 deletions

View file

@ -74,7 +74,8 @@ test.describe('My Namespaces super admin actions (Real API)', () => {
namespaceArchived = true
await page.goto('/dashboard/publish')
await page.getByRole('button', { name: 'Select namespace', exact: true }).click()
const namespaceTrigger = page.locator('#namespace')
await namespaceTrigger.click()
await page.getByRole('searchbox', { name: 'Search namespaces' }).fill(activeNamespace.slug)
const activeOption = page.getByRole('button', {
name: `${activeNamespace.displayName} (@${activeNamespace.slug})`,
@ -82,7 +83,8 @@ test.describe('My Namespaces super admin actions (Real API)', () => {
await expect(activeOption).toBeVisible()
await activeOption.click()
await page.getByRole('button', { name: `@${activeNamespace.slug}`, exact: true }).click()
await expect(namespaceTrigger).toContainText(`@${activeNamespace.slug}`)
await namespaceTrigger.click()
await page.getByRole('searchbox', { name: 'Search namespaces' }).fill(namespace.slug)
await expect(page.getByText('No namespaces found')).toBeVisible()
await expect(page.getByRole('button', {
@ -90,7 +92,7 @@ test.describe('My Namespaces super admin actions (Real API)', () => {
})).toHaveCount(0)
await page.goto(`/dashboard/publish?namespace=${encodeURIComponent(namespace.slug)}&visibility=PUBLIC`)
await expect(page.getByRole('button', { name: `@${namespace.slug}`, exact: true })).toBeVisible()
await expect(namespaceTrigger).toContainText(`@${namespace.slug}`)
await expect(page.getByText('The selected namespace is not active or is no longer available.')).toBeVisible()
await page.goto('/dashboard/namespaces')

View file

@ -166,6 +166,7 @@ export function PublishPage() {
<Label htmlFor="namespace" className="text-sm font-semibold font-heading">{t('publish.namespace')}</Label>
<NamespacePicker
id="namespace"
accessibleLabel={t('publish.namespace')}
value={namespaceSlug}
onValueChange={setNamespaceSlug}
status="ACTIVE"

View file

@ -79,11 +79,21 @@ describe('NamespacePicker', () => {
}, true)
})
it('forwards the trigger id for labels and stable form selectors', () => {
render(<NamespacePicker id="namespace" value="" onValueChange={vi.fn()} />)
it('keeps the current value in the accessible name when associated with a label', () => {
render(
<>
<label htmlFor="namespace">Namespace</label>
<NamespacePicker
id="namespace"
accessibleLabel="Namespace"
value="active-team"
onValueChange={vi.fn()}
/>
</>,
)
expect(document.getElementById('namespace')).toBe(
screen.getByRole('button', { name: 'namespacePicker.placeholder' }),
screen.getByRole('button', { name: 'Namespace: @active-team' }),
)
})

View file

@ -17,6 +17,7 @@ const PAGE_SIZE = 20
interface NamespacePickerProps {
id?: string
accessibleLabel?: string
value: string
onValueChange: (slug: string) => void
status?: 'ACTIVE' | 'FROZEN' | 'ARCHIVED'
@ -29,6 +30,7 @@ interface NamespacePickerProps {
*/
export function NamespacePicker({
id,
accessibleLabel,
value,
onValueChange,
status,
@ -40,6 +42,7 @@ export function NamespacePicker({
const [page, setPage] = useState(0)
const [search, setSearch] = useState('')
const debouncedSearch = useDebounce(search.trim(), 300)
const triggerText = value ? `@${value}` : emptyValueLabel ?? t('namespacePicker.placeholder')
const query = useMyNamespacesPage({
page,
size: PAGE_SIZE,
@ -60,8 +63,15 @@ export function NamespacePicker({
return (
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger asChild>
<Button id={id} type="button" variant="outline" disabled={disabled} className="w-full justify-start">
{value ? `@${value}` : emptyValueLabel ?? t('namespacePicker.placeholder')}
<Button
id={id}
type="button"
variant="outline"
disabled={disabled}
aria-label={accessibleLabel ? `${accessibleLabel}: ${triggerText}` : undefined}
className="w-full justify-start"
>
{triggerText}
</Button>
</DialogTrigger>
<DialogContent aria-label={t('namespacePicker.title')}>