Frontend: lightweight-charts jsdom mock contract tests (stub enrichment + canvas options) #227

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

Summary

Reduce lightweight-charts stub drift (#105) by enriching the global jsdom mock and adding a contract test for PriceChartLightweightCanvas that asserts exact options passed to createChart / addSeries / applyOptions without running the real canvas library.

Bundled scope: enrich lightweightChartsJsdomMock.ts · PriceChartLightweightCanvas stub contract tests


Current codebase

Area Files
Global stub frontend-dapp/src/test/lightweightChartsJsdomMock.ts — createChart, addSeries, removeSeries, panes, timeScale().fitContent, minimal priceScale
Spy API lwChartTestDouble.seriesSpies, reset()
Vitest registration vitest.config.ts, vitest.config.integration.ts
Real library suite vitest.config.charts.ts — does not load stub (#211)
Canvas component PriceChartLightweightCanvas.tsx — rich createChart options (panes, crosshair, autoscaleInfoProvider)
Existing tests PriceChart.test.tsx uses spy counts; no assertion on option objects

Stub does not record: applyOptions, autoscaleInfoProvider, pane indices on addSeries, removePane arguments, or ResizeObserver lifecycle.


Why this is needed

  1. New production APIs (e.g. subscribeVisibleLogicalRangeChange) can ship while the mock stays minimal — green CI, broken browser.
  2. #211 chose real-library tests for init/setData; fast PR feedback still needs stub fidelity for layout/options regressions.
  3. Option B from #211 — incremental, complements test:charts.

Constraints and guardrails

  1. Do not remove real-library test:charts suite — stub complements, not replaces.
  2. Keep npm run test:run fast — contract tests use mock only.
  3. Extend mock additively — existing PriceChart.test.tsx spy expectations must keep passing.
  4. Naming: lightweight-charts, not TradingView widget.
  5. Export test helpers from mock module only when needed (getLastApplyOptions, etc.).

Relevant files

  • frontend-dapp/src/test/lightweightChartsJsdomMock.ts
  • frontend-dapp/src/components/charts/PriceChartLightweightCanvas.tsx
  • frontend-dapp/src/components/charts/__tests__/PriceChartLightweightCanvas.test.tsx (new)
  • frontend-dapp/src/components/charts/__tests__/PriceChart.test.tsx
  • frontend-dapp/vitest.config.ts
  • docs/testing.md, skills/AGENTS_FRONTEND_PRICE_CHART.md, skills/AGENTS_TESTING_P2_EPIC.md

  1. Enrich mock: Spy arrays for applyOptions calls; capture autoscaleInfoProvider on candlestick series; record addSeries(..., paneIndex); implement removePane with index tracking matching production.
  2. Contract test file: PriceChartLightweightCanvas.test.tsx — render with fixture props; assert createChart called with expected layout.panes.enableResize: false, dimensions, crosshair mode; assert volume pane index 1; assert autoscale provider wraps clampUsdPriceChartAutoscale behavior via invoking captured provider.
  3. Document stub catalog in skills/AGENTS_TESTING_P2_EPIC.md.

Acceptance criteria

  • Mock records applyOptions, autoscaleInfoProvider, pane indices, removePane(2) for RSI off.
  • PriceChartLightweightCanvas.test.tsx fails if enableResize or pane layout options regress.
  • lwChartTestDouble.reset() clears new spies between tests.
  • npm run test:run green; no change required to test:charts unless shared fixtures extracted.
  • docs/testing.md stub section updated.

Test plan — functional paths

# Path Expected
1 Mount canvas One createChart; candle + volume series
2 applyOptions on layout Width/height from container
3 Autoscale provider Invoked; clamp prevents min < 0
4 Toggle MA7 addSeries line on pane 0; removeSeries on off
5 Toggle RSI addPane; removePane(2) on off
6 setData on prop change seriesSpies updated; no second createChart
7 Reset between tests No spy leakage

Test plan — attack vectors

Vector Approach Expected
Mock incomplete API Production adds new series API Contract test or TypeScript forces mock update
Provider throws Mock original() throws Chart init still handled
Double mount StrictMode double effect Document expected call counts

Verification criteria

  1. npm run test:run — new contract tests + existing PriceChart.test.tsx pass.
  2. Deliberately break enableResize: false — contract test fails.
  3. Cross-link from #211 and stub epic #105.

## Summary Reduce **lightweight-charts** stub drift ([#105](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/105)) by enriching the global jsdom mock and adding a **contract test** for `PriceChartLightweightCanvas` that asserts exact options passed to `createChart` / `addSeries` / `applyOptions` without running the real canvas library. **Bundled scope:** enrich `lightweightChartsJsdomMock.ts` · `PriceChartLightweightCanvas` stub contract tests --- ## Current codebase | Area | Files | |------|--------| | Global stub | `frontend-dapp/src/test/lightweightChartsJsdomMock.ts` — `createChart`, `addSeries`, `removeSeries`, panes, `timeScale().fitContent`, minimal `priceScale` | | Spy API | `lwChartTestDouble.seriesSpies`, `reset()` | | Vitest registration | `vitest.config.ts`, `vitest.config.integration.ts` | | Real library suite | `vitest.config.charts.ts` — **does not** load stub ([#211](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/211)) | | Canvas component | `PriceChartLightweightCanvas.tsx` — rich `createChart` options (panes, crosshair, autoscaleInfoProvider) | | Existing tests | `PriceChart.test.tsx` uses spy counts; no assertion on **option objects** | Stub does **not** record: `applyOptions`, `autoscaleInfoProvider`, pane indices on `addSeries`, `removePane` arguments, or `ResizeObserver` lifecycle. --- ## Why this is needed 1. New production APIs (e.g. `subscribeVisibleLogicalRangeChange`) can ship while the mock stays minimal — **green CI, broken browser**. 2. **#211** chose real-library tests for init/setData; fast PR feedback still needs stub fidelity for layout/options regressions. 3. Option B from [#211](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/211) — incremental, complements `test:charts`. --- ## Constraints and guardrails 1. **Do not remove** real-library `test:charts` suite — stub complements, not replaces. 2. **Keep `npm run test:run` fast** — contract tests use mock only. 3. **Extend mock additively** — existing `PriceChart.test.tsx` spy expectations must keep passing. 4. **Naming:** lightweight-charts, not TradingView widget. 5. Export test helpers from mock module only when needed (`getLastApplyOptions`, etc.). --- ## Relevant files - `frontend-dapp/src/test/lightweightChartsJsdomMock.ts` - `frontend-dapp/src/components/charts/PriceChartLightweightCanvas.tsx` - `frontend-dapp/src/components/charts/__tests__/PriceChartLightweightCanvas.test.tsx` (new) - `frontend-dapp/src/components/charts/__tests__/PriceChart.test.tsx` - `frontend-dapp/vitest.config.ts` - `docs/testing.md`, `skills/AGENTS_FRONTEND_PRICE_CHART.md`, `skills/AGENTS_TESTING_P2_EPIC.md` --- ## Recommended direction 1. **Enrich mock:** Spy arrays for `applyOptions` calls; capture `autoscaleInfoProvider` on candlestick series; record `addSeries(..., paneIndex)`; implement `removePane` with index tracking matching production. 2. **Contract test file:** `PriceChartLightweightCanvas.test.tsx` — render with fixture props; assert `createChart` called with expected `layout.panes.enableResize: false`, dimensions, crosshair mode; assert volume pane index `1`; assert autoscale provider wraps `clampUsdPriceChartAutoscale` behavior via invoking captured provider. 3. **Document** stub catalog in `skills/AGENTS_TESTING_P2_EPIC.md`. --- ## Acceptance criteria - [ ] Mock records `applyOptions`, `autoscaleInfoProvider`, pane indices, `removePane(2)` for RSI off. - [ ] `PriceChartLightweightCanvas.test.tsx` fails if `enableResize` or pane layout options regress. - [ ] `lwChartTestDouble.reset()` clears new spies between tests. - [ ] `npm run test:run` green; no change required to `test:charts` unless shared fixtures extracted. - [ ] `docs/testing.md` stub section updated. --- ## Test plan — functional paths | # | Path | Expected | |---|------|----------| | 1 | Mount canvas | One `createChart`; candle + volume series | | 2 | `applyOptions` on layout | Width/height from container | | 3 | Autoscale provider | Invoked; clamp prevents min < 0 | | 4 | Toggle MA7 | `addSeries` line on pane 0; `removeSeries` on off | | 5 | Toggle RSI | `addPane`; `removePane(2)` on off | | 6 | `setData` on prop change | `seriesSpies` updated; no second `createChart` | | 7 | Reset between tests | No spy leakage | --- ## Test plan — attack vectors | Vector | Approach | Expected | |--------|----------|----------| | Mock incomplete API | Production adds new series API | Contract test or TypeScript forces mock update | | Provider throws | Mock `original()` throws | Chart init still handled | | Double mount | StrictMode double effect | Document expected call counts | --- ## Verification criteria 1. `npm run test:run` — new contract tests + existing `PriceChart.test.tsx` pass. 2. Deliberately break `enableResize: false` — contract test fails. 3. Cross-link from [#211](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/211) and stub epic [#105](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/105). --- ## Related issues - [#211](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/211), [#105](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/105), [#151](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/151), [#150](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/150)
PlasticDigits commented 2026-05-29 05:41:06 +00:00 (Migrated from gitlab.com)

marked as related to #211

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

marked as related to #105

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

marked as related to #151

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

marked as related to #150

marked as related to #150
PlasticDigits commented 2026-05-29 08:26:23 +00:00 (Migrated from gitlab.com)

mentioned in commit 8e9f32365e

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

Implementation summary (merged to main)

Reduced lightweight-charts jsdom stub drift (#105) by enriching the global mock and adding fast contract tests for PriceChartLightweightCanvas (#227). Complements real-library npm run test:charts (#211, #229) — does not replace it.

Code changes

  • frontend-dapp/src/test/lightweightChartsJsdomMock.ts: records createChart options, applyOptions calls, addSeries (pane index + autoscaleInfoProvider), timeScale().getVisibleLogicalRange; exports getLastCreateChartOptions(), getLastApplyOptions(), getCandlestickAutoscaleProvider(), addSeriesCalls; reset() clears new spies.
  • PriceChartLightweightCanvas.test.tsx: new describe createChart contract — enableResize: false, crosshair mode, pane 0/1 series, autoscale clamp, MA7/RSI toggles, setData without second createChart, spy reset.

Docs / agent playbooks


Verification checklist

  • cd frontend-dapp && npm run test:run -- PriceChartLightweightCanvas.test.tsx — 17 tests green (8 lifecycle #225 + 9 contract #227)
  • npm run test:run -- PriceChart.test.tsx — existing spy expectations still pass
  • Deliberately set layout.panes.enableResize: true in PriceChartLightweightCanvas.tsx → contract test mount passes layout… fails
  • npm run test:charts unchanged requirement (still green in CI)
  • Docs cross-links: #211, #225, #227, #105 readable from testing.md stub section

@brouie — please verify the checklist above on latest main when you have a moment. Leaving this issue open until sign-off.

## Implementation summary (merged to `main`) Reduced **lightweight-charts** jsdom stub drift ([#105](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/105)) by enriching the global mock and adding fast **contract** tests for `PriceChartLightweightCanvas` ([#227](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/227)). Complements real-library `npm run test:charts` ([#211](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/211), [#229](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/229)) — does not replace it. ### Code changes - **`frontend-dapp/src/test/lightweightChartsJsdomMock.ts`**: records `createChart` options, `applyOptions` calls, `addSeries` (pane index + `autoscaleInfoProvider`), `timeScale().getVisibleLogicalRange`; exports `getLastCreateChartOptions()`, `getLastApplyOptions()`, `getCandlestickAutoscaleProvider()`, `addSeriesCalls`; `reset()` clears new spies. - **`PriceChartLightweightCanvas.test.tsx`**: new describe *createChart contract* — `enableResize: false`, crosshair mode, pane 0/1 series, autoscale clamp, MA7/RSI toggles, `setData` without second `createChart`, spy reset. ### Docs / agent playbooks - [`docs/testing.md`](docs/testing.md), [`docs/frontend.md`](docs/frontend.md) (price chart invariants) - [`skills/AGENTS_FRONTEND_PRICE_CHART.md`](skills/AGENTS_FRONTEND_PRICE_CHART.md), [`skills/AGENTS_TESTING_P2_EPIC.md`](skills/AGENTS_TESTING_P2_EPIC.md) --- ### Verification checklist - [ ] `cd frontend-dapp && npm run test:run -- PriceChartLightweightCanvas.test.tsx` — 17 tests green (8 lifecycle #225 + 9 contract #227) - [ ] `npm run test:run -- PriceChart.test.tsx` — existing spy expectations still pass - [ ] Deliberately set `layout.panes.enableResize: true` in `PriceChartLightweightCanvas.tsx` → contract test *mount passes layout…* fails - [ ] `npm run test:charts` unchanged requirement (still green in CI) - [ ] Docs cross-links: #211, #225, #227, #105 readable from testing.md stub section --- @brouie — please verify the checklist above on latest `main` when you have a moment. Leaving this issue **open** until sign-off.
PlasticDigits commented 2026-05-30 06:36:16 +00:00 (Migrated from gitlab.com)

Verification complete (agent, verify/issue-227 worktree on 54a6346)

Verified all acceptance criteria and the checklist from the implementation comment on latest main. No code changes required.

What was verified

Acceptance criteria

  • Mock records applyOptions, autoscaleInfoProvider, pane indices, removePane(2) for RSI off — confirmed in lightweightChartsJsdomMock.ts + contract tests
  • PriceChartLightweightCanvas.test.tsx fails on enableResize regression — temporarily set enableResize: true; mount passes layout… failed as expected
  • lwChartTestDouble.reset() clears new spies — dedicated test passes
  • npm run test:run green — 17 canvas tests + 20 PriceChart.test.tsx tests
  • docs/testing.md stub section updated with #227 / #105 / #211 cross-links

Functional test plan (stub contract)

# Path Result
1 Mount canvas — one createChart; candle + volume pass
2 applyOptions width/height from container pass
3 Autoscale provider clamps min ≥ 0 pass
4 Toggle MA7 — addSeries pane 0 / removeSeries off pass
5 Toggle RSI — addPane / removePane(2) off pass
6 Prop change — setData only, no second createChart pass
7 Reset between tests — no spy leakage pass

Additional

  • npm run test:charts — 21 passed, 1 skipped (real library suite unchanged)
  • Agent playbooks cross-linked: skills/AGENTS_FRONTEND_PRICE_CHART.md, skills/AGENTS_TESTING_P2_EPIC.md

Commands run

cd frontend-dapp && npm run test:run -- PriceChartLightweightCanvas.test.tsx   # 17/17
npm run test:run -- PriceChart.test.tsx                                         # 20/20
npm run test:charts                                                             # 21 passed | 1 skipped
# Regression guard: enableResize: true → contract test fails (reverted)

Manual checklist for future regressions

  • After changing PriceChartLightweightCanvas layout/pane options, run npm run test:run -- PriceChartLightweightCanvas.test.tsx
  • After adding new lightweight-charts series APIs, extend lightweightChartsJsdomMock.ts and contract tests
  • Keep real-library coverage in npm run test:charts — do not load jsdom stub in vitest.config.charts.ts

Closing — all issue-body and comment verification criteria pass.

## Verification complete (agent, `verify/issue-227` worktree on `54a6346`) Verified all acceptance criteria and the checklist from the implementation comment on latest `main`. No code changes required. ### What was verified **Acceptance criteria** - [x] Mock records `applyOptions`, `autoscaleInfoProvider`, pane indices, `removePane(2)` for RSI off — confirmed in `lightweightChartsJsdomMock.ts` + contract tests - [x] `PriceChartLightweightCanvas.test.tsx` fails on `enableResize` regression — temporarily set `enableResize: true`; *mount passes layout…* failed as expected - [x] `lwChartTestDouble.reset()` clears new spies — dedicated test passes - [x] `npm run test:run` green — 17 canvas tests + 20 `PriceChart.test.tsx` tests - [x] `docs/testing.md` stub section updated with #227 / #105 / #211 cross-links **Functional test plan (stub contract)** | # | Path | Result | |---|------|--------| | 1 | Mount canvas — one `createChart`; candle + volume | pass | | 2 | `applyOptions` width/height from container | pass | | 3 | Autoscale provider clamps min ≥ 0 | pass | | 4 | Toggle MA7 — `addSeries` pane 0 / `removeSeries` off | pass | | 5 | Toggle RSI — `addPane` / `removePane(2)` off | pass | | 6 | Prop change — `setData` only, no second `createChart` | pass | | 7 | Reset between tests — no spy leakage | pass | **Additional** - [x] `npm run test:charts` — 21 passed, 1 skipped (real library suite unchanged) - [x] Agent playbooks cross-linked: `skills/AGENTS_FRONTEND_PRICE_CHART.md`, `skills/AGENTS_TESTING_P2_EPIC.md` ### Commands run ```bash cd frontend-dapp && npm run test:run -- PriceChartLightweightCanvas.test.tsx # 17/17 npm run test:run -- PriceChart.test.tsx # 20/20 npm run test:charts # 21 passed | 1 skipped # Regression guard: enableResize: true → contract test fails (reverted) ``` ### Manual checklist for future regressions - [ ] After changing `PriceChartLightweightCanvas` layout/pane options, run `npm run test:run -- PriceChartLightweightCanvas.test.tsx` - [ ] After adding new lightweight-charts series APIs, extend `lightweightChartsJsdomMock.ts` and contract tests - [ ] Keep real-library coverage in `npm run test:charts` — do not load jsdom stub in `vitest.config.charts.ts` Closing — all issue-body and comment verification criteria pass.
PlasticDigits (Migrated from gitlab.com) closed this issue 2026-05-30 06:36:20 +00:00
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#227
No description provided.