mirror of
https://github.com/iflytek/skillhub.git
synced 2026-10-15 04:18:20 +00:00
test(web): align namespace flows with unified space navigation
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
This commit is contained in:
parent
3bfd8a322a
commit
1d7daeb150
7 changed files with 95 additions and 36 deletions
|
|
@ -50,7 +50,9 @@ test.describe('Batch Import Members (Real API)', () => {
|
|||
}
|
||||
|
||||
await page.goto(`/dashboard/namespaces/${namespace.slug}/members`)
|
||||
await expect(page.getByRole('heading', { name: 'Member Management' })).toBeVisible()
|
||||
await expect(page.getByRole('heading', { name: namespace.displayName, exact: true })).toBeVisible()
|
||||
await expect(page.getByRole('navigation', { name: 'Space management' })
|
||||
.getByRole('link', { name: 'Members', exact: true })).toHaveAttribute('aria-current', 'page')
|
||||
|
||||
const batchButton = page.getByRole('button', { name: 'Batch Import' })
|
||||
await expect(batchButton).toBeVisible()
|
||||
|
|
|
|||
|
|
@ -43,6 +43,8 @@ test.describe('Dashboard Routes (Real API)', () => {
|
|||
await expect(page.getByRole('heading', { name: 'Namespace not found' })).toBeVisible()
|
||||
|
||||
await page.goto('/dashboard/namespaces/e2e-missing-namespace/reviews')
|
||||
await expect(page.getByRole('heading', { name: 'Namespace Reviews' })).toBeVisible()
|
||||
const reviewSection = page.getByRole('region', { name: 'Namespace Reviews' })
|
||||
await expect(reviewSection).toBeVisible()
|
||||
await expect(reviewSection.getByText('No review records', { exact: true })).toBeVisible()
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,13 +1,31 @@
|
|||
import { expect, test } from '@playwright/test'
|
||||
import { expect, test, type Page } from '@playwright/test'
|
||||
import { setEnglishLocale } from './helpers/auth-fixtures'
|
||||
import { E2eTestDataBuilder } from './helpers/test-data-builder'
|
||||
import { loginWithCredentials } from './helpers/session'
|
||||
|
||||
async function findNamespaceCard(page: Page, slug: string) {
|
||||
await page.goto('/dashboard/namespaces')
|
||||
await expect(page.getByRole('heading', { name: 'My Namespaces' })).toBeVisible()
|
||||
const card = page.getByTestId(`namespace-card-${slug}`)
|
||||
const next = page.getByRole('button', { name: 'Next', exact: true })
|
||||
const firstCard = page.locator('[data-testid^="namespace-card-"]').first()
|
||||
await expect(firstCard).toBeVisible()
|
||||
while (!(await card.isVisible()) && await next.count() > 0 && await next.isEnabled()) {
|
||||
const previousId = await firstCard.getAttribute('data-testid')
|
||||
await next.click()
|
||||
await expect(firstCard).not.toHaveAttribute('data-testid', previousId!)
|
||||
}
|
||||
await expect(card.getByText(`@${slug}`, { exact: true })).toBeVisible()
|
||||
return card
|
||||
}
|
||||
|
||||
test.describe('My Namespaces Data (Real API)', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
test.beforeEach(async ({ page }, testInfo) => {
|
||||
await setEnglishLocale(page)
|
||||
await page.context().setExtraHTTPHeaders({
|
||||
'X-Mock-User-Id': 'local-admin',
|
||||
})
|
||||
await loginWithCredentials(page, {
|
||||
username: process.env.E2E_ADMIN_USERNAME ?? process.env.BOOTSTRAP_ADMIN_USERNAME ?? 'admin',
|
||||
password: process.env.E2E_ADMIN_PASSWORD ?? process.env.BOOTSTRAP_ADMIN_PASSWORD ?? 'ChangeMe!2026',
|
||||
}, testInfo)
|
||||
})
|
||||
|
||||
test('shows namespace created by request helper', async ({ page }, testInfo) => {
|
||||
|
|
@ -15,11 +33,8 @@ test.describe('My Namespaces Data (Real API)', () => {
|
|||
await builder.init()
|
||||
|
||||
try {
|
||||
const namespace = await builder.ensureWritableNamespace()
|
||||
await page.goto('/dashboard/namespaces')
|
||||
|
||||
await expect(page.getByRole('heading', { name: 'My Namespaces' })).toBeVisible()
|
||||
await expect(page.getByText(`@${namespace.slug}`)).toBeVisible()
|
||||
const namespace = await builder.createNamespace('e2e-list')
|
||||
await findNamespaceCard(page, namespace.slug)
|
||||
} finally {
|
||||
await builder.cleanup()
|
||||
}
|
||||
|
|
@ -32,11 +47,12 @@ test.describe('My Namespaces Data (Real API)', () => {
|
|||
try {
|
||||
const namespace = await builder.createNamespace('e2e-delete')
|
||||
|
||||
await page.goto('/dashboard/namespaces')
|
||||
|
||||
const namespaceCard = page.getByTestId(`namespace-card-${namespace.slug}`)
|
||||
await expect(namespaceCard.getByText(`@${namespace.slug}`)).toBeVisible()
|
||||
const namespaceCard = await findNamespaceCard(page, namespace.slug)
|
||||
|
||||
await namespaceCard.getByRole('button', { name: 'Enter space', exact: true }).click()
|
||||
await page.getByRole('navigation', { name: 'Space management' })
|
||||
.getByRole('link', { name: 'Settings', exact: true }).click()
|
||||
await expect(page.getByRole('heading', { name: 'Space lifecycle', exact: true })).toBeVisible()
|
||||
await page.getByTestId(`delete-namespace-${namespace.slug}`).click()
|
||||
await expect(page.getByTestId('namespace-action-dialog-delete')).toBeVisible()
|
||||
|
||||
|
|
@ -48,7 +64,8 @@ test.describe('My Namespaces Data (Real API)', () => {
|
|||
const deleteResponse = await deleteResponsePromise
|
||||
|
||||
expect(deleteResponse.ok()).toBeTruthy()
|
||||
await expect(page.getByText(`@${namespace.slug}`)).toHaveCount(0)
|
||||
await expect(page).toHaveURL(/\/dashboard\/namespaces$/)
|
||||
await expect(page.getByTestId(`namespace-card-${namespace.slug}`)).toHaveCount(0)
|
||||
} finally {
|
||||
await builder.cleanup()
|
||||
}
|
||||
|
|
@ -66,10 +83,11 @@ test.describe('My Namespaces Data (Real API)', () => {
|
|||
description: 'Prevents namespace deletion during Playwright validation',
|
||||
})
|
||||
|
||||
await page.goto('/dashboard/namespaces')
|
||||
|
||||
const namespaceCard = page.getByTestId(`namespace-card-${namespace.slug}`)
|
||||
await expect(namespaceCard.getByText(`@${namespace.slug}`)).toBeVisible()
|
||||
const namespaceCard = await findNamespaceCard(page, namespace.slug)
|
||||
await namespaceCard.getByRole('button', { name: 'Enter space', exact: true }).click()
|
||||
await page.getByRole('navigation', { name: 'Space management' })
|
||||
.getByRole('link', { name: 'Settings', exact: true }).click()
|
||||
await expect(page.getByRole('heading', { name: 'Space lifecycle', exact: true })).toBeVisible()
|
||||
await expect(page.getByTestId(`delete-namespace-${namespace.slug}`)).toHaveCount(0)
|
||||
} finally {
|
||||
await builder.cleanup()
|
||||
|
|
|
|||
|
|
@ -18,8 +18,11 @@ test.describe('Namespace Members Data (Real API)', () => {
|
|||
|
||||
await page.goto(`/dashboard/namespaces/${namespace.slug}/members`)
|
||||
|
||||
await expect(page.getByRole('heading', { name: 'Member Management' })).toBeVisible()
|
||||
await expect(page.getByText(`@${namespace.slug}`).first()).toBeVisible()
|
||||
await expect(page.getByRole('heading', { name: namespace.displayName, exact: true })).toBeVisible()
|
||||
await expect(page.getByRole('navigation', { name: 'Space management' })
|
||||
.getByRole('link', { name: 'Members', exact: true })).toHaveAttribute('aria-current', 'page')
|
||||
await expect(page.getByText(`@${namespace.slug}`, { exact: true })).toBeVisible()
|
||||
await expect(page.getByRole('table')).toBeVisible()
|
||||
} finally {
|
||||
await builder.cleanup()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,10 @@ test.describe('Namespace Review Detail Access (Real API)', () => {
|
|||
|
||||
await page.goto(`/dashboard/namespaces/${seeded.namespace.slug}/reviews`)
|
||||
|
||||
await expect(page.getByRole('heading', { name: 'Namespace Reviews' })).toBeVisible()
|
||||
await expect(page.getByRole('heading', { name: seeded.namespace.displayName, exact: true })).toBeVisible()
|
||||
await expect(page.getByRole('navigation', { name: 'Space management' })
|
||||
.getByRole('link', { name: 'Reviews', exact: true })).toHaveAttribute('aria-current', 'page')
|
||||
await expect(page.getByRole('region', { name: 'Namespace Reviews' })).toBeVisible()
|
||||
await expect(page.getByText(`${seeded.namespace.slug}/${seeded.skill.slug}`)).toBeVisible()
|
||||
|
||||
await page.getByRole('link', { name: 'Open review' }).first().click()
|
||||
|
|
@ -37,7 +40,12 @@ test.describe('Namespace Review Detail Access (Real API)', () => {
|
|||
await page.goto('/dashboard/reviews')
|
||||
|
||||
await expect(page).toHaveURL(/\/dashboard\/namespaces\/.+\/reviews$/)
|
||||
await expect(page.getByRole('heading', { name: 'Namespace Reviews' })).toBeVisible()
|
||||
const selectedSlug = decodeURIComponent(new URL(page.url()).pathname.split('/')[3])
|
||||
await expect(page.getByRole('heading', { level: 1 })).toBeVisible()
|
||||
await expect(page.getByText(`@${selectedSlug}`, { exact: true })).toBeVisible()
|
||||
await expect(page.getByRole('navigation', { name: 'Space management' })
|
||||
.getByRole('link', { name: 'Reviews', exact: true })).toHaveAttribute('aria-current', 'page')
|
||||
await expect(page.getByRole('region', { name: 'Namespace Reviews' })).toBeVisible()
|
||||
} finally {
|
||||
await seeded?.cleanup()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,8 +15,12 @@ test.describe('Namespace Reviews Data (Real API)', () => {
|
|||
seeded = await createNamespaceReviewData(browser, page, testInfo)
|
||||
await page.goto(`/dashboard/namespaces/${seeded.namespace.slug}/reviews`)
|
||||
|
||||
await expect(page.getByRole('heading', { name: 'Namespace Reviews' })).toBeVisible()
|
||||
await expect(page.getByText(`Review tasks for ${seeded.namespace.displayName}`)).toBeVisible()
|
||||
await expect(page.getByRole('heading', { name: seeded.namespace.displayName, exact: true })).toBeVisible()
|
||||
await expect(page.getByRole('navigation', { name: 'Space management' })
|
||||
.getByRole('link', { name: 'Reviews', exact: true })).toHaveAttribute('aria-current', 'page')
|
||||
await expect(page.getByRole('region', { name: 'Namespace Reviews' })).toBeVisible()
|
||||
await expect(page.getByText(`${seeded.namespace.slug}/${seeded.skill.slug}`, { exact: true })).toBeVisible()
|
||||
await expect(page.getByRole('combobox', { name: 'Review status' })).toHaveText('Pending')
|
||||
} finally {
|
||||
await seeded?.cleanup()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,15 @@
|
|||
import { expect, test } from '@playwright/test'
|
||||
import { setEnglishLocale } from './helpers/auth-fixtures'
|
||||
import { registerSession } from './helpers/session'
|
||||
import { loginWithCredentials } from './helpers/session'
|
||||
import { E2eTestDataBuilder } from './helpers/test-data-builder'
|
||||
|
||||
test.describe('Namespace Skill List Pagination (Real API)', () => {
|
||||
test.beforeEach(async ({ page }, testInfo) => {
|
||||
await setEnglishLocale(page)
|
||||
await registerSession(page, testInfo)
|
||||
await loginWithCredentials(page, {
|
||||
username: process.env.E2E_ADMIN_USERNAME ?? process.env.BOOTSTRAP_ADMIN_USERNAME ?? 'admin',
|
||||
password: process.env.E2E_ADMIN_PASSWORD ?? process.env.BOOTSTRAP_ADMIN_PASSWORD ?? 'ChangeMe!2026',
|
||||
}, testInfo)
|
||||
})
|
||||
|
||||
test('shows namespace page with skills and no pagination when under 20 skills', async ({ page }, testInfo) => {
|
||||
|
|
@ -14,17 +17,28 @@ test.describe('Namespace Skill List Pagination (Real API)', () => {
|
|||
await builder.init()
|
||||
|
||||
try {
|
||||
const namespace = await builder.ensureWritableNamespace()
|
||||
const namespace = await builder.createNamespace('e2e-pagination-small')
|
||||
await builder.publishSkill(namespace.slug)
|
||||
|
||||
const searchResponsePromise = page.waitForResponse((response) => {
|
||||
const url = new URL(response.url())
|
||||
return url.pathname === '/api/web/skills'
|
||||
&& url.searchParams.get('namespace') === namespace.slug
|
||||
})
|
||||
await page.goto(`/space/${namespace.slug}`)
|
||||
const searchResponse = await searchResponsePromise
|
||||
expect(searchResponse.ok()).toBeTruthy()
|
||||
const search: { data: { total: number } } = await searchResponse.json()
|
||||
expect(search.data.total).toBeLessThanOrEqual(20)
|
||||
|
||||
await expect(page.getByText(`@${namespace.slug}`).first()).toBeVisible()
|
||||
await expect(page.getByRole('heading', { name: 'Skills', exact: true })).toBeVisible()
|
||||
|
||||
// Verify pagination controls do not appear when there are fewer than 20 skills
|
||||
await expect(page.getByRole('button', { name: 'Previous' })).toHaveCount(0)
|
||||
await expect(page.getByRole('button', { name: 'Next' })).toHaveCount(0)
|
||||
// Fresh namespace keeps this fixture independent of previous tests.
|
||||
const skillList = page.getByRole('heading', { name: 'Skills', exact: true }).locator('..')
|
||||
await expect(skillList.getByRole('navigation', { name: 'Pagination', exact: true })).toHaveCount(0)
|
||||
await expect(skillList.getByRole('button', { name: 'Previous', exact: true })).toHaveCount(0)
|
||||
await expect(skillList.getByRole('button', { name: 'Next', exact: true })).toHaveCount(0)
|
||||
} finally {
|
||||
await builder.cleanup()
|
||||
}
|
||||
|
|
@ -35,7 +49,7 @@ test.describe('Namespace Skill List Pagination (Real API)', () => {
|
|||
await builder.init()
|
||||
|
||||
try {
|
||||
const namespace = await builder.ensureWritableNamespace()
|
||||
const namespace = await builder.createNamespace('e2e-pagination-many')
|
||||
|
||||
// Build a fake skill list to simulate >20 skills without hitting rate limits.
|
||||
const fakeSkill = (i: number) => ({
|
||||
|
|
@ -77,8 +91,10 @@ test.describe('Namespace Skill List Pagination (Real API)', () => {
|
|||
await expect(page.getByRole('heading', { name: 'Skills', exact: true })).toBeVisible()
|
||||
|
||||
// Verify pagination controls appear
|
||||
const previousButton = page.getByRole('button', { name: 'Previous' }).first()
|
||||
const nextButton = page.getByRole('button', { name: 'Next' }).first()
|
||||
const skillList = page.getByRole('heading', { name: 'Skills', exact: true }).locator('..')
|
||||
const pagination = skillList.getByRole('navigation', { name: 'Pagination', exact: true })
|
||||
const previousButton = pagination.getByRole('button', { name: 'Previous', exact: true })
|
||||
const nextButton = pagination.getByRole('button', { name: 'Next', exact: true })
|
||||
|
||||
await expect(previousButton).toBeVisible()
|
||||
await expect(nextButton).toBeVisible()
|
||||
|
|
@ -87,16 +103,22 @@ test.describe('Namespace Skill List Pagination (Real API)', () => {
|
|||
await expect(previousButton).toBeDisabled()
|
||||
await expect(nextButton).toBeEnabled()
|
||||
|
||||
await expect(skillList.getByText('Fake Skill 0', { exact: true })).toBeVisible()
|
||||
// Navigate to second page
|
||||
await nextButton.click()
|
||||
|
||||
// Second page: Previous should be enabled
|
||||
await expect(previousButton).toBeEnabled()
|
||||
await expect(nextButton).toBeDisabled()
|
||||
await expect(skillList.getByText('Fake Skill 20', { exact: true })).toBeVisible()
|
||||
await expect(skillList.getByText('Fake Skill 0', { exact: true })).toHaveCount(0)
|
||||
await expect(pagination.getByRole('button', { name: 'Go to page 2', exact: true })).toHaveAttribute('aria-current', 'page')
|
||||
|
||||
// Navigate back to first page
|
||||
await previousButton.click()
|
||||
await expect(previousButton).toBeDisabled()
|
||||
await expect(nextButton).toBeEnabled()
|
||||
await expect(skillList.getByText('Fake Skill 0', { exact: true })).toBeVisible()
|
||||
} finally {
|
||||
await builder.cleanup()
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue