| 12345678910111213141516171819202122232425262728293031323334353637383940 |
- import assert from 'node:assert/strict';
- import { readFile, writeFile, mkdir } from 'node:fs/promises';
- import { chromium } from 'playwright';
- const accounts = JSON.parse(await readFile(new URL('../../.work/frontend-accounts.json', import.meta.url), 'utf8'));
- const base = process.env.FRONTEND_URL || 'http://127.0.0.1:18763';
- const browser = await chromium.launch({ headless: true, executablePath: process.env.PLAYWRIGHT_CHROMIUM_EXECUTABLE });
- const page = await browser.newPage();
- const errors = [];
- page.on('pageerror', error => errors.push(error.message));
- try {
- await page.goto(`${base}/#/merchant/login`);
- const panel = page.locator('.login-panel');
- const username = `rate-check-${crypto.randomUUID()}`;
- // 使用独立的不存在账户触发真实 Redis 登录限流,总计限制为 11 次请求。
- for (let attempt = 0; attempt < 10; attempt++) {
- const response = await page.request.post(`${base}/openapi/v1/auth/sessions`, {
- data: { tenant_id: accounts.tenant_id, username, password: 'invalid-credentials' },
- });
- assert.equal(response.status(), 401, '未授权账户返回统一登录失败');
- }
- await panel.getByLabel('商家标识').fill(accounts.tenant_id);
- await panel.getByLabel('员工账户').fill(username);
- await panel.getByLabel('密码', { exact: true }).fill('invalid-credentials');
- const received = page.waitForResponse(response => response.request().method() === 'POST' && response.url().endsWith('/auth/sessions'));
- await panel.getByRole('button', { name: '登录', exact: true }).click();
- const response = await received;
- assert.equal(response.status(), 429);
- assert.equal(response.headers()['retry-after'], '60');
- await panel.getByRole('alert').filter({ hasText: '请等待 60 秒后重试' }).waitFor();
- assert.equal(await panel.getByLabel('密码', { exact: true }).inputValue(), '');
- assert.equal(await panel.getByLabel('员工账户').inputValue(), username);
- assert.equal(await page.locator('.admin-shell').count(), 0);
- assert.deepEqual(errors, []);
- await mkdir(new URL('../../.work/frontend-verification/', import.meta.url), { recursive: true });
- await writeFile(new URL('../../.work/frontend-verification/login-rate-limit.json', import.meta.url), JSON.stringify({ date: new Date().toISOString(), requests: 11, checks: ['真实账户限流', '服务端等待时间展示', '失败后清空密码并保留账户', '受保护内容隐藏'], browserErrors: errors, generatedModelCalls: 0 }, null, 2));
- console.log('登录限流真实接口与页面检查通过,共 11 次请求。');
- } finally {
- await browser.close();
- }
|