mirror of
https://github.com/arch3rPro/1Panel-Appstore.git
synced 2026-05-08 10:22:12 +08:00
feat: add app playwright
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "playwright-test-environment",
|
||||
"version": "1.0.0",
|
||||
"description": "Playwright test environment for 1Panel",
|
||||
"main": "server.js",
|
||||
"scripts": {
|
||||
"start": "node server.js",
|
||||
"test": "playwright test"
|
||||
},
|
||||
"dependencies": {
|
||||
"@playwright/test": "^1.55.0",
|
||||
"express": "^4.18.2"
|
||||
},
|
||||
"keywords": ["playwright", "testing", "automation"],
|
||||
"author": "1Panel-Appstore",
|
||||
"license": "MIT"
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import { defineConfig, devices } from '@playwright/test';
|
||||
|
||||
export default defineConfig({
|
||||
testDir: './tests',
|
||||
fullyParallel: true,
|
||||
forbidOnly: !!process.env.CI,
|
||||
retries: process.env.CI ? 2 : 0,
|
||||
workers: process.env.CI ? 1 : undefined,
|
||||
reporter: [['html', { outputFolder: './test-results' }]],
|
||||
use: {
|
||||
baseURL: 'http://localhost:3000',
|
||||
trace: 'on-first-retry',
|
||||
screenshot: 'only-on-failure',
|
||||
},
|
||||
projects: [
|
||||
{
|
||||
name: 'chromium',
|
||||
use: { ...devices['Desktop Chrome'] },
|
||||
},
|
||||
{
|
||||
name: 'firefox',
|
||||
use: { ...devices['Desktop Firefox'] },
|
||||
},
|
||||
{
|
||||
name: 'webkit',
|
||||
use: { ...devices['Desktop Safari'] },
|
||||
},
|
||||
],
|
||||
});
|
||||
@@ -0,0 +1,176 @@
|
||||
const express = require('express');
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const { spawn } = require('child_process');
|
||||
|
||||
const app = express();
|
||||
const port = process.env.PORT || 3000;
|
||||
|
||||
app.use(express.json());
|
||||
app.use('/test-results', express.static(path.join(__dirname, 'test-results')));
|
||||
app.use('/tests', express.static(path.join(__dirname, 'tests')));
|
||||
|
||||
app.get('/', (req, res) => {
|
||||
res.send(`
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Playwright Test Environment</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
max-width: 800px;
|
||||
margin: 50px auto;
|
||||
padding: 20px;
|
||||
background: #f5f5f5;
|
||||
}
|
||||
.container {
|
||||
background: white;
|
||||
padding: 30px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||||
}
|
||||
.btn {
|
||||
background: #007bff;
|
||||
color: white;
|
||||
padding: 10px 20px;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
margin: 5px;
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
}
|
||||
.btn:hover { background: #0056b3; }
|
||||
.section {
|
||||
margin: 20px 0;
|
||||
padding: 20px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 8px;
|
||||
background: #f9f9f9;
|
||||
}
|
||||
.status { color: #28a745; font-weight: bold; }
|
||||
.code {
|
||||
background: #f8f9fa;
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
font-family: monospace;
|
||||
margin: 10px 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>🎭 Playwright Test Environment</h1>
|
||||
<p class="status">✅ Environment is ready!</p>
|
||||
|
||||
<div class="section">
|
||||
<h2>Quick Actions</h2>
|
||||
<button class="btn" onclick="runTests()">Run All Tests</button>
|
||||
<a class="btn" href="/test-results" target="_blank">View Reports</a>
|
||||
<button class="btn" onclick="generateExample()">Generate Example Test</button>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<h2>Environment Info</h2>
|
||||
<p><strong>Playwright Version:</strong> v1.55.0</p>
|
||||
<p><strong>Available Browsers:</strong> Chromium, Firefox, WebKit</p>
|
||||
<p><strong>Test Directory:</strong> ./tests</p>
|
||||
<p><strong>Reports Directory:</strong> ./test-results</p>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<h2>Usage Instructions</h2>
|
||||
<ol>
|
||||
<li>Upload test files to the <code>tests/</code> directory</li>
|
||||
<li>Configure tests in <code>playwright.config.ts</code></li>
|
||||
<li>Run tests using the button above or CLI command</li>
|
||||
<li>View HTML reports in the test-results directory</li>
|
||||
</ol>
|
||||
|
||||
<h3>Example Test Code</h3>
|
||||
<div class="code">
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
test('basic test', async ({ page }) => {
|
||||
await page.goto('https://playwright.dev/');
|
||||
await expect(page).toHaveTitle(/Playwright/);
|
||||
});
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function runTests() {
|
||||
fetch('/api/run-tests', { method: 'POST' })
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
alert('Tests started: ' + data.message);
|
||||
setTimeout(() => {
|
||||
window.open('/test-results', '_blank');
|
||||
}, 3000);
|
||||
})
|
||||
.catch(err => alert('Error: ' + err));
|
||||
}
|
||||
|
||||
function generateExample() {
|
||||
fetch('/api/generate-example', { method: 'POST' })
|
||||
.then(response => response.json())
|
||||
.then(data => alert('Example generated: ' + data.message))
|
||||
.catch(err => alert('Error: ' + err));
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
`);
|
||||
});
|
||||
|
||||
app.post('/api/run-tests', (req, res) => {
|
||||
const testProcess = spawn('npx', ['playwright', 'test'], {
|
||||
cwd: process.cwd(),
|
||||
stdio: 'inherit'
|
||||
});
|
||||
|
||||
res.json({ message: 'Tests execution started, check reports in 30 seconds' });
|
||||
});
|
||||
|
||||
app.post('/api/generate-example', (req, res) => {
|
||||
const exampleTest = `import { test, expect } from '@playwright/test';
|
||||
|
||||
test('playwright homepage test', async ({ page }) => {
|
||||
await page.goto('https://playwright.dev/');
|
||||
|
||||
// Expect a title "to contain" a substring.
|
||||
await expect(page).toHaveTitle(/Playwright/);
|
||||
|
||||
// create a locator
|
||||
const getStarted = page.getByRole('link', { name: 'Get started' });
|
||||
|
||||
// Expect an attribute "to be strictly equal" to the value.
|
||||
await expect(getStarted).toHaveAttribute('href', '/docs/intro');
|
||||
|
||||
// Click the get started link.
|
||||
await getStarted.click();
|
||||
|
||||
// Expects the URL to contain intro.
|
||||
await expect(page).toHaveURL(/.*intro/);
|
||||
});
|
||||
|
||||
test('example.com test', async ({ page }) => {
|
||||
await page.goto('https://example.com');
|
||||
await expect(page).toHaveTitle('Example Domain');
|
||||
await expect(page.locator('h1')).toContainText('Example Domain');
|
||||
});`;
|
||||
|
||||
if (!fs.existsSync('./tests')) {
|
||||
fs.mkdirSync('./tests', { recursive: true });
|
||||
}
|
||||
|
||||
fs.writeFileSync('./tests/example.spec.ts', exampleTest);
|
||||
res.json({ message: 'Example test generated at ./tests/example.spec.ts' });
|
||||
});
|
||||
|
||||
app.listen(port, '0.0.0.0', () => {
|
||||
console.log(`🎭 Playwright server running at http://0.0.0.0:${port}`);
|
||||
console.log(`📊 Test reports will be available at http://0.0.0.0:${port}/test-results`);
|
||||
});
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "🎭 Setting up Playwright Test Environment..."
|
||||
|
||||
# 确保目录存在
|
||||
mkdir -p tests test-results
|
||||
|
||||
# 安装依赖
|
||||
echo "📦 Installing dependencies..."
|
||||
npm install
|
||||
|
||||
# 安装 Playwright 浏览器
|
||||
echo "🌐 Installing Playwright browsers..."
|
||||
npx playwright install
|
||||
|
||||
# 启动服务器
|
||||
echo "🚀 Starting Playwright server..."
|
||||
node server.js
|
||||
@@ -0,0 +1,17 @@
|
||||
additionalProperties:
|
||||
formFields:
|
||||
- default: 3000
|
||||
edit: true
|
||||
envKey: PANEL_APP_PORT_HTTP
|
||||
label:
|
||||
en: Port
|
||||
zh: 端口
|
||||
zh-Hant: 埠
|
||||
ja: ポート
|
||||
ms: Port
|
||||
pt-br: Porta
|
||||
ru: Порт
|
||||
ko: 포트
|
||||
required: true
|
||||
rule: paramPort
|
||||
type: number
|
||||
@@ -0,0 +1,51 @@
|
||||
services:
|
||||
playwright-init:
|
||||
image: mcr.microsoft.com/playwright:v1.55.0-noble
|
||||
user: "root"
|
||||
volumes:
|
||||
- ./data:/home/pwuser/app
|
||||
- ./config:/home/pwuser/config:ro
|
||||
working_dir: /home/pwuser/app
|
||||
command: >
|
||||
sh -c "
|
||||
cp -r /home/pwuser/config/* /home/pwuser/app/ &&
|
||||
chown -R pwuser:pwuser /home/pwuser/app &&
|
||||
chmod +x /home/pwuser/app/start.sh
|
||||
"
|
||||
restart: "no"
|
||||
|
||||
playwright:
|
||||
image: mcr.microsoft.com/playwright:v1.55.0-noble
|
||||
container_name: ${CONTAINER_NAME}
|
||||
restart: always
|
||||
networks:
|
||||
- 1panel-network
|
||||
ports:
|
||||
- "${PANEL_APP_PORT_HTTP}:3000"
|
||||
volumes:
|
||||
- ./data:/home/pwuser/app
|
||||
working_dir: /home/pwuser/app
|
||||
user: "pwuser"
|
||||
environment:
|
||||
- NODE_ENV=production
|
||||
- PORT=3000
|
||||
init: true
|
||||
ipc: host
|
||||
security_opt:
|
||||
- seccomp:unconfined
|
||||
command: "./start.sh"
|
||||
depends_on:
|
||||
playwright-init:
|
||||
condition: service_completed_successfully
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:3000"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 90s
|
||||
labels:
|
||||
createdBy: "Apps"
|
||||
|
||||
networks:
|
||||
1panel-network:
|
||||
external: true
|
||||
Reference in New Issue
Block a user