import { expect, test } from '@playwright/test' async function login(page: import('@playwright/test').Page) { await page.goto('http://127.0.0.1:5173/login') await page.getByLabel(/ایمیل|Email/).fill('designer@microlearn.test') await page.getByLabel(/رمز عبور|Password/).fill('password') await page.getByRole('button', { name: /ورود|Sign in/ }).click() await expect(page).toHaveURL(/\/app\/dashboard$/) } test('builder uses the production authoring workspace architecture', async ({ page }) => { await page.setViewportSize({ width: 1440, height: 900 }) await login(page) await page.goto('http://127.0.0.1:5173/app/builder-preview') await expect(page.getByRole('heading', { name: 'بهترین روش‌های ایمنی در محیط کار' })).toBeVisible() await expect(page.getByRole('banner')).toContainText('ذخیره خودکار فعال است') await expect(page.getByRole('complementary', { name: 'ساختار دوره' })).toBeVisible() await page.getByRole('button', { name: 'افزودن', exact: true }).click() const library = page.getByRole('dialog', { name: 'کتابخانه بلاک‌ها' }) const search = library.getByRole('searchbox', { name: 'جست‌وجوی بلاک‌ها' }) await expect(search).toBeVisible() await search.fill('تصویر') await expect(library.getByRole('button', { name: 'افزودن تصویر', exact: true })).toBeVisible() await expect(library.getByRole('button', { name: 'افزودن متن', exact: true })).toHaveCount(0) await search.fill('') await library.getByLabel('بستن کتابخانه').click() await page.getByRole('heading', { name: 'بهترین روش‌های ایمنی در محیط کار' }).click() const panel = page.getByLabel('تنظیمات زمینه‌ای') await expect(panel.getByRole('button', { name: 'محتوا' })).toBeVisible() await expect(panel.getByRole('button', { name: 'دسترس‌پذیری' })).toBeVisible() await panel.getByRole('button', { name: 'طراحی' }).click() await panel.getByLabel('اندازه فونت').fill('44') await expect(page.locator('.canvas-block.is-selected .render-heading')).toHaveCSS('font-size', '44px') await expect(panel.getByText(/ذخیره شد · ویرایش/)).toBeVisible() await page.evaluate(() => (document.activeElement as HTMLElement | null)?.blur()) await page.keyboard.press('/') await expect(page.getByRole('dialog', { name: 'انتخاب بلاک' })).toBeVisible() await page.keyboard.press('Escape') await expect(page.getByRole('dialog', { name: 'انتخاب بلاک' })).toHaveCount(0) await page.getByRole('heading', { name: 'بهترین روش‌های ایمنی در محیط کار' }).click() const canvasShare = await page.evaluate(() => { const workspace = document.querySelector('.builder-workspace')?.getBoundingClientRect() const canvas = document.querySelector('.builder-canvas-wrap')?.getBoundingClientRect() return workspace && canvas ? canvas.width / workspace.width : 0 }) expect(canvasShare).toBeGreaterThan(0.35) await expect(page.getByText(/زمان تخمینی:/)).toBeVisible() expect(await page.evaluate(() => document.documentElement.scrollWidth <= document.documentElement.clientWidth)).toBe(true) }) test('AI Studio four-stage workflow stays usable on a narrow viewport', async ({ page }) => { await page.setViewportSize({ width: 375, height: 812 }) await login(page) await page.goto('http://127.0.0.1:5173/app/ai-studio') await expect(page.getByRole('heading', { name: 'استودیوی هوش مصنوعی' })).toBeVisible() const workflow = page.getByRole('list', { name: 'مراحل ساخت با هوش مصنوعی' }) await expect(workflow).toBeVisible() await expect(workflow.getByText('منبع').locator('..')).toHaveAttribute('aria-current', 'step') await expect(page.getByLabel('مخاطب')).toBeVisible() await page.getByLabel('مخاطب').selectOption('managers') await page.getByLabel('موضوع دوره').fill('ایمنی محیط کار') await page.getByRole('button', { name: 'ادامه به طراحی یادگیری' }).click() await expect(page.getByRole('heading', { name: 'طراحی دوره' })).toBeVisible() await expect(page.getByLabel('مخاطب')).toHaveCount(0) await expect(page.getByText('مدیران', { exact: true })).toBeVisible() await page.getByRole('button', { name: 'ادامه به مرور درخواست' }).click() await expect(page.getByRole('heading', { name: 'مرور درخواست' })).toBeVisible() await expect(page.getByText('مدیران', { exact: true })).toBeVisible() await expect(page.getByRole('button', { name: /شروع تولید/ })).toBeVisible() expect(await page.evaluate(() => document.documentElement.scrollWidth <= document.documentElement.clientWidth)).toBe(true) await expect(page.locator('html')).toHaveAttribute('dir', 'rtl') await page.locator('html').evaluate(element => element.setAttribute('dir', 'ltr')) expect(await page.evaluate(() => document.documentElement.scrollWidth <= document.documentElement.clientWidth)).toBe(true) await page.evaluate(() => window.localStorage.setItem('microlearn.theme', 'dark')) await page.reload() await expect(page.locator('html')).toHaveAttribute('data-theme', 'dark') await expect(page.locator('.ai-course-details')).toBeVisible() const darkSurfaceColors = await page.evaluate(() => { const step = document.querySelector('.ai-course-details') const probe = document.createElement('div') probe.style.background = 'var(--surface)' document.body.append(probe) const colors = { step: step ? getComputedStyle(step).backgroundColor : 'missing', token: getComputedStyle(probe).backgroundColor } probe.remove() return colors }) expect(darkSurfaceColors.step).toBe(darkSurfaceColors.token) })