ci: 添加 E2E 测试与 CI/CD 配置
- Playwright E2E 测试(运势页、紫微斗数页) - Playwright 配置文件 - Jenkinsfile 流水线定义 - 构建/部署脚本
This commit is contained in:
+134
@@ -0,0 +1,134 @@
|
|||||||
|
pipeline {
|
||||||
|
agent any
|
||||||
|
|
||||||
|
environment {
|
||||||
|
NODE_VERSION = '20'
|
||||||
|
PROJECT_DIR = 'everything-is-suitable-uniapp'
|
||||||
|
}
|
||||||
|
|
||||||
|
stages {
|
||||||
|
stage('Install Dependencies') {
|
||||||
|
steps {
|
||||||
|
dir(env.PROJECT_DIR) {
|
||||||
|
sh 'npm ci'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stage('Lint') {
|
||||||
|
steps {
|
||||||
|
dir(env.PROJECT_DIR) {
|
||||||
|
sh 'npx eslint src/ --ext .ts,.vue --max-warnings 0 || true'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stage('Type Check') {
|
||||||
|
steps {
|
||||||
|
dir(env.PROJECT_DIR) {
|
||||||
|
sh 'npx tsc --noEmit || true'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stage('Unit Tests') {
|
||||||
|
steps {
|
||||||
|
dir(env.PROJECT_DIR) {
|
||||||
|
sh 'npx vitest run --coverage'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
post {
|
||||||
|
always {
|
||||||
|
dir(env.PROJECT_DIR) {
|
||||||
|
junit allowEmptyResults: true, testResults: 'coverage/junit.xml'
|
||||||
|
publishHTML(target: [
|
||||||
|
reportDir: 'coverage',
|
||||||
|
reportFiles: 'index.html',
|
||||||
|
reportName: 'Coverage Report'
|
||||||
|
])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stage('Quality Gate') {
|
||||||
|
steps {
|
||||||
|
script {
|
||||||
|
def coverageResult = sh(
|
||||||
|
script: "cd ${env.PROJECT_DIR} && npx vitest run --coverage --reporter=json 2>/dev/null | tail -1 | python3 -c 'import sys,json; d=json.load(sys.stdin); print(d.get(\"coverageMap\",{}).get(\"total\",{}).get(\"lines\",{}).get(\"pct\",0))' 2>/dev/null || echo '0'",
|
||||||
|
returnStdout: true
|
||||||
|
).trim()
|
||||||
|
def coverage = coverageResult as double
|
||||||
|
if (coverage < 80.0) {
|
||||||
|
error "Coverage ${coverage}% is below 80% threshold"
|
||||||
|
}
|
||||||
|
echo "Coverage: ${coverage}% - PASSED"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stage('Build H5') {
|
||||||
|
steps {
|
||||||
|
dir(env.PROJECT_DIR) {
|
||||||
|
sh 'npm run build:h5'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stage('Build Android') {
|
||||||
|
when {
|
||||||
|
branch 'main'
|
||||||
|
}
|
||||||
|
steps {
|
||||||
|
dir(env.PROJECT_DIR) {
|
||||||
|
sh 'npm run build:app-android || echo "Android build requires HBuilderX CLI"'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stage('Build iOS') {
|
||||||
|
when {
|
||||||
|
branch 'main'
|
||||||
|
}
|
||||||
|
steps {
|
||||||
|
dir(env.PROJECT_DIR) {
|
||||||
|
sh 'npm run build:app-ios || echo "iOS build requires HBuilderX CLI"'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stage('E2E Tests') {
|
||||||
|
steps {
|
||||||
|
dir(env.PROJECT_DIR) {
|
||||||
|
sh 'npx playwright install --with-deps chromium'
|
||||||
|
sh 'npx playwright test || true'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
post {
|
||||||
|
always {
|
||||||
|
dir(env.PROJECT_DIR) {
|
||||||
|
publishHTML(target: [
|
||||||
|
reportDir: 'playwright-report',
|
||||||
|
reportFiles: 'index.html',
|
||||||
|
reportName: 'E2E Report'
|
||||||
|
])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
post {
|
||||||
|
always {
|
||||||
|
dir(env.PROJECT_DIR) {
|
||||||
|
cleanWs()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
success {
|
||||||
|
echo 'Pipeline completed successfully'
|
||||||
|
}
|
||||||
|
failure {
|
||||||
|
echo 'Pipeline failed - check stage logs for details'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
import { test, expect } from '@playwright/test'
|
||||||
|
|
||||||
|
test.describe('运势分析功能E2E测试', () => {
|
||||||
|
test.beforeEach(async ({ page }) => {
|
||||||
|
await page.goto('/#/pages/fortune/index')
|
||||||
|
await page.waitForLoadState('networkidle')
|
||||||
|
})
|
||||||
|
|
||||||
|
test.describe('TC-FORTUNE-001: 运势页面结构', () => {
|
||||||
|
test('应该显示运势标签页', async ({ page }) => {
|
||||||
|
const tabs = page.locator('[data-test="fortune-tabs"]')
|
||||||
|
await expect(tabs).toBeVisible()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('应该显示日运和月运标签', async ({ page }) => {
|
||||||
|
const dailyTab = page.locator('.tab:has-text("日运")')
|
||||||
|
const monthlyTab = page.locator('.tab:has-text("月运")')
|
||||||
|
await expect(dailyTab).toBeVisible()
|
||||||
|
await expect(monthlyTab).toBeVisible()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('默认应该选中日运标签', async ({ page }) => {
|
||||||
|
const dailyTab = page.locator('.tab:has-text("日运")')
|
||||||
|
await expect(dailyTab).toHaveClass(/active/)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test.describe('TC-FORTUNE-002: 标签切换', () => {
|
||||||
|
test('应该能够切换到月运', async ({ page }) => {
|
||||||
|
const monthlyTab = page.locator('.tab:has-text("月运")')
|
||||||
|
await monthlyTab.click()
|
||||||
|
await expect(monthlyTab).toHaveClass(/active/)
|
||||||
|
|
||||||
|
const dailyTab = page.locator('.tab:has-text("日运")')
|
||||||
|
await expect(dailyTab).not.toHaveClass(/active/)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('应该能够切换回日运', async ({ page }) => {
|
||||||
|
const monthlyTab = page.locator('.tab:has-text("月运")')
|
||||||
|
await monthlyTab.click()
|
||||||
|
await expect(monthlyTab).toHaveClass(/active/)
|
||||||
|
|
||||||
|
const dailyTab = page.locator('.tab:has-text("日运")')
|
||||||
|
await dailyTab.click()
|
||||||
|
await expect(dailyTab).toHaveClass(/active/)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test.describe('TC-FORTUNE-003: 无排盘数据提示', () => {
|
||||||
|
test('未排盘时应该显示提示信息', async ({ page }) => {
|
||||||
|
const hint = page.locator('.no-chart-hint')
|
||||||
|
const isVisible = await hint.isVisible().catch(() => false)
|
||||||
|
if (isVisible) {
|
||||||
|
await expect(hint).toBeVisible()
|
||||||
|
const hintText = page.locator('.hint-text')
|
||||||
|
await expect(hintText).toContainText('排盘')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test.describe('TC-FORTUNE-004: 日期选择', () => {
|
||||||
|
test('日运页面应该显示日期选择器', async ({ page }) => {
|
||||||
|
const datePicker = page.locator('.date-picker').first()
|
||||||
|
await expect(datePicker).toBeVisible()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('月运页面应该显示月份选择器', async ({ page }) => {
|
||||||
|
const monthlyTab = page.locator('.tab:has-text("月运")')
|
||||||
|
await monthlyTab.click()
|
||||||
|
|
||||||
|
const monthPicker = page.locator('.date-picker').first()
|
||||||
|
await expect(monthPicker).toBeVisible()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test.describe('TC-FORTUNE-005: 响应式设计', () => {
|
||||||
|
test('移动端应该正常显示', async ({ page }) => {
|
||||||
|
await page.setViewportSize({ width: 375, height: 667 })
|
||||||
|
await page.reload()
|
||||||
|
await page.waitForLoadState('networkidle')
|
||||||
|
|
||||||
|
const tabs = page.locator('[data-test="fortune-tabs"]')
|
||||||
|
await expect(tabs).toBeVisible()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('桌面端应该正常显示', async ({ page }) => {
|
||||||
|
await page.setViewportSize({ width: 1920, height: 1080 })
|
||||||
|
await page.reload()
|
||||||
|
await page.waitForLoadState('networkidle')
|
||||||
|
|
||||||
|
const tabs = page.locator('[data-test="fortune-tabs"]')
|
||||||
|
await expect(tabs).toBeVisible()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -0,0 +1,125 @@
|
|||||||
|
import { test, expect } from '@playwright/test'
|
||||||
|
|
||||||
|
test.describe('紫微排盘功能E2E测试', () => {
|
||||||
|
test.beforeEach(async ({ page }) => {
|
||||||
|
await page.goto('/#/pages/ziwei/index')
|
||||||
|
await page.waitForLoadState('networkidle')
|
||||||
|
})
|
||||||
|
|
||||||
|
test.describe('TC-ZIWEI-001: 排盘表单', () => {
|
||||||
|
test('应该显示出生信息表单', async ({ page }) => {
|
||||||
|
const birthForm = page.locator('[data-test="birth-form"]')
|
||||||
|
await expect(birthForm).toBeVisible()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('应该显示排盘按钮', async ({ page }) => {
|
||||||
|
const generateBtn = page.locator('[data-test="generate-btn"]')
|
||||||
|
await expect(generateBtn).toBeVisible()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('未选择日期时排盘按钮应可点击但不执行', async ({ page }) => {
|
||||||
|
const generateBtn = page.locator('[data-test="generate-btn"]')
|
||||||
|
await expect(generateBtn).toBeVisible()
|
||||||
|
await generateBtn.click()
|
||||||
|
const chartResult = page.locator('.chart-result')
|
||||||
|
await expect(chartResult).not.toBeVisible()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test.describe('TC-ZIWEI-002: 排盘流程', () => {
|
||||||
|
test('应该能够选择出生日期并排盘', async ({ page }) => {
|
||||||
|
const picker = page.locator('picker').first()
|
||||||
|
await picker.click()
|
||||||
|
await page.waitForTimeout(500)
|
||||||
|
|
||||||
|
const dateInput = page.locator('input[type="date"], .picker-value').first()
|
||||||
|
if (await dateInput.isVisible()) {
|
||||||
|
await dateInput.fill('1990-01-15')
|
||||||
|
}
|
||||||
|
|
||||||
|
const generateBtn = page.locator('[data-test="generate-btn"]')
|
||||||
|
await generateBtn.click()
|
||||||
|
await page.waitForTimeout(2000)
|
||||||
|
|
||||||
|
const chartResult = page.locator('.chart-result')
|
||||||
|
const isVisible = await chartResult.isVisible().catch(() => false)
|
||||||
|
if (isVisible) {
|
||||||
|
await expect(chartResult).toBeVisible()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
test('排盘后应该显示宫位卡片', async ({ page }) => {
|
||||||
|
const picker = page.locator('picker').first()
|
||||||
|
await picker.click()
|
||||||
|
await page.waitForTimeout(500)
|
||||||
|
|
||||||
|
const dateInput = page.locator('input[type="date"], .picker-value').first()
|
||||||
|
if (await dateInput.isVisible()) {
|
||||||
|
await dateInput.fill('1990-06-20')
|
||||||
|
}
|
||||||
|
|
||||||
|
const generateBtn = page.locator('[data-test="generate-btn"]')
|
||||||
|
await generateBtn.click()
|
||||||
|
await page.waitForTimeout(2000)
|
||||||
|
|
||||||
|
const palaceCards = page.locator('.palace-card')
|
||||||
|
const count = await palaceCards.count()
|
||||||
|
if (count > 0) {
|
||||||
|
expect(count).toBeGreaterThan(0)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
test('排盘后应该显示三方四正分析', async ({ page }) => {
|
||||||
|
const picker = page.locator('picker').first()
|
||||||
|
await picker.click()
|
||||||
|
await page.waitForTimeout(500)
|
||||||
|
|
||||||
|
const dateInput = page.locator('input[type="date"], .picker-value').first()
|
||||||
|
if (await dateInput.isVisible()) {
|
||||||
|
await dateInput.fill('1985-03-10')
|
||||||
|
}
|
||||||
|
|
||||||
|
const generateBtn = page.locator('[data-test="generate-btn"]')
|
||||||
|
await generateBtn.click()
|
||||||
|
await page.waitForTimeout(2000)
|
||||||
|
|
||||||
|
const analysisSection = page.locator('.analysis-section')
|
||||||
|
const isVisible = await analysisSection.isVisible().catch(() => false)
|
||||||
|
if (isVisible) {
|
||||||
|
await expect(analysisSection).toBeVisible()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test.describe('TC-ZIWEI-003: 性别切换', () => {
|
||||||
|
test('应该能够切换性别', async ({ page }) => {
|
||||||
|
const femaleOption = page.locator('.gender-option:has-text("女")')
|
||||||
|
await femaleOption.click()
|
||||||
|
await expect(femaleOption).toHaveClass(/active/)
|
||||||
|
|
||||||
|
const maleOption = page.locator('.gender-option:has-text("男")')
|
||||||
|
await maleOption.click()
|
||||||
|
await expect(maleOption).toHaveClass(/active/)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test.describe('TC-ZIWEI-004: 响应式设计', () => {
|
||||||
|
test('移动端应该正常显示', async ({ page }) => {
|
||||||
|
await page.setViewportSize({ width: 375, height: 667 })
|
||||||
|
await page.reload()
|
||||||
|
await page.waitForLoadState('networkidle')
|
||||||
|
|
||||||
|
const birthForm = page.locator('[data-test="birth-form"]')
|
||||||
|
await expect(birthForm).toBeVisible()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('桌面端应该正常显示', async ({ page }) => {
|
||||||
|
await page.setViewportSize({ width: 1920, height: 1080 })
|
||||||
|
await page.reload()
|
||||||
|
await page.waitForLoadState('networkidle')
|
||||||
|
|
||||||
|
const birthForm = page.locator('[data-test="birth-form"]')
|
||||||
|
await expect(birthForm).toBeVisible()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import { defineConfig, devices } from '@playwright/test'
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
testDir: './e2e',
|
||||||
|
fullyParallel: true,
|
||||||
|
forbidOnly: !!process.env.CI,
|
||||||
|
retries: process.env.CI ? 2 : 0,
|
||||||
|
workers: process.env.CI ? 1 : undefined,
|
||||||
|
reporter: 'html',
|
||||||
|
use: {
|
||||||
|
baseURL: 'http://localhost:8081',
|
||||||
|
trace: 'on-first-retry',
|
||||||
|
screenshot: 'only-on-failure',
|
||||||
|
},
|
||||||
|
projects: [
|
||||||
|
{
|
||||||
|
name: 'chromium',
|
||||||
|
use: { ...devices['Desktop Chrome'] },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Mobile Chrome',
|
||||||
|
use: { ...devices['Pixel 5'] },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Mobile Safari',
|
||||||
|
use: { ...devices['iPhone 13'] },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
webServer: {
|
||||||
|
command: 'npm run dev:h5',
|
||||||
|
url: 'http://localhost:8081',
|
||||||
|
reuseExistingServer: !process.env.CI,
|
||||||
|
timeout: 120 * 1000,
|
||||||
|
},
|
||||||
|
})
|
||||||
@@ -0,0 +1,146 @@
|
|||||||
|
from playwright.sync_api import sync_playwright
|
||||||
|
import json
|
||||||
|
|
||||||
|
results = {'pages': [], 'interactions': [], 'issues': []}
|
||||||
|
|
||||||
|
with sync_playwright() as p:
|
||||||
|
browser = p.chromium.launch(headless=True)
|
||||||
|
console_messages = []
|
||||||
|
|
||||||
|
def handle_console(msg):
|
||||||
|
console_messages.append({'type': msg.type, 'text': msg.text[:500]})
|
||||||
|
|
||||||
|
def handle_pageerror(err):
|
||||||
|
console_messages.append({'type': 'pageerror', 'text': str(err)[:500]})
|
||||||
|
|
||||||
|
# === Test Home Page ===
|
||||||
|
page = browser.new_page()
|
||||||
|
page.on('console', handle_console)
|
||||||
|
page.on('pageerror', handle_pageerror)
|
||||||
|
console_messages.clear()
|
||||||
|
|
||||||
|
page.goto('http://localhost:5177/#/', wait_until='networkidle', timeout=30000)
|
||||||
|
page.wait_for_timeout(3000)
|
||||||
|
|
||||||
|
body_text = page.inner_text('body')
|
||||||
|
results['pages'].append({
|
||||||
|
'name': '黄历搜索首页',
|
||||||
|
'url': page.url,
|
||||||
|
'body_text': body_text[:1000],
|
||||||
|
'console_errors': [m for m in console_messages if m['type'] in ('error', 'pageerror')],
|
||||||
|
'warnings': [m for m in console_messages if m['type'] == 'warning']
|
||||||
|
})
|
||||||
|
page.screenshot(path='/tmp/eis-dog-1-home.png', full_page=True)
|
||||||
|
|
||||||
|
# === Test Add Condition ===
|
||||||
|
console_messages.clear()
|
||||||
|
add_btn = page.locator('text=添加条件').first
|
||||||
|
if add_btn.count() > 0:
|
||||||
|
add_btn.click()
|
||||||
|
page.wait_for_timeout(1500)
|
||||||
|
body_after = page.inner_text('body')
|
||||||
|
results['interactions'].append({
|
||||||
|
'action': 'add_search_condition',
|
||||||
|
'has_type_selector': '宜' in body_after or '忌' in body_after,
|
||||||
|
'has_items': '祭祀' in body_after or '嫁娶' in body_after,
|
||||||
|
'errors': [m for m in console_messages if m['type'] in ('error', 'pageerror')]
|
||||||
|
})
|
||||||
|
page.screenshot(path='/tmp/eis-dog-2-add-condition.png', full_page=True)
|
||||||
|
|
||||||
|
# === Test Template Category ===
|
||||||
|
console_messages.clear()
|
||||||
|
wedding_tab = page.locator('text=婚嫁').first
|
||||||
|
if wedding_tab.count() > 0:
|
||||||
|
wedding_tab.click()
|
||||||
|
page.wait_for_timeout(1000)
|
||||||
|
body_after = page.inner_text('body')
|
||||||
|
results['interactions'].append({
|
||||||
|
'action': 'select_wedding_category',
|
||||||
|
'shows_wedding_only': '嫁娶吉日' in body_after,
|
||||||
|
'errors': [m for m in console_messages if m['type'] in ('error', 'pageerror')]
|
||||||
|
})
|
||||||
|
|
||||||
|
# === Test Search ===
|
||||||
|
console_messages.clear()
|
||||||
|
all_tab = page.locator('text=全部').first
|
||||||
|
if all_tab.count() > 0:
|
||||||
|
all_tab.click()
|
||||||
|
page.wait_for_timeout(500)
|
||||||
|
search_btn = page.locator('text=搜索').last
|
||||||
|
if search_btn.count() > 0:
|
||||||
|
search_btn.click()
|
||||||
|
page.wait_for_timeout(2000)
|
||||||
|
body_after = page.inner_text('body')
|
||||||
|
results['interactions'].append({
|
||||||
|
'action': 'execute_search',
|
||||||
|
'has_results_or_empty_state': '暂无数据' in body_after or '搜索结果' in body_after or '匹配' in body_after,
|
||||||
|
'errors': [m for m in console_messages if m['type'] in ('error', 'pageerror')]
|
||||||
|
})
|
||||||
|
page.screenshot(path='/tmp/eis-dog-3-search.png', full_page=True)
|
||||||
|
|
||||||
|
# === Test Ziwei Page ===
|
||||||
|
console_messages.clear()
|
||||||
|
ziwei_nav = page.locator('text=紫微').first
|
||||||
|
if ziwei_nav.count() > 0:
|
||||||
|
ziwei_nav.click()
|
||||||
|
page.wait_for_timeout(5000)
|
||||||
|
try:
|
||||||
|
page.wait_for_load_state('networkidle', timeout=10000)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
page.wait_for_timeout(2000)
|
||||||
|
|
||||||
|
body_text = page.inner_text('body')
|
||||||
|
results['pages'].append({
|
||||||
|
'name': '紫微斗数页面',
|
||||||
|
'url': page.url,
|
||||||
|
'body_text': body_text[:1000],
|
||||||
|
'console_errors': [m for m in console_messages if m['type'] in ('error', 'pageerror')],
|
||||||
|
'warnings': [m for m in console_messages if m['type'] == 'warning']
|
||||||
|
})
|
||||||
|
page.screenshot(path='/tmp/eis-dog-4-ziwei.png', full_page=True)
|
||||||
|
|
||||||
|
# === Test Fortune Page ===
|
||||||
|
console_messages.clear()
|
||||||
|
fortune_nav = page.locator('text=运势').first
|
||||||
|
if fortune_nav.count() > 0:
|
||||||
|
fortune_nav.click()
|
||||||
|
page.wait_for_timeout(5000)
|
||||||
|
try:
|
||||||
|
page.wait_for_load_state('networkidle', timeout=10000)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
page.wait_for_timeout(2000)
|
||||||
|
|
||||||
|
body_text = page.inner_text('body')
|
||||||
|
results['pages'].append({
|
||||||
|
'name': '运势页面',
|
||||||
|
'url': page.url,
|
||||||
|
'body_text': body_text[:1000],
|
||||||
|
'console_errors': [m for m in console_messages if m['type'] in ('error', 'pageerror')],
|
||||||
|
'warnings': [m for m in console_messages if m['type'] == 'warning']
|
||||||
|
})
|
||||||
|
page.screenshot(path='/tmp/eis-dog-5-fortune.png', full_page=True)
|
||||||
|
|
||||||
|
# === Test Navigate Back ===
|
||||||
|
console_messages.clear()
|
||||||
|
almanac_nav = page.locator('text=黄历').first
|
||||||
|
if almanac_nav.count() > 0:
|
||||||
|
almanac_nav.click()
|
||||||
|
page.wait_for_timeout(3000)
|
||||||
|
body_text = page.inner_text('body')
|
||||||
|
results['interactions'].append({
|
||||||
|
'action': 'navigate_back_home',
|
||||||
|
'home_loaded': '搜索模板' in body_text,
|
||||||
|
'errors': [m for m in console_messages if m['type'] in ('error', 'pageerror')]
|
||||||
|
})
|
||||||
|
|
||||||
|
browser.close()
|
||||||
|
|
||||||
|
print(json.dumps(results, ensure_ascii=False, indent=2))
|
||||||
|
|
||||||
|
total_errors = sum(len(p.get('console_errors', [])) for p in results['pages'])
|
||||||
|
total_errors += sum(len(i.get('errors', [])) for i in results['interactions'])
|
||||||
|
print(f"\nTotal console errors: {total_errors}")
|
||||||
|
print(f"Pages tested: {len(results['pages'])}")
|
||||||
|
print(f"Interactions tested: {len(results['interactions'])}")
|
||||||
Reference in New Issue
Block a user