spec: plan account concentration tab (WealthLedger/main#48)
This commit is contained in:
@@ -0,0 +1,135 @@
|
||||
# Test Cases — conc (вкладка «Концентрация», разрезы, доли)
|
||||
|
||||
Cases пишутся только там, где нужны данные, шаги или oracle сверх Scenario;
|
||||
остальные строки Coverage Matrix в `../qa-analysis.md` ссылаются на Scenarios
|
||||
Delta Specs `portfolio-concentration` (PC) и `portfolio-view` (PVΔ).
|
||||
|
||||
### TC-CONC-002 Вкладка в состояниях страницы
|
||||
|
||||
- **Verifies:** `portfolio-concentration` — `Вкладка в состояниях страницы` / все 3 Scenario
|
||||
- **Risk / Priority:** средний / high — вкладка не должна появляться при загрузке, ошибке и пустом Portfolio, но должна при Cash Balance
|
||||
- **Preconditions:** тестовый пользователь с тремя счетами (см. данные); frontend с управляемым API-моком
|
||||
- **Test Data:** счёт A — Portfolio пуст (нет позиций и остатков); счёт B — только Cash Balance 1 000 RUB; счёт C — одна акция; мок: GET `/portfolio/{C}` сначала pending, потом 500
|
||||
- **Steps:**
|
||||
1. Открыть счёт A → проверить набор вкладок.
|
||||
2. Открыть счёт B → открыть вкладку «Концентрация».
|
||||
3. Открыть счёт C при pending GET и при ответе 500.
|
||||
- **Expected Results:** A — вкладки «Концентрация» нет. B — вкладка есть, разрез «Акции» в пустом состоянии («Акции», RUB не показан — валют нет). C — в обоих случаях вкладки нет.
|
||||
- **Automation Candidate:** yes (component)
|
||||
|
||||
### TC-CONC-005 Сброс состояния при новом заходе и смене счёта
|
||||
|
||||
- **Verifies:** `portfolio-concentration` — `Начальное состояние вкладки` (норма + Scenario «Новый заход»)
|
||||
- **Risk / Priority:** средний / high — ошибочный persist состояния между заходами даёт чужой разрез/валюту
|
||||
- **Preconditions:** счёт с позициями в RUB и USD (доступные валюты: RUB, USD — первая RUB)
|
||||
- **Test Data:** портфель из TC-CONC-007; на вкладке выбраны «Секторы» и USD
|
||||
- **Steps:**
|
||||
1. Открыть счёт, вкладку «Концентрация», выбрать «Секторы», валюту USD.
|
||||
2. Перезагрузить страницу → открыть вкладку.
|
||||
3. Уйти со страницы счёта (список счетов) и вернуться → открыть вкладку.
|
||||
4. Переключить счёт на счёт C (одна акция) → открыть вкладку.
|
||||
- **Expected Results:** после шагов 2–4: разрез «Акции», выбрана первая валюта списка (RUB для этого счёта; для счёта C — валюта его акции).
|
||||
- **Automation Candidate:** yes (e2e)
|
||||
|
||||
### TC-CONC-006 Сохранение состояния при переключении вкладок страницы
|
||||
|
||||
- **Verifies:** `portfolio-concentration` — `Начальное состояние вкладки` («Пока User остаётся на странице… разрез и валюта SHALL сохраняться»)
|
||||
- **Risk / Priority:** низкий / medium — поведение внутри одной сессии страницы
|
||||
- **Preconditions:** как TC-CONC-005
|
||||
- **Steps:**
|
||||
1. Вкладка «Концентрация»: выбрать «Облигации», USD.
|
||||
2. Переключиться на вкладку страницы «Позиции».
|
||||
3. Вернуться на «Концентрацию».
|
||||
- **Expected Results:** открыт «Облигации» в USD.
|
||||
- **Automation Candidate:** yes (e2e; объединяется с TC-CONC-005 в один прогон)
|
||||
|
||||
### TC-CONC-007 Состав разрезов по таблице типов
|
||||
|
||||
- **Verifies:** `portfolio-concentration` — `Состав разрезов` (все ветви таблицы) + `Расчёт долей`
|
||||
- **Risk / Priority:** высокий / high — фильтр типов и агрегация определяют все цифры вкладки
|
||||
- **Preconditions:** вкладка открыта, валюта RUB
|
||||
- **Test Data (RUB, один счёт):** S1 `STOCK` 400, sector `energy`, issuer `b1` «Сбер»; S2 `STOCK` 100, sector `energy`, issuer `b1` «Сбербанк»; B1 `BOND` 100, sector `energy`, issuer `b1` «Сбер»; F1 `FUND` 300, sector `financial`, issuer `b1`; C1 `CURRENCY` 50; O1 `OTHER` 10
|
||||
- **Steps:**
|
||||
1. Разрез «Акции» → суммы и доли.
|
||||
2. Разрез «Облигации».
|
||||
3. Разрез «Секторы».
|
||||
4. Разрез «Эмитенты».
|
||||
- **Expected Results (расчёт):**
|
||||
- Акции: S1 400 ₽ «80 %», S2 100 ₽ «20 %» (база 500 = 400+100; 400/500 = 80 %, 100/500 = 20 %).
|
||||
- Облигации: B1 100 ₽ «100 %».
|
||||
- Секторы: «Энергетика» 600 ₽ (400+100+100) «66,7 %», «Финансы» 300 ₽ «33,3 %» (база 900; 600/900 = 66,666… % → «66,7 %», 300/900 = 33,333… % → «33,3 %»); C1 и O1 не входят.
|
||||
- Эмитенты: «Сбер» 600 ₽ «100 %» (400+100+100; фонд F1 исключён; имя — по наибольшей позиции S1 400 > B1 100 → «Сбер»).
|
||||
- **Automation Candidate:** yes (component, вычислитель разреза)
|
||||
|
||||
### TC-CONC-008 Цепочка названия элемента name → ticker → FIGI
|
||||
|
||||
- **Verifies:** `portfolio-concentration` — `Названия элементов` + `portfolio-view` — `Нормализованный состав Portfolio` (отображаемый идентификатор)
|
||||
- **Risk / Priority:** средний / medium — пустое название ломает список
|
||||
- **Test Data:** акция A с name «Газпром»; акция B без name, ticker `SBER`; акция C без name и ticker, FIGI `BBG000123456`; позиция без issuer в «Эмитентах»
|
||||
- **Steps:**
|
||||
1. Разрез «Акции»: прочитать названия трёх строк.
|
||||
2. Разрез «Эмитенты» для позиции без issuer.
|
||||
- **Expected Results:** строки названы «Газпром», `SBER`, `BBG000123456`; в «Эмитентах» — «Эмитент не указан».
|
||||
- **Automation Candidate:** yes (component)
|
||||
|
||||
### TC-CONC-015 Независимость выбора валюты и fallback при исчезновении
|
||||
|
||||
- **Verifies:** `portfolio-concentration` — `Независимый выбор валюты вкладки` (2 Scenario)
|
||||
- **Risk / Priority:** средний / high — общий Select протекает между виджетами; пропавшая валюта оставляет битое состояние
|
||||
- **Preconditions:** позиции в RUB и USD; «Структура портфеля» на той же странице
|
||||
- **Steps:**
|
||||
1. В «Структуре портфеля» выбрать USD; на вкладке «Концентрация» выбрать RUB.
|
||||
2. В «Структуре портфеля» сменить USD → RUB → USD.
|
||||
3. Обновить Portfolio моком так, чтобы позиций в RUB не осталось (только USD-акции).
|
||||
- **Expected Results:** после шага 2 на вкладке по-прежнему RUB. После шага 3 выбрана первая валюта нового списка — USD (единственная), разрез пересчитан по USD-позициям.
|
||||
- **Automation Candidate:** yes (component + e2e)
|
||||
|
||||
### TC-CONC-016 Границы 5/6/7 элементов и счётчик «Прочее»
|
||||
|
||||
- **Verifies:** `portfolio-concentration` — `Топ-5 и строка «Прочее»`, `Суммарная доля топ-5`
|
||||
- **Risk / Priority:** высокий / high — граничные значения и формулировка числа элементов
|
||||
- **Preconditions:** возможность подмены портфеля (мок/API-фикстура)
|
||||
- **Test Data (RUB, суммы):** набор-1: 400, 250, 150, 100, 50, 30, 20; набор-2: 300, 250, 200, 150, 60, 40; набор-3: 300, 250, 200, 150, 100; набор-4: одна акция 100; набор-5: 12 акций, из них 7 в «Прочее»
|
||||
- **Steps:** для каждого набора открыть разрез «Акции», прочитать строки, счётчик «Прочее» и центр диаграммы.
|
||||
- **Expected Results (расчёт):**
|
||||
- Набор-1 (сумма 1 000): 5 строк + «Прочее» 50 ₽ (2 элемента) «5 %»; доли строк «40 %», «25 %», «15 %», «10 %», «5 %»; центр «Топ-5 · 95 %» и «1 000 ₽».
|
||||
- Набор-2 (сумма 1 000): 6 строк без «Прочее», доли «30 %», «25 %», «20 %», «15 %», «6 %», «4 %»; центр «Топ-5 · 96 %».
|
||||
- Набор-3 (сумма 1 000): 5 строк, доли «30 %», «25 %», «20 %», «15 %», «10 %», «Прочее» нет; центр без «Топ-5».
|
||||
- Набор-4: одна строка «100 %», центр только сумма.
|
||||
- Набор-5: счётчик «Прочее» — «7 элементов»; доли по фактическим суммам.
|
||||
- **Automation Candidate:** yes (component)
|
||||
|
||||
### TC-CONC-020 Формат и округление показанных долей
|
||||
|
||||
- **Verifies:** `portfolio-concentration` — `Показ долей` (все ветви нормы)
|
||||
- **Risk / Priority:** средний / high — владелец сверяет доли с суммами; неверный формат подрывает доверие
|
||||
- **Preconditions:** разрез «Акции», RUB; управляемый портфель (мок/API-фикстура)
|
||||
- **Test Data (RUB, суммы):** набор-A: 1 и 15; набор-B: 100 000 000 и 1; набор-C: 100, 100, 100
|
||||
- **Steps:** для каждого набора прочитать показанные доли строк и их сумму.
|
||||
- **Expected Results (расчёт):**
|
||||
- Набор-A (база 16): точные доли 1/16 = 6,25 % и 15/16 = 93,75 %. Округление до десятых, середина вверх: «6,3 %» и «93,8 %». Сумма показанных 6,3 + 93,8 = 100,1 % ≠ 100 % — допустимо (компенсации нет).
|
||||
- Набор-B (база 100 000 001): 100 000 000/100 000 001 = 99,999999 % → «100 %» (без «,0»); 1/100 000 001 = 0,000001 % < 0,1 % → «< 0,1 %».
|
||||
- Набор-C: 100/300 = 33,333… % → у всех трёх «33,3 %» (сумма показанных 99,9 % — допустимо).
|
||||
- **Automation Candidate:** yes (component)
|
||||
|
||||
### TC-CONC-024 Полный проход таблицы подписей секторов
|
||||
|
||||
- **Verifies:** `portfolio-concentration` — `Русские подписи известных секторов` (все 11 строк таблицы)
|
||||
- **Risk / Priority:** низкий / medium — таблица — эталон, одна ошибка портит разрез
|
||||
- **Test Data:** 11 позиций (BOND/STOCK/FUND) секторов `consumer`, `energy`, `financial`, `health_care`, `industrials`, `it`, `materials`, `real_estate`, `telecom`, `utilities`, `government` по 1 ₽ каждая — доли не важны, важны названия
|
||||
- **Steps:** открыть «Секторы», сверить каждую строку с таблицей PC:374.
|
||||
- **Expected Results:** подписи точно по таблице: Потребительский сектор, Энергетика, Финансы, Здравоохранение, Промышленность, Информационные технологии, Материалы, Недвижимость, Телекоммуникации, Коммунальные услуги, Государственный сектор.
|
||||
- **Automation Candidate:** yes (component, table-driven)
|
||||
|
||||
### TC-CONC-027 Доступность диаграммы скринридером и без цвета
|
||||
|
||||
- **Verifies:** `portfolio-concentration` — `Доступность диаграммы без цвета`
|
||||
- **Risk / Priority:** средний / high (a11y) — информация только цветом недопустима
|
||||
- **Preconditions:** набор-2 из TC-CONC-016; VoiceOver (или NVDA); тема светлая и тёмная
|
||||
- **Steps:**
|
||||
1. Прочитать диаграмму скринридером в свёрнутом состоянии.
|
||||
2. Раскрыть «Прочее» (набор-1) и прочитать снова.
|
||||
3. Клавиатурой: Tab к переключателям разрезов и строкам, Enter на «Прочее».
|
||||
4. Сравнить контраст сегментов и подписей в обеих темах с макетами ux-design v2.
|
||||
- **Expected Results:** скринридер читает для каждого сегмента название, сумму и долю в порядке списка (для набор-2: шесть пар «название — N ₽ — N %»); раскрытие не меняет прочитанный состав (6 сегментов); Enter/Space раскрывают «Прочее», focus видим; контраст соответствует макетам.
|
||||
- **Automation Candidate:** no (ручная/visual; текстовый эквивалент — component)
|
||||
@@ -0,0 +1,68 @@
|
||||
# Test Cases — meta (sector/issuer enrichment, Snapshot-инварианты)
|
||||
|
||||
Cases добавляют данные/порядок событий/oracle сверх Scenarios Delta Specs
|
||||
`portfolio-view` (PVΔ). Требуют управляемое время обхода (час) и управляемые
|
||||
ответы T-Bank (integration, configured HTTP tests, моки по proto).
|
||||
|
||||
### TC-META-002 Token-отказ при получении сектора/бренда не маскируется fallback
|
||||
|
||||
- **Verifies:** `portfolio-view` — `Свежесть и fallback полного Portfolio Snapshot` (исключение token) / Scenario «Отказ token при получении бренда»
|
||||
- **Risk / Priority:** высокий / high — invalid token, замаскированный старым Snapshot, скрывает от владельца потерю доступа
|
||||
- **Preconditions:** сохранённый полный Snapshot старше 60 минут; подключение с invalid token; GET выполняется после обхода
|
||||
- **Test Data:** мок T-Bank: GetPortfolio/GetPositions — PERMISSION_DENIED; типизированный инструмент (sector) — UNAUTHENTICATED
|
||||
- **Steps:**
|
||||
1. Дождаться обхода (или вызвать принудительно в тесте).
|
||||
2. GET Portfolio пользователем.
|
||||
3. Повторить с отказом только на `GetAssetBy` (бренд), финансы успешны.
|
||||
- **Expected Results:** шаг 2 — `400` Problem Details, code `INVALID_TBANK_TOKEN`, fallback Snapshot не возвращается. Шаг 3 — тот же `400`/`INVALID_TBANK_TOKEN`: отказ token на любом звене сектора/бренда приравнен к отказу обхода (требование «Свежесть и fallback полного Portfolio Snapshot»), хотя финансы могли быть получены.
|
||||
- **Automation Candidate:** yes (integration)
|
||||
|
||||
### TC-META-003 Суточный цикл обновления сектора
|
||||
|
||||
- **Verifies:** `portfolio-view` — `Обновление сектора и эмитента` / Scenario «Обход через 24 часа» + 24h-отсчёт таблицы `Результат получения сектора и эмитента`
|
||||
- **Risk / Priority:** высокий / high — ошибка отсчёта даёт вечное старое значение или вечный ре-fetch
|
||||
- **Preconditions:** управляемое время обхода (шаг «час»); позиция P; T-Bank меняет сектор P на `financial` сразу после T0
|
||||
- **Steps (линейная шкала):**
|
||||
1. T0: обход — успех, `sector: energy` (отсчёт с T0).
|
||||
2. T0+1h … T0+23h: обходы — обращений за сектором нет.
|
||||
3. T0+24h: обход запрашивает сектор, T-Bank отвечает UNAVAILABLE.
|
||||
4. T0+25h: обход запрашивает сектор (ошибка не сбросила отсчёт), T-Bank отвечает `financial`.
|
||||
5. T0+26h … T0+48h: обходы.
|
||||
6. T0+49h: обход.
|
||||
- **Expected Results:**
|
||||
- Шаги 2: `sector: energy`.
|
||||
- Шаг 3: `sector: energy` (последнее известное), отсчёт не сброшен (идёт от T0) — поэтому шаг 4 снова обращается.
|
||||
- Шаг 4: `sector: financial`, отсчёт с T0+25h.
|
||||
- Шаги 5: `sector: financial`, обращений нет (T0+25h+24h = T0+49h).
|
||||
- Шаг 6: первое обращение после успеха — сектор запрошен.
|
||||
- **Automation Candidate:** yes (integration, управляемое время)
|
||||
|
||||
### TC-META-004 Четыре исхода получения: поле и отсчёт 24 часов
|
||||
|
||||
- **Verifies:** `portfolio-view` — `Результат получения сектора и эмитента` (каждая строка таблицы) / Scenarios «Ответ без значения заменяет известное значение», «"Не найдено" перезапускает отсчёт», «Ответ о другом инструменте», «Недоступность T-Bank сохраняет известное значение», «Значение ещё не известно»
|
||||
- **Risk / Priority:** высокий / high — таблица — ядро нового контракта; классификация NOT_FOUND решает поведение
|
||||
- **Preconditions:** 4 позиции P1–P4, у каждой известен `sector: energy` (успех в T0); управляемое время; моки по proto
|
||||
- **Test Data:** P1 → ответ со значением `it`; P2 → NOT_FOUND (и вариант «пустой объект без sector» отдельным прогоном); P3 → ответ с чужим `asset_uid`/UID; P4 → UNAVAILABLE (timeout)
|
||||
- **Steps:**
|
||||
1. В T0+24h провести обход со всеми четырьмя моками.
|
||||
2. GET Portfolio, прочитать `sector` P1–P4.
|
||||
3. В T0+25h: P2 теперь отвечает значением `financial`; P3 и P4 — тоже успех `financial`.
|
||||
4. Обход T0+25h; GET; прочитать `sector`.
|
||||
5. Обход T0+48h: P1 и P2 — успех `financial`; P3 и P4 — `energy`.
|
||||
- **Expected Results:**
|
||||
- Шаг 2: P1 `it` (отсчёт сброшен на T0+24h), P2 `null` (сброшен на T0+24h), P3 `energy` (не сброшен, retry), P4 `energy` (не сброшен, retry).
|
||||
- Шаг 4: P2 — по правилу `Обновление сектора и эмитента` значение появляется только при обходе ≥24 ч после «не найдено» (T0+24h), поэтому в T0+25h остаётся `null`; P3 и P4 — `financial` (получено, сброс отсчёта на T0+25h).
|
||||
- Шаг 5: P1 — запрошен снова (отсчёт сброшен в T0+24h, T0+48h ≥ 24 ч), становится `financial`; P2 — запрошен (≥24 ч от «не найдено»), становится `financial`; P3 и P4 — не запрашиваются (последний успех T0+25h, T0+48h < T0+49h), `sector: financial` остаётся.
|
||||
- **Automation Candidate:** yes (integration; P2-ветка — минимальное воспроизведение перезапуска отсчёта)
|
||||
|
||||
### TC-META-005 Смена и удаление подключения: sector/brand не протекают
|
||||
|
||||
- **Verifies:** `portfolio-view` — `Свежесть и fallback` («прежние личные datasets недоступны…»), failure-model F11
|
||||
- **Risk / Priority:** высокий / high — утечка данных между подключениями
|
||||
- **Preconditions:** пользователь, подключения K1 (счёт A, позиции с sector/brand) и K2 (счёт B)
|
||||
- **Steps:**
|
||||
1. Заменить K1 на новое подключение K1' (новый token, те же счёта): GET счёта A.
|
||||
2. Удалить K1': GET счёта A.
|
||||
3. Поздняя публикация обхода K1 (симуляция задержанной попытки) — проверить счёт A и B.
|
||||
- **Expected Results:** шаг 1 — 404/409/400 по контракту замены, прежние datasets K1 недоступны; sector/brand позиции не выдаются до первого успешного обхода K1'. Шаг 2 — 404. Шаг 3 — публикация отклонена (`id`/`attemptId`/`running`), в Portfolio K2 и нового K1' данные K1 не появляются.
|
||||
- **Automation Candidate:** yes (integration)
|
||||
@@ -0,0 +1,28 @@
|
||||
# Test Cases — reg (регрессия затронутых областей)
|
||||
|
||||
Проверки сохранения существующего поведения, изменённого рисками change.
|
||||
|
||||
### TC-REG-001 Существующая вкладка «Позиции» неизменна
|
||||
|
||||
- **Verifies:** `portfolio-concentration` — `Вкладка «Концентрация» страницы счёта` («SHALL NOT менять вкладку по умолчанию и содержание остальных вкладок»); регрессионный baseline canonical `portfolio-view`
|
||||
- **Risk / Priority:** высокий / high — новая вкладка не должна ломать существующий экран
|
||||
- **Preconditions:** счёт с позициями и Cash Balance; вкладка «Позиции» открывается по умолчанию в canonical-поведении
|
||||
- **Steps:**
|
||||
1. Открыть страницу счёта: какая вкладка активна, состав и порядок вкладок.
|
||||
2. Пройтись по каждой прежней вкладке: содержимое и сортировка списка позиций, валютная сводка.
|
||||
3. Режим «Все счета»: проверить отсутствие «Концентрации» и целостность прежних вкладок.
|
||||
- **Expected Results:** по умолчанию открыта прежняя вкладка («Позиции»); «Концентрация» — рядом, последней из новых; содержание остальных вкладок и «Всех счетов» идентично canonical (сравнение по эталонным данным).
|
||||
- **Automation Candidate:** yes (e2e + существующий regression-прогон)
|
||||
|
||||
### TC-REG-004 Часовой обход: sector/brand не влияют на успех и нагрузку синхронизации
|
||||
|
||||
- **Verifies:** `hourly-investment-sync` (canonical) + PVΔ `Свежесть и fallback` / F07, F10, F14
|
||||
- **Risk / Priority:** высокий / high — новые RPC-вызовы в обходе могут ломать или замедлять финансовую синхронизацию
|
||||
- **Preconditions:** тестовое подключение; счёт из TC-CONC-007 (6 позиций, смешанные секторы/бренды); метрики `tbank.rpc.*`
|
||||
- **Steps:**
|
||||
1. Обход при полностью успешных ответах: события `tbank.rpc.*`, успех публикации, `lastSuccessfulAt`.
|
||||
2. Обход с тотальным сбоем sector/brand (UNAVAILABLE на все инструментальные вызовы), финансы успешны.
|
||||
3. Обход с RESOURCE_EXHAUSTED на `GetAssetBy` (после повторов клиента).
|
||||
4. Обход, где финансовые ответы не получены, но sector/brand успешны.
|
||||
- **Expected Results:** шаг 1 — Snapshot опубликован, `isStale: false`. Шаги 2–3 — Snapshot опубликован, успех/свежесть финансов не изменены («Результат получения сектора и эмитента»: неуспешное получение SHALL NOT мешать обновлению Portfolio), sector/brand — прежние известные. Шаг 4 — публикации нет, прежний Snapshot с `isStale: true` (F01: успех sector/brand не заменяет финансовый). Число новых RPC-вызовов за обход фиксируется как baseline для Q-F3.
|
||||
- **Automation Candidate:** yes (integration)
|
||||
Reference in New Issue
Block a user