|
- import type { Page } from '@playwright/test';
- import {
- adminStorageStatePath,
- expect,
- rootStorageStatePath,
- test,
- } from './fixtures/cluster';
-
- function nextBatchName(prefix: string) {
- return `${prefix}-${Date.now()}-${Math.floor(Math.random() * 1000)}`;
- }
-
- async function gotoUserPage(page: Page) {
- await page.goto('/console/user');
- await expect(page.getByTestId('user-page')).toBeVisible();
- }
-
- async function openMigrationTab(page: Page) {
- const migrationTab = page.getByTestId('user-migration-tab');
- await expect(migrationTab).toBeVisible();
- await migrationTab.click();
- await expect(page.getByTestId('user-migration-center')).toBeVisible();
- }
-
- async function selectCandidateUser(page: Page, userId: number) {
- const row = page.getByTestId(`migration-candidate-row-${userId}`);
- await expect(row).toBeVisible();
-
- const checkboxInput = row.locator('input[type="checkbox"]');
- if ((await checkboxInput.count()) > 0) {
- await checkboxInput.first().check({ force: true });
- return;
- }
-
- await row.locator('.semi-checkbox').first().click();
- }
-
- async function createBatch(
- page: Page,
- batchName: string,
- selectedUserIds: number[] = [],
- ) {
- await page.getByTestId('migration-create-batch-button').click();
- await expect(
- page.getByTestId('migration-selection-mode-group'),
- ).toBeVisible();
-
- if (selectedUserIds.length > 0) {
- await page.getByTestId('migration-selection-mode-explicit').click();
- await expect(page.getByTestId('migration-candidate-table')).toBeVisible();
- for (const userId of selectedUserIds) {
- await selectCandidateUser(page, userId);
- }
- }
- await page.getByTestId('migration-create-batch-submit').click();
-
- const nameField = page.getByTestId('migration-batch-name-field');
- await expect(nameField).toBeVisible();
- await nameField.fill(batchName);
-
- await page.getByTestId('migration-create-batch-submit').click();
- await expect(page.getByTestId('migration-batch-table')).toContainText(
- batchName,
- );
- await page.getByTestId('migration-batch-table').getByText(batchName).click();
- await expect(page.getByTestId('migration-execution-panel')).toBeVisible();
- await expect(page.getByTestId('migration-batch-detail')).toBeVisible();
- }
-
- test.describe('User Migration Access', () => {
- test.use({ storageState: adminStorageStatePath });
-
- test('non-root admin cannot see migration tab', async ({ page }) => {
- await gotoUserPage(page);
- await expect(page.getByTestId('user-migration-tab')).toHaveCount(0);
- });
- });
-
- test.describe.serial('User Migration Smoke', () => {
- test.use({ storageState: rootStorageStatePath });
-
- test('root can open migration center and create a batch', async ({
- page,
- }) => {
- const batchName = nextBatchName('ui-create');
-
- await gotoUserPage(page);
- await openMigrationTab(page);
- await createBatch(page, batchName);
-
- await expect(page.getByTestId('migration-batch-status')).toHaveText(
- 'draft',
- );
- });
-
- test('root can clear selected batch from the list', async ({ page }) => {
- const batchName = nextBatchName('ui-clear');
-
- await gotoUserPage(page);
- await openMigrationTab(page);
- await createBatch(page, batchName);
-
- await expect(page.getByTestId('migration-batch-detail')).toBeVisible();
- await page.getByTestId('migration-clear-batch-selection-button').click();
- await expect(page.getByTestId('migration-batch-detail')).toHaveCount(0);
- await expect(page.getByTestId('migration-execution-panel')).toHaveCount(0);
- });
-
- test('root can create explicit_ids batch from candidate users', async ({
- page,
- }) => {
- const batchName = nextBatchName('ui-explicit');
-
- await gotoUserPage(page);
- await openMigrationTab(page);
- await createBatch(page, batchName, [10000003, 10000004]);
-
- await expect(page.getByTestId('migration-batch-table')).toContainText(
- '指定 2 人',
- );
- await expect(page.getByTestId('migration-selection-summary')).toContainText(
- '已选 2 人',
- );
- });
-
- test('root can cancel a batch and recreate selected users in a new batch', async ({
- page,
- }) => {
- const firstBatchName = nextBatchName('ui-cancel-source');
- const secondBatchName = nextBatchName('ui-cancel-recreate');
-
- await gotoUserPage(page);
- await openMigrationTab(page);
- await createBatch(page, firstBatchName, [10000001, 10000002]);
-
- await page.getByTestId('migration-cancel-button').click();
- await expect(page.getByTestId('migration-cancel-confirm')).toBeVisible();
- await page.getByTestId('migration-cancel-confirm').click();
- await expect(page.getByTestId('migration-batch-status')).toHaveText(
- 'cancelled',
- );
-
- await createBatch(page, secondBatchName, [10000001, 10000002]);
- await expect(page.getByTestId('migration-batch-table')).toContainText(
- secondBatchName,
- );
- });
-
- test('root can scan, resolve conflicts, execute, and verify a batch', async ({
- page,
- }) => {
- const batchName = nextBatchName('ui-flow');
-
- await gotoUserPage(page);
- await openMigrationTab(page);
- await createBatch(page, batchName);
-
- await page.getByTestId('migration-scan-button').click();
- await expect(page.getByTestId('migration-batch-status')).toHaveText(
- /scanning|scanned/,
- );
- await expect(page.getByTestId('migration-batch-status')).toHaveText(
- 'scanned',
- {
- timeout: 25_000,
- },
- );
-
- await expect(page.getByTestId('migration-conflict-table')).toBeVisible();
- await page.getByTestId('migration-resolve-skip-10000003').click();
- await page.getByTestId('migration-resolve-skip-10000004').click();
- await expect(page.getByTestId('migration-batch-status')).toHaveText(
- 'ready',
- );
-
- await page.getByTestId('migration-execute-button').click();
- await expect(page.getByTestId('migration-execute-confirm')).toBeVisible();
- await page.getByTestId('migration-execute-confirm').click();
-
- await expect(page.getByTestId('migration-batch-status')).toHaveText(
- /running|completed/,
- );
- await expect(page.getByTestId('migration-batch-status')).toHaveText(
- 'completed',
- {
- timeout: 25_000,
- },
- );
-
- await page.getByTestId('migration-verify-button').click();
- await expect(
- page.getByTestId('migration-verify-results-table'),
- ).toBeVisible();
- await expect(
- page.getByTestId('migration-verify-results-table'),
- ).toContainText('10000001');
- await expect(
- page.getByTestId('migration-batch-detail-table'),
- ).toContainText('migrated');
- });
-
- test('page reload keeps batch list and detail loading available', async ({
- page,
- }) => {
- const batchName = nextBatchName('ui-refresh');
-
- await gotoUserPage(page);
- await openMigrationTab(page);
- await createBatch(page, batchName);
-
- await page.getByTestId('migration-scan-button').click();
- await expect(page.getByTestId('migration-batch-status')).toHaveText(
- 'scanned',
- {
- timeout: 25_000,
- },
- );
-
- await page.reload();
- await gotoUserPage(page);
- await openMigrationTab(page);
-
- await expect(page.getByTestId('migration-batch-table')).toContainText(
- batchName,
- );
- await page
- .getByTestId('migration-batch-table')
- .getByText(batchName)
- .click();
- await expect(page.getByTestId('migration-batch-detail')).toBeVisible();
- await expect(page.getByTestId('migration-batch-status')).toHaveText(
- 'scanned',
- );
- });
- });
|