Files
dsas-cca-backend-bun/test/auth.spec.ts
JamesFlare1212 a8f468a497 feat: 使用 Playwright 实现自动化 cookie 获取和验证
主要变更:
- 新增 Playwright 登录认证服务 (services/playwright-auth.ts)
- 重构 get-activity.ts 使用 Playwright 替代 Axios 登录
- 实现自动 cookie 过期检测和重试机制
- 优化 Docker 配置支持 Playwright 浏览器运行
- 添加启动脚本自动验证和刷新 cookies
- 完善错误处理:区分 4xx(认证失败) 和 5xx(服务器错误)

技术细节:
- 删除旧版 login_template.txt 和 nkcs-engage.cookie.txt
- 添加 startup.sh 启动时自动验证 cookies
- 改进 cookie 验证逻辑,添加指数退避重试
- Dockerfile 安装 Playwright 系统依赖
- docker-compose.yaml 添加 volumes 和 health checks

测试:
- 添加 auth.spec.ts 自动化测试
- 添加 get-cookies.ts 和 test-cookies-validity.ts 工具脚本
- 验证 401/500/000 等错误场景处理正确
2026-04-06 16:05:38 -04:00

119 lines
3.7 KiB
TypeScript

import { test, expect } from 'bun:test';
import { chromium, type Cookie } from 'playwright';
import * as fs from 'fs';
import { resolve, dirname } from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const COOKIE_FILE_PATH = resolve(__dirname, '../services/cookies.json');
const testUsername = process.env.API_USERNAME || 'test@test.com';
const testPassword = process.env.API_PASSWORD || 'test123';
test('should login and extract cookies successfully', async () => {
const browser = await chromium.launch({
headless: true,
args: ['--no-sandbox', '--disable-setuid-sandbox']
});
try {
const context = await browser.newContext({
userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
});
const page = await context.newPage();
await page.goto('https://engage.nkcswx.cn/Login.aspx', {
waitUntil: 'networkidle',
timeout: 60000
});
const usernameField = page.locator('input[name="ctl00$PageContent$loginControl$txtUN"]');
await usernameField.fill(decodeURIComponent(testUsername));
const passwordField = page.locator('input[name="ctl00$PageContent$loginControl$txtPwd"]');
await passwordField.fill(decodeURIComponent(testPassword));
const loginButton = page.locator('input[name="ctl00$PageContent$loginControl$btnLogin"]');
await loginButton.click();
await page.waitForLoadState('networkidle', { timeout: 60000 });
const cookies = await context.cookies();
expect(cookies).toBeDefined();
expect(cookies.length).toBeGreaterThan(0);
const hasSessionCookie = cookies.some(c => c.name === 'ASP.NET_SessionId');
expect(hasSessionCookie).toBe(true);
fs.writeFileSync(COOKIE_FILE_PATH, JSON.stringify(cookies, null, 2));
} finally {
await browser.close();
}
}, 120000);
test('should load cookies from file if exists', () => {
if (!fs.existsSync(COOKIE_FILE_PATH)) {
throw new Error('Cookie file does not exist');
}
const cookies = JSON.parse(fs.readFileSync(COOKIE_FILE_PATH, 'utf-8')) as Cookie[];
expect(cookies.length).toBeGreaterThan(0);
});
test('should test cookie validity', async () => {
if (!fs.existsSync(COOKIE_FILE_PATH)) {
throw new Error('Cookie file does not exist');
}
const cookies = JSON.parse(fs.readFileSync(COOKIE_FILE_PATH, 'utf-8')) as Cookie[];
const browser = await chromium.launch({
headless: true,
args: ['--no-sandbox', '--disable-setuid-sandbox']
});
try {
const context = await browser.newContext();
await context.addCookies(cookies);
const page = await context.newPage();
await page.goto('https://engage.nkcswx.cn/', {
waitUntil: 'networkidle',
timeout: 30000
});
const url = page.url();
const isRedirectedToLogin = url.includes('/Login.aspx');
expect(isRedirectedToLogin).toBe(false);
} finally {
await browser.close();
}
}, 60000);
test('should convert cookies to string format', () => {
if (!fs.existsSync(COOKIE_FILE_PATH)) {
throw new Error('Cookie file does not exist');
}
const cookies = JSON.parse(fs.readFileSync(COOKIE_FILE_PATH, 'utf-8')) as Cookie[];
const cookieString = cookies.map(c => `${c.name}=${c.value}`).join('; ');
expect(cookieString).toBeDefined();
expect(cookieString.length).toBeGreaterThan(0);
expect(cookieString).toContain('ASP.NET_SessionId=');
});
test('should clear cookie cache', () => {
if (fs.existsSync(COOKIE_FILE_PATH)) {
fs.unlinkSync(COOKIE_FILE_PATH);
}
const exists = fs.existsSync(COOKIE_FILE_PATH);
expect(exists).toBe(false);
});