VCST-4776: Add coupon scenarios (E2E, GraphQL, dataset) - #187
Open
Lenajava1 wants to merge 14 commits into
Open
Conversation
Add coupon test coverage for the cart discount/coupons sidebar and the /account/coupons page, plus the supporting GraphQL and UI layers and seeded coupon/promotion/product dataset. - GraphQL: validateCoupon operation, promotionCoupons operation + type, cart discountTotal/taxTotal fields - E2E: cart coupon presets (apply/remove/anonymous), percentage-on-sale, account coupon list, copy-to-clipboard, VCST-5233 case-fidelity guard - Dataset: preset/percentage/fixed/expired/lowercase coupons + SALE-001 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
CI (latest frontend build) confirmed 5 tests fail when the coupon UI/data is absent. Make them skip gracefully or assert robustly instead: - promotionCoupons: poll_until populated; skip on persistent-empty - account coupons E2E (x3): probe-and-skip when /account/coupons markup absent - percentage_ui_on_sale: skip when product not on sale; assert discount>0 and grand-total drop instead of brittle subtotal*pct Real assertions preserved on builds that do surface the coupon UI. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…style Add isPublic, localizedLabel, and endDate to coupon promotion seeds so promotionCoupons and preset E2E tests exercise real data instead of skipping. Use `is True` over `== True` and strip trailing whitespace. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Assert cart money fields are present before dereferencing in _assert_totals_consistent so a missing field fails cleanly instead of raising AttributeError. Drop the brittle grand-total-text delta check in the preset-switch E2E test; applied-card identity already proves the switch. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The copy handler writes via the async Clipboard API, which has not always resolved by the time click() returns, so an immediate readText() intermittently saw an empty clipboard (empty at t=0ms, populated at t=200ms in local runs). Poll the read briefly until the write lands. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace CartCouponSection.card_by_name (brittle promotion-name substring match) with applied_code_input, the applied card's readonly code field. Assert the preset apply/switch via expect(...).to_have_value(code): the code survives both default and applied states (the applied card's button drops it, and value is not a reflected DOM attribute), and to_have_value polls out the non-atomic switch between two applied coupons. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Non-public promotion (unreachable $100k min-subtotal) plus its QAMINSUB100K coupon, for the unmet-condition coupon test. Adds the MIN_SUBTOTAL_COUPON_CODE constant. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- promotionCoupons: first limit + name asc/desc sort (verified live); anonymous access is denied server-side (Unauthorized). - Cart coupon rejected by an unmet min-subtotal condition (recorded but is_applied_successfully False, no discount). - E2E: preset-coupon removal restores the cart; the "View all" link opens /account/coupons in a new tab. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The returns/localized-label/end-date tests each re-ran the identical get_promotion_coupons(first=100) query, then asserted a different field. Merge them into one test with three Allure steps — same assertions, one round-trip instead of three. Pagination/sort and anonymous-denied stay standalone. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ized case
Both an unknown code and a found-but-expired code are rejected identically
at the UI ("This code is not valid"), so collapse the two near-duplicate
tests into one parametrized test over both codes. The semantic difference
is already covered at the API layer by test_validate_coupon_valid_and_invalid.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…skips The cart is a single-page checkout that auto-initializes shipment and payment concurrently with every coupon mutation. Each background write returns the whole cart and can briefly carry a not-yet-re-evaluated coupon snapshot (isAppliedSuccessfully:false, pre-discount total). When such a stale write lands in the SPA after addCoupon/removeCoupon, it clobbers the applied state non-deterministically, and the clobbering write is sometimes the last one in the cascade, so no wait converges. This surfaced as a different coupon test failing on each full-file run while each passed in isolation. Rewrite the apply/switch/remove flows to await the coupon mutation's own GraphQL response and then reload the cart, so assertions read the authoritative, settled cart (promotion re-evaluation done, no concurrent stale write). This is deterministic where a longer timeout was not (verified 8/8 consecutive full-file runs green, zero skipped, zero failed). Assertions are unchanged in strength: a coupon that never applies still fails loudly. Also remove the capability-probe skips that could mask real failures: _require_coupon_ui and the preset-count/view-all guards in test_cart_coupon.py, _require_account_coupons in test_account_coupons.py, and the <2-coupons guard in test_promotion_coupons.py. On a properly seeded store these tests now run and pass outright; missing UI/data fails loudly instead of silently skipping. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The prior fix covered only the coupon-mutation race and still flaked in full-file runs — including test_cart_coupon_presets_render, which applies no coupon. Root cause: the cart is a single-page checkout that, on a fresh cart, auto-initializes shipment then payment (AddOrUpdateCartShipment -> AddOrUpdateCartPayment, landing ~5s after the load event). That cascade keeps re-rendering the coupon section for several seconds, so on faster machines the read-only preset assertions read mid-re-render (transient empty/detached nodes) and the coupon-state assertions read a stale, concurrently-clobbered snapshot. Route every cart open through _open_cart, which waits for network idle so the whole shipment/payment cascade quiesces before any assertion runs (measured: cascade done ~5s, idle ~9s — reads now happen strictly after it, independent of machine speed). Route every coupon mutation through _apply_and_settle, which awaits the mutation's own GraphQL response (so the reopen cannot cancel the in-flight request) then reopens the settled cart; on reopen the coupon is already persisted/re-evaluated and shipment/ payment do not re-fire, so nothing clobbers the applied state. Preset label/name reads are now web-first (expect .to_have_text) so any residual micro-re-render is retried rather than captured. No sleeps, no skips; assertions unchanged in strength. Verified 10/10 consecutive full-file runs, 8 passed / 0 skipped / 0 failed each. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…dead code) - Narrow Optional discount_total/tax_total before .amount access (fixes 8 pyright reportOptionalMemberAccess errors) via a _discount() helper. - Rework promotionCoupons sort assertion to compare the name sort-key sequence instead of coupon-code order, so it stays correct under shared names; guard the asc!=desc check for single-coupon stores. - Drop the Lucide icon-class applied-state assertion (applied state is already proven by applied_cards count + applied_code_input value). - Remove dead code: unused SALE_PRODUCT_LIST/SALE_PRICE constants, AccountCouponsPage.find_card, unused cart subtotal/discount labels. - Import Callable from collections.abc. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.
Add coupon test coverage for the cart discount/coupons sidebar and the /account/coupons page, plus the supporting GraphQL and UI layers and seeded coupon/promotion/product dataset.