shell.spec.ts 3.78 KB
import { test, expect, type Page } from '@playwright/test';

// 桩后端:版本下拉 / 登录 / 用户列表(仅为标签挂载,不验列表内容)。不依赖真实后端起服。
async function stubBackend(page: Page) {
  await page.route('**/api/usr/companies', async (route) => {
    await route.fulfill({
      status: 200,
      contentType: 'application/json',
      body: JSON.stringify({
        code: 0,
        message: 'success',
        data: [{ id: 1, sCompanyName: '甲公司', sVersion: '标准版' }],
      }),
    });
  });
  await page.route('**/api/usr/login', async (route) => {
    await route.fulfill({
      status: 200,
      contentType: 'application/json',
      body: JSON.stringify({
        code: 0,
        message: 'success',
        data: {
          token: 'tk-e2e',
          user: { id: 1, sUserName: '朱子纯', sUserType: '超级管理员', sLanguage: '中文' },
        },
      }),
    });
  });
  await page.route('**/api/usr/users**', async (route) => {
    await route.fulfill({
      status: 200,
      contentType: 'application/json',
      body: JSON.stringify({
        code: 0,
        message: 'success',
        data: { records: [], total: 0, pageNum: 1, pageSize: 10 },
      }),
    });
  });
}

async function login(page: Page) {
  await page.goto('/login');
  await page.getByPlaceholder('请输入你的用户名').fill('admin');
  await page.getByPlaceholder('请输入你的密码').fill('secret');
  // 单一版本时 LoginPage 自动选中(spec § 6.3),无需手动展开下拉
  await expect(page.getByText('甲公司(标准版)')).toBeVisible();
  await page.getByRole('button', { name: /登\s*录/ }).click();
}

test.describe('应用外壳关键旅程', () => {
  test('login then lands on home with topbar and KPI title', async ({ page }) => {
    await stubBackend(page);
    await login(page);
    await expect(page).toHaveURL(/\/$/);
    await expect(page.getByRole('button', { name: '全部导航' })).toBeVisible();
    await expect(page.getByText('KPI监控')).toBeVisible();
  });

  test('open and close 全部导航 overlay', async ({ page }) => {
    await stubBackend(page);
    await login(page);
    await page.getByRole('button', { name: '全部导航' }).click();
    await expect(page.getByTestId('nav-overlay')).toBeVisible();
    await expect(page.getByText('期初设置')).toBeVisible();
    await expect(page.getByText('API对接管理')).toBeVisible();
    // Esc 关闭
    await page.keyboard.press('Escape');
    await expect(page.getByTestId('nav-overlay')).toHaveCount(0);
  });

  test('open 用户列表 tab from common ops then close back to home', async ({ page }) => {
    await stubBackend(page);
    await login(page);
    // 常用操作卡内「用户列表」
    await page.getByRole('button', { name: '用户列表' }).click();
    await expect(page).toHaveURL(/\/usr\/users$/);
    await expect(page.getByTestId('tab-userlist')).toBeVisible();
    // 关闭用户列表标签 → 回主页
    await page.getByTestId('tab-close-userlist').click();
    await expect(page).toHaveURL(/\/$/);
    await expect(page.getByTestId('tab-userlist')).toHaveCount(0);
  });

  test('logout returns to /login', async ({ page }) => {
    await stubBackend(page);
    await login(page);
    await page.getByText('朱子纯(超级管理员)').click();
    await page.getByText('退出登录').click();
    await expect(page).toHaveURL(/\/login$/);
    await expect(page.getByText('已退出登录')).toBeVisible();
  });

  test('visiting / unauthenticated redirects to /login', async ({ page }) => {
    await stubBackend(page);
    // 不登录,清 token 后直接访问 /
    await page.goto('/login');
    await page.evaluate(() => localStorage.removeItem('xly_erp_token'));
    await page.goto('/');
    await expect(page).toHaveURL(/\/login$/);
  });
});