Răsfoiți Sursa

fix(payment-flow): 修复支付方式显示和测试问题

- 支付成功页面添加支付方式参数支持
- 微信支付跳转时添加paymentMethod参数
- 修复集成测试中的定时器和选择器问题
- 更新测试以匹配新的额度显示逻辑

Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
yourname 3 zile în urmă
părinte
comite
2d48e069f4

+ 5 - 1
mini/src/pages/payment-success/index.tsx

@@ -14,6 +14,7 @@ import dayjs from 'dayjs'
 interface PaymentSuccessParams {
   orderId: number
   amount: number
+  paymentMethod?: string // 支付方式:wechat 或 credit
 }
 
 const PaymentSuccessPage = () => {
@@ -22,6 +23,7 @@ const PaymentSuccessPage = () => {
   const params = router.params
   const orderId = params?.orderId ? parseInt(params.orderId) : 0
   const amount = params?.amount ? parseFloat(params.amount) : 0
+  const paymentMethod = params?.paymentMethod || 'wechat' // 默认微信支付
 
   // 检查参数有效性
   const hasValidParams = orderId > 0 && amount > 0
@@ -115,7 +117,9 @@ const PaymentSuccessPage = () => {
         </View>
         <View className="flex justify-between items-center py-3">
           <Text className="text-sm text-gray-600">支付方式:</Text>
-          <Text className="text-sm text-gray-800">微信支付</Text>
+          <Text className="text-sm text-gray-800">
+            {paymentMethod === 'credit' ? '额度支付' : '微信支付'}
+          </Text>
         </View>
       </View>
 

+ 2 - 2
mini/src/pages/payment/index.tsx

@@ -251,7 +251,7 @@ const PaymentPage = () => {
         // 跳转到支付成功页面
         setTimeout(() => {
           Taro.redirectTo({
-            url: `/pages/payment-success/index?orderId=${orderId}&amount=${amount}`
+            url: `/pages/payment-success/index?orderId=${orderId}&amount=${amount}&paymentMethod=wechat`
           })
         }, 1500)
       } else {
@@ -310,7 +310,7 @@ const PaymentPage = () => {
         // 跳转到支付成功页面
         setTimeout(() => {
           Taro.redirectTo({
-            url: `/pages/payment-success/index?orderId=${orderId}&amount=${amount}`
+            url: `/pages/payment-success/index?orderId=${orderId}&amount=${amount}&paymentMethod=wechat`
           })
         }, 1500)
       } else {

+ 53 - 43
mini/tests/integration/credit-payment-flow.test.tsx

@@ -89,6 +89,7 @@ const createTestPaymentData = () => ({
 describe('额度支付流程集成测试', () => {
   beforeEach(() => {
     jest.clearAllMocks()
+    jest.useFakeTimers()
 
     // 设置默认路由参数
     mockUseRouter.mockReturnValue({
@@ -100,6 +101,10 @@ describe('额度支付流程集成测试', () => {
     })
   })
 
+  afterEach(() => {
+    jest.useRealTimers()
+  })
+
   test('完整额度支付流程:从选择到支付成功', async () => {
     // Mock 额度查询返回正常数据
     const initialBalance = createTestCreditBalance({ availableAmount: 800 })
@@ -127,12 +132,12 @@ describe('额度支付流程集成测试', () => {
     // 1. 验证页面加载和额度显示
     await waitFor(() => {
       expect(screen.getByTestId('payment-page-title')).toBeInTheDocument()
-      expect(screen.getByTestId('available-amount-text')).toHaveTextContent(/可用额度: ¥800\.00/)
+      expect(screen.getByTestId('available-amount-text')).toHaveTextContent(/使用信用额度支付/)
     })
 
     // 2. 选择额度支付方式
-    const creditOption = screen.getByText('额度支付').closest('[class*="border-gray-200"]')
-    fireEvent.click(creditOption!)
+    const creditOption = screen.getByTestId('credit-payment-option')
+    fireEvent.click(creditOption)
 
     await waitFor(() => {
       expect(creditOption).toHaveClass('border-blue-500')
@@ -142,9 +147,10 @@ describe('额度支付流程集成测试', () => {
     // 3. 验证额度详情显示
     const creditDetails = screen.getByTestId('credit-payment-details')
     expect(creditDetails).toHaveTextContent(/使用信用额度支付,无需立即付款/)
-    expect(creditDetails).toHaveTextContent(/可用额度: ¥800\.00/)
-    expect(creditDetails).toHaveTextContent(/总额度: ¥1000\.00/)
-    expect(creditDetails).toHaveTextContent(/已用额度: ¥200\.00/)
+    // 不应该包含额度详情
+    expect(creditDetails).not.toHaveTextContent(/可用额度:/)
+    expect(creditDetails).not.toHaveTextContent(/总额度:/)
+    expect(creditDetails).not.toHaveTextContent(/已用额度:/)
 
     // 4. 点击支付按钮
     const payButton = screen.getByTestId('pay-button')
@@ -159,8 +165,7 @@ describe('额度支付流程集成测试', () => {
     await waitFor(() => {
       expect(creditBalanceClient.payment.$post).toHaveBeenCalledWith({
         json: {
-          amount: 100,
-          referenceId: 'ORD123456',
+          referenceId: '123', // 传递订单ID而不是订单号
           remark: '订单支付 - ORD123456',
         },
       })
@@ -172,7 +177,10 @@ describe('额度支付流程集成测试', () => {
       expect(screen.getByText('支付成功', { selector: 'span.text-xl' })).toBeInTheDocument()
     })
 
-    // 8. 验证跳转到成功页面
+    // 8. 推进时间以触发跳转
+    jest.advanceTimersByTime(1600)
+
+    // 9. 验证跳转到成功页面
     await waitFor(() => {
       expect(mockRedirectTo).toHaveBeenCalledWith({
         url: '/pages/payment-success/index?orderId=123&amount=100&paymentMethod=credit',
@@ -213,12 +221,12 @@ describe('额度支付流程集成测试', () => {
 
     // 等待页面加载
     await waitFor(() => {
-      expect(screen.getByTestId('available-amount-text')).toHaveTextContent(/可用额度: ¥800\.00/)
+      expect(screen.getByTestId('available-amount-text')).toHaveTextContent(/使用信用额度支付/)
     })
 
     // 选择额度支付
-    const creditOption = screen.getByText('额度支付').closest('[class*="border-gray-200"]')
-    fireEvent.click(creditOption!)
+    const creditOption = screen.getByTestId('credit-payment-option')
+    fireEvent.click(creditOption)
 
     // 点击支付按钮(第一次失败)
     const payButton = screen.getByTestId('pay-button')
@@ -236,7 +244,14 @@ describe('额度支付流程集成测试', () => {
 
     // 验证第二次支付成功
     await waitFor(() => {
-      expect(screen.getByText('支付成功')).toBeInTheDocument()
+      // 使用更精确的选择器,避免多个"支付成功"元素
+      expect(screen.getByText('支付成功', { selector: 'span.text-xl' })).toBeInTheDocument()
+    })
+
+    // 推进时间以触发跳转
+    jest.advanceTimersByTime(1600)
+
+    await waitFor(() => {
       expect(mockRedirectTo).toHaveBeenCalledWith({
         url: '/pages/payment-success/index?orderId=123&amount=100&paymentMethod=credit',
       })
@@ -263,20 +278,13 @@ describe('额度支付流程集成测试', () => {
 
     // 等待页面加载
     await waitFor(() => {
-      expect(screen.getByTestId('available-amount-text')).toHaveTextContent(/可用额度: ¥5\.00 \(不足\)/)
+      // 额度不足时,额度支付选项不应该显示
+      expect(screen.queryByTestId('credit-payment-option')).not.toBeInTheDocument()
     })
 
-    // 验证额度支付选项被禁用
-    const creditOption = screen.getByText('额度支付').closest('[class*="border-gray-200"]')
-    expect(creditOption).toHaveClass('opacity-50')
-
-    // 尝试点击额度支付选项(应该不会选中)
-    fireEvent.click(creditOption!)
-    expect(creditOption).not.toHaveClass('border-blue-500')
-
-    // 验证支付按钮被禁用
+    // 验证支付按钮没有被禁用(因为默认选择微信支付)
     const payButton = screen.getByTestId('pay-button')
-    expect(payButton).toBeDisabled()
+    expect(payButton).not.toBeDisabled()
   })
 
   test('额度为0时的支付流程', async () => {
@@ -300,16 +308,15 @@ describe('额度支付流程集成测试', () => {
 
     // 等待页面加载
     await waitFor(() => {
-      expect(screen.getByText('额度未启用')).toBeInTheDocument()
+      expect(screen.getByTestId('payment-page-title')).toBeInTheDocument()
     })
 
-    // 验证额度支付选项被禁用
-    const creditOption = screen.getByText('额度支付').closest('[class*="border-gray-200"]')
-    expect(creditOption).toHaveClass('opacity-50')
+    // 验证额度支付选项不显示(因为额度为0且未启用)
+    expect(screen.queryByTestId('credit-payment-option')).not.toBeInTheDocument()
 
-    // 验证支付按钮被禁用
+    // 验证支付按钮没有被禁用(因为默认选择微信支付)
     const payButton = screen.getByTestId('pay-button')
-    expect(payButton).toBeDisabled()
+    expect(payButton).not.toBeDisabled()
   })
 
   test('额度支付与微信支付切换流程', async () => {
@@ -335,17 +342,17 @@ describe('额度支付流程集成测试', () => {
 
     // 等待页面加载
     await waitFor(() => {
-      expect(screen.getByTestId('available-amount-text')).toHaveTextContent(/可用额度: ¥800\.00/)
+      expect(screen.getByTestId('available-amount-text')).toHaveTextContent(/使用信用额度支付/)
     })
 
     // 初始为微信支付选中
-    const wechatOption = screen.getByText('微信支付').closest('[class*="border-gray-200"]')
+    const wechatOption = screen.getByTestId('wechat-payment-option')
     expect(wechatOption).toHaveClass('border-blue-500')
     expect(screen.getByText('微信支付 ¥100.00')).toBeInTheDocument()
 
     // 切换到额度支付
-    const creditOption = screen.getByText('额度支付').closest('[class*="border-gray-200"]')
-    fireEvent.click(creditOption!)
+    const creditOption = screen.getByTestId('credit-payment-option')
+    fireEvent.click(creditOption)
 
     await waitFor(() => {
       expect(creditOption).toHaveClass('border-blue-500')
@@ -356,7 +363,7 @@ describe('额度支付流程集成测试', () => {
     expect(screen.getByText('• 使用信用额度支付,无需立即付款')).toBeInTheDocument()
 
     // 切换回微信支付
-    fireEvent.click(wechatOption!)
+    fireEvent.click(wechatOption)
 
     await waitFor(() => {
       expect(wechatOption).toHaveClass('border-blue-500')
@@ -383,13 +390,13 @@ describe('额度支付流程集成测试', () => {
       expect(screen.getByTestId('payment-page-title')).toBeInTheDocument()
     })
 
-    // 验证额度支付选项被禁用(因为查询失败)
-    const creditOption = screen.getByText('额度支付').closest('[class*="border-gray-200"]')
-    expect(creditOption).toHaveClass('opacity-50')
+    // 验证额度支付选项不显示(因为查询失败)
+    // 当额度查询失败时,额度支付选项不应该显示
+    expect(screen.queryByTestId('credit-payment-option')).not.toBeInTheDocument()
 
-    // 验证支付按钮被禁用
+    // 验证支付按钮没有被禁用(因为默认选择微信支付,额度查询失败不影响微信支付)
     const payButton = screen.getByTestId('pay-button')
-    expect(payButton).toBeDisabled()
+    expect(payButton).not.toBeDisabled()
   })
 
   test('支付过程中的取消操作', async () => {
@@ -415,12 +422,12 @@ describe('额度支付流程集成测试', () => {
 
     // 等待页面加载
     await waitFor(() => {
-      expect(screen.getByTestId('available-amount-text')).toHaveTextContent(/可用额度: ¥800\.00/)
+      expect(screen.getByTestId('available-amount-text')).toHaveTextContent(/使用信用额度支付/)
     })
 
     // 选择额度支付
-    const creditOption = screen.getByText('额度支付').closest('[class*="border-gray-200"]')
-    fireEvent.click(creditOption!)
+    const creditOption = screen.getByTestId('credit-payment-option')
+    fireEvent.click(creditOption)
 
     // 点击支付按钮
     const payButton = screen.getByTestId('pay-button')
@@ -450,5 +457,8 @@ describe('额度支付流程集成测试', () => {
       // 使用更具体的查询,避免多个"支付成功"元素
       expect(screen.getByText('支付成功', { selector: 'span.text-xl' })).toBeInTheDocument()
     })
+
+    // 推进时间以触发跳转
+    jest.advanceTimersByTime(1600)
   })
 })