Playwright
npm install @tracera/playwright
يتطلب Node.js ≥ 22.19 (انظر محوّلات الاختبار الآلي). @tracera/playwright على npm.
في playwright.config.ts:
import '@tracera/playwright/register';
import { defineConfig } from '@playwright/test';
export default defineConfig({
reporter: [['@tracera/playwright/reporter']],
use: {
screenshot: 'only-on-failure',
video: 'retain-on-failure',
trace: 'retain-on-failure', // or "on-first-retry"
},
});
import "@tracera/playwright/register" يرقّع test.step / الخطافات في كل عامل حتى تقع tracera.comment / tracera.error على الخطوة الحالية.
فعّل screenshot / video / trace مرة واحدة في الإعداد — تُمرَّر مخرجات Playwright تلقائيًا إلى نتيجة Tracera (10 مرفقات كحد أقصى للنتيجة و10 لكل خطوة). مع إعادة المحاولة يُبلَّغ عن المحاولة النهائية فقط. إن كانت إعادة محاولة (retry > 0) تظهر PLAYWRIGHT_RETRY في تبويب Env — قيمة testInfo.retry في Playwright (1 تعني التشغيل الثاني).
متغيرات البيئة ووضع التشغيل: محوّلات الاختبار الآلي.
ربط testCaseId و autotestName
استورد test / expect من @playwright/test، وtracera / annotations من @tracera/playwright.
إن لم تُحدّد autotestName، يستخدم المحوّل عنوان اختبار Playwright.
عند التصريح (المفضّل):
import { test, expect } from '@playwright/test';
import { annotations } from '@tracera/playwright';
test('login', { annotation: annotations(42, 'e2e/login') }, async ({ page }) => {
await page.goto('/login');
await expect(page.getByRole('button', { name: 'Sign in' })).toBeVisible();
});
داخل الاختبار (اختياري إذا ربطت annotations الحالة مسبقًا):
import { test, expect } from '@playwright/test';
import { tracera } from '@tracera/playwright';
test('login', async ({ page }) => {
tracera.testCase(42, 'e2e/login');
await page.goto('/login');
await expect(page.getByRole('button', { name: 'Sign in' })).toBeVisible();
});
الخطوات
استخدم Playwright test.step — تُسجَّل الخطوة تحت الاختبار. tracera.step هو نفس واجهة الإبلاغ إن فضّلت الـ API المشترك مع العدّائين الآخرين. الخطوات داخل test.beforeEach تذهب إلى الإعداد؛ والخطوات داخل test.afterEach إلى التنظيف.
import { test } from '@playwright/test';
import { annotations } from '@tracera/playwright';
test.beforeEach(async ({ page }) => {
await test.step('open shop', async () => {
await page.goto('/shop');
});
});
test('checkout', { annotation: annotations(10, 'e2e/checkout') }, async ({ page }) => {
await test.step('add to cart', async () => {
await page.getByRole('button', { name: 'Add' }).click();
});
});
test.afterEach(async ({ page }) => {
await test.step('cleanup', async () => {
await page.goto('/cart/clear');
});
});
التعليقات والأخطاء والمرفقات
داخل الخطوة حقول تلك الخطوة. خارج الخطوة حقول النتيجة.
import { test } from '@playwright/test';
import { tracera, annotations } from '@tracera/playwright';
test('login', { annotation: annotations(42, 'e2e/login') }, async ({ page }, testInfo) => {
tracera.comment('result-level note');
tracera.error('result-level error text');
await test.step('open login', async () => {
await page.goto('/login');
tracera.comment('landed on login');
});
await testInfo.attach('suite-log.txt', {
body: 'finished login flow',
contentType: 'text/plain',
});
});
استخدم testInfo.attach للملفات المخصصة. يُرفق Playwright لقطات الشاشة وتسجيل المتصفح وtrace بنفسه — في Tracera تفتح الصور في عارض ضوئي، ويُشغَّل التسجيل ضمن الصفحة، ويُفتح trace في Trace Viewer.
اختبارات مُعامَلة
import { test, expect } from '@playwright/test';
import { annotations } from '@tracera/playwright';
const rows = [
{ id: 42, name: 'e2e/login-ok', path: '/login' },
{ id: 43, name: 'e2e/login-sso', path: '/login/sso' },
];
for (const row of rows) {
test(row.name, { annotation: annotations(row.id, row.name) }, async ({ page }) => {
await test.step('open', async () => {
await page.goto(row.path);
});
await expect(page.getByRole('button', { name: 'Sign in' })).toBeVisible();
});
}
أو استدعِ tracera.testCase(row.id, row.name) داخل الجسم بدل annotations.
fixtures مخصصة
وسّع test القياسي من Playwright كالمعتاد:
import { test as base, expect } from '@playwright/test';
import { tracera } from '@tracera/playwright';
export const test = base.extend<{ asUser: void }>({
asUser: [
async ({ page }, use) => {
await page.goto('/login');
await page.getByLabel('Email').fill('user@example.com');
await page.getByRole('button', { name: 'Sign in' }).click();
await use();
},
{ auto: true },
],
});
test('dashboard', async ({ page }) => {
tracera.testCase(99, 'e2e/dashboard');
await expect(page.getByRole('heading', { name: 'Dashboard' })).toBeVisible();
});