mirror of
https://gitee.com/kekingcn/file-online-preview.git
synced 2026-03-14 05:03:49 +08:00
test(e2e): phase-3 add nightly full run and perf smoke checks (#717)
* test(e2e): phase-3 add nightly workflow and perf smoke suite * test(e2e): address copilot review for phase-3 fixture and readiness flow
This commit is contained in:
129
.github/workflows/nightly-e2e.yml
vendored
Normal file
129
.github/workflows/nightly-e2e.yml
vendored
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
name: Nightly E2E Full
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '30 18 * * *' # 02:30 Asia/Shanghai
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
e2e-nightly:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 50
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup JDK 21
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
distribution: temurin
|
||||||
|
java-version: '21'
|
||||||
|
cache: maven
|
||||||
|
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: '20'
|
||||||
|
cache: 'npm'
|
||||||
|
cache-dependency-path: tests/e2e/package-lock.json
|
||||||
|
|
||||||
|
- name: Setup Python 3.11
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: '3.11'
|
||||||
|
|
||||||
|
- name: Install LibreOffice + zip
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y libreoffice zip
|
||||||
|
|
||||||
|
- name: Setup Python deps for office fixtures
|
||||||
|
run: |
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
pip install -r tests/e2e/requirements.txt
|
||||||
|
|
||||||
|
- name: Build kkFileView
|
||||||
|
run: mvn -q -pl server -DskipTests package
|
||||||
|
|
||||||
|
- name: Install E2E deps
|
||||||
|
working-directory: tests/e2e
|
||||||
|
run: |
|
||||||
|
npm ci
|
||||||
|
npx playwright install --with-deps chromium
|
||||||
|
|
||||||
|
- name: Generate E2E fixtures
|
||||||
|
working-directory: tests/e2e
|
||||||
|
run: npm run gen:all
|
||||||
|
|
||||||
|
- name: Start fixture server
|
||||||
|
run: |
|
||||||
|
cd tests/e2e/fixtures
|
||||||
|
python3 -m http.server 18080 > /tmp/fixture-server.log 2>&1 &
|
||||||
|
|
||||||
|
- name: Start kkFileView
|
||||||
|
run: |
|
||||||
|
JAR_PATH=$(ls server/target/kkFileView-*.jar | head -n 1)
|
||||||
|
nohup env KK_TRUST_HOST='*' KK_NOT_TRUST_HOST='10.*,172.16.*,192.168.*' java -jar "$JAR_PATH" > /tmp/kkfileview.log 2>&1 &
|
||||||
|
|
||||||
|
- name: Wait for services
|
||||||
|
run: |
|
||||||
|
fixture_ready=false
|
||||||
|
for i in {1..60}; do
|
||||||
|
if curl -fsS http://127.0.0.1:18080/sample.txt >/dev/null; then
|
||||||
|
fixture_ready=true
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
if [ "$fixture_ready" != "true" ]; then
|
||||||
|
echo "Error: fixture server did not become ready within 60 seconds." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
kkfileview_ready=false
|
||||||
|
for i in {1..120}; do
|
||||||
|
if curl -fsS http://127.0.0.1:8012/ >/dev/null; then
|
||||||
|
kkfileview_ready=true
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
if [ "$kkfileview_ready" != "true" ]; then
|
||||||
|
echo "Error: kkFileView service did not become ready within 120 seconds." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Run smoke suite
|
||||||
|
working-directory: tests/e2e
|
||||||
|
env:
|
||||||
|
KK_BASE_URL: http://127.0.0.1:8012
|
||||||
|
FIXTURE_BASE_URL: http://127.0.0.1:18080
|
||||||
|
run: npm run test:smoke
|
||||||
|
|
||||||
|
- name: Run perf suite
|
||||||
|
working-directory: tests/e2e
|
||||||
|
env:
|
||||||
|
KK_BASE_URL: http://127.0.0.1:8012
|
||||||
|
FIXTURE_BASE_URL: http://127.0.0.1:18080
|
||||||
|
E2E_MAX_PREVIEW_MS: 20000
|
||||||
|
run: npm run test:perf
|
||||||
|
|
||||||
|
- name: Upload Playwright report
|
||||||
|
if: always()
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: nightly-playwright-report
|
||||||
|
path: tests/e2e/playwright-report
|
||||||
|
|
||||||
|
- name: Upload service logs
|
||||||
|
if: always()
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: nightly-e2e-service-logs
|
||||||
|
path: |
|
||||||
|
/tmp/kkfileview.log
|
||||||
|
/tmp/fixture-server.log
|
||||||
@@ -11,6 +11,7 @@ This folder contains a first MVP of end-to-end automated tests.
|
|||||||
- Security regression checks for blocked internal-network hosts (`10.*`) on:
|
- Security regression checks for blocked internal-network hosts (`10.*`) on:
|
||||||
- `/onlinePreview`
|
- `/onlinePreview`
|
||||||
- `/getCorsFile`
|
- `/getCorsFile`
|
||||||
|
- Basic performance smoke checks (configurable threshold): txt/docx/xlsx preview response time
|
||||||
|
|
||||||
## Local run
|
## Local run
|
||||||
|
|
||||||
@@ -52,3 +53,13 @@ KK_TRUST_HOST='*' KK_NOT_TRUST_HOST='10.*,172.16.*,192.168.*' java -jar "$JAR_PA
|
|||||||
cd tests/e2e
|
cd tests/e2e
|
||||||
KK_BASE_URL=http://127.0.0.1:8012 FIXTURE_BASE_URL=http://127.0.0.1:18080 npm test
|
KK_BASE_URL=http://127.0.0.1:8012 FIXTURE_BASE_URL=http://127.0.0.1:18080 npm test
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Optional:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# smoke only (self-contained: will auto-generate fixtures)
|
||||||
|
npm run test:smoke
|
||||||
|
|
||||||
|
# perf smoke (self-contained; default threshold 15000ms)
|
||||||
|
E2E_MAX_PREVIEW_MS=15000 npm run test:perf
|
||||||
|
```
|
||||||
|
|||||||
@@ -9,7 +9,11 @@
|
|||||||
"gen:all": "npm run gen:fixtures && npm run gen:office",
|
"gen:all": "npm run gen:fixtures && npm run gen:office",
|
||||||
"pretest": "npm run gen:all",
|
"pretest": "npm run gen:all",
|
||||||
"test": "playwright test",
|
"test": "playwright test",
|
||||||
"test:headed": "playwright test --headed"
|
"test:headed": "playwright test --headed",
|
||||||
|
"pretest:smoke": "npm run gen:all",
|
||||||
|
"test:smoke": "playwright test specs/preview-smoke.spec.ts",
|
||||||
|
"pretest:perf": "npm run gen:all",
|
||||||
|
"test:perf": "playwright test specs/perf-smoke.spec.ts"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@playwright/test": "^1.55.0"
|
"@playwright/test": "^1.55.0"
|
||||||
|
|||||||
@@ -4,8 +4,10 @@ export default defineConfig({
|
|||||||
testDir: './specs',
|
testDir: './specs',
|
||||||
timeout: 30_000,
|
timeout: 30_000,
|
||||||
expect: { timeout: 10_000 },
|
expect: { timeout: 10_000 },
|
||||||
|
retries: process.env.CI ? 1 : 0,
|
||||||
reporter: [['list'], ['html', { outputFolder: 'playwright-report', open: 'never' }]],
|
reporter: [['list'], ['html', { outputFolder: 'playwright-report', open: 'never' }]],
|
||||||
use: {
|
use: {
|
||||||
baseURL: process.env.KK_BASE_URL || 'http://127.0.0.1:8012',
|
baseURL: process.env.KK_BASE_URL || 'http://127.0.0.1:8012',
|
||||||
|
trace: 'on-first-retry',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
47
tests/e2e/specs/perf-smoke.spec.ts
Normal file
47
tests/e2e/specs/perf-smoke.spec.ts
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
import { test, expect, request as playwrightRequest } from '@playwright/test';
|
||||||
|
|
||||||
|
const fixtureBase = process.env.FIXTURE_BASE_URL || 'http://127.0.0.1:18080';
|
||||||
|
const envMaxMs = Number(process.env.E2E_MAX_PREVIEW_MS);
|
||||||
|
const maxMs = Number.isFinite(envMaxMs) ? envMaxMs : 15000;
|
||||||
|
|
||||||
|
function b64(v: string): string {
|
||||||
|
return Buffer.from(v).toString('base64');
|
||||||
|
}
|
||||||
|
|
||||||
|
async function timedPreview(request: any, fileUrl: string) {
|
||||||
|
const started = Date.now();
|
||||||
|
const resp = await request.get(`/onlinePreview?url=${b64(fileUrl)}`);
|
||||||
|
const elapsed = Date.now() - started;
|
||||||
|
return { resp, elapsed };
|
||||||
|
}
|
||||||
|
|
||||||
|
test.beforeAll(async () => {
|
||||||
|
const api = await playwrightRequest.newContext();
|
||||||
|
const required = ['sample.txt', 'sample.docx', 'sample.xlsx'];
|
||||||
|
try {
|
||||||
|
for (const name of required) {
|
||||||
|
const resp = await api.get(`${fixtureBase}/${name}`);
|
||||||
|
expect(resp.ok(), `fixture missing or unavailable: ${name}`).toBeTruthy();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
await api.dispose();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test('perf: txt preview response under threshold', async ({ request }) => {
|
||||||
|
const { resp, elapsed } = await timedPreview(request, `${fixtureBase}/sample.txt`);
|
||||||
|
expect(resp.status()).toBe(200);
|
||||||
|
expect(elapsed).toBeLessThan(maxMs);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('perf: docx preview response under threshold', async ({ request }) => {
|
||||||
|
const { resp, elapsed } = await timedPreview(request, `${fixtureBase}/sample.docx`);
|
||||||
|
expect(resp.status()).toBe(200);
|
||||||
|
expect(elapsed).toBeLessThan(maxMs);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('perf: xlsx preview response under threshold', async ({ request }) => {
|
||||||
|
const { resp, elapsed } = await timedPreview(request, `${fixtureBase}/sample.xlsx`);
|
||||||
|
expect(resp.status()).toBe(200);
|
||||||
|
expect(elapsed).toBeLessThan(maxMs);
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user