b9137204a0
- FilePreview.vue: add normalizedFileType computed to handle backend returning uppercase HTML/MD/PPTX (fixes preview/download buttons) - FilePreview.vue: bg-gradient-to-r from-orange-500 -> bg-orange-500 (Tailwind v4 gradient + CSS variable = transparent) - ReportCard.vue: bg-gradient-to-r -> bg-orange-600 for selected state - Add .opencode/, node_modules/, dist/ to .gitignore - Initial git setup for publish project
131 lines
5.2 KiB
JavaScript
131 lines
5.2 KiB
JavaScript
import { test, expect } from '@playwright/test'
|
|
|
|
/**
|
|
* Cover Image Upload E2E Tests
|
|
* Tests for the cover image upload functionality on ProjectDetail page
|
|
*/
|
|
test.describe('Cover Image Upload', () => {
|
|
test.beforeEach(async ({ page }) => {
|
|
await page.goto('/')
|
|
await page.waitForLoadState('networkidle')
|
|
await page.waitForTimeout(1000)
|
|
})
|
|
|
|
test('should navigate to project detail page', async ({ page }) => {
|
|
await expect(page.locator('text=项目一').first()).toBeVisible({ timeout: 15000 })
|
|
// Click the first project card by text
|
|
await page.locator('text=项目一').first().click()
|
|
await expect(page).toHaveURL(/\/project\/\d+/, { timeout: 10000 })
|
|
})
|
|
|
|
test('should enter project edit mode by clicking project name', async ({ page }) => {
|
|
await expect(page.locator('text=项目一').first()).toBeVisible({ timeout: 15000 })
|
|
await page.locator('text=项目一').first().click()
|
|
await expect(page).toHaveURL(/\/project\/\d+/, { timeout: 10000 })
|
|
|
|
// Click on project name to enter edit mode
|
|
const projectName = page.locator('h2').first()
|
|
await expect(projectName).toBeVisible({ timeout: 5000 })
|
|
await projectName.click()
|
|
|
|
// Should show edit form with file input
|
|
await expect(page.locator('input[type="file"]').first()).toBeVisible({ timeout: 5000 })
|
|
})
|
|
|
|
test('should show save and cancel buttons in edit mode', async ({ page }) => {
|
|
await expect(page.locator('text=项目一').first()).toBeVisible({ timeout: 15000 })
|
|
await page.locator('text=项目一').first().click()
|
|
await expect(page).toHaveURL(/\/project\/\d+/, { timeout: 10000 })
|
|
|
|
// Enter edit mode
|
|
const projectName = page.locator('h2').first()
|
|
await projectName.click()
|
|
await page.waitForTimeout(300)
|
|
|
|
// Should show save button
|
|
const saveButton = page.locator('button:has-text("保存")')
|
|
await expect(saveButton).toBeVisible({ timeout: 5000 })
|
|
|
|
// Should show cancel button
|
|
const cancelButton = page.locator('button:has-text("取消")')
|
|
await expect(cancelButton).toBeVisible({ timeout: 5000 })
|
|
})
|
|
|
|
test('should have image file input accepting image types', async ({ page }) => {
|
|
await expect(page.locator('text=项目一').first()).toBeVisible({ timeout: 15000 })
|
|
await page.locator('text=项目一').first().click()
|
|
await expect(page).toHaveURL(/\/project\/\d+/, { timeout: 10000 })
|
|
|
|
// Enter edit mode
|
|
const projectName = page.locator('h2').first()
|
|
await projectName.click()
|
|
await page.waitForTimeout(300)
|
|
|
|
// File input should accept images
|
|
const fileInput = page.locator('input[type="file"]').first()
|
|
await expect(fileInput).toBeVisible({ timeout: 5000 })
|
|
const accept = await fileInput.getAttribute('accept')
|
|
expect(accept).toBe('image/*')
|
|
})
|
|
|
|
test('should cancel edit mode and restore original state', async ({ page }) => {
|
|
await expect(page.locator('text=项目一').first()).toBeVisible({ timeout: 15000 })
|
|
await page.locator('text=项目一').first().click()
|
|
await expect(page).toHaveURL(/\/project\/\d+/, { timeout: 10000 })
|
|
|
|
// Enter edit mode
|
|
const projectName = page.locator('h2').first()
|
|
await projectName.click()
|
|
await page.waitForTimeout(300)
|
|
|
|
// Click cancel
|
|
const cancelButton = page.locator('button:has-text("取消")')
|
|
await cancelButton.click()
|
|
await page.waitForTimeout(300)
|
|
|
|
// Edit form should be hidden, back to display mode
|
|
const fileInput = page.locator('input[type="file"]')
|
|
await expect(fileInput).toHaveCount(0, { timeout: 5000 })
|
|
})
|
|
})
|
|
|
|
/**
|
|
* Cover Image Refresh E2E Tests
|
|
* Tests that cover image changes reflect on project list after saving
|
|
*/
|
|
test.describe('Cover Image - List Refresh', () => {
|
|
test.beforeEach(async ({ page }) => {
|
|
await page.goto('/')
|
|
await page.waitForLoadState('networkidle')
|
|
await page.waitForTimeout(1000)
|
|
})
|
|
|
|
test('should refresh project list after navigating back from detail', async ({ page }) => {
|
|
// Get initial project count
|
|
await expect(page.locator('text=个项目').first()).toBeVisible({ timeout: 15000 })
|
|
|
|
// Navigate to a project
|
|
await expect(page.locator('text=项目一').first()).toBeVisible({ timeout: 15000 })
|
|
await page.locator('text=项目一').first().click()
|
|
await expect(page).toHaveURL(/\/project\/\d+/, { timeout: 10000 })
|
|
|
|
// Navigate back to project list
|
|
await page.locator('a[href="/"]').click()
|
|
await expect(page.locator('text=选择项目').first()).toBeVisible({ timeout: 10000 })
|
|
|
|
// Should still show correct project count (list refreshed)
|
|
await expect(page.locator('text=个项目').first()).toBeVisible({ timeout: 5000 })
|
|
})
|
|
|
|
test('should display report count on stats cards', async ({ page }) => {
|
|
// Stats cards should show actual counts
|
|
await expect(page.locator('text=个项目').first()).toBeVisible({ timeout: 15000 })
|
|
await expect(page.locator('text=份报告').first()).toBeVisible({ timeout: 5000 })
|
|
await expect(page.locator('text=文件类型').first()).toBeVisible({ timeout: 5000 })
|
|
|
|
// Check that the stats numbers are visible (4xl font size)
|
|
const statsNumbers = page.locator('.text-4xl')
|
|
const count = await statsNumbers.count()
|
|
expect(count).toBeGreaterThanOrEqual(3)
|
|
})
|
|
}) |