|
|
@@ -0,0 +1,99 @@
|
|
|
+/**
|
|
|
+ * 验收逻辑守卫:我的优惠券「已领取券」按钮修复 + 使用按券类型跳转
|
|
|
+ * 对应需求文档:docs/superpowers/specs/2026-11-06-coupon-claimed-actions.md
|
|
|
+ *
|
|
|
+ * 说明(与仓库既有约定一致,见 FamilyRelationGraph.test.js):
|
|
|
+ * cfc-frontend jest 配置 testEnvironment=node,且仅 babel-jest 转换 .js,
|
|
|
+ * 无 vue-jest,故 .vue SFC 方法无法直接挂载测试。仓库惯例是把组件中
|
|
|
+ * 的「纯决策逻辑」抽取为本地函数在此测试。以下函数镜像 coupons.vue
|
|
|
+ * useCoupon()/giftCoupon() 的跳转决策表(spec §4.1 / §验收标准 2-5)。
|
|
|
+ *
|
|
|
+ * 建议(非本闭环范围,禁止改生产源码):将 resolveCouponUseRoute 抽到
|
|
|
+ * utils/couponRoute.js,届时本测试直接 import 真实实现即可升级为真正单测。
|
|
|
+ */
|
|
|
+
|
|
|
+// ---- 镜像 coupons.vue useCoupon(coupon) 的路由决策 ----
|
|
|
+function resolveCouponUseRoute(coupon) {
|
|
|
+ const applicableTo = coupon && coupon.applicableTo
|
|
|
+ if (applicableTo === 'PRODUCT') {
|
|
|
+ // 指定商品券:跳确认订单页,自动选券(用券实例 id 作为 couponId)
|
|
|
+ const productId = coupon.productId
|
|
|
+ if (productId) {
|
|
|
+ return `/pages/shop/checkout/checkout?from=coupon&id=${productId}&couponId=${coupon.id}`
|
|
|
+ }
|
|
|
+ // productId 缺失兜底跳商城,不报错(spec §风险)
|
|
|
+ return '/pages/shop/index/index'
|
|
|
+ }
|
|
|
+ if (applicableTo === 'ALL') {
|
|
|
+ return '/pages/shop/index/index' // 全品类 → 商城
|
|
|
+ }
|
|
|
+ if (applicableTo === 'MEMBERSHIP') {
|
|
|
+ return '/pages/membership/upgrade' // 会员券 → 开通会员
|
|
|
+ }
|
|
|
+ // 兜底(ASSESSMENT/其他/null)→ 商城
|
|
|
+ return '/pages/shop/index/index'
|
|
|
+}
|
|
|
+
|
|
|
+// 转赠统一跳赠送会员券页(spec §4.1.3)
|
|
|
+function resolveCouponGiftRoute() {
|
|
|
+ return '/pages/membership/gift-coupon'
|
|
|
+}
|
|
|
+
|
|
|
+// 已领取券应显示「使用 + 转赠」,不再显示「立即领取」(spec §验收 1/6)
|
|
|
+function canClaim(coupon) {
|
|
|
+ // 已领取券 status 为 AVAILABLE/USED/EXPIRED,均非可领取态
|
|
|
+ const claimable = !coupon || !coupon.status || coupon.status === 'AVAILABLE'
|
|
|
+ // spec 根因:canClaim 对“已领取(有券实例)”应返回 false
|
|
|
+ const isClaimedInstance = !!(coupon && coupon.id && coupon.couponId)
|
|
|
+ return claimable && !isClaimedInstance
|
|
|
+}
|
|
|
+
|
|
|
+describe('resolveCouponUseRoute - 使用按钮按券类型跳转', () => {
|
|
|
+ it('PRODUCT 券带 productId → 跳确认订单并自动选券(实例id)', () => {
|
|
|
+ const route = resolveCouponUseRoute({ applicableTo: 'PRODUCT', productId: 9527, id: 7001, couponId: 2001 })
|
|
|
+ expect(route).toBe('/pages/shop/checkout/checkout?from=coupon&id=9527&couponId=7001')
|
|
|
+ })
|
|
|
+
|
|
|
+ it('PRODUCT 券 couponId 必须用实例id(7001)而非模板id(2001)', () => {
|
|
|
+ const route = resolveCouponUseRoute({ applicableTo: 'PRODUCT', productId: 9527, id: 7001, couponId: 2001 })
|
|
|
+ expect(route).toContain('couponId=7001')
|
|
|
+ expect(route).not.toContain('couponId=2001')
|
|
|
+ })
|
|
|
+
|
|
|
+ it('PRODUCT 券 productId 缺失 → 兜底跳商城(不报错)', () => {
|
|
|
+ const route = resolveCouponUseRoute({ applicableTo: 'PRODUCT', id: 7001 })
|
|
|
+ expect(route).toBe('/pages/shop/index/index')
|
|
|
+ })
|
|
|
+
|
|
|
+ it('ALL 全品类券 → 跳商城', () => {
|
|
|
+ expect(resolveCouponUseRoute({ applicableTo: 'ALL', id: 7001 })).toBe('/pages/shop/index/index')
|
|
|
+ })
|
|
|
+
|
|
|
+ it('MEMBERSHIP 会员券 → 跳开通会员', () => {
|
|
|
+ expect(resolveCouponUseRoute({ applicableTo: 'MEMBERSHIP', id: 7001 })).toBe('/pages/membership/upgrade')
|
|
|
+ })
|
|
|
+
|
|
|
+ it('兜底(ASSESSMENT/null) → 跳商城', () => {
|
|
|
+ expect(resolveCouponUseRoute({ applicableTo: 'ASSESSMENT', id: 7001 })).toBe('/pages/shop/index/index')
|
|
|
+ expect(resolveCouponUseRoute({ id: 7001 })).toBe('/pages/shop/index/index')
|
|
|
+ })
|
|
|
+})
|
|
|
+
|
|
|
+describe('resolveCouponGiftRoute - 转赠按钮跳转', () => {
|
|
|
+ it('转赠 → 跳赠送会员券页', () => {
|
|
|
+ expect(resolveCouponGiftRoute()).toBe('/pages/membership/gift-coupon')
|
|
|
+ })
|
|
|
+})
|
|
|
+
|
|
|
+describe('canClaim - 已领取券不再显示「立即领取」', () => {
|
|
|
+ it('已领取券实例(有 id+couponId) → 不可领取', () => {
|
|
|
+ expect(canClaim({ id: 7001, couponId: 2001, status: 'AVAILABLE' })).toBe(false)
|
|
|
+ })
|
|
|
+ it('已使用/已过期券 → 不可领取', () => {
|
|
|
+ expect(canClaim({ id: 7001, couponId: 2001, status: 'USED' })).toBe(false)
|
|
|
+ expect(canClaim({ id: 7001, couponId: 2001, status: 'EXPIRED' })).toBe(false)
|
|
|
+ })
|
|
|
+ it('无券实例(纯模板) → 可领取', () => {
|
|
|
+ expect(canClaim({ status: 'AVAILABLE' })).toBe(true)
|
|
|
+ })
|
|
|
+})
|