我正在为我的 Web 应用程序运行 Playwright 测试。测试成功执行,但没有生成视频记录。我已在
playwright.config.js
中配置了视频录制,但 handleTestVideo
挂钩中的 afterEach
功能始终报告没有录制视频。
export default defineConfig({
use: {
video: {
mode: 'on',
size: { width: 640, height: 480 }
},
},
});
查看完整代码仅供参考
// @ts-check
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
testDir: './playwright',
fullyParallel: true,
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 2 : 0,
workers: process.env.CI ? 1 : undefined,
reporter: [['list'], ['json', { outputFile: 'test-results.json' }]],
outputDir: 'test-results',
use: {
baseURL: 'http://localhost:8080',
trace: 'on-first-retry',
screenshot: 'on',
video: {
mode: 'on',
size: { width: 640, height: 480 }
},
headless: true,
},
projects: [
{
name: 'chromium',
use: {
...devices['Desktop Chrome'],
},
},
],
webServer: {
command: 'python3 manage.py runserver',
url: 'http://localhost:8080',
reuseExistingServer: !process.env.CI,
timeout: 120 * 1000
},
preserveOutput: 'never',
});
test('Validate message send form and capture screenshots', async ({ page }) => {
// Test actions, pass as expected...
});
test.afterEach(async ({ }, testInfo) => {
await handleTestVideo(testInfo);
});
查看官方playwright文档应该不需要使用任何utils,解决方案应该比这简单得多。
我知道这个调试步骤几乎毫无价值(对我温柔一点,我还很初级......)但我的主要观点是没有视频。
export async function handleTestVideo(testInfo) {
console.log('Handling test video...');
console.log('Test status:', testInfo.status);
// Wait for the video to be ready
await testInfo.attachments.find(attachment => attachment.name === 'video');
console.log('Video attachment found:', testInfo.attachments.find(attachment => attachment.name === 'video'));
const videoAttachment = testInfo.attachments.find(attachment => attachment.name === 'video');
console.log('Video attachment:', videoAttachment);
if (videoAttachment) {
const videoPath = videoAttachment.path;
console.log('Video path:', videoPath);
if (videoPath) {
const videoDir = path.join('playwright', 'videos', testInfo.title);
const newPath = path.join(videoDir, `${testInfo.title}.webm`);
// Ensure the directory exists
fs.mkdirSync(videoDir, { recursive: true });
// Wait for the video file to be fully written
await new Promise(resolve => setTimeout(resolve, 1000));
// Move the video file
fs.renameSync(videoPath, newPath);
console.log(`Video saved to: ${newPath}`);
} else {
console.log('Video path is undefined.');
}
} else {
console.log('No video attachment found for this test.');
}
}
[test logs as expected, pass]
Handling test video...
Test status: passed
Video attachment found: undefined
Video attachment: undefined
No video attachment found for this test
import { test, expect } from '@playwright/test';
import { login, captureScreenshot, handleTestVideo, baseURL, handleFailedTestVideo } from './testUtils';
import path from 'path';
const BASE_URL = baseURL;
test.describe('Message Detail Send Form Validation', () => {
test('Validate message send form and capture screenshots', async ({ page }) => {
await login(page);
console.log(`Navigating to ${BASE_URL}/messages/1`);
await page.goto(`${BASE_URL}/messages/1`);
console.log('Starting message send form validation tests');
await page.waitForSelector('form', { state: 'visible' });
// Test: Empty submission
console.log('Testing empty submission');
await page.click('button:has-text("Send")');
// Wait for the alert to appear
await page.waitForSelector('.alert-warning', { state: 'visible', timeout: 5000 });
const alertText = await page.textContent('.alert-warning');
expect(alertText).toContain('Please enter a message or upload an image');
await captureScreenshot(page, 'message-send', '1-empty-submission');
console.log('Captured screenshot for empty submission');
// Test: Message too long
console.log('Testing message too long');
await page.fill('textarea[name="content"]', 'a'.repeat(1001));
await page.click('button:has-text("Send")');
// Wait for the alert to appear
await page.waitForSelector('.alert-warning', { state: 'visible', timeout: 5000 });
const longMessageAlertText = await page.textContent('.alert-warning');
expect(longMessageAlertText).toContain('Message should not exceed 1000 characters');
await captureScreenshot(page, 'message-send', '2-message-too-long');
console.log('Captured screenshot for message too long');
// Test: Message with only spaces
console.log('Testing message with only spaces');
await page.fill('textarea[name="content"]', ' ');
await page.click('button:has-text("Send")');
// Wait for the alert to appear
await page.waitForSelector('.alert-warning', { state: 'visible', timeout: 5000 });
const spacesAlertText = await page.textContent('.alert-warning');
expect(spacesAlertText).toContain('Please enter a message or upload an image');
await captureScreenshot(page, 'message-send', '3-spaces-only');
console.log('Captured screenshot for spaces-only message');
// Test: Image file too large
console.log('Testing image file too large');
const largeImagePath = path.join(__dirname, 'test-assets', 'large-image.jpg');
await page.setInputFiles('input[type="file"]', largeImagePath);
// Wait for the alert to appear
await page.waitForSelector('.alert-warning', { state: 'visible', timeout: 5000 });
const largeImageAlertText = await page.textContent('.alert-warning');
expect(largeImageAlertText).toContain('Image file size should not exceed 5MB');
await captureScreenshot(page, 'message-send', '4-image-too-large');
console.log('Captured screenshot for image too large');
// Test: invalid image type
console.log('Testing invalid image type');
const invalidImagePath = path.join(__dirname, 'test-assets', 'test-file.txt');
await page.setInputFiles('input[type="file"]', invalidImagePath);
// Wait for the alert to appear
await page.waitForSelector('.alert-warning', { state: 'visible', timeout: 5000 });
const invalidImageAlertText = await page.textContent('.alert-warning');
expect(invalidImageAlertText).toContain('Only JPEG, PNG, and GIF images are allowed');
await captureScreenshot(page, 'message-send', '5-invalid-image-type');
console.log('Captured screenshot for invalid image type');
console.log('Message send form validation tests completed');
// Test: Valid image with no message
console.log('Testing valid image with no message');
const validImagePath = path.join(__dirname, 'test-assets', 'test-image.jpg');
await page.fill('textarea[name="content"]', '');
await page.setInputFiles('input[type="file"]', validImagePath);
await captureScreenshot(page, 'message-send', '6.1-valid-image-no-message-preview');
await page.click('button:has-text("Send")');
await page.waitForTimeout(200);
// Check if there are no error messages
const errorMessages = await page.$$('.alert-warning');
expect(errorMessages.length).toBe(0);
await page.waitForTimeout(2000);
await captureScreenshot(page, 'message-send', '6-valid-image-no-message');
console.log('Captured screenshot for valid image with no message');
// Test: Valid message with no image
console.log('Testing valid message with no image');
await page.fill('textarea[name="content"]', 'Hello, world!');
await page.click('button:has-text("Send")');
// wait for network idle
await page.waitForTimeout(2000);
await captureScreenshot(page, 'message-send', '7-valid-message-no-image');
});
});
test.afterEach(async ({ }, testInfo) => {
await handleTestVideo(testInfo);
});
有人在剧作家中录制过视频吗?他们是怎么做到的?我错过了什么?
文档表明这非常简单 - 我的屏幕截图运行良好。
您需要使用毕竟。仅当浏览器关闭时才会写入视频,并且在 afterEach 中您仍然可以访问您的浏览器实例。
test.afterAll(async ({ }, testInfo) => {
await handleTestVideo(testInfo);
});