docs(specs): archive frontend quality guardrails
This commit is contained in:
@@ -0,0 +1,3 @@
|
|||||||
|
schema: spec-driven
|
||||||
|
created: 2026-08-24
|
||||||
|
goal: Закрыть WL-P3-02, WL-P3-03, WL-P3-05 и WL-P3-06 без расширения MVP scope.
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# tighten-frontend-quality-guardrails
|
||||||
|
|
||||||
|
Закрыть согласованные frontend quality guardrails из аудита 20.08.2026.
|
||||||
@@ -0,0 +1,129 @@
|
|||||||
|
## Context
|
||||||
|
|
||||||
|
См. motivation в `proposal.md` и behavioral contract в
|
||||||
|
`specs/frontend-quality-guardrails/spec.md`. Baseline под Node 22.21.0:
|
||||||
|
`npm run verify` проходит (17 test files, 55 tests), coverage составляет
|
||||||
|
82.46% statements, 75.68% branches, 75.47% functions и 83.41% lines, но
|
||||||
|
Vite создаёт один JS entry asset размером 628,212 bytes minified.
|
||||||
|
|
||||||
|
Текущий dependency-cruiser проверяет только направление FSD layers. Он не
|
||||||
|
включает `no-circular` и не различает public `index.ts` от внутренних files
|
||||||
|
другого slice. `shared/i18n/index.ts -> zod.ts -> index.ts` образует cycle;
|
||||||
|
`app/ui/App.tsx` и `features/auth/ui/AuthForm.tsx` обходят public API routes и
|
||||||
|
i18n. `AppRoutes` статически импортирует все page components. Vitest собирает
|
||||||
|
coverage, но не задаёт thresholds.
|
||||||
|
|
||||||
|
### Baseline bundle measurement
|
||||||
|
|
||||||
|
Vite manifest при текущем build содержит один `isEntry` JavaScript asset
|
||||||
|
`assets/index-DEUAdr-U.js` размером 628,212 bytes. Bundle gate будет читать
|
||||||
|
manifest и filesystem, а не парсить human-oriented Vite output.
|
||||||
|
|
||||||
|
## Goals / Non-Goals
|
||||||
|
|
||||||
|
**Goals:**
|
||||||
|
|
||||||
|
- Сделать существующий `npm run verify` источником enforced structural,
|
||||||
|
bundle и coverage guarantees.
|
||||||
|
- Дать routes lazy-loading boundary без ручного vendor chunk policy.
|
||||||
|
- Сделать изменение policy проверяемым через focused regression tests и
|
||||||
|
deterministic build artifacts.
|
||||||
|
|
||||||
|
**Non-Goals:**
|
||||||
|
|
||||||
|
- Не закрывать WL-P3-04: не менять `lang`, ARIA/live-region policy или
|
||||||
|
application accessibility semantics. Для loading fallback используется
|
||||||
|
Mantine component без нового собственного accessibility primitive.
|
||||||
|
- Не вводить CI/CD, new runtime dependencies, API/backend changes, route
|
||||||
|
contract changes или manual `manualChunks` policy.
|
||||||
|
- Не повышать coverage ради процента и не создавать general-purpose
|
||||||
|
architecture linter вне существующего dependency-cruiser gate.
|
||||||
|
|
||||||
|
## Decisions
|
||||||
|
|
||||||
|
### Dependency-cruiser остаётся единственным structural graph gate
|
||||||
|
|
||||||
|
Configuration задаёт `severity: error` для всех FSD rules (default
|
||||||
|
dependency-cruiser severity — `warn`) и добавляет `no-circular` и rule с
|
||||||
|
capture groups: она запрещает
|
||||||
|
dependency из одного slice во внутренний module другого slice, но разрешает
|
||||||
|
внутренние imports того же slice и target public `index.ts`. Это охватывает
|
||||||
|
application и colocated tests, не создавая allowlist для известных violations.
|
||||||
|
|
||||||
|
Текущий i18n initialisation переезжает в leaf module; public `index.ts`
|
||||||
|
сохраняет только consumer-facing validation helper, а `zod.ts` импортирует
|
||||||
|
leaf напрямую. Route boundary реэкспортируется из public routes API;
|
||||||
|
application потребляет его оттуда. Это устраняет текущие violations, не
|
||||||
|
оставляя неиспользуемый public symbol.
|
||||||
|
|
||||||
|
Альтернатива — отдельный regex linter для import strings. Она отвергнута,
|
||||||
|
поскольку duplicate resolver легко расходится с TypeScript alias и не даёт
|
||||||
|
cycle analysis. Альтернатива с постоянными exception paths отвергнута: она
|
||||||
|
сделает public API policy необязательной.
|
||||||
|
|
||||||
|
### Initial budget считается по Vite manifest import graph
|
||||||
|
|
||||||
|
Vite build пишет manifest. `bundle:check` находит `isEntry` JavaScript entry,
|
||||||
|
рекурсивно суммирует только его `imports`, читает sizes assets с диска и
|
||||||
|
завершается ошибкой выше 500 * 1024 bytes. `dynamicImports` намеренно не
|
||||||
|
попадают в initial payload.
|
||||||
|
|
||||||
|
Route pages загружаются через `React.lazy`; единственный route-level Suspense
|
||||||
|
fallback использует Mantine loader. После выделения страниц manifest показал,
|
||||||
|
что protected application shell всё ещё достижим из entry graph; поэтому
|
||||||
|
`ProtectedLayout` также становится lazy route boundary. Это снизило measured
|
||||||
|
initial graph с 549,665 до 509,165 bytes. Script отдельно сохраняет размер
|
||||||
|
каждого dynamic route boundary — page и `ProtectedLayout` — в committed
|
||||||
|
baseline JSON. При последующем build script падает, если существующий lazy
|
||||||
|
route chunk стал больше baseline; обновление baseline выполняется только
|
||||||
|
отдельной явной командой после review.
|
||||||
|
|
||||||
|
Альтернатива — опираться на Vite `chunkSizeWarningLimit`. Она отвергнута:
|
||||||
|
warning не является gate и измеряет отдельный asset, а не весь eagerly loaded
|
||||||
|
entry graph. Альтернатива с `manualChunks` отвергнута как premature vendor
|
||||||
|
optimization.
|
||||||
|
|
||||||
|
### Coverage thresholds являются floors, а не delivery metric
|
||||||
|
|
||||||
|
Vitest получает global thresholds, округлённые вниз от observed baseline:
|
||||||
|
82/75/75/83, и instrumentирует весь committed application source
|
||||||
|
`src/**/*.{ts,tsx}` (исключая test/support source). Любое уменьшение metrics
|
||||||
|
останавливает test:coverage stage; scenario tests по-прежнему определяют
|
||||||
|
достаточность поведения.
|
||||||
|
|
||||||
|
Альтернатива — exact current percentages. Она отвергнута, поскольку малое
|
||||||
|
изменение числа instrumented lines создаёт шум без полезного risk signal.
|
||||||
|
|
||||||
|
### Remediation lifecycle сохраняет фактический scope
|
||||||
|
|
||||||
|
До реализации registry помечает данный change active только для WL-P3-02,
|
||||||
|
WL-P3-03, WL-P3-05 и WL-P3-06. WL-P3-04 остаётся planned, так как owner
|
||||||
|
исключил application accessibility work из MVP scope. После успешного archive
|
||||||
|
registry фиксирует terminal evidence и называет `tighten-backend-request-feedback`
|
||||||
|
следующей единственной recommended task.
|
||||||
|
|
||||||
|
## Risks / Trade-offs
|
||||||
|
|
||||||
|
- [Lazy routes кратко показывают fallback] → использовать единственный Mantine
|
||||||
|
loader без изменения domain, route или application accessibility policy.
|
||||||
|
- [Vite manifest shape меняется при обновлении tooling] → bundle script
|
||||||
|
валидирует required manifest fields и сообщает format error вместо false
|
||||||
|
green result.
|
||||||
|
- [Новый lazy route не имеет baseline] → explicit baseline command создаёт его
|
||||||
|
только после review; normal verify не переписывает committed baseline.
|
||||||
|
- [Structural rule ловит корректный generated import] → exception добавляется
|
||||||
|
только с documented generator constraint и regression evidence.
|
||||||
|
- [Coverage floor блокирует полезный refactor] → добавить scenario coverage
|
||||||
|
либо принять отдельное согласованное изменение baseline, а не обходить gate.
|
||||||
|
|
||||||
|
## Migration Plan
|
||||||
|
|
||||||
|
1. Сделать dependency, public-API и route-loading behavior testable; затем
|
||||||
|
изменить минимальные source/config files, пока tests and structural gate
|
||||||
|
не станут green.
|
||||||
|
2. Добавить manifest-based bundle tooling, сформировать reviewed lazy baseline
|
||||||
|
и включить bundle check в `verify`.
|
||||||
|
3. Добавить coverage floors, выполнить full Node 22 frontend verify и
|
||||||
|
OpenSpec/docs gates.
|
||||||
|
4. Rollback — independent Git revert в frontend/specs/docs. Нет persisted data
|
||||||
|
migration, API migration или browser storage migration.
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
## Why
|
||||||
|
|
||||||
|
Аудит 20.08.2026 подтвердил, что frontend не принуждает две уже объявленные
|
||||||
|
структурные границы: i18n имеет import cycle, а cross-slice imports могут
|
||||||
|
обходить public `index.ts`. Одновременно production build содержит один
|
||||||
|
initial JavaScript chunk 628.21 kB minified, а coverage запускается без
|
||||||
|
минимальных порогов. Поэтому green `npm run verify` ещё не гарантирует
|
||||||
|
сохранение этих quality properties при следующем изменении.
|
||||||
|
|
||||||
|
## What Changes
|
||||||
|
|
||||||
|
- Закрепить отсутствие import cycles и обхода public API между любыми разными
|
||||||
|
FSD slices в `frontend/src`, включая `app` и tests; generated-code exception
|
||||||
|
допустим только как явно документированное вынужденное исключение.
|
||||||
|
- Устранить текущий i18n cycle и текущие deep imports без изменения
|
||||||
|
пользовательского API или HTTP-контракта.
|
||||||
|
- Lazy-load route page boundaries и добавить проверяемый budget: сумма entry
|
||||||
|
bundle и всех его eagerly loaded JavaScript dependencies не превышает
|
||||||
|
500 kB minified. Lazy route chunks получают baseline только для последующих
|
||||||
|
регрессий; ручной vendor chunking не вводится.
|
||||||
|
- Закрепить coverage floors как anti-regression signal: statements 82%,
|
||||||
|
branches 75%, functions 75%, lines 83%.
|
||||||
|
- Перевести remediation registry в active для WL-P3-02, WL-P3-03, WL-P3-05 и
|
||||||
|
WL-P3-06. WL-P3-04 остаётся `planned`: accessibility semantics не входят в
|
||||||
|
текущий MVP scope.
|
||||||
|
|
||||||
|
## Capabilities
|
||||||
|
|
||||||
|
### New Capabilities
|
||||||
|
|
||||||
|
- `frontend-quality-guardrails`: воспроизводимые structural, bundle и coverage
|
||||||
|
guards для delivered React client.
|
||||||
|
|
||||||
|
### Modified Capabilities
|
||||||
|
|
||||||
|
_Нет._
|
||||||
|
|
||||||
|
## Impact
|
||||||
|
|
||||||
|
- Frontend: FSD dependency configuration, i18n and app public imports,
|
||||||
|
route loading, Vite/Vitest configuration, package scripts и targeted tests.
|
||||||
|
- Specs/docs: delta-spec, change design/tasks и audit remediation registry.
|
||||||
|
|
||||||
|
Не изменяются HTTP/OpenAPI contract, domain terminology, backend, T-Bank
|
||||||
|
integration, Mantine accessibility semantics, CI/CD или deferred Prisma work.
|
||||||
+77
@@ -0,0 +1,77 @@
|
|||||||
|
## Purpose
|
||||||
|
|
||||||
|
Гарантирует, что frontend сохраняет проверяемые structural, startup-size и
|
||||||
|
test-coverage свойства при последующих изменениях React client.
|
||||||
|
|
||||||
|
## ADDED Requirements
|
||||||
|
|
||||||
|
### Requirement: Frontend сохраняет structural boundaries slice public API
|
||||||
|
|
||||||
|
Frontend MUST не содержать cycles в import graph `src` и MUST обращаться к
|
||||||
|
другому FSD slice только через его public `index.ts`, независимо от слоя,
|
||||||
|
включая `app` и test source. Generated source MAY быть исключён только при
|
||||||
|
документированном вынужденном исключении в dependency configuration.
|
||||||
|
|
||||||
|
#### Scenario: Добавлен import cycle
|
||||||
|
|
||||||
|
- **WHEN** исходный или test module в `src` создаёт прямой либо косвенный
|
||||||
|
import cycle
|
||||||
|
- **THEN** documented frontend dependency gate завершается с ошибкой до
|
||||||
|
передачи изменения
|
||||||
|
|
||||||
|
#### Scenario: Slice обходит public API другого slice
|
||||||
|
|
||||||
|
- **WHEN** module одного slice импортирует внутренний file другого slice,
|
||||||
|
минуя его public `index.ts`
|
||||||
|
- **THEN** documented frontend dependency gate завершается с ошибкой и
|
||||||
|
сообщает boundary violation
|
||||||
|
|
||||||
|
#### Scenario: Application использует public route API
|
||||||
|
|
||||||
|
- **WHEN** application container использует route-level component
|
||||||
|
- **THEN** import проходит через public API routes slice и dependency gate
|
||||||
|
завершается успешно при отсутствии остальных violations
|
||||||
|
|
||||||
|
### Requirement: Frontend ограничивает initial JavaScript payload
|
||||||
|
|
||||||
|
Production frontend MUST lazy-load route page boundaries. Сумма minified
|
||||||
|
JavaScript entry bundle и всех его eagerly loaded JavaScript dependencies MUST
|
||||||
|
NOT превышать 500 kB. Lazy route chunks MUST иметь зафиксированный baseline
|
||||||
|
для последующих регрессий; bundle policy MUST NOT требовать ручного vendor
|
||||||
|
chunking.
|
||||||
|
|
||||||
|
#### Scenario: Production build укладывается в initial budget
|
||||||
|
|
||||||
|
- **WHEN** frontend production build создаёт entry bundle и eagerly loaded
|
||||||
|
JavaScript dependencies суммарным размером не более 500 kB minified
|
||||||
|
- **THEN** documented bundle gate завершается успешно
|
||||||
|
|
||||||
|
#### Scenario: Production build превышает initial budget
|
||||||
|
|
||||||
|
- **WHEN** frontend production build создаёт entry bundle и eagerly loaded
|
||||||
|
JavaScript dependencies суммарным размером более 500 kB minified
|
||||||
|
- **THEN** documented bundle gate завершается с ошибкой и сообщает measured
|
||||||
|
initial payload
|
||||||
|
|
||||||
|
#### Scenario: Изменён lazy route chunk
|
||||||
|
|
||||||
|
- **WHEN** lazy-loaded route chunk превышает свой зафиксированный baseline
|
||||||
|
- **THEN** documented bundle gate завершается с ошибкой до передачи изменения
|
||||||
|
|
||||||
|
### Requirement: Frontend coverage является anti-regression gate
|
||||||
|
|
||||||
|
Documented frontend coverage command MUST завершаться с ошибкой, если global
|
||||||
|
coverage committed source ниже 82% statements, 75% branches, 75% functions
|
||||||
|
или 83% lines. Эти пороги SHALL служить только сигналом регрессии и MUST NOT
|
||||||
|
заменять scenario-based tests.
|
||||||
|
|
||||||
|
#### Scenario: Coverage сохраняет каждый baseline floor
|
||||||
|
|
||||||
|
- **WHEN** frontend test suite достигает либо превышает все четыре coverage
|
||||||
|
floors
|
||||||
|
- **THEN** documented coverage command завершается успешно
|
||||||
|
|
||||||
|
#### Scenario: Coverage опускается ниже floor
|
||||||
|
|
||||||
|
- **WHEN** frontend test suite опускается ниже хотя бы одного coverage floor
|
||||||
|
- **THEN** documented coverage command завершается с ошибкой по этой метрике
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
## 1. Зафиксировать remediation scope
|
||||||
|
|
||||||
|
- [x] 1.1 В `docs/development/audit-remediation.md` перевести WL-P3-02,
|
||||||
|
WL-P3-03, WL-P3-05 и WL-P3-06 в `active` с change
|
||||||
|
`tighten-frontend-quality-guardrails`; WL-P3-04 оставить `planned` и не
|
||||||
|
добавлять terminal evidence до archive.
|
||||||
|
- [x] 1.2 Зафиксировать Node 22 baseline: выполнить frontend `npm run verify`,
|
||||||
|
записать observed tests, coverage и initial bundle size в change evidence.
|
||||||
|
|
||||||
|
## 2. Enforce structural public API boundaries
|
||||||
|
|
||||||
|
- [x] 2.1 Добавить fixture-based failing checks для dependency-cruiser: cycle
|
||||||
|
и import внутреннего file другого slice должны быть rejected, а same-slice и
|
||||||
|
public-index imports должны оставаться allowed.
|
||||||
|
- [x] 2.2 Запустить новые dependency fixture checks до implementation и
|
||||||
|
подтвердить expected red result для отсутствующих rules.
|
||||||
|
- [x] 2.3 Добавить `no-circular` и capture-group public-API rule в
|
||||||
|
`frontend/dependency-cruiser.cjs`; включить fixture checks в documented
|
||||||
|
frontend dependency gate.
|
||||||
|
- [x] 2.4 Вынести i18n initialization в leaf module, сохранить public exports
|
||||||
|
через `shared/i18n/index.ts` и перевести validation helper на leaf import,
|
||||||
|
чтобы устранить cycle.
|
||||||
|
- [x] 2.5 Реэкспортировать route error boundary из public routes API и
|
||||||
|
перевести application и auth imports на соответствующие public APIs.
|
||||||
|
- [x] 2.6 Выполнить targeted tests и `npm run deps`; подтвердить green result
|
||||||
|
для committed source и expected rejection обоих fixture violations.
|
||||||
|
|
||||||
|
## 3. Сделать initial payload измеримым и ограниченным
|
||||||
|
|
||||||
|
- [x] 3.1 Написать failing unit tests для manifest parser: он суммирует entry
|
||||||
|
asset с transitive eager imports, не включает dynamic imports, отклоняет
|
||||||
|
malformed manifest и сообщает initial-budget/lazy-baseline regressions.
|
||||||
|
- [x] 3.2 Запустить bundle parser tests и подтвердить expected red result до
|
||||||
|
создания parser/check command.
|
||||||
|
- [x] 3.3 Реализовать manifest-based bundle budget and explicit baseline
|
||||||
|
scripts без runtime dependencies; normal check не должен изменять baseline.
|
||||||
|
- [x] 3.4 Lazy-load route page boundaries через React lazy/Suspense с Mantine
|
||||||
|
fallback, не меняя route paths, auth redirects или application
|
||||||
|
accessibility policy.
|
||||||
|
- [x] 3.5 Включить Vite manifest output, bundle check и explicit reviewed lazy
|
||||||
|
route baseline в package scripts; добавить bundle check в `npm run verify`.
|
||||||
|
- [x] 3.6 Сформировать initial lazy-route baseline после code splitting и
|
||||||
|
подтвердить, что build проходит initial budget ≤ 500 * 1024 bytes.
|
||||||
|
- [x] 3.7 Выполнить bundle parser tests, route regression tests и bundle gate;
|
||||||
|
подтвердить green result и absence ручного vendor chunk policy.
|
||||||
|
|
||||||
|
## 4. Закрепить coverage floors
|
||||||
|
|
||||||
|
- [x] 4.1 Добавить global Vitest thresholds: statements 82, branches 75,
|
||||||
|
functions 75, lines 83, не меняя scenario tests ради процента.
|
||||||
|
- [x] 4.2 Запустить coverage command и подтвердить, что committed suite
|
||||||
|
проходит все четыре floors.
|
||||||
|
|
||||||
|
## 5. Провести completion checks
|
||||||
|
|
||||||
|
- [x] 5.1 Выполнить frontend `npm run verify` под Node 22, targeted tests,
|
||||||
|
`git diff --check` и зафиксировать observed results.
|
||||||
|
- [x] 5.2 Выполнить strict change validation, synced-spec validation и
|
||||||
|
OpenSpec authority verifier с `--store wealth-ledger-specs`.
|
||||||
|
- [x] 5.3 Провести independent read-only review implementation, tests,
|
||||||
|
generated/build artifacts и docs scope; устранить blocking findings до
|
||||||
|
archive.
|
||||||
|
- [x] 5.4 Выполнить applicable `opsx-verify` procedure и устранить every
|
||||||
|
blocking completeness, correctness или coherence result до archive.
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
# frontend-quality-guardrails Specification
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
|
||||||
|
Гарантирует, что frontend сохраняет проверяемые structural, startup-size и
|
||||||
|
test-coverage свойства при последующих изменениях React client.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
### Requirement: Frontend сохраняет structural boundaries slice public API
|
||||||
|
|
||||||
|
Frontend MUST не содержать cycles в import graph `src` и MUST обращаться к
|
||||||
|
другому FSD slice только через его public `index.ts`, независимо от слоя,
|
||||||
|
включая `app` и test source. Generated source MAY быть исключён только при
|
||||||
|
документированном вынужденном исключении в dependency configuration.
|
||||||
|
|
||||||
|
#### Scenario: Добавлен import cycle
|
||||||
|
|
||||||
|
- **WHEN** исходный или test module в `src` создаёт прямой либо косвенный
|
||||||
|
import cycle
|
||||||
|
- **THEN** documented frontend dependency gate завершается с ошибкой до
|
||||||
|
передачи изменения
|
||||||
|
|
||||||
|
#### Scenario: Slice обходит public API другого slice
|
||||||
|
|
||||||
|
- **WHEN** module одного slice импортирует внутренний file другого slice,
|
||||||
|
минуя его public `index.ts`
|
||||||
|
- **THEN** documented frontend dependency gate завершается с ошибкой и
|
||||||
|
сообщает boundary violation
|
||||||
|
|
||||||
|
#### Scenario: Application использует public route API
|
||||||
|
|
||||||
|
- **WHEN** application container использует route-level component
|
||||||
|
- **THEN** import проходит через public API routes slice и dependency gate
|
||||||
|
завершается успешно при отсутствии остальных violations
|
||||||
|
|
||||||
|
### Requirement: Frontend ограничивает initial JavaScript payload
|
||||||
|
|
||||||
|
Production frontend MUST lazy-load route page boundaries. Сумма minified
|
||||||
|
JavaScript entry bundle и всех его eagerly loaded JavaScript dependencies MUST
|
||||||
|
NOT превышать 500 kB. Lazy route chunks MUST иметь зафиксированный baseline
|
||||||
|
для последующих регрессий; bundle policy MUST NOT требовать ручного vendor
|
||||||
|
chunking.
|
||||||
|
|
||||||
|
#### Scenario: Production build укладывается в initial budget
|
||||||
|
|
||||||
|
- **WHEN** frontend production build создаёт entry bundle и eagerly loaded
|
||||||
|
JavaScript dependencies суммарным размером не более 500 kB minified
|
||||||
|
- **THEN** documented bundle gate завершается успешно
|
||||||
|
|
||||||
|
#### Scenario: Production build превышает initial budget
|
||||||
|
|
||||||
|
- **WHEN** frontend production build создаёт entry bundle и eagerly loaded
|
||||||
|
JavaScript dependencies суммарным размером более 500 kB minified
|
||||||
|
- **THEN** documented bundle gate завершается с ошибкой и сообщает measured
|
||||||
|
initial payload
|
||||||
|
|
||||||
|
#### Scenario: Изменён lazy route chunk
|
||||||
|
|
||||||
|
- **WHEN** lazy-loaded route chunk превышает свой зафиксированный baseline
|
||||||
|
- **THEN** documented bundle gate завершается с ошибкой до передачи изменения
|
||||||
|
|
||||||
|
### Requirement: Frontend coverage является anti-regression gate
|
||||||
|
|
||||||
|
Documented frontend coverage command MUST завершаться с ошибкой, если global
|
||||||
|
coverage committed source ниже 82% statements, 75% branches, 75% functions
|
||||||
|
или 83% lines. Эти пороги SHALL служить только сигналом регрессии и MUST NOT
|
||||||
|
заменять scenario-based tests.
|
||||||
|
|
||||||
|
#### Scenario: Coverage сохраняет каждый baseline floor
|
||||||
|
|
||||||
|
- **WHEN** frontend test suite достигает либо превышает все четыре coverage
|
||||||
|
floors
|
||||||
|
- **THEN** documented coverage command завершается успешно
|
||||||
|
|
||||||
|
#### Scenario: Coverage опускается ниже floor
|
||||||
|
|
||||||
|
- **WHEN** frontend test suite опускается ниже хотя бы одного coverage floor
|
||||||
|
- **THEN** documented coverage command завершается с ошибкой по этой метрике
|
||||||
Reference in New Issue
Block a user