[598][@ant] feat(docs-harness): 3 пилот-сценария для новых страниц marketplace
Сценарии для прогона harness'ом по реализованным страницам: - onboarding/coop-accept-cpp.mjs (chairman ant, L1 ЦПП) - orderer/consolidated.mjs (ivanpetrov, партии заказчика) - chairman/category-whitelist.mjs (chairman ant, whitelist категорий) Прогон самим harness'ом пока ЗАБЛОКИРОВАН — shared desktop dev :3029 не видит worktree-страниц (src vs node_modules: src в worktree локален, а node_modules симлинкованы). Чтобы снять скриншоты: вариант A — sync 9 pages в shared desktop; вариант B — поднять отдельный worktree desktop dev (медленно). Остальные 6 сценариев (offerer/incoming-orders, offerer/my-offers, branch-chairman/branch-orders, board/agenda-writeoff, board/payouts-readonly, onboarding/member-pick-cpp) — создаются после прогона пилот-тройки. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
// Сценарий: Председатель настраивает whitelist доступных категорий товаров.
|
||||
// Эпик 3 / Story 3.x — пустой whitelist означает, что доступен весь
|
||||
// глобальный каталог; с whitelist'ом — только перечисленные категории.
|
||||
//
|
||||
// Backend `available-category-admin.resolver.ts` (@AuthRoles chairman).
|
||||
// Tree-выбор через `marketplaceGetCategoryTree` подключится на следующем
|
||||
// шаге; в MVP — диалог с ручным вводом ID через запятую.
|
||||
//
|
||||
// Фикстура: chairman кооператива (ant, Иван Иванов).
|
||||
|
||||
import { loginAsChairman, dismissOnboardingDialogs } from '../../../lib/harness.mjs';
|
||||
|
||||
export const meta = {
|
||||
title: 'Whitelist категорий товаров кооператива',
|
||||
docPath: 'new/marketplace/chairman/category-whitelist.md',
|
||||
assetsDir: 'assets/new/marketplace/chairman/category-whitelist',
|
||||
role: 'chairman',
|
||||
};
|
||||
|
||||
export default async ({ page, context, shot, env }) => {
|
||||
await loginAsChairman(page, context);
|
||||
await dismissOnboardingDialogs(page);
|
||||
|
||||
// 1. Открыть страницу доступных категорий
|
||||
await page.goto(`${env.BASE_URL}/#/${env.COOPNAME}/market/category-whitelist`, {
|
||||
waitUntil: 'domcontentloaded',
|
||||
});
|
||||
await page.waitForSelector('text=Доступные категории', { timeout: 60000 });
|
||||
await page.waitForLoadState('networkidle', { timeout: 15000 }).catch(() => {});
|
||||
await page.waitForTimeout(900);
|
||||
await dismissOnboardingDialogs(page);
|
||||
await shot(
|
||||
page,
|
||||
'01-overview',
|
||||
'Страница «Доступные категории»: 4 stat-карточки в шапке — всего записей, число категорий, число типов товаров и состояние whitelist (активен / открыт каталог). Пустой whitelist означает, что пайщикам доступен весь глобальный каталог категорий.',
|
||||
);
|
||||
|
||||
// 2. Открыть диалог добавления категорий
|
||||
const addBtn = page.locator('button:has-text("Добавить")').first();
|
||||
if (await addBtn.isVisible().catch(() => false)) {
|
||||
await addBtn.click();
|
||||
await page.waitForSelector('text=Добавить категории в whitelist', { timeout: 10000 });
|
||||
await page.waitForTimeout(500);
|
||||
await shot(
|
||||
page,
|
||||
'02-add-dialog',
|
||||
'Диалог добавления: в MVP — ручной ввод ID через запятую (1, 7, 15). На следующем шаге Story 3.x подключится tree-выбор через marketplaceGetCategoryTree — выбор по дереву категорий и типов.',
|
||||
);
|
||||
await page.keyboard.press('Escape');
|
||||
await page.waitForTimeout(500);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,52 @@
|
||||
// Сценарий: Председатель кооператива принимает ЦПП «Стол заказов».
|
||||
// Эпик 1 / Story 1.9-1.10 — L1 онбординг кооператива.
|
||||
//
|
||||
// Председатель видит статус ЦПП (active / not_accepted) и кнопку
|
||||
// «Принять ЦПП Marketplace». После клика — диалог подтверждения с
|
||||
// stub `accepted_by_board_decision_id` (в MVP — текстовая ссылка;
|
||||
// полноценная повестка совета — FR40 / Эпик 8, Phase 2).
|
||||
//
|
||||
// Фикстура: chairman кооператива (ant, Иван Иванов).
|
||||
|
||||
import { loginAsChairman, dismissOnboardingDialogs } from '../../../lib/harness.mjs';
|
||||
|
||||
export const meta = {
|
||||
title: 'L1 онбординг — приём ЦПП «Стол заказов» кооперативом',
|
||||
docPath: 'new/marketplace/onboarding/coop-accept-cpp.md',
|
||||
assetsDir: 'assets/new/marketplace/onboarding/coop-accept-cpp',
|
||||
role: 'chairman',
|
||||
};
|
||||
|
||||
export default async ({ page, context, shot, env }) => {
|
||||
await loginAsChairman(page, context);
|
||||
await dismissOnboardingDialogs(page);
|
||||
|
||||
// 1. Открыть страницу подключения ЦПП
|
||||
await page.goto(`${env.BASE_URL}/#/${env.COOPNAME}/market/onboarding/coop-cpp`, {
|
||||
waitUntil: 'domcontentloaded',
|
||||
});
|
||||
await page.waitForSelector('text=Подключение ЦПП', { timeout: 60000 });
|
||||
await page.waitForLoadState('networkidle', { timeout: 15000 }).catch(() => {});
|
||||
await page.waitForTimeout(800);
|
||||
await dismissOnboardingDialogs(page);
|
||||
await shot(
|
||||
page,
|
||||
'01-status',
|
||||
'Страница подключения ЦПП «Стол заказов»: chip справа показывает текущий статус расширения (Подключено / Не подключено). Карточка под шапкой раскрывает статус, реестр оферты, дату принятия и решение совета.',
|
||||
);
|
||||
|
||||
// 2. Если не принято — открыть диалог подтверждения принятия
|
||||
const acceptBtn = page.locator('button:has-text("Принять ЦПП Marketplace")');
|
||||
if (await acceptBtn.isVisible().catch(() => false)) {
|
||||
await acceptBtn.click();
|
||||
await page.waitForSelector('text=Принять ЦПП', { timeout: 10000 });
|
||||
await page.waitForTimeout(600);
|
||||
await shot(
|
||||
page,
|
||||
'02-confirm-dialog',
|
||||
'Диалог подтверждения принятия ЦПП «Стол заказов». В MVP — stub решения совета; полноценная повестка подключится в Эпике 8 (FR40).',
|
||||
);
|
||||
await page.keyboard.press('Escape');
|
||||
await page.waitForTimeout(500);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,61 @@
|
||||
// Сценарий: Сводный обзор заказов пайщика-заказчика.
|
||||
// Эпик 4 / Story 4.4 — заказы группируются по cycle_id (time_based /
|
||||
// volume_based / open_subscription / individual) с суммарной стоимостью
|
||||
// партии и общим этапом партии (минимальный активный по STAGE_RANK).
|
||||
//
|
||||
// Канон-виджет `OrderCard` для отдельных заказов в партии.
|
||||
// Polling 15s — обновляет список без перезагрузки.
|
||||
//
|
||||
// Фикстура: ivanpetrov (Иван Сергеевич Петров), пайщик-заказчик.
|
||||
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { loginAs, env, cleanViteOverlays } from '../../../lib/harness.mjs';
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
const loadFixture = (username) =>
|
||||
JSON.parse(
|
||||
fs.readFileSync(path.resolve(__dirname, `../../../state/participants/${username}.json`), 'utf8'),
|
||||
);
|
||||
|
||||
export const meta = {
|
||||
title: 'Сводный заказ: партии заказчика по cycle_id',
|
||||
docPath: 'new/marketplace/orderer/consolidated.md',
|
||||
assetsDir: 'assets/new/marketplace/orderer/consolidated',
|
||||
role: 'user',
|
||||
fixture: 'ivanpetrov',
|
||||
};
|
||||
|
||||
export default async ({ page, shot }) => {
|
||||
const fixture = loadFixture('ivanpetrov');
|
||||
await loginAs(page, fixture);
|
||||
await page.evaluate(() => localStorage.setItem('harness:noBranchOverlay', '1'));
|
||||
|
||||
// 1. Открыть страницу сводного заказа
|
||||
await page.goto(`${env.BASE_URL}/#/${env.COOPNAME}/market/consolidated`, {
|
||||
waitUntil: 'domcontentloaded',
|
||||
});
|
||||
await page.waitForSelector('text=Сводный заказ', { timeout: 60000 });
|
||||
await page.waitForLoadState('networkidle', { timeout: 15000 }).catch(() => {});
|
||||
await page.waitForTimeout(1200);
|
||||
await cleanViteOverlays(page);
|
||||
await shot(
|
||||
page,
|
||||
'01-overview',
|
||||
'Сводный обзор партий заказов пайщика-заказчика. Партии с cycle_id выводятся первыми (заказы внутри партии обслуживаются совместно — на одном цикле, с одной поставкой), индивидуальные заказы — отдельной группой. Для каждой партии показан тип цикла, этап партии, суммарная стоимость и ПВЗ доставки.',
|
||||
);
|
||||
|
||||
// 2. Развернуть первую партию (если есть заказы)
|
||||
const firstGroup = page.locator('.mp-consolidated__group').first();
|
||||
if (await firstGroup.isVisible().catch(() => false)) {
|
||||
await firstGroup.scrollIntoViewIfNeeded();
|
||||
await page.waitForTimeout(400);
|
||||
await shot(
|
||||
page,
|
||||
'02-group-detail',
|
||||
'Партия развёрнута: внутри — карточки отдельных заказов (канон OrderCard role=orderer). Этап партии = минимальный активный статус среди заказов (если хотя бы один ждёт цикл — вся партия «Активна»).',
|
||||
);
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user