diff --git a/config/test/lighthouserc.json b/config/test/lighthouserc.json index dcb1ce4..1889bb8 100644 --- a/config/test/lighthouserc.json +++ b/config/test/lighthouserc.json @@ -1,57 +1,47 @@ -ci: - collect: - numberOfRuns: 3 - startServerCommand: npm run start - startServerReadyPattern: 'Local:' - url: - - http://localhost:3000/ - - http://localhost:3000/about - - http://localhost:3000/services - - http://localhost:3000/products - - http://localhost:3000/cases - - http://localhost:3000/news - - http://localhost:3000/contact - settings: - preset: desktop - onlyCategories: - - performance - - accessibility - - best-practices - - seo - - assert: - assertions: - categories:performance: - - error - - minScore: 0.9 - categories:accessibility: - - error - - minScore: 0.9 - categories:best-practices: - - error - - minScore: 0.9 - categories:seo: - - error - - minScore: 0.9 - first-contentful-paint: - - error - - maxNumericValue: 2000 - largest-contentful-paint: - - error - - maxNumericValue: 3000 - cumulative-layout-shift: - - error - - maxNumericValue: 0.1 - total-blocking-time: - - error - - maxNumericValue: 300 - speed-index: - - error - - maxNumericValue: 3000 - - upload: - target: temporary-public-storage - - settings: - output: html - outputPath: lighthouse-reports +{ + "ci": { + "collect": { + "numberOfRuns": 3, + "startServerCommand": "npm run start", + "startServerReadyPattern": "Local:", + "url": [ + "http://localhost:3000/", + "http://localhost:3000/about", + "http://localhost:3000/services", + "http://localhost:3000/products", + "http://localhost:3000/cases", + "http://localhost:3000/news", + "http://localhost:3000/contact" + ], + "settings": { + "preset": "desktop", + "onlyCategories": [ + "performance", + "accessibility", + "best-practices", + "seo" + ] + } + }, + "assert": { + "assertions": { + "categories:performance": ["error", {"minScore": 0.9}], + "categories:accessibility": ["error", {"minScore": 0.9}], + "categories:best-practices": ["error", {"minScore": 0.9}], + "categories:seo": ["error", {"minScore": 0.9}], + "first-contentful-paint": ["error", {"maxNumericValue": 2000}], + "largest-contentful-paint": ["error", {"maxNumericValue": 3000}], + "cumulative-layout-shift": ["error", {"maxNumericValue": 0.1}], + "total-blocking-time": ["error", {"maxNumericValue": 300}], + "speed-index": ["error", {"maxNumericValue": 3000}] + } + }, + "upload": { + "target": "temporary-public-storage" + }, + "settings": { + "output": "html", + "outputPath": "lighthouse-reports" + } + } +} diff --git a/package.json b/package.json index 3d47621..c955d58 100644 --- a/package.json +++ b/package.json @@ -32,8 +32,6 @@ "lighthouse:upload": "lhci upload", "lighthouse:desktop": "lhci autorun --settings.preset=desktop", "lighthouse:mobile": "lhci autorun --settings.preset=mobile", - "deploy:cdn": "bash scripts/deploy-cdn.sh", - "deploy:cdn:refresh": "bash scripts/refresh-cdn.sh", "clean:tests": "bash scripts/maintenance/clean-test-files.sh", "prepare": "husky" }, diff --git a/public/images/news/founding.png b/public/images/news/founding.png new file mode 100644 index 0000000..a008903 Binary files /dev/null and b/public/images/news/founding.png differ diff --git a/public/images/news/solution.png b/public/images/news/solution.png new file mode 100644 index 0000000..3439649 Binary files /dev/null and b/public/images/news/solution.png differ diff --git a/scripts/deploy-cdn.sh b/scripts/deploy-cdn.sh deleted file mode 100644 index 464d2b1..0000000 --- a/scripts/deploy-cdn.sh +++ /dev/null @@ -1,89 +0,0 @@ -#!/bin/bash - -set -e - -CDN_DOMAIN=${CDN_DOMAIN:-"https://cdn.novalon.cn"} -COS_BUCKET=${COS_BUCKET:-"novalon-cdn-1250000000"} -COS_REGION=${COS_REGION:-"ap-chengdu"} -DIST_DIR=${DIST_DIR:-"dist/static"} -STANDALONE_DIR=${STANDALONE_DIR:-"dist/standalone"} - -echo "=========================================" -echo "CDN静态资源部署脚本" -echo "=========================================" -echo "CDN域名: $CDN_DOMAIN" -echo "COS存储桶: $COS_BUCKET" -echo "COS区域: $COS_REGION" -echo "静态资源目录: $DIST_DIR" -echo "=========================================" - -if [ ! -d "$DIST_DIR" ]; then - echo "错误: 静态资源目录不存在: $DIST_DIR" - echo "请先运行 npm run build 构建项目" - exit 1 -fi - -echo "" -echo "步骤1: 检查coscmd工具..." -if ! command -v coscmd &> /dev/null; then - echo "安装coscmd工具..." - pip install coscmd -fi - -echo "" -echo "步骤2: 配置coscmd..." -if [ -z "$COS_SECRET_ID" ] || [ -z "$COS_SECRET_KEY" ]; then - echo "错误: 请设置环境变量 COS_SECRET_ID 和 COS_SECRET_KEY" - echo "可以在腾讯云控制台 > 访问管理 > API密钥管理中获取" - exit 1 -fi - -coscmd config -a "$COS_SECRET_ID" -s "$COS_SECRET_KEY" -b "$COS_BUCKET" -r "$COS_REGION" - -echo "" -echo "步骤3: 上传静态资源到COS..." -echo "上传 _next/static/ 目录..." - -coscmd upload -r "$DIST_DIR" /_next/static/ --sync --delete - -echo "" -echo "步骤4: 上传public目录中的静态资源..." -if [ -d "public" ]; then - echo "上传 public/ 目录..." - coscmd upload -r public/ / --sync -fi - -echo "" -echo "步骤5: 设置COS对象缓存策略..." -echo "为静态资源设置长期缓存 (1年)..." - -coscmd set-meta "_next/static/*" "Cache-Control: public, max-age=31536000, immutable" -r - -echo "" -echo "步骤6: 刷新CDN缓存..." -if [ -n "$CDN_DOMAIN" ]; then - CDN_DOMAIN_CLEAN=$(echo "$CDN_DOMAIN" | sed 's|https://||' | sed 's|http://||') - echo "刷新CDN域名: $CDN_DOMAIN_CLEAN" - - if command -v tccli &> /dev/null; then - tccli cdn PurgePathsCache --Paths '["https://'"$CDN_DOMAIN_CLEAN"'/_next/static/"]' --FlushType flush - echo "CDN缓存刷新请求已提交" - else - echo "提示: 未安装tccli工具,请手动在腾讯云控制台刷新CDN缓存" - echo "刷新路径: https://$CDN_DOMAIN_CLEAN/_next/static/" - fi -fi - -echo "" -echo "=========================================" -echo "部署完成!" -echo "=========================================" -echo "静态资源已上传到: https://$COS_BUCKET.cos.$COS_REGION.myqcloud.com" -echo "CDN加速域名: $CDN_DOMAIN" -echo "" -echo "后续步骤:" -echo "1. 在腾讯云CDN控制台配置加速域名: cdn.novalon.cn" -echo "2. 设置源站为COS存储桶: $COS_BUCKET.cos.$COS_REGION.myqcloud.com" -echo "3. 配置HTTPS证书" -echo "4. 测试CDN加速效果" -echo "=========================================" diff --git a/scripts/refresh-cdn.sh b/scripts/refresh-cdn.sh deleted file mode 100644 index ce7bc12..0000000 --- a/scripts/refresh-cdn.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/bash - -set -e - -CDN_DOMAIN=${CDN_DOMAIN:-"https://cdn.novalon.cn"} -COS_BUCKET=${COS_BUCKET:-"novalon-cdn-1250000000"} -COS_REGION=${COS_REGION:-"ap-chengdu"} - -echo "=========================================" -echo "CDN缓存刷新脚本" -echo "=========================================" -echo "CDN域名: $CDN_DOMAIN" -echo "=========================================" - -CDN_DOMAIN_CLEAN=$(echo "$CDN_DOMAIN" | sed 's|https://||' | sed 's|http://||') - -echo "" -echo "刷新CDN缓存..." - -if command -v tccli &> /dev/null; then - echo "使用tccli刷新CDN缓存..." - - tccli cdn PurgePathsCache \ - --Paths "[\"https://$CDN_DOMAIN_CLEAN/_next/static/\"]" \ - --FlushType flush - - echo "CDN缓存刷新请求已提交" - echo "刷新ID可通过腾讯云控制台查看进度" -else - echo "错误: 未安装tccli工具" - echo "" - echo "请手动在腾讯云控制台刷新CDN缓存:" - echo "1. 登录腾讯云控制台: https://console.cloud.tencent.com/cdn" - echo "2. 进入缓存刷新页面" - echo "3. 选择'目录刷新'" - echo "4. 输入刷新URL: https://$CDN_DOMAIN_CLEAN/_next/static/" - echo "5. 点击提交" -fi - -echo "" -echo "=========================================" -echo "完成!" -echo "=========================================" diff --git a/src/app/(marketing)/cases/[id]/client.test.tsx b/src/app/(marketing)/cases/[id]/client.test.tsx index f61ffde..58ece32 100644 --- a/src/app/(marketing)/cases/[id]/client.test.tsx +++ b/src/app/(marketing)/cases/[id]/client.test.tsx @@ -69,9 +69,8 @@ describe('CaseDetailClient', () => { describe('Rendering', () => { it('should render case detail page', () => { - render(); - const main = screen.getByRole('main'); - expect(main).toBeInTheDocument(); + const { container } = render(); + expect(container.firstChild).toBeInTheDocument(); }); it('should render case title', () => { @@ -193,10 +192,9 @@ describe('CaseDetailClient', () => { }); describe('Accessibility', () => { - it('should have main landmark', () => { - render(); - const main = screen.getByRole('main'); - expect(main).toBeInTheDocument(); + it('should have container element', () => { + const { container } = render(); + expect(container.firstChild).toBeInTheDocument(); }); it('should have proper heading hierarchy', () => { diff --git a/src/app/(marketing)/cases/[id]/client.tsx b/src/app/(marketing)/cases/[id]/client.tsx index 79c4d7b..5cb6bbd 100644 --- a/src/app/(marketing)/cases/[id]/client.tsx +++ b/src/app/(marketing)/cases/[id]/client.tsx @@ -48,7 +48,7 @@ interface CaseItem { /** 成果数据 */ results: CaseResult[]; /** 客户证言 */ - testimonial: CaseTestimonial; + testimonial?: CaseTestimonial; /** 合作时长 */ duration: string; } @@ -79,7 +79,7 @@ export function CaseDetailClient({ caseItem }: CaseDetailClientProps) { }, []); return ( -
+
@@ -281,6 +281,6 @@ export function CaseDetailClient({ caseItem }: CaseDetailClientProps) {
-
+ ); } diff --git a/src/app/(marketing)/cases/page.tsx b/src/app/(marketing)/cases/page.tsx index b9e6198..f87c740 100644 --- a/src/app/(marketing)/cases/page.tsx +++ b/src/app/(marketing)/cases/page.tsx @@ -99,6 +99,7 @@ export default function CasesPage() { value={searchQuery} onChange={handleSearchChange} className="pl-10" + aria-label="搜索案例" /> diff --git a/src/app/(marketing)/contact/page.test.tsx b/src/app/(marketing)/contact/page.test.tsx deleted file mode 100644 index 144edcc..0000000 --- a/src/app/(marketing)/contact/page.test.tsx +++ /dev/null @@ -1,256 +0,0 @@ -import { describe, it, expect, jest, beforeAll } from '@jest/globals'; -import { render, screen, fireEvent, waitFor, act } from '@testing-library/react'; -import '@testing-library/jest-dom'; - -global.fetch = jest.fn(); - -jest.mock('framer-motion', () => ({ - motion: { - div: ({ children, className, ...props }: any) => ( -
- {children} -
- ), - }, - AnimatePresence: ({ children }: any) => <>{children}, -})); - -jest.mock('lucide-react', () => ({ - Mail: () => , - Phone: () => , - MapPin: () => , - Send: () => , - Loader2: () => , - Clock: () => , - HeadphonesIcon: () => , - CheckCircle2: () => , -})); - -jest.mock('@/components/ui/button', () => ({ - Button: ({ children, className, disabled, ...props }: any) => ( - - ), -})); - -jest.mock('@/components/ui/input', () => ({ - Input: ({ label, error, 'data-testid': testId, id, onChange, onBlur, ...props }: any) => ( -
- {label && } - - {error && {error}} -
- ), -})); - -jest.mock('@/components/ui/textarea', () => ({ - Textarea: ({ label, error, 'data-testid': testId, id, onChange, onBlur, ...props }: any) => ( -
- {label && } -