fix(web): polish social UI and prevent doubled shared audio
ci / mobile / mobile (Metro-бандл Android) (push) Successful in 1m20s
release / desktop (Linux и Windows в релиз) (push) Successful in 19m22s
ci / ts / ts (packages + web) (push) Successful in 3m9s
release / release (версия и заметки) (push) Successful in 10s
release / android (APK в релиз) (push) Successful in 4m7s
release / prune (старые файлы и прогоны) (push) Successful in 11s
ci / mobile / mobile (Metro-бандл Android) (push) Successful in 1m20s
release / desktop (Linux и Windows в релиз) (push) Successful in 19m22s
ci / ts / ts (packages + web) (push) Successful in 3m9s
release / release (версия и заметки) (push) Successful in 10s
release / android (APK в релиз) (push) Successful in 4m7s
release / prune (старые файлы и прогоны) (push) Successful in 11s
This commit is contained in:
1 parent
6450027b88
commit
cb22f15912
17 files changed
+405
-63
No files matched your search
@@ -1,8 +1,9 @@
|
||||
import axe from 'axe-core';
|
||||
import { expect, test } from '@playwright/test';
|
||||
|
||||
for (const width of [1280, 1920]) {
|
||||
test(`mini chat keeps the page and draft at ${width}px`, async ({ page }, info) => {
|
||||
await page.setViewportSize({ width, height: 900 });
|
||||
for (const { width, height, light } of [{ width: 1280, height: 900, light: false }, { width: 1920, height: 900, light: false }, { width: 1024, height: 600, light: false }, { width: 1280, height: 720, light: true }]) {
|
||||
test(`mini chat keeps the page and draft at ${width}x${height} ${light ? 'light' : 'dark'}`, async ({ page }, info) => {
|
||||
await page.setViewportSize({ width, height });
|
||||
await page.addInitScript(() => localStorage.setItem('pipu.locale', 'ru'));
|
||||
await page.goto('/login');
|
||||
await page.getByLabel('Логин', { exact: true }).fill('alice');
|
||||
@@ -15,11 +16,13 @@ for (const width of [1280, 1920]) {
|
||||
await expect(page.getByRole('button', { name: 'Остров', exact: true })).toHaveAttribute('aria-pressed', 'true');
|
||||
await page.getByRole('link', { name: 'Главная', exact: true }).first().click();
|
||||
}
|
||||
if (light) await page.evaluate(() => { document.documentElement.dataset.theme = 'light'; });
|
||||
const dock = page.getByRole('complementary', { name: 'Друзья и чат', exact: true });
|
||||
const toggle = dock.getByRole('button', { name: 'Друзья и чат', exact: true });
|
||||
await toggle.click();
|
||||
const panel = dock.getByRole('region', { name: 'Друзья и общение', exact: true });
|
||||
await panel.getByRole('textbox', { name: 'Найти диалог', exact: true }).fill('moderator');
|
||||
await expect(panel.getByRole('textbox', { name: 'Найти диалог', exact: true })).toHaveCSS('outline-style', 'none');
|
||||
await panel.getByRole('button', { name: /moderator/ }).click();
|
||||
const composer = panel.getByRole('textbox', { name: 'Сообщение', exact: true });
|
||||
await composer.fill('Черновик из мини-чата');
|
||||
@@ -40,6 +43,17 @@ for (const width of [1280, 1920]) {
|
||||
expect(panelBox.x).toBeGreaterThanOrEqual(width - 640);
|
||||
expect(panelBox.y).toBeGreaterThanOrEqual(60);
|
||||
expect(panelBox.y + panelBox.height).toBeLessThan(playerBox.y);
|
||||
await panel.evaluate(async element => {
|
||||
await Promise.all(element.getAnimations({ subtree: true })
|
||||
.filter(animation => animation.effect?.getTiming().iterations !== Infinity)
|
||||
.map(animation => animation.finished.catch(() => undefined)));
|
||||
});
|
||||
await page.addScriptTag({ content: axe.source });
|
||||
const violations = await page.evaluate(async (selector) => {
|
||||
const result = await (window as unknown as { axe: typeof axe }).axe.run(document.querySelector(selector)!, { runOnly: { type: 'tag', values: ['wcag2a', 'wcag2aa'] } });
|
||||
return result.violations.map(violation => ({ id: violation.id, nodes: violation.nodes.map(node => ({ target: node.target, summary: node.failureSummary })) }));
|
||||
}, '[id="mini-social-panel"]');
|
||||
expect(violations).toEqual([]);
|
||||
await page.screenshot({ path: info.outputPath('mini-chat.png'), fullPage: true });
|
||||
await composer.fill('Продолжить в полном чате');
|
||||
await composer.press('Escape');
|
||||
@@ -48,7 +62,7 @@ for (const width of [1280, 1920]) {
|
||||
await expect(composer).toHaveValue('Продолжить в полном чате');
|
||||
await page.setViewportSize({ width: 800, height: 900 });
|
||||
await expect(dock).toHaveCount(0);
|
||||
await page.setViewportSize({ width, height: 900 });
|
||||
await page.setViewportSize({ width, height });
|
||||
await expect(composer).toHaveValue('Продолжить в полном чате');
|
||||
await panel.getByRole('button', { name: 'Открыть раздел', exact: true }).click();
|
||||
await expect(page).toHaveURL(/\/friends\?/);
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
import axe from 'axe-core';
|
||||
import { expect, test } from '@playwright/test';
|
||||
|
||||
for (const width of [390, 1280]) {
|
||||
test(`notification history scrolls inside the dialog at ${width}px`, async ({ page }, info) => {
|
||||
await page.setViewportSize({ width, height: 900 });
|
||||
await page.addInitScript(() => {
|
||||
localStorage.setItem('pipu.locale', 'ru');
|
||||
localStorage.setItem('pipu.e2e.notifications', '1');
|
||||
});
|
||||
await page.goto('/login');
|
||||
await page.getByLabel('Логин', { exact: true }).fill('alice');
|
||||
await page.getByRole('textbox', { name: 'Пароль', exact: true }).fill('alice-password');
|
||||
await page.getByRole('button', { name: 'Войти', exact: true }).click();
|
||||
await page.getByRole('button', { name: 'Меню профиля', exact: true }).click();
|
||||
await page.getByRole('menuitem', { name: 'Уведомления 4', exact: true }).click();
|
||||
const dialog = page.getByRole('dialog', { name: 'Уведомления', exact: true });
|
||||
const list = dialog.getByRole('region', { name: 'Уведомления', exact: true });
|
||||
await expect(list.getByRole('article')).toHaveCount(28);
|
||||
const box = (await dialog.boundingBox())!;
|
||||
expect(box.height).toBeLessThanOrEqual(680);
|
||||
expect(box.width).toBeLessThanOrEqual(Math.min(600, width - (width < 768 ? 24 : 32)));
|
||||
const close = dialog.getByRole('button', { name: 'Закрыть', exact: true });
|
||||
const closeBefore = (await close.boundingBox())!;
|
||||
await list.evaluate(element => { element.scrollTop = element.scrollHeight; });
|
||||
await expect(close).toBeVisible();
|
||||
expect((await close.boundingBox())!.y).toBe(closeBefore.y);
|
||||
await list.evaluate(element => { element.scrollTop = 0; });
|
||||
await page.addScriptTag({ content: axe.source });
|
||||
const violations = await page.evaluate(async (selector) => {
|
||||
const result = await (window as unknown as { axe: typeof axe }).axe.run(document.querySelector(selector)!, { runOnly: { type: 'tag', values: ['wcag2a', 'wcag2aa'] } });
|
||||
return result.violations.map(violation => ({ id: violation.id, nodes: violation.nodes.map(node => node.target) }));
|
||||
}, '[role="dialog"]');
|
||||
expect(violations).toEqual([]);
|
||||
await page.screenshot({ path: info.outputPath('notifications.png'), fullPage: true });
|
||||
await dialog.getByRole('button', { name: 'Непрочитанные 4', exact: true }).click();
|
||||
await expect(list.getByRole('article')).toHaveCount(4);
|
||||
await list.getByRole('button', { name: 'Прочитано', exact: true }).first().click();
|
||||
await expect(list.getByRole('article')).toHaveCount(3);
|
||||
await dialog.getByRole('button', { name: 'Все', exact: true }).click();
|
||||
await expect(list.getByRole('article')).toHaveCount(28);
|
||||
await close.click();
|
||||
await expect(dialog).toBeHidden();
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
import axe from 'axe-core';
|
||||
import { expect, test } from '@playwright/test';
|
||||
|
||||
for (const { width, light } of [{ width: 390, light: false }, { width: 1280, light: false }, { width: 1280, light: true }]) {
|
||||
test(`social profile settings at ${width}px ${light ? 'light' : 'dark'}`, async ({ page }, info) => {
|
||||
await page.setViewportSize({ width, height: 900 });
|
||||
await page.addInitScript(() => localStorage.setItem('pipu.locale', 'ru'));
|
||||
await page.goto('/login');
|
||||
await page.getByLabel('Логин', { exact: true }).fill('alice');
|
||||
await page.getByRole('textbox', { name: 'Пароль', exact: true }).fill('alice-password');
|
||||
await page.getByRole('button', { name: 'Войти', exact: true }).click();
|
||||
if (light) await page.evaluate(() => { document.documentElement.dataset.theme = 'light'; });
|
||||
await page.getByRole('button', { name: 'Меню профиля', exact: true }).click();
|
||||
await expect(page.getByRole('menuitem', { name: 'Уведомления', exact: true })).toBeVisible();
|
||||
await page.getByRole('menuitem', { name: 'Моя музыка скрыта', exact: true }).click();
|
||||
const dialog = page.getByRole('dialog', { name: 'Приватность и общение', exact: true });
|
||||
const visibility = dialog.getByRole('group', { name: 'Кто видит мою музыку', exact: true });
|
||||
const friends = visibility.getByRole('button', { name: 'Друзьям', exact: true });
|
||||
await friends.click();
|
||||
await expect(friends).toHaveAttribute('aria-pressed', 'true');
|
||||
await expect(friends).toBeEnabled();
|
||||
await expect(friends).toBeFocused();
|
||||
await dialog.getByText('Слушать вместе', { exact: true }).click();
|
||||
await expect(dialog.getByRole('group', { name: 'Принимать запросы и приглашения от', exact: true })).toBeVisible();
|
||||
expect((await dialog.boundingBox())!.width).toBeLessThanOrEqual(width - 24);
|
||||
await expect.poll(() => dialog.evaluate(element => element.scrollWidth - element.clientWidth)).toBeLessThanOrEqual(1);
|
||||
await page.addScriptTag({ content: axe.source });
|
||||
const violations = await page.evaluate(async () => {
|
||||
const result = await (window as unknown as { axe: typeof axe }).axe.run(document.querySelector('[role="dialog"]')!, { runOnly: { type: 'tag', values: ['wcag2a', 'wcag2aa'] } });
|
||||
return result.violations.map(violation => ({ id: violation.id, nodes: violation.nodes.map(node => node.target) }));
|
||||
});
|
||||
expect(violations).toEqual([]);
|
||||
await page.screenshot({ path: info.outputPath('privacy.png'), fullPage: true });
|
||||
await dialog.getByRole('button', { name: 'Закрыть', exact: true }).click();
|
||||
if (width < 768) await page.getByRole('button', { name: 'Ещё', exact: true }).click();
|
||||
await page.getByRole('link', { name: 'Друзья и общение', exact: true }).click();
|
||||
const heading = page.getByRole('heading', { name: 'Друзья и общение', exact: true });
|
||||
await expect(heading).toBeVisible();
|
||||
expect((await heading.locator('..').boundingBox())!.height).toBeLessThanOrEqual(40);
|
||||
await expect(page.getByRole('button', { name: 'Моя музыка скрыта', exact: true })).toHaveCount(0);
|
||||
await expect(page.getByRole('button', { name: 'Уведомления', exact: true })).toHaveCount(0);
|
||||
});
|
||||
}
|
||||
@@ -65,9 +65,11 @@ for (const width of [320, 800, 1280]) {
|
||||
await page.getByRole('button', { name: /moderator/ }).filter({ has: page.locator('strong') }).click();
|
||||
await page.setViewportSize({ width, height: 560 });
|
||||
}
|
||||
const composerBox = (await page.getByRole('textbox', { name: 'Сообщение', exact: true }).boundingBox())!;
|
||||
const playerBox = (await page.getByRole('contentinfo', { name: 'Плеер' }).boundingBox())!;
|
||||
expect(composerBox.y + composerBox.height).toBeLessThanOrEqual(playerBox.y);
|
||||
await expect.poll(async () => {
|
||||
const composerBox = (await page.getByRole('textbox', { name: 'Сообщение', exact: true }).boundingBox())!;
|
||||
const playerBox = (await page.getByRole('contentinfo', { name: 'Плеер' }).boundingBox())!;
|
||||
return composerBox.y + composerBox.height - playerBox.y;
|
||||
}).toBeLessThanOrEqual(0);
|
||||
await expect.poll(() => page.evaluate(() => {
|
||||
const main = document.querySelector('main')!;
|
||||
return Math.max(document.documentElement.scrollWidth - innerWidth, main.scrollWidth - main.clientWidth);
|
||||
|
||||
Reference in new issue
Block a user