krona-front/e2e/11-modules-catalog.spec.ts

190 lines
8.7 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { test, expect } from '@playwright/test';
test.describe('Scenario 11: Universal Modules Catalog & Profiles', () => {
test.beforeEach(async ({ page }) => {
await page.goto('/', { waitUntil: 'domcontentloaded' });
});
test('1. First open immediately displays all 18 modules with "Все модули" active by default', async ({ page }) => {
const container = page.locator('[data-testid="modules-catalog-container"]');
await expect(container).toBeVisible({ timeout: 15000 });
await expect(page.locator('h1')).toContainText('Единый каталог модулей Krona');
const allProfileBtn = page.locator('[data-testid="profile-filter-all"]');
await expect(allProfileBtn).toBeVisible();
await expect(allProfileBtn).toContainText('Все модули (18)');
const cards = page.locator('[data-testid^="module-card-"]');
await expect(cards).toHaveCount(18);
await expect(page.locator('[data-testid="module-card-crm"]')).toBeVisible();
await expect(page.locator('[data-testid="module-card-procurement"]')).toBeVisible();
await expect(page.locator('[data-testid="module-card-operations"]')).toBeVisible();
await expect(page.locator('[data-testid="module-card-finance"]')).toBeVisible();
});
test('2. Industry profile highlights recommended modules without hiding the rest', async ({ page }) => {
const restaurantBtn = page.locator('[data-testid="profile-filter-restaurant_hall_delivery"]');
await expect(restaurantBtn).toBeVisible();
await restaurantBtn.click();
const recommendedSection = page.locator('[data-testid="recommended-section"]');
const otherSection = page.locator('[data-testid="other-modules-section"]');
await expect(recommendedSection).toBeVisible();
await expect(otherSection).toBeVisible();
// Recommended section must contain restaurant modules (e.g. operations)
await expect(recommendedSection.locator('[data-testid="module-card-operations"]')).toBeVisible();
// Other section must contain non-restaurant recommended modules (e.g. helpdesk, not hidden!)
await expect(otherSection.locator('[data-testid="module-card-helpdesk"]')).toBeVisible();
// Total count of modules across both sections must still be 18
const totalCards = page.locator('[data-testid^="module-card-"]');
await expect(totalCards).toHaveCount(18);
// Reset button returns to "Все модули"
const resetBtn = page.locator('[data-testid="reset-profile-filter-btn"]');
await expect(resetBtn).toBeVisible();
await resetBtn.click();
await expect(page.locator('[data-testid="all-modules-grid"]')).toBeVisible();
});
test('3. Search and category filters work properly', async ({ page }) => {
const goodsCategoryBtn = page.locator('[data-testid="category-filter-inventory"]');
await expect(goodsCategoryBtn).toBeVisible();
await goodsCategoryBtn.click();
const filteredCards = page.locator('[data-testid^="module-card-"]');
await expect(filteredCards).toHaveCount(2);
await expect(page.locator('[data-testid="module-card-inventory"]')).toBeVisible();
await expect(page.locator('[data-testid="module-card-procurement"]')).toBeVisible();
const searchInput = page.locator('[data-testid="catalog-search-input"]');
await searchInput.fill('закупки');
await expect(filteredCards).toHaveCount(1);
await expect(page.locator('[data-testid="module-card-procurement"]')).toBeVisible();
const resetAllBtn = page.locator('[data-testid="reset-all-filters-btn"]');
await expect(resetAllBtn).toBeVisible();
await resetAllBtn.click();
await expect(page.locator('[data-testid^="module-card-"]')).toHaveCount(18);
});
test('4. Module cards navigate directly to module route', async ({ page }) => {
const crmOpenBtn = page.locator('[data-testid="module-open-btn-crm"]');
await expect(crmOpenBtn).toBeVisible();
await crmOpenBtn.click();
await page.waitForURL('**/crm');
await expect(page.locator('h1, h2').first()).toBeVisible();
await page.goto('/', { waitUntil: 'domcontentloaded' });
await page.waitForLoadState('domcontentloaded');
const procOpenBtn = page.locator('[data-testid="module-open-btn-procurement"]');
await expect(procOpenBtn).toBeVisible();
await procOpenBtn.click();
await page.waitForURL('**/procurement');
await expect(page.locator('h1')).toContainText('Закупки и управление поставщиками');
await expect(page.getByTestId('maturity-badge-planned')).toBeVisible();
});
test('5. "О модуле" opens informative details modal', async ({ page }) => {
const detailsBtn = page.locator('[data-testid="module-details-btn-procurement"]');
await expect(detailsBtn).toBeVisible();
await detailsBtn.click();
const modal = page.locator('[data-testid="module-info-modal"]');
await expect(modal).toBeVisible();
await expect(modal).toContainText('Закупки и поставщики');
await expect(modal).toContainText('Назначение модуля');
await expect(modal).toContainText('Ключевые функциональные возможности');
await expect(modal).toContainText('Статус реализации');
await expect(modal).toContainText('Запланированные интеграции');
const closeBtn = page.locator('[data-testid="close-module-info-modal"]');
await closeBtn.click();
await expect(modal).not.toBeVisible();
});
test('6. Database reset in Settings restores "Все модули" filter mode', async ({ page }) => {
const retailBtn = page.locator('[data-testid="profile-filter-retail"]');
await expect(retailBtn).toBeVisible();
await retailBtn.click();
await expect(page.locator('[data-testid="recommended-section"]')).toBeVisible();
await page.goto('/settings/entities', { waitUntil: 'domcontentloaded' });
await page.waitForLoadState('domcontentloaded');
const resetBtn = page.getByRole('button', { name: /Сбросить базу данных/i });
await expect(resetBtn).toBeVisible({ timeout: 10000 });
await resetBtn.click();
const confirmBtn = page.getByRole('button', { name: /Да, сбросить/i });
if (await confirmBtn.isVisible()) {
await confirmBtn.click();
}
await page.waitForTimeout(1000);
await page.goto('/', { waitUntil: 'domcontentloaded' });
await page.waitForLoadState('domcontentloaded');
const allProfileBtn = page.locator('[data-testid="profile-filter-all"]');
await expect(allProfileBtn).toBeVisible();
await expect(page.locator('[data-testid="all-modules-grid"]')).toBeVisible();
await expect(page.locator('[data-testid^="module-card-"]')).toHaveCount(18);
});
test('7. Catalog renders with zero horizontal overflow across viewport', async ({ page }) => {
const isOverflowing = await page.evaluate(() => {
return document.documentElement.scrollWidth > document.documentElement.clientWidth;
});
expect(isOverflowing).toBe(false);
const kpiTab = page.locator('[data-testid="view-tab-dashboard"]');
await expect(kpiTab).toBeVisible();
await kpiTab.click();
await expect(page.locator('text=Выручка').first()).toBeVisible({ timeout: 10000 });
const catalogTab = page.locator('[data-testid="view-tab-catalog"]');
await catalogTab.click();
await expect(page.locator('[data-testid="modules-catalog-container"]')).toBeVisible();
});
test('8. Mobile filter drawer, density switcher, and quick access block function smoothly', async ({ page }) => {
// Quick access block
const quickAccess = page.locator('[data-testid="quick-access-block"]');
await expect(quickAccess).toBeVisible();
await expect(page.locator('[data-testid="quick-access-crm"]')).toBeVisible();
// Density toggle
const compactToggle = page.locator('[data-testid="density-toggle-compact"]');
const detailedToggle = page.locator('[data-testid="density-toggle-detailed"]');
await expect(compactToggle).toBeVisible();
await expect(detailedToggle).toBeVisible();
await compactToggle.click();
await expect(page.locator('text=Ключевые возможности:').first()).not.toBeVisible();
await detailedToggle.click();
await expect(page.locator('text=Ключевые возможности:').first()).toBeVisible();
// Filter drawer
const filterDrawerBtn = page.locator('[data-testid="mobile-filter-drawer-btn"]');
await expect(filterDrawerBtn).toBeVisible();
await filterDrawerBtn.click();
const applyDrawerBtn = page.locator('[data-testid="apply-filters-drawer-btn"]');
await expect(applyDrawerBtn).toBeVisible();
await applyDrawerBtn.click();
await expect(applyDrawerBtn).not.toBeVisible();
});
});