import { test, expect } from '@playwright/test'; test.describe('关键词搜索功能E2E测试', () => { let baseUrl: string; test.beforeAll(async () => { baseUrl = 'http://localhost:8081'; }); test.describe('TC-KEYWORD-001: 首页搜索入口', () => { test.beforeEach(async ({ page }) => { await page.goto(`${baseUrl}/#/pages/index/index`); await page.waitForLoadState('networkidle'); }); test('应该显示搜索入口', async ({ page }) => { const searchEntry = page.locator('.search-entry, [class*="search-entry"], .search-box'); expect(await searchEntry.isVisible()).toBe(true); }); test('点击搜索入口应该打开搜索面板', async ({ page }) => { const searchEntry = page.locator('.search-entry, [class*="search-entry"], .search-box'); await searchEntry.click(); await page.waitForTimeout(500); const searchPanel = page.locator('.search-condition-panel, [class*="SearchConditionPanel"]'); expect(await searchPanel.isVisible()).toBe(true); }); test('搜索面板应该包含关键词输入框', async ({ page }) => { const searchEntry = page.locator('.search-entry, [class*="search-entry"], .search-box'); await searchEntry.click(); await page.waitForTimeout(500); const keywordInput = page.locator('.keyword-input, input[placeholder*="关键词"], input[placeholder*="搜索"]'); expect(await keywordInput.isVisible()).toBe(true); }); }); test.describe('TC-KEYWORD-002: 关键词搜索流程', () => { test.beforeEach(async ({ page }) => { await page.goto(`${baseUrl}/#/pages/index/index`); await page.waitForLoadState('networkidle'); }); test('应该能够输入关键词进行搜索', async ({ page }) => { const searchEntry = page.locator('.search-entry, [class*="search-entry"], .search-box'); await searchEntry.click(); await page.waitForTimeout(500); const keywordInput = page.locator('.keyword-input, input[placeholder*="关键词"], input[placeholder*="搜索"]'); await keywordInput.fill('祭祀'); await page.waitForTimeout(300); const searchButton = page.locator('.search-btn, button:has-text("搜索")'); if (await searchButton.isVisible()) { await searchButton.click(); await page.waitForTimeout(1000); await page.waitForURL(/almanac-search/, { timeout: 5000 }); } }); test('空关键词不应该触发搜索', async ({ page }) => { const searchEntry = page.locator('.search-entry, [class*="search-entry"], .search-box'); await searchEntry.click(); await page.waitForTimeout(500); const keywordInput = page.locator('.keyword-input, input[placeholder*="关键词"], input[placeholder*="搜索"]'); await keywordInput.fill(''); await page.waitForTimeout(300); const searchButton = page.locator('.search-btn, button:has-text("搜索")'); if (await searchButton.isVisible()) { await searchButton.click(); await page.waitForTimeout(500); const currentUrl = page.url(); expect(currentUrl).not.toContain('keyword='); } }); test('应该能够清除关键词', async ({ page }) => { const searchEntry = page.locator('.search-entry, [class*="search-entry"], .search-box'); await searchEntry.click(); await page.waitForTimeout(500); const keywordInput = page.locator('.keyword-input, input[placeholder*="关键词"], input[placeholder*="搜索"]'); await keywordInput.fill('测试关键词'); await page.waitForTimeout(300); const clearButton = page.locator('.clear-btn, [class*="clear"]'); if (await clearButton.isVisible()) { await clearButton.click(); await page.waitForTimeout(300); const inputValue = await keywordInput.inputValue(); expect(inputValue).toBe(''); } }); }); test.describe('TC-KEYWORD-003: 搜索历史', () => { test.beforeEach(async ({ page }) => { await page.goto(`${baseUrl}/#/pages/index/index`); await page.waitForLoadState('networkidle'); }); test('应该保存搜索历史', async ({ page }) => { const searchEntry = page.locator('.search-entry, [class*="search-entry"], .search-box'); await searchEntry.click(); await page.waitForTimeout(500); const keywordInput = page.locator('.keyword-input, input[placeholder*="关键词"], input[placeholder*="搜索"]'); await keywordInput.fill('历史测试'); const searchButton = page.locator('.search-btn, button:has-text("搜索")'); if (await searchButton.isVisible()) { await searchButton.click(); await page.waitForTimeout(1000); } await page.goto(`${baseUrl}/#/pages/index/index`); await page.waitForLoadState('networkidle'); await searchEntry.click(); await page.waitForTimeout(500); const historyItem = page.locator('.history-item:has-text("历史测试"), [class*="history"]:has-text("历史测试")'); const historyVisible = await historyItem.isVisible().catch(() => false); if (historyVisible) { expect(historyVisible).toBe(true); } }); test('应该能够清除搜索历史', async ({ page }) => { const searchEntry = page.locator('.search-entry, [class*="search-entry"], .search-box'); await searchEntry.click(); await page.waitForTimeout(500); const clearHistoryBtn = page.locator('.clear-history, button:has-text("清除历史")'); if (await clearHistoryBtn.isVisible()) { await clearHistoryBtn.click(); await page.waitForTimeout(500); const historyItems = page.locator('.history-item, [class*="history-item"]'); const count = await historyItems.count(); expect(count).toBe(0); } }); }); test.describe('TC-KEYWORD-004: 搜索结果页', () => { test.beforeEach(async ({ page }) => { await page.goto(`${baseUrl}/#/pages/almanac-search/index?keyword=%E7%A5%AD%E7%A5%80`); await page.waitForLoadState('networkidle'); }); test('应该显示搜索结果', async ({ page }) => { await page.waitForTimeout(2000); const results = page.locator('.search-result-card, [class*="SearchResultCard"], .result-item'); const count = await results.count(); if (count > 0) { expect(await results.first().isVisible()).toBe(true); } }); test('应该显示加载状态', async ({ page }) => { const loadingIndicator = page.locator('.loading-indicator, [class*="loading"]'); const loadingVisible = await loadingIndicator.isVisible().catch(() => false); if (loadingVisible) { expect(loadingVisible).toBe(true); } }); test('无结果时应该显示空状态', async ({ page }) => { await page.goto(`${baseUrl}/#/pages/almanac-search/index?keyword=xyz123notexist`); await page.waitForLoadState('networkidle'); await page.waitForTimeout(2000); const results = page.locator('.search-result-card, [class*="SearchResultCard"]'); const count = await results.count(); if (count === 0) { const emptyState = page.locator('.empty-state, [class*="EmptyState"], .no-result'); const emptyVisible = await emptyState.isVisible().catch(() => false); expect(emptyVisible).toBe(true); } }); }); test.describe('TC-KEYWORD-005: 高级搜索与关键词搜索切换', () => { test.beforeEach(async ({ page }) => { await page.goto(`${baseUrl}/#/pages/index/index`); await page.waitForLoadState('networkidle'); }); test('应该能够切换到高级搜索', async ({ page }) => { const searchEntry = page.locator('.search-entry, [class*="search-entry"], .search-box'); await searchEntry.click(); await page.waitForTimeout(500); const advancedTab = page.locator('.tab:has-text("高级"), [class*="tab"]:has-text("高级")'); if (await advancedTab.isVisible()) { await advancedTab.click(); await page.waitForTimeout(300); const conditionPanel = page.locator('.condition-list, [class*="condition"]'); expect(await conditionPanel.isVisible()).toBe(true); } }); test('应该能够切换回关键词搜索', async ({ page }) => { const searchEntry = page.locator('.search-entry, [class*="search-entry"], .search-box'); await searchEntry.click(); await page.waitForTimeout(500); const advancedTab = page.locator('.tab:has-text("高级"), [class*="tab"]:has-text("高级")'); if (await advancedTab.isVisible()) { await advancedTab.click(); await page.waitForTimeout(300); const keywordTab = page.locator('.tab:has-text("关键词"), [class*="tab"]:has-text("关键词")'); if (await keywordTab.isVisible()) { await keywordTab.click(); await page.waitForTimeout(300); const keywordInput = page.locator('.keyword-input, input[placeholder*="关键词"]'); expect(await keywordInput.isVisible()).toBe(true); } } }); }); test.describe('TC-KEYWORD-006: 响应式设计', () => { test('移动端应该正常显示搜索入口', async ({ page }) => { await page.setViewportSize({ width: 375, height: 667 }); await page.goto(`${baseUrl}/#/pages/index/index`); await page.waitForLoadState('networkidle'); const searchEntry = page.locator('.search-entry, [class*="search-entry"], .search-box'); expect(await searchEntry.isVisible()).toBe(true); }); test('桌面端应该正常显示搜索入口', async ({ page }) => { await page.setViewportSize({ width: 1920, height: 1080 }); await page.goto(`${baseUrl}/#/pages/index/index`); await page.waitForLoadState('networkidle'); const searchEntry = page.locator('.search-entry, [class*="search-entry"], .search-box'); expect(await searchEntry.isVisible()).toBe(true); }); }); });