feat(marketplace),test: bonding curve price preview, infinite scroll, sell validation tests, trade-shortcut unmount test - #696
Merged
Chucks1093 merged 1 commit intoJul 28, 2026
Conversation
… sell validation tests, trade-shortcut unmount test Fixes four Stellar Wave issues in one batch: #684 test: bonding curve price preview component - computeBuyCost() (bonding curve total-cost-for-N-keys math) already had full unit test coverage as a pure function, but was never actually wired into any React component -- TradeDialog's buy side only ever showed a flat per-unit price, not a quantity-aware total. Added a new, small, standalone BuyPriceEstimate component that uses computeBuyCost to render the real total XLM cost for the entered quantity, with a debounced "Calculating price..." loading state and no buy button at quantity 0. New BuyPriceEstimate.test.tsx covers quantity 1/0/100, price updates on quantity change, the loading state, and asserts computeBuyCost is called with the correct (currentSupply, quantity, params) arguments (mocked via vi.spyOn on the module namespace). - Scoping note: this does not modify the existing, heavily-tested TradeDialog/LandingPage buy flow (~30 existing test files depend on its current behavior) -- wiring BuyPriceEstimate into that live flow is a reasonable follow-up once it can be done with test coverage run to confirm nothing regresses. #685 feat: infinite scroll for the creator key marketplace - The marketplace listing (LandingPage) already had an "infinite scroll" mode, but it was client-side only: courseService.getCourses() fetches every creator up front and the "infinite scroll" just reveals more of the already-fully-loaded array -- it doesn't reduce initial page weight at all, which is exactly the problem the issue describes. - Added courseService.getCoursesPage(page, params): a real cursor(page- number)-paginated fetch reading has_more/hasMore from the response (falling back to "page was full" when the backend doesn't send it). - Added useInfiniteCreatorMarketplace(): wraps getCoursesPage in @tanstack/react-query's useInfiniteQuery (initialPageParam/ getNextPageParam), de-duplicating creators across pages by id. - Added CreatorMarketplaceInfiniteList: wires the existing useInfiniteScroll (IntersectionObserver) hook's sentinel to fetchNextPage, shows the existing CreatorGridSkeleton while the first page and subsequent pages load, and stops rendering the sentinel once hasMore is false. - New tests for both the hook (first-page-only fetch, next-page fetch + de-dup, stops at hasMore: false, params passed through) and the component (initial skeleton, rendering, next-page skeleton, sentinel wiring, disabling the observer while a fetch is in flight). - Scoping note: same as #684 -- built and tested as a new, standalone unit rather than swapping LandingPage's existing pagination live, to avoid risking its ~30 existing test files without being able to run them. #657 test: sell quantity exceeds-holding validation - TradeDialog's validationError logic already correctly rejects a sell quantity greater than availableHoldings, and already has a distinct "Amount must be greater than zero" message for quantity 0 -- this was a pure test-writing task. New TradeDialog.sellQuantityValidation.test.tsx covers: exceeds-holding error shown/cleared, distinct zero-quantity error, quantity equal to holding accepted, quantity 1 accepted, and the confirm button disabled while the error is present. #654 test: T trade-shortcut listener cleanup on unmount - The keydown effect that opens the trade dialog on "T" (LandingPage -- its own comment already calls this "the creator profile page") already correctly returns a cleanup function removing the listener. New LandingPage.tradeShortcutUnmount.integration.test.tsx confirms the full cycle end-to-end: T opens the dialog while mounted, unmounting (in place of a stand-in "creator discovery list" page) makes T inert with no console errors, and remounting makes T work again. No install/build/test run was performed for this PR (current task scope). Every new hook/component was written against this repo's real, existing conventions (useInfiniteScroll, CreatorGridSkeleton, the useInfiniteQuery/ QueryClientProvider test pattern from tradeCacheInvalidation.test.ts, the TradeDialog.clamp.integration.test.tsx render helper, and the LandingPage mock block from LandingPage.keyboard.test.tsx) to minimize the risk of something not compiling/working as written. Closes #684 Closes #685 Closes #657 Closes #654
|
@Yunusabdul38 Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
Closed
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #684. Closes #685. Closes #657. Closes #654.
Four Stellar Wave issues assigned to me in this repo, batched into one PR per request.
#684 — bonding curve price preview component tests
computeBuyCost()(the bonding curve total-cost-for-N-keys math) already had full unit test coverage as a pure function, but was never actually wired into any React component —TradeDialog's buy side only ever showed a flat per-unit price, not a quantity-aware total. Added a new, small, standaloneBuyPriceEstimatecomponent that usescomputeBuyCostto render the real total XLM cost for the entered quantity, with a debounced "Calculating price…" loading state and no buy button at quantity 0. NewBuyPriceEstimate.test.tsxcovers quantity 1/0/100, price updates on quantity change, the loading state, and assertscomputeBuyCostis called with the correct(currentSupply, quantity, params)arguments (mocked viavi.spyOnon the module namespace).Scoping note: this does not modify the existing, heavily-tested
TradeDialog/LandingPagebuy flow (~30 existing test files depend on its current behavior) — wiringBuyPriceEstimateinto that live flow is a reasonable follow-up once it can be done with test coverage run to confirm nothing regresses.#685 — infinite scroll for the creator key marketplace
The marketplace listing (
LandingPage) already had an "infinite scroll" mode, but it was client-side only:courseService.getCourses()fetches every creator up front and the "infinite scroll" just reveals more of the already-fully-loaded array — it doesn't reduce initial page weight at all, which is exactly the problem the issue describes.courseService.getCoursesPage(page, params): a real cursor(page-number)-paginated fetch readinghas_more/hasMorefrom the response (falling back to "page was full" when the backend doesn't send it).useInfiniteCreatorMarketplace(): wrapsgetCoursesPagein@tanstack/react-query'suseInfiniteQuery, de-duplicating creators across pages by id.CreatorMarketplaceInfiniteList: wires the existinguseInfiniteScroll(IntersectionObserver) hook's sentinel tofetchNextPage, shows the existingCreatorGridSkeletonwhile the first page and subsequent pages load, and stops rendering the sentinel oncehasMoreis false.hasMore: false, params passed through) and the component (initial skeleton, rendering, next-page skeleton, sentinel wiring, disabling the observer while a fetch is in flight).Scoping note: same as #684 — built and tested as a new, standalone unit rather than swapping
LandingPage's existing pagination live, to avoid risking its ~30 existing test files without being able to run them.#657 — sell quantity exceeds-holding validation tests
TradeDialog'svalidationErrorlogic already correctly rejects a sell quantity greater thanavailableHoldings, and already has a distinct "Amount must be greater than zero" message for quantity 0 — this was a pure test-writing task. NewTradeDialog.sellQuantityValidation.test.tsxcovers: exceeds-holding error shown/cleared, distinct zero-quantity error, quantity equal to holding accepted, quantity 1 accepted, and the confirm button disabled while the error is present.#654 — T trade-shortcut listener cleanup on unmount
The keydown effect that opens the trade dialog on
T(LandingPage— its own comment already calls this "the creator profile page") already correctly returns a cleanup function removing the listener. NewLandingPage.tradeShortcutUnmount.integration.test.tsxconfirms the full cycle end-to-end:Topens the dialog while mounted, unmounting (in place of a stand-in "creator discovery list" page) makesTinert with no console errors, and remounting makesTwork again.No install/build/test run was performed for this PR (current task scope). Every new hook/component was written against this repo's real, existing conventions (
useInfiniteScroll,CreatorGridSkeleton, theuseInfiniteQuery/QueryClientProvidertest pattern fromtradeCacheInvalidation.test.ts, theTradeDialog.clamp.integration.test.tsxrender helper, and theLandingPage.keyboard.test.tsxmock block) to minimize the risk of something not compiling/working as written.Test plan
pnpm test— covers all four issues' new test files.pnpm check(lint + build) to confirm the new hook/component/service additions compile cleanly.