import { test, expect } from '../../fixtures'; test.describe('سناریوی اعتبارسنجی امنیتی XSS و محدودیت نرخ پیامک (Security XSS & Rate-Limiting)', () => { test('تزریق اسکریپت مخرب در فیلدهای فرم تماس و راستی‌آزمایی عدم اجرای XSS در فرانت و پنل ادمین', async ({ page }) => { let capturedPayload: Record = {}; await page.route(/\/api\/contact|\/contact/, async (route) => { if (route.request().method() === 'POST') { capturedPayload = route.request().postDataJSON?.() || {}; await route.fulfill({ status: 201, contentType: 'application/json', body: JSON.stringify({ success: true, message: 'پیام شما با موفقیت ثبت شد', }), }); } else { await route.continue(); } }); let dialogFired = false; page.on('dialog', async (dialog) => { dialogFired = true; await dialog.dismiss(); }); // 1. ورود به صفحه تماس با ما await page.goto('/contact', { waitUntil: 'domcontentloaded' }); await expect(page).toHaveURL(/\/contact/); // 2. پر کردن فیلدها با پی‌لود خطرناک XSS const xssPayload = ''; const nameInput = page.locator('#contact-name'); const phoneInput = page.locator('#contact-phone'); const subjectInput = page.locator('#contact-subject'); const messageInput = page.locator('#contact-message'); await expect(nameInput).toBeVisible({ timeout: 10000 }); await nameInput.click(); await nameInput.fill(xssPayload); await phoneInput.click(); await phoneInput.fill('09121112233'); await subjectInput.click(); await subjectInput.fill('XSS Test Subject'); await messageInput.click(); await messageInput.fill(' متن درخواست تستی'); // 3. ارسال فرم تماس const submitBtn = page.locator('[data-testid="contact-form-submit-btn"]').first(); await expect(submitBtn).toBeVisible({ timeout: 10000 }); await submitBtn.click(); // 4. راستی‌آزمایی نمایش پیام موفقیت بدون فعال شدن هیچ alert/dialog مخرب const successBox = page.locator('h4').filter({ hasText: 'پیام شما با موفقیت ثبت شد' }); await expect(successBox).toBeVisible({ timeout: 15000 }); // راستی‌آزمایی قطعی عدم اجرای alert جاوااسکریپت در مرورگر کلاینت expect(dialogFired).toBe(false); expect(capturedPayload.phone).toBe('09121112233'); expect(capturedPayload.name).toBe(xssPayload); expect(capturedPayload.phone).toBe('09121112233'); }); test('شبیه‌سازی محدودیت نرخ و تلاش مجدد با خطای ۴۲۹ (Rate-Limiting & 429 Cooldown Enforcement)', async ({ page }) => { let sendOtpAttempts = 0; await page.route('**/api/auth/send-otp*', async (route) => { sendOtpAttempts++; if (sendOtpAttempts === 1) { await route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify({ success: true, code: '12345' }), }); } else { await route.fulfill({ status: 429, contentType: 'application/json', body: JSON.stringify({ success: false, message: 'تعداد درخواست‌های شما بیش از حد مجاز است. لطفاً ۲ دقیقه صبر کنید.', }), }); } }); // 1. باز کردن مودال ورود با OTP await page.goto('/', { waitUntil: 'domcontentloaded' }); const headerLoginBtn = page.locator('[data-testid="header-login-btn"]').first(); await expect(headerLoginBtn).toBeVisible({ timeout: 15000 }); await headerLoginBtn.click(); // 2. ورود با کد پیامکی (OTP) const otpOptionBtn = page.locator('button').filter({ hasText: /ورود با کد پیامکی \(OTP\)/i }).first(); await expect(otpOptionBtn).toBeVisible({ timeout: 10000 }); await otpOptionBtn.click(); // 3. وارد کردن شماره موبایل و ارسال اولین OTP const phoneInput = page.locator('input[type="tel"]').first(); await expect(phoneInput).toBeVisible({ timeout: 10000 }); await phoneInput.fill('09129998877'); const sendOtpBtn = page.locator('button[type="submit"]').filter({ hasText: /ارسال کد تایید/i }).first(); await expect(sendOtpBtn).toBeVisible(); await sendOtpBtn.click(); // 4. راستی‌آزمایی فعال بودن متن تایمر معکوس (Cooldown Timer) const timerText = page.locator('span').filter({ hasText: /ارسال مجدد کد تا/i }).first(); await expect(timerText).toBeVisible({ timeout: 10000 }); // 5. ارسال درخواست مستقیم دوم در بازه Cooldown و راستی‌آزمایی قطعی پاسخ 429 سرور const rateLimitResponse = await page.evaluate(async () => { const res = await fetch('/api/auth/send-otp', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ mobile: '09129998877' }), }); return { status: res.status, data: await res.json() }; }); expect(rateLimitResponse.status).toBe(429); expect(rateLimitResponse.data.message).toContain('بیش از حد مجاز'); expect(sendOtpAttempts).toBe(2); }); });