Frontend: real-library Vitest hardening (large candles + visible-range autoscale) #229

Closed
opened 2026-05-29 05:41:43 +00:00 by PlasticDigits · 12 comments
PlasticDigits commented 2026-05-29 05:41:43 +00:00 (Migrated from gitlab.com)

Summary

Extend the real-library Vitest suite (#211) with a large-candle performance guard and USD autoscale integration using the chart’s actual visible logical range (not only a synthetic original() callback).

Bundled scope: large-candle perf guard · real visible-range autoscale


Current codebase

Area Files
Charts Vitest vitest.config.charts.ts, src/test/chartsSetup.ts
Real tests priceChartLightweightRealLibrary.charts.test.ts — 220 candles OK; autoscale test invokes provider with mock original()
Pure scale tests priceChartPriceScale.test.ts — minLowInVisibleLogicalRange, clampUsdPriceChartAutoscale
Canvas wiring PriceChartLightweightCanvas.tsx — provider reads chart.timeScale().getVisibleLogicalRange()
Fixtures src/test/chartTestFixtures.ts, chartTestOptions.ts
CI .github/workflows/test.yml — npm run test:charts in frontend job after unit tests
Timeout testTimeout: 15000 in charts config

Why this is needed

  1. Perf regressions: Large indexer responses (500–2000+ candles) may pass stub tests but OOM or timeout in Node canvas CI.
  2. Autoscale #151: Current real test proves clamp with fake original() output; production bug could mis-read visible range and still pass.
  3. #211 acceptance gap: “Visible-range clamp respects lowest visible low” — strengthen with library-backed logical range.

Constraints and guardrails

  1. Only in npm run test:charts — do not slow default test:run.
  2. Document CI ceiling (e.g. 2000 candles, <10s) — avoid 50k-row hangs.
  3. No flaky timing assertions — use upper-bound timeout, not wall-clock benchmarks in shared CI.
  4. Keep pure tests in priceChartPriceScale.test.ts — don’t duplicate all cases.
  5. lightweight-charts naming.

Relevant files

  • frontend-dapp/src/components/charts/__tests__/priceChartLightweightRealLibrary.charts.test.ts
  • frontend-dapp/src/components/charts/__tests__/PriceChartLightweightCanvas.charts.test.tsx
  • frontend-dapp/src/components/charts/priceChartPriceScale.ts
  • frontend-dapp/src/test/chartTestFixtures.ts
  • frontend-dapp/vitest.config.charts.ts
  • frontend-dapp/package.json (test:charts)
  • docs/testing.md, skills/AGENTS_FRONTEND_PRICE_CHART.md

  1. Large dataset: Add test makeChartCandlePoints(500) or 1500 with testTimeout bump if needed; assert completes, canvas present, chart.remove() succeeds.
  2. Optional: describe.runIf(process.env.CI) for 2000+ row soak — document in testing.md.
  3. Real autoscale: After setData + fitContent, set visible logical range (or scroll) so subset of candles visible; invoke captured autoscaleInfoProvider; assert minValue >= 0 and minValue >= minLow of visible subset.
  4. Link invariant #151 in test names.

Acceptance criteria

  • test:charts includes large-candle case (≥500 rows) within configured timeout.
  • Autoscale test uses real getVisibleLogicalRange() + fixture candle lows.
  • Document max row count / timeout in docs/testing.md.
  • npm run test:run unchanged.
  • CI frontend job still passes (or separate job if split — see bundled CI issue).

Test plan — functional paths

# Path Expected
1 500 candles init Completes < timeout; canvas > 0
2 1500 candles init Same or documented skip in CI
3 setData refresh 500→600 No second chart
4 Autoscale all visible min ≥ 0
5 Autoscale zoomed window min ≥ visible min low
6 Single candle autoscale min ≥ 0
7 teardown remove(); no canvases

Test plan — attack vectors

Vector Approach Expected
50k candles Optional local-only / skipped Documented; CI does not hang
Empty logical range getVisibleLogicalRange() null Provider uses full-series fallback per priceChartPriceScale
All lows > 0, original negative Clamp still ≥ 0 #151

Verification criteria

  1. npm run test:charts green locally and in CI.
  2. make test-frontend-charts green.
  3. docs/frontend.md invariant table references new tests.

## Summary Extend the **real-library Vitest** suite ([#211](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/211)) with a **large-candle performance guard** and **USD autoscale integration** using the chart’s actual visible logical range (not only a synthetic `original()` callback). **Bundled scope:** large-candle perf guard · real visible-range autoscale --- ## Current codebase | Area | Files | |------|--------| | Charts Vitest | `vitest.config.charts.ts`, `src/test/chartsSetup.ts` | | Real tests | `priceChartLightweightRealLibrary.charts.test.ts` — 220 candles OK; autoscale test invokes provider with **mock** `original()` | | Pure scale tests | `priceChartPriceScale.test.ts` — `minLowInVisibleLogicalRange`, `clampUsdPriceChartAutoscale` | | Canvas wiring | `PriceChartLightweightCanvas.tsx` — provider reads `chart.timeScale().getVisibleLogicalRange()` | | Fixtures | `src/test/chartTestFixtures.ts`, `chartTestOptions.ts` | | CI | `.github/workflows/test.yml` — `npm run test:charts` in `frontend` job after unit tests | | Timeout | `testTimeout: 15000` in charts config | --- ## Why this is needed 1. **Perf regressions:** Large indexer responses (500–2000+ candles) may pass stub tests but OOM or timeout in Node canvas CI. 2. **Autoscale #151:** Current real test proves clamp with **fake** `original()` output; production bug could mis-read visible range and still pass. 3. **#211 acceptance gap:** “Visible-range clamp respects lowest visible low” — strengthen with library-backed logical range. --- ## Constraints and guardrails 1. **Only in `npm run test:charts`** — do not slow default `test:run`. 2. **Document CI ceiling** (e.g. 2000 candles, &lt;10s) — avoid 50k-row hangs. 3. **No flaky timing assertions** — use upper-bound timeout, not wall-clock benchmarks in shared CI. 4. **Keep pure tests** in `priceChartPriceScale.test.ts` — don’t duplicate all cases. 5. **lightweight-charts** naming. --- ## Relevant files - `frontend-dapp/src/components/charts/__tests__/priceChartLightweightRealLibrary.charts.test.ts` - `frontend-dapp/src/components/charts/__tests__/PriceChartLightweightCanvas.charts.test.tsx` - `frontend-dapp/src/components/charts/priceChartPriceScale.ts` - `frontend-dapp/src/test/chartTestFixtures.ts` - `frontend-dapp/vitest.config.charts.ts` - `frontend-dapp/package.json` (`test:charts`) - `docs/testing.md`, `skills/AGENTS_FRONTEND_PRICE_CHART.md` --- ## Recommended direction 1. **Large dataset:** Add test `makeChartCandlePoints(500)` or `1500` with `testTimeout` bump if needed; assert completes, canvas present, `chart.remove()` succeeds. 2. **Optional:** `describe.runIf(process.env.CI)` for 2000+ row soak — document in testing.md. 3. **Real autoscale:** After `setData` + `fitContent`, set visible logical range (or scroll) so subset of candles visible; invoke captured `autoscaleInfoProvider`; assert `minValue >= 0` and `minValue >= minLow` of visible subset. 4. Link invariant [#151](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/151) in test names. --- ## Acceptance criteria - [ ] `test:charts` includes large-candle case (≥500 rows) within configured timeout. - [ ] Autoscale test uses **real** `getVisibleLogicalRange()` + fixture candle lows. - [ ] Document max row count / timeout in `docs/testing.md`. - [ ] `npm run test:run` unchanged. - [ ] CI `frontend` job still passes (or separate job if split — see bundled CI issue). --- ## Test plan — functional paths | # | Path | Expected | |---|------|----------| | 1 | 500 candles init | Completes &lt; timeout; canvas &gt; 0 | | 2 | 1500 candles init | Same or documented skip in CI | | 3 | `setData` refresh 500→600 | No second chart | | 4 | Autoscale all visible | min ≥ 0 | | 5 | Autoscale zoomed window | min ≥ visible min low | | 6 | Single candle autoscale | min ≥ 0 | | 7 | teardown | `remove()`; no canvases | --- ## Test plan — attack vectors | Vector | Approach | Expected | |--------|----------|----------| | 50k candles | Optional local-only / skipped | Documented; CI does not hang | | Empty logical range | `getVisibleLogicalRange()` null | Provider uses full-series fallback per `priceChartPriceScale` | | All lows &gt; 0, original negative | Clamp still ≥ 0 | [#151](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/151) | --- ## Verification criteria 1. `npm run test:charts` green locally and in CI. 2. `make test-frontend-charts` green. 3. `docs/frontend.md` invariant table references new tests. --- ## Related issues - [#211](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/211), [#151](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/151), [#113](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/113)
PlasticDigits commented 2026-05-29 05:41:44 +00:00 (Migrated from gitlab.com)

marked as related to #211

marked as related to #211
PlasticDigits commented 2026-05-29 05:41:45 +00:00 (Migrated from gitlab.com)

marked as related to #151

marked as related to #151
PlasticDigits commented 2026-05-29 05:41:45 +00:00 (Migrated from gitlab.com)

marked as related to #113

marked as related to #113
PlasticDigits commented 2026-05-29 05:41:52 +00:00 (Migrated from gitlab.com)

mentioned in issue #230

mentioned in issue #230
PlasticDigits commented 2026-05-29 08:24:16 +00:00 (Migrated from gitlab.com)

mentioned in commit 13e8c0392f

mentioned in commit 13e8c0392f28270ef3b8563e7b6380b1c0668691
PlasticDigits commented 2026-05-29 08:24:16 +00:00 (Migrated from gitlab.com)

mentioned in commit 0413c55d02

mentioned in commit 0413c55d02e78b31a1c2ad01547e5c8dee01ed4e
PlasticDigits commented 2026-05-29 08:24:26 +00:00 (Migrated from gitlab.com)

Implementation complete (merged to main)

@brouie — please verify when you have a moment. Leaving this issue open until QA sign-off.

Summary

Extended the real-library Vitest suite (#211) per #229:

  • Large-candle guards: 500 and 1500 candle init tests; optional 2000-candle CI soak (it.runIf(process.env.CI)).
  • Real visible-range USD autoscale (#151): After setVisibleLogicalRange, autoscale uses the chart’s actual getVisibleLogicalRange() (not only a synthetic original() callback).
  • Harness: frontend-dapp/src/test/chartRealLibraryHarness.ts — shared mount + production-mirror autoscale wiring.
  • Docs: docs/testing.md (CI ceiling), docs/frontend.md (invariant table), skills/AGENTS_FRONTEND_PRICE_CHART.md.

Merge commit on main: 13e8c03.

Verification checklist

  • cd frontend-dapp && npm run test:charts — 21 passed, 1 skipped locally (2000 soak skipped without CI)
  • CI=1 npm run test:charts — 22 passed including 2000-candle soak
  • make test-frontend-charts from repo root
  • npm run test:run — unchanged (pure scale math still in priceChartPriceScale.test.ts only)
  • Skim docs/testing.md § Real lightweight-charts — large-candle ceiling documented
  • Skim skills/AGENTS_FRONTEND_PRICE_CHART.md — #229 cross-links present

Commands

make test-frontend-charts
CI=1 bash scripts/with-node.sh --cwd frontend-dapp -- npm run test:charts
## Implementation complete (merged to `main`) @brouie — please verify when you have a moment. Leaving this issue **open** until QA sign-off. ### Summary Extended the real-library Vitest suite ([#211](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/211)) per #229: - **Large-candle guards:** 500 and 1500 candle init tests; optional **2000**-candle CI soak (`it.runIf(process.env.CI)`). - **Real visible-range USD autoscale ([#151](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/151)):** After `setVisibleLogicalRange`, autoscale uses the chart’s actual `getVisibleLogicalRange()` (not only a synthetic `original()` callback). - **Harness:** `frontend-dapp/src/test/chartRealLibraryHarness.ts` — shared mount + production-mirror autoscale wiring. - **Docs:** `docs/testing.md` (CI ceiling), `docs/frontend.md` (invariant table), `skills/AGENTS_FRONTEND_PRICE_CHART.md`. Merge commit on `main`: `13e8c03`. ### Verification checklist - [ ] `cd frontend-dapp && npm run test:charts` — 21 passed, 1 skipped locally (2000 soak skipped without `CI`) - [ ] `CI=1 npm run test:charts` — 22 passed including 2000-candle soak - [ ] `make test-frontend-charts` from repo root - [ ] `npm run test:run` — unchanged (pure scale math still in `priceChartPriceScale.test.ts` only) - [ ] Skim `docs/testing.md` § Real lightweight-charts — large-candle ceiling documented - [ ] Skim `skills/AGENTS_FRONTEND_PRICE_CHART.md` — #229 cross-links present ### Commands ```bash make test-frontend-charts CI=1 bash scripts/with-node.sh --cwd frontend-dapp -- npm run test:charts ```
PlasticDigits commented 2026-05-29 08:26:23 +00:00 (Migrated from gitlab.com)

mentioned in commit 09550bc777

mentioned in commit 09550bc7777aa84fe90c7da0182bd076e5278198
PlasticDigits commented 2026-05-29 08:26:35 +00:00 (Migrated from gitlab.com)

mentioned in issue #227

mentioned in issue #227
PlasticDigits commented 2026-05-29 12:15:55 +00:00 (Migrated from gitlab.com)

mentioned in issue #211

mentioned in issue #211
PlasticDigits commented 2026-05-30 06:38:40 +00:00 (Migrated from gitlab.com)

QA verification complete (@agent verify/issue-229)

Verified on main @ 54a6346 using git worktree verify/issue-229. No code changes required — implementation meets all acceptance criteria from the issue body and the post-merge checklist.

Commands run

Check Result
make test-frontend-charts ✅ 21 passed, 1 skipped (2000 soak skipped without CI)
CI=1 npm run test:charts ✅ 22 passed (includes 2000-candle CI soak)
npm run test:run ✅ 710 passed — charts suite isolated from default run

Acceptance criteria (issue body)

  • test:charts includes large-candle case (≥500 rows) within configured timeout — 500 + 1500 tests in priceChartLightweightRealLibrary.charts.test.ts
  • Autoscale uses real getVisibleLogicalRange() after setVisibleLogicalRange — zoom test asserts minValue >= expectedMinLow from fixture lows
  • Max row count / timeout documented in docs/testing.md § Real lightweight-charts — 500/1500 always, 2000 CI-only, 15s default / 25–30s per large tests
  • npm run test:run unchanged (pure scale math remains in priceChartPriceScale.test.ts)
  • docs/frontend.md invariant table references #229 tests + chartRealLibraryHarness.ts

Functional test plan (issue table)

# Path Status
1 500 candles init ✅
2 1500 candles init ✅
3 setData refresh 500→600 ✅
4 Autoscale all visible ✅ min ≥ 0
5 Autoscale zoomed window ✅ min ≥ visible min low (#151)
6 Single candle autoscale ✅
7 teardown / remove() ✅

Attack vectors

Vector Status
50k candles ✅ Not in CI; documented ceiling in docs/testing.md
Empty logical range ✅ uses full-series min low when visible logical range is null
original() negative floor ✅ Clamp still ≥ 0 with synthetic negative original()
  • docs/testing.md — #229 row in P2 table + large-candle ceiling paragraph
  • docs/frontend.md — price chart invariant table cites #229, 500/1500/2000 guards
  • skills/AGENTS_FRONTEND_PRICE_CHART.md — harness + test file mapping for #229

Closing as all verification criteria pass.

## QA verification complete (@agent verify/issue-229) Verified on `main` @ `54a6346` using git worktree `verify/issue-229`. No code changes required — implementation meets all acceptance criteria from the issue body and the post-merge checklist. ### Commands run | Check | Result | |-------|--------| | `make test-frontend-charts` | ✅ 21 passed, 1 skipped (2000 soak skipped without `CI`) | | `CI=1 npm run test:charts` | ✅ 22 passed (includes 2000-candle CI soak) | | `npm run test:run` | ✅ 710 passed — charts suite isolated from default run | ### Acceptance criteria (issue body) - [x] `test:charts` includes large-candle case (≥500 rows) within configured timeout — 500 + 1500 tests in `priceChartLightweightRealLibrary.charts.test.ts` - [x] Autoscale uses **real** `getVisibleLogicalRange()` after `setVisibleLogicalRange` — zoom test asserts `minValue >= expectedMinLow` from fixture lows - [x] Max row count / timeout documented in `docs/testing.md` § Real lightweight-charts — 500/1500 always, 2000 CI-only, 15s default / 25–30s per large tests - [x] `npm run test:run` unchanged (pure scale math remains in `priceChartPriceScale.test.ts`) - [x] `docs/frontend.md` invariant table references #229 tests + `chartRealLibraryHarness.ts` ### Functional test plan (issue table) | # | Path | Status | |---|------|--------| | 1 | 500 candles init | ✅ | | 2 | 1500 candles init | ✅ | | 3 | `setData` refresh 500→600 | ✅ | | 4 | Autoscale all visible | ✅ min ≥ 0 | | 5 | Autoscale zoomed window | ✅ min ≥ visible min low (#151) | | 6 | Single candle autoscale | ✅ | | 7 | teardown / `remove()` | ✅ | ### Attack vectors | Vector | Status | |--------|--------| | 50k candles | ✅ Not in CI; documented ceiling in `docs/testing.md` | | Empty logical range | ✅ `uses full-series min low when visible logical range is null` | | original() negative floor | ✅ Clamp still ≥ 0 with synthetic negative `original()` | ### Docs / agent cross-links - `docs/testing.md` — #229 row in P2 table + large-candle ceiling paragraph - `docs/frontend.md` — price chart invariant table cites #229, 500/1500/2000 guards - `skills/AGENTS_FRONTEND_PRICE_CHART.md` — harness + test file mapping for #229 Closing as all verification criteria pass.
PlasticDigits (Migrated from gitlab.com) closed this issue 2026-05-30 06:38:43 +00:00
PlasticDigits commented 2026-06-07 12:14:15 +00:00 (Migrated from gitlab.com)

mentioned in issue #337

mentioned in issue #337
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
code/cl8y-dex-terraclassic#229
No description provided.