190 خطوط
12 KiB
TypeScript
190 خطوط
12 KiB
TypeScript
import { expect, test } from '@playwright/test'
|
||
|
||
async function login(page: import('@playwright/test').Page, email: string, home: RegExp) {
|
||
await page.goto('http://127.0.0.1:5173/login')
|
||
await page.getByLabel(/ایمیل|Email/).fill(email)
|
||
await page.getByLabel(/رمز عبور|Password/).fill('password')
|
||
await page.getByRole('button', { name: /ورود|Sign in/ }).click()
|
||
await expect(page).toHaveURL(home)
|
||
}
|
||
|
||
test('Builder switches between Quick Edit and desktop canvas at Phase 7 viewports', async ({ page }) => {
|
||
await login(page, 'designer@microlearn.test', /\/app\/dashboard$/)
|
||
for (const width of [375, 430, 768, 1024, 1280, 1440, 1920]) {
|
||
await page.setViewportSize({ width, height: width < 768 ? 812 : 900 })
|
||
await page.goto('http://127.0.0.1:5173/app/builder-preview')
|
||
if (width < 768) {
|
||
await expect(page.getByRole('region', { name: 'ویرایش سریع موبایل' })).toBeVisible()
|
||
await expect(page.getByRole('button', { name: 'افزودن بلاک', exact: true })).toBeVisible()
|
||
} else {
|
||
await expect(page.locator('.builder-canvas')).toBeVisible()
|
||
}
|
||
expect(await page.evaluate(() => document.documentElement.scrollWidth <= document.documentElement.clientWidth), `${width}px overflow`).toBe(true)
|
||
}
|
||
|
||
await page.setViewportSize({ width: 375, height: 812 })
|
||
await page.getByRole('button', { name: /ویرایش بلاک بهترین روشهای ایمنی/ }).click()
|
||
await expect(page.getByRole('dialog', { name: 'ویرایش بلاک در موبایل' })).toBeVisible()
|
||
await page.keyboard.press('Escape')
|
||
await expect(page.getByRole('dialog', { name: 'ویرایش بلاک در موبایل' })).toBeHidden()
|
||
})
|
||
|
||
test('Learner Home is action-led, responsive, offline-aware and accessible', async ({ page, context }) => {
|
||
const runtimeErrors: string[] = []
|
||
page.on('pageerror', error => runtimeErrors.push(error.message))
|
||
page.on('console', message => { if (message.type() === 'error') runtimeErrors.push(message.text()) })
|
||
await page.setViewportSize({ width: 430, height: 932 })
|
||
await login(page, 'maryam@microlearn.test', /\/learn\/home$/)
|
||
await expect(page.getByRole('navigation', { name: 'ناوبری یادگیرنده' }).getByRole('link')).toHaveCount(5)
|
||
await expect(page.getByRole('heading', { name: 'ادامه یادگیری', level: 2 })).toBeVisible()
|
||
await expect(page.getByRole('heading', { name: 'جلسه امروز', level: 2 })).toBeVisible()
|
||
await expect(page.getByRole('heading', { name: 'موعدهای نزدیک', level: 2 })).toBeVisible()
|
||
await expect(page.getByRole('heading', { name: 'اعلانهای مهم', level: 2 })).toBeVisible()
|
||
await expect(page.locator('.learner-primary-action')).toHaveCount(1)
|
||
for (const width of [320, 375, 430, 768]) {
|
||
await page.setViewportSize({ width, height: width < 768 ? 812 : 900 })
|
||
expect(await page.evaluate(() => document.documentElement.scrollWidth <= document.documentElement.clientWidth), `${width}px learner overflow`).toBe(true)
|
||
await expect(page.getByRole('navigation', { name: 'ناوبری یادگیرنده' })).toBeVisible()
|
||
expect(await page.getByRole('navigation', { name: 'ناوبری یادگیرنده' }).evaluate(element => getComputedStyle(element).position)).toBe('fixed')
|
||
}
|
||
await page.setViewportSize({ width: 430, height: 932 })
|
||
|
||
await context.setOffline(true)
|
||
await page.evaluate(() => window.dispatchEvent(new Event('offline')))
|
||
await expect(page.getByText('آفلاین هستید')).toBeVisible()
|
||
await expect(page.locator('.learner-next-action')).toBeVisible()
|
||
await context.setOffline(false)
|
||
await page.evaluate(() => window.dispatchEvent(new Event('online')))
|
||
|
||
const account = page.getByRole('button', { name: 'بازکردن حساب کاربری' })
|
||
await account.click()
|
||
await expect(page.getByRole('dialog', { name: 'حساب کاربری' })).toBeFocused()
|
||
await page.keyboard.press('Escape')
|
||
await expect(account).toBeFocused()
|
||
|
||
await account.click()
|
||
await page.getByRole('button', { name: 'English' }).click()
|
||
await page.getByRole('button', { name: 'Change theme' }).click()
|
||
await expect(page.locator('html')).toHaveAttribute('dir', 'ltr')
|
||
await expect(page.locator('html')).toHaveAttribute('lang', 'en')
|
||
await expect(page.locator('html')).toHaveAttribute('data-theme', 'dark')
|
||
await expect(page.getByRole('navigation', { name: 'Learner navigation' })).toBeVisible()
|
||
expect(runtimeErrors).toEqual([])
|
||
})
|
||
|
||
test('My Learning works as a searchable responsive portfolio', async ({ page, context }) => {
|
||
const runtimeErrors: string[] = []
|
||
page.on('pageerror', error => runtimeErrors.push(error.message))
|
||
page.on('console', message => { if (message.type() === 'error') runtimeErrors.push(message.text()) })
|
||
await page.setViewportSize({ width: 430, height: 932 })
|
||
await login(page, 'maryam@microlearn.test', /\/learn\/home$/)
|
||
await page.goto('http://127.0.0.1:5173/learn/my-learning')
|
||
|
||
await expect(page.getByRole('heading', { name: 'یادگیریهای من', level: 1 })).toBeVisible()
|
||
await expect(page.getByRole('searchbox', { name: 'جستجو در یادگیریهای من' })).toBeVisible()
|
||
await expect(page.getByRole('tab', { name: 'در حال انجام' })).toHaveAttribute('aria-selected', 'true')
|
||
await expect(page.getByRole('navigation', { name: 'ناوبری یادگیرنده' }).getByRole('link', { name: 'یادگیری من' })).toHaveAttribute('aria-current', 'page')
|
||
|
||
const filterButton = page.getByRole('button', { name: /^(?:فیلترها.*|بازکردن فیلترها)$/ })
|
||
await filterButton.click()
|
||
const filtersDialog = page.getByRole('dialog', { name: 'فیلتر و مرتبسازی' })
|
||
await expect(filtersDialog).toBeVisible()
|
||
await filtersDialog.getByRole('combobox').last().selectOption('progress')
|
||
await page.keyboard.press('Escape')
|
||
await expect(filterButton).toHaveAttribute('aria-expanded', 'false')
|
||
|
||
const overflowButton = page.getByRole('button', { name: /عملیات / }).first()
|
||
if (await overflowButton.count()) {
|
||
await overflowButton.click()
|
||
await expect(page.getByRole('menu')).toBeVisible()
|
||
await expect(page.getByRole('menuitem', { name: 'مشاهده جزئیات' })).toBeVisible()
|
||
await page.keyboard.press('Escape')
|
||
await expect(page.getByRole('menu')).toBeHidden()
|
||
}
|
||
|
||
for (const width of [320, 375, 430, 768]) {
|
||
await page.setViewportSize({ width, height: width < 768 ? 812 : 900 })
|
||
expect(await page.evaluate(() => document.documentElement.scrollWidth <= document.documentElement.clientWidth), `${width}px portfolio overflow`).toBe(true)
|
||
const targets = page.locator('.my-learning-segments button, .my-learning-filter-trigger')
|
||
const heights = await targets.evaluateAll(elements => elements.map(element => element.getBoundingClientRect().height))
|
||
expect(heights.every(height => height >= 44), `${width}px portfolio touch targets`).toBe(true)
|
||
}
|
||
|
||
await context.setOffline(true)
|
||
await page.evaluate(() => window.dispatchEvent(new Event('offline')))
|
||
await expect(page.getByText('آفلاین هستید')).toBeVisible()
|
||
await expect(page.getByRole('heading', { name: 'یادگیریهای من', level: 1 })).toBeVisible()
|
||
await context.setOffline(false)
|
||
await page.evaluate(() => window.dispatchEvent(new Event('online')))
|
||
expect(runtimeErrors).toEqual([])
|
||
})
|
||
|
||
test('Daily Learning creates a focused, persistent and offline-aware session', async ({ page, context }) => {
|
||
const runtimeErrors: string[] = []
|
||
page.on('pageerror', error => runtimeErrors.push(error.message))
|
||
page.on('console', message => { if (message.type() === 'error') runtimeErrors.push(message.text()) })
|
||
await page.setViewportSize({ width: 430, height: 932 })
|
||
await login(page, 'maryam@microlearn.test', /\/learn\/home$/)
|
||
await page.evaluate(() => { localStorage.removeItem('microlearn.daily.history'); localStorage.removeItem('microlearn.daily.duration'); sessionStorage.removeItem('microlearn.daily.active') })
|
||
await page.goto('http://127.0.0.1:5173/learn/daily')
|
||
|
||
await expect(page.getByRole('heading', { name: 'جلسه امروز', level: 1 })).toBeVisible()
|
||
await expect(page.getByText('امروز چقدر وقت داری؟')).toBeVisible()
|
||
await expect(page.getByRole('button', { name: '۱۰ دقیقه' })).toHaveAttribute('aria-pressed', 'true')
|
||
await expect(page.getByRole('heading', { name: 'جلسه امروز شما', level: 2 })).toBeVisible()
|
||
await expect(page.getByRole('button', { name: 'شروع جلسه' })).toHaveCount(1)
|
||
await page.getByRole('button', { name: '۱۵ دقیقه' }).click()
|
||
expect(await page.evaluate(() => localStorage.getItem('microlearn.daily.duration'))).toBe('15')
|
||
|
||
const why = page.getByText('چرا این محتوا پیشنهاد شده؟')
|
||
await why.click()
|
||
await expect(why.locator('xpath=..')).toHaveAttribute('open', '')
|
||
|
||
for (const width of [320, 375, 430, 768]) {
|
||
await page.setViewportSize({ width, height: width < 768 ? 812 : 900 })
|
||
expect(await page.evaluate(() => document.documentElement.scrollWidth <= document.documentElement.clientWidth), `${width}px daily overflow`).toBe(true)
|
||
const targets = page.locator('.daily-time-selector button, .daily-primary-action')
|
||
const heights = await targets.evaluateAll(elements => elements.map(element => element.getBoundingClientRect().height))
|
||
expect(heights.every(height => height >= 44), `${width}px daily touch targets`).toBe(true)
|
||
}
|
||
|
||
await context.setOffline(true)
|
||
await page.evaluate(() => window.dispatchEvent(new Event('offline')))
|
||
await expect(page.getByText('آفلاین هستید')).toBeVisible()
|
||
await expect(page.getByRole('heading', { name: 'جلسه امروز شما', level: 2 })).toBeVisible()
|
||
await context.setOffline(false)
|
||
await page.evaluate(() => window.dispatchEvent(new Event('online')))
|
||
|
||
const activityCount = await page.locator('.daily-activity-list > li').count()
|
||
await page.getByRole('button', { name: 'شروع جلسه' }).click()
|
||
await expect(page).toHaveURL(/\/learn\/player\/.*daily=1/)
|
||
for (let index = 0; index < activityCount; index += 1) {
|
||
const before = page.url()
|
||
await page.getByRole('button', { name: 'تکمیل فعالیت' }).click()
|
||
if (index < activityCount - 1) await expect.poll(() => page.url()).not.toBe(before)
|
||
}
|
||
await expect(page).toHaveURL(/\/learn\/daily\?completed=1/)
|
||
await expect(page.locator('.daily-completion')).toBeFocused()
|
||
expect(runtimeErrors).toEqual([])
|
||
})
|
||
|
||
test('Course Player keeps progress and touch actions usable at all target viewports', async ({ page }) => {
|
||
await page.setViewportSize({ width: 375, height: 812 })
|
||
await login(page, 'maryam@microlearn.test', /\/learn\/home$/)
|
||
const continueLink = page.locator('.learner-next-action').first()
|
||
await expect(continueLink).toBeVisible()
|
||
await continueLink.click()
|
||
await expect(page).toHaveURL(/\/learn\/player\//)
|
||
await expect(page.getByRole('progressbar', { name: 'پیشرفت دوره' })).toBeVisible()
|
||
await expect(page.getByText(/درس .* از/)).toBeVisible()
|
||
|
||
for (const width of [375, 430, 768, 1024, 1280, 1440, 1920]) {
|
||
await page.setViewportSize({ width, height: width < 768 ? 812 : 900 })
|
||
expect(await page.evaluate(() => document.documentElement.scrollWidth <= document.documentElement.clientWidth), `${width}px player overflow`).toBe(true)
|
||
const actions = page.locator('.player-footer .button')
|
||
await expect(actions).toHaveCount(3)
|
||
const heights = await actions.evaluateAll(elements => elements.map(element => element.getBoundingClientRect().height))
|
||
expect(heights.every(height => height >= 44), `${width}px player touch targets`).toBe(true)
|
||
}
|
||
})
|