cabloy 5.1.122 → 5.1.124
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cabloy-version +1 -1
- package/.claude/skills/cabloy-frontend-scaffold/SKILL.md +13 -3
- package/.claude/skills/cabloy-workflow/SKILL.md +6 -0
- package/.claude/skills/cabloy-workflow/evals/evals.json +6 -0
- package/CHANGELOG.md +24 -0
- package/CLAUDE.md +1 -1
- package/cabloy-docs/.vitepress/config.mjs +4 -0
- package/cabloy-docs/frontend/form-layout-guide.md +29 -7
- package/cabloy-docs/fullstack/parallel-worktree-environment.md +87 -0
- package/e2e/scripts/e2e.ts +13 -1
- package/e2e/scripts/startE2eVona.ts +4 -1
- package/e2e/specs/a-commerce/commerce.spec.ts +129 -32
- package/package.json +2 -1
- package/playwright-report/data/24ac790ec112339c76cfb0c8e2c2539c2f953a0b.zip +0 -0
- package/playwright-report/data/2fddcabcdbd0b695061a565acfff243cb3a4f5e3.zip +0 -0
- package/playwright-report/data/4738038d9e861d63fd25937c9a3570934786a62f.zip +0 -0
- package/playwright-report/data/72f99c7da67c7f6ea53cab7d8681798b70d79a10.md +222 -0
- package/playwright-report/data/7b9684a7c793e9798b898f8ff50177b660a7a733.md +222 -0
- package/playwright-report/data/8b31595f5f1cc9d23863af51a592e6b90dcbc4ce.zip +0 -0
- package/playwright-report/data/95b578407a68806202dda917a61c50c750bd285b.md +222 -0
- package/playwright-report/data/ad960b3a58f224f5b4cad04a24067600064ffb7b.md +222 -0
- package/playwright-report/index.html +90 -0
- package/playwright-report/trace/assets/codeMirrorModule-LEHpjmcn.js +32 -0
- package/playwright-report/trace/assets/defaultSettingsView-BNmKHKpQ.js +264 -0
- package/playwright-report/trace/assets/urlMatch-BYQrIQwR.js +1 -0
- package/playwright-report/trace/codeMirrorModule.DYBRYzYX.css +1 -0
- package/playwright-report/trace/codicon.DCmgc-ay.ttf +0 -0
- package/playwright-report/trace/defaultSettingsView.CjdS-WJx.css +1 -0
- package/playwright-report/trace/index.CzXZzn5A.css +1 -0
- package/playwright-report/trace/index.DMMX1gXU.js +2 -0
- package/playwright-report/trace/index.html +44 -0
- package/playwright-report/trace/manifest.webmanifest +16 -0
- package/playwright-report/trace/playwright-logo.svg +9 -0
- package/playwright-report/trace/snapshot.html +10 -0
- package/playwright-report/trace/snapshot.v8KI4P3m.js +2 -0
- package/playwright-report/trace/sw.bundle.js +5 -0
- package/playwright-report/trace/uiMode.BZQ54Kgt.css +1 -0
- package/playwright-report/trace/uiMode.Ut8wwJNp.js +6 -0
- package/playwright-report/trace/uiMode.html +18 -0
- package/playwright-report/trace/xtermModule.DYP7pi_n.css +32 -0
- package/vona/env/.env +12 -0
- package/vona/env/.env.test +7 -0
- package/vona/packages-cli/cli/package.json +1 -1
- package/vona/packages-cli/cli-set-api/cli/templates/tools/crudBasic/boilerplate/src/dto/{{resourceName}}Create.tsx_ +19 -1
- package/vona/packages-cli/cli-set-api/cli/templates/tools/crudBasic/boilerplate/src/dto/{{resourceName}}Update.tsx_ +19 -1
- package/vona/packages-cli/cli-set-api/cli/templates/tools/crudBasic/boilerplate/src/dto/{{resourceName}}View.tsx_ +19 -1
- package/vona/packages-cli/cli-set-api/cli/templates/tools/crudBasic/snippets/3-en-us.ts +6 -1
- package/vona/packages-cli/cli-set-api/cli/templates/tools/crudBasic/snippets/4-zh-cn.ts +6 -1
- package/vona/packages-cli/cli-set-api/cli/templates/tools/crudStart/boilerplate/src/dto/{{resourceName}}Create.tsx_ +19 -1
- package/vona/packages-cli/cli-set-api/cli/templates/tools/crudStart/boilerplate/src/dto/{{resourceName}}Update.tsx_ +19 -1
- package/vona/packages-cli/cli-set-api/cli/templates/tools/crudStart/boilerplate/src/dto/{{resourceName}}View.tsx_ +19 -1
- package/vona/packages-cli/cli-set-api/cli/templates/tools/crudStart/snippets/3-en-us.ts +6 -1
- package/vona/packages-cli/cli-set-api/cli/templates/tools/crudStart/snippets/4-zh-cn.ts +6 -1
- package/vona/packages-cli/cli-set-api/package.json +1 -1
- package/vona/pnpm-lock.yaml +255 -12
- package/vona/pnpm-workspace.yaml +1 -1
- package/vona/src/suite/a-commerce/modules/commerce-payment/package.json +4 -1
- package/vona/src/suite/a-commerce/modules/commerce-payment/src/.metadata/index.ts +45 -3
- package/vona/src/suite/a-commerce/modules/commerce-payment/src/bean/meta.index.ts +1 -0
- package/vona/src/suite/a-commerce/modules/commerce-payment/src/bean/meta.version.ts +25 -1
- package/vona/src/suite/a-commerce/modules/commerce-payment/src/bean/payScene.commerceOrder.ts +20 -0
- package/vona/src/suite/a-commerce/modules/commerce-payment/src/entity/paymentAttempt.tsx +9 -0
- package/vona/src/suite/a-commerce/modules/commerce-payment/src/entity/paymentAudit.tsx +5 -2
- package/vona/src/suite/a-commerce/modules/commerce-payment/src/entity/refundAttempt.tsx +6 -0
- package/vona/src/suite/a-commerce/modules/commerce-payment/src/index.ts +2 -0
- package/vona/src/suite/a-commerce/modules/commerce-payment/src/lib/index.ts +1 -0
- package/vona/src/suite/a-commerce/modules/commerce-payment/src/service/commercePayScene.ts +54 -0
- package/vona/src/suite/a-commerce/modules/commerce-payment/src/service/paymentAttempt.ts +7 -1
- package/vona/src/suite/a-commerce/modules/commerce-payment/src/types/index.ts +1 -0
- package/vona/src/suite/a-commerce/modules/commerce-payment/test/paymentAttempt.test.ts +21 -0
- package/vona/src/suite/a-commerce/modules/commerce-promotion/src/.metadata/index.ts +30 -0
- package/vona/src/suite/a-commerce/modules/commerce-promotion/src/config/locale/en-us.ts +4 -0
- package/vona/src/suite/a-commerce/modules/commerce-promotion/src/config/locale/zh-cn.ts +4 -0
- package/vona/src/suite/a-commerce/modules/commerce-promotion/src/dto/couponTemplateCreate.tsx +88 -1
- package/vona/src/suite/a-commerce/modules/commerce-promotion/src/dto/couponTemplateUpdate.tsx +44 -1
- package/vona/src/suite/a-commerce/modules/commerce-promotion/src/dto/couponTemplateView.tsx +72 -1
- package/vona/src/suite/a-commerce/modules/commerce-promotion/test/couponTemplateFormLayout.test.ts +121 -0
- package/vona/src/suite/a-commerce/modules/commerce-siteweb/src/bean/ssrMenu.home.ts +4 -1
- package/vona/src/suite/a-commerce/modules/commerce-trade/package.json +4 -1
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/.metadata/index.ts +0 -21
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/checkoutResult.tsx +3 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/service/order.ts +79 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/test/orderSnapshot.test.ts +227 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/test/paymentOutcome.test.ts +121 -13
- package/vona/src/suite/a-commerce/modules/commerce-trade/test/refundLifecycle.test.ts +312 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/package.json +76 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/.metadata/index.ts +842 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/.metadata/this.ts +2 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/bean/bean.payProvider.ts +92 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/bean/bean.payScene.ts +105 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/bean/meta.index.ts +28 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/bean/meta.redlock.ts +11 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/bean/meta.version.ts +113 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/bean/queue.outboxDispatch.ts +31 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/bean/schedule.outboxDispatch.ts +11 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/controller/paymentSession.ts +55 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/controller/webhook.ts +47 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/dto/paymentSessionStart.tsx +8 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/dto/paymentSessionView.tsx +69 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/dto/webhookReceipt.tsx +12 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/entity/outboxEvent.tsx +46 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/entity/paymentAudit.tsx +36 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/entity/paymentSession.tsx +72 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/entity/providerOperation.tsx +54 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/entity/refundOperation.tsx +37 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/entity/webhookInbox.tsx +59 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/index.ts +3 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/lib/index.ts +2 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/lib/payProvider.ts +7 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/lib/payScene.ts +7 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/model/outboxEvent.ts +10 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/model/paymentAudit.ts +10 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/model/paymentSession.ts +10 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/model/providerOperation.ts +10 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/model/refundOperation.ts +10 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/model/webhookInbox.ts +10 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/service/outbox.ts +156 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/service/paymentSession.ts +278 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/service/providerOperation.ts +5 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/service/webhook.ts +127 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/types/index.ts +3 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/types/payProvider.ts +74 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/types/payScene.ts +63 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/types/payment.ts +151 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/test/outbox.test.ts +209 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/test/paymentSession.test.ts +153 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/test/webhook.test.ts +278 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/tsconfig.build.json +11 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/tsconfig.json +7 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-mock/package.json +55 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-mock/src/.metadata/index.ts +182 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-mock/src/.metadata/this.ts +2 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-mock/src/bean/payProvider.mock.ts +149 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-mock/src/controller/mockPayment.ts +25 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-mock/src/dto/mockPaymentComplete.tsx +13 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-mock/src/dto/mockPaymentReceipt.tsx +16 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-mock/src/index.ts +3 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-mock/src/lib/index.ts +1 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-mock/src/service/payMock.ts +78 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-mock/src/types/index.ts +10 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-mock/test/payMock.test.ts +141 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-mock/tsconfig.build.json +11 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-mock/tsconfig.json +7 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-paypal/package.json +55 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-paypal/src/.metadata/index.ts +62 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-paypal/src/.metadata/this.ts +2 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-paypal/src/bean/payProvider.paypal.ts +91 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-paypal/src/index.ts +3 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-paypal/src/lib/index.ts +1 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-paypal/src/types/index.ts +9 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-paypal/tsconfig.build.json +11 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-paypal/tsconfig.json +7 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-stripe/package.json +55 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-stripe/src/.metadata/index.ts +62 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-stripe/src/.metadata/this.ts +2 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-stripe/src/bean/payProvider.stripe.ts +88 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-stripe/src/index.ts +2 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-stripe/src/types/index.ts +8 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-stripe/tsconfig.build.json +11 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-stripe/tsconfig.json +7 -0
- package/vona/src/suite-vendor/a-pay/package.json +15 -0
- package/vona/src/suite-vendor/a-pay/tsconfig.base.json +4 -0
- package/vona/src/suite-vendor/a-pay/tsconfig.json +19 -0
- package/zova/env/.env +1 -0
- package/zova/openapi.config.ts +5 -1
- package/zova/package.original.json +1 -1
- package/zova/packages-cli/cli/package.json +2 -2
- package/zova/packages-cli/cli-set-front/cli/templates/openapi/config/boilerplate/project/openapi.config.ts +5 -1
- package/zova/packages-cli/cli-set-front/package.json +1 -1
- package/zova/packages-cli/cli-set-front/src/lib/bean/cli.openapi.generate.ts +8 -0
- package/zova/packages-cli/cli-set-front/src/lib/common/cliCreatePage.ts +7 -24
- package/zova/packages-cli/cli-set-front/src/lib/common/utils.ts +10 -1
- package/zova/packages-utils/zova-jsx/package.json +2 -2
- package/zova/packages-zova/zova/package.json +3 -3
- package/zova/packages-zova/zova-core/package.json +1 -1
- package/zova/packages-zova/zova-core/src/types/interface/component.ts +5 -0
- package/zova/pnpm-lock.yaml +96 -26
- package/zova/src/front/config/config/config.cabloyCommerce.ts +1 -1
- package/zova/src/suite/a-commerce/modules/commerce-promotion/src/api/openapi/schemas.ts +110 -12
- package/zova/src/suite/a-commerce/modules/commerce-promotion/src/api/openapi/types.ts +1292 -160
- package/zova/src/suite/a-commerce/modules/commerce-trade/cli/openapi.config.ts +0 -1
- package/zova/src/suite/a-commerce/modules/commerce-trade/package.json +4 -1
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/.metadata/index.ts +1 -47
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/api/openapi/schemas.ts +23 -8
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/api/openapi/types.ts +249 -62
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/page/checkout/controller.tsx +5 -1
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/page/payment/controller.tsx +152 -39
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/routes.ts +1 -1
- package/zova/src/suite-vendor/a-pay/modules/a-pay/cli/openapi.config.ts +9 -0
- package/zova/src/suite-vendor/a-pay/modules/a-pay/package.json +53 -0
- package/zova/src/suite-vendor/a-pay/modules/a-pay/src/.metadata/component/paymentNextAction.ts +31 -0
- package/zova/src/suite-vendor/a-pay/modules/a-pay/src/.metadata/index.ts +217 -0
- package/zova/src/suite-vendor/a-pay/modules/a-pay/src/.metadata/this.ts +2 -0
- package/zova/src/suite-vendor/a-pay/modules/a-pay/src/api/openapi/baseURL.ts +5 -0
- package/zova/src/suite-vendor/a-pay/modules/a-pay/src/api/openapi/index.ts +3 -0
- package/zova/src/suite-vendor/a-pay/modules/a-pay/src/api/openapi/schemas.ts +584 -0
- package/zova/src/suite-vendor/a-pay/modules/a-pay/src/api/openapi/types.ts +9324 -0
- package/zova/src/suite-vendor/a-pay/modules/a-pay/src/api/paymentSession.ts +52 -0
- package/zova/src/suite-vendor/a-pay/modules/a-pay/src/apiSchema/paymentSession.ts +20 -0
- package/zova/src/suite-vendor/a-pay/modules/a-pay/src/component/paymentNextAction/controller.tsx +76 -0
- package/zova/src/suite-vendor/a-pay/modules/a-pay/src/index.ts +3 -0
- package/zova/src/suite-vendor/a-pay/modules/a-pay/src/lib/index.ts +1 -0
- package/zova/src/suite-vendor/a-pay/modules/a-pay/src/model/paymentSession.ts +32 -0
- package/zova/src/suite-vendor/a-pay/modules/a-pay/src/service/paymentCoordinator.ts +13 -0
- package/zova/src/suite-vendor/a-pay/modules/a-pay/src/types/index.ts +1 -0
- package/zova/src/suite-vendor/a-pay/modules/a-pay/src/types/payment.ts +25 -0
- package/zova/src/suite-vendor/a-pay/modules/a-pay/tsconfig.build.json +13 -0
- package/zova/src/suite-vendor/a-pay/modules/a-pay/tsconfig.json +5 -0
- package/zova/src/suite-vendor/a-pay/modules/pay-mock/cli/openapi.config.ts +9 -0
- package/zova/src/suite-vendor/a-pay/modules/pay-mock/package.json +53 -0
- package/zova/src/suite-vendor/a-pay/modules/pay-mock/src/.metadata/index.ts +140 -0
- package/zova/src/suite-vendor/a-pay/modules/pay-mock/src/.metadata/this.ts +2 -0
- package/zova/src/suite-vendor/a-pay/modules/pay-mock/src/api/openapi/baseURL.ts +5 -0
- package/zova/src/suite-vendor/a-pay/modules/pay-mock/src/api/openapi/index.ts +3 -0
- package/zova/src/suite-vendor/a-pay/modules/pay-mock/src/api/openapi/schemas.ts +584 -0
- package/zova/src/suite-vendor/a-pay/modules/pay-mock/src/api/openapi/types.ts +9324 -0
- package/zova/src/suite-vendor/a-pay/modules/pay-mock/src/api/payMockPayment.ts +34 -0
- package/zova/src/suite-vendor/a-pay/modules/pay-mock/src/apiSchema/payMockPayment.ts +13 -0
- package/zova/src/suite-vendor/a-pay/modules/pay-mock/src/index.ts +1 -0
- package/zova/src/suite-vendor/a-pay/modules/pay-mock/src/model/payMockPayment.ts +20 -0
- package/zova/src/suite-vendor/a-pay/modules/pay-mock/tsconfig.build.json +13 -0
- package/zova/src/suite-vendor/a-pay/modules/pay-mock/tsconfig.json +5 -0
- package/zova/src/suite-vendor/a-pay/modules/pay-paypal/package.json +52 -0
- package/zova/src/suite-vendor/a-pay/modules/pay-paypal/src/.metadata/index.ts +26 -0
- package/zova/src/suite-vendor/a-pay/modules/pay-paypal/src/.metadata/this.ts +2 -0
- package/zova/src/suite-vendor/a-pay/modules/pay-paypal/src/index.ts +1 -0
- package/zova/src/suite-vendor/a-pay/modules/pay-paypal/tsconfig.build.json +13 -0
- package/zova/src/suite-vendor/a-pay/modules/pay-paypal/tsconfig.json +5 -0
- package/zova/src/suite-vendor/a-pay/modules/pay-stripe/package.json +52 -0
- package/zova/src/suite-vendor/a-pay/modules/pay-stripe/src/.metadata/index.ts +26 -0
- package/zova/src/suite-vendor/a-pay/modules/pay-stripe/src/.metadata/this.ts +2 -0
- package/zova/src/suite-vendor/a-pay/modules/pay-stripe/src/index.ts +1 -0
- package/zova/src/suite-vendor/a-pay/modules/pay-stripe/tsconfig.build.json +13 -0
- package/zova/src/suite-vendor/a-pay/modules/pay-stripe/tsconfig.json +5 -0
- package/zova/src/suite-vendor/a-pay/package.json +15 -0
- package/zova/src/suite-vendor/a-pay/tsconfig.base.json +4 -0
- package/zova/src/suite-vendor/a-pay/tsconfig.json +4 -0
- package/zova/src/suite-vendor/a-zova/modules/a-zova/package.json +2 -2
- package/zova/src/suite-vendor/a-zova/package.json +2 -2
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/controller/payment.ts +0 -23
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/api/commerceTradePayment.ts +0 -36
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/apiSchema/commerceTradePayment.ts +0 -13
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/model/payment.ts +0 -25
- /package/vona/patches/{zova-core@5.1.79.patch → zova-core@5.1.81.patch} +0 -0
package/.cabloy-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
5.1.
|
|
1
|
+
5.1.124
|
|
@@ -36,6 +36,14 @@ Then classify the request:
|
|
|
36
36
|
|
|
37
37
|
Default to frontend-first. Only escalate mentally to a broader fullstack workflow when the frontend task obviously crosses the contract boundary.
|
|
38
38
|
|
|
39
|
+
### Decide a form layout or ask
|
|
40
|
+
|
|
41
|
+
When the task changes a schema-driven form, inspect the generated baseline, operation-specific DTO/schema, nearby Cabloy forms, the active edition and UI adapter, field relationships, and the user's stated workflow before choosing a layout.
|
|
42
|
+
|
|
43
|
+
Proceed autonomously when that evidence establishes the form purpose and field relationships. Choose the smallest fitting structure: no explicit layout for a short conventional form, flow for compact filters, Grid for responsive related fields, a group for one meaningful business boundary, or tabs for genuinely independent domains or workflows. State the consequential business assumptions with the implementation.
|
|
44
|
+
|
|
45
|
+
Ask one focused business question only when the layout would encode an unresolved semantic or authority decision: whether areas are independent or one workflow, which audience or task has priority, whether a form is a compact filter or a full entry workflow, or whether staged responsibilities are intended. Do not ask merely because several visual arrangements are technically valid.
|
|
46
|
+
|
|
39
47
|
If the user is still deciding a new business-domain boundary or suite/module naming, use the root `cabloy-domain-planning` skill before scaffolding.
|
|
40
48
|
|
|
41
49
|
If the task is really a broad cross-stack workflow, consider whether the root `cabloy-workflow` skill is the better primary router.
|
|
@@ -205,6 +213,7 @@ Especially relevant pages include:
|
|
|
205
213
|
- `cabloy-docs/frontend/route-alias-guide.md`
|
|
206
214
|
- `cabloy-docs/frontend/navigation-guards-guide.md`
|
|
207
215
|
- `cabloy-docs/frontend/component-guide.md`
|
|
216
|
+
- `cabloy-docs/frontend/form-layout-guide.md` for schema-driven field placement, Grid/flow selection, groups, tabs, or embedded filter actions
|
|
208
217
|
- `cabloy-docs/frontend/component-props-guide.md`
|
|
209
218
|
- `cabloy-docs/frontend/component-v-model-guide.md`
|
|
210
219
|
- `cabloy-docs/frontend/generic-component-guide.md`
|
|
@@ -249,8 +258,9 @@ When helpful, structure the response around these points:
|
|
|
249
258
|
1. detected edition
|
|
250
259
|
2. frontend-first or clearly fullstack-sensitive classification
|
|
251
260
|
3. recommended Zova CLI path
|
|
252
|
-
4.
|
|
253
|
-
5.
|
|
254
|
-
6.
|
|
261
|
+
4. form-layout decision, consequential business assumptions, and any user-confirmed boundary when the task is layout-sensitive
|
|
262
|
+
5. required frontend follow-up layers to check
|
|
263
|
+
6. optional backend-contract reminder if applicable
|
|
264
|
+
7. verification steps
|
|
255
265
|
|
|
256
266
|
Keep the response practical. The value of this skill is turning Cabloy frontend requests into the right generation + refactor + verification workflow, not writing more prose than necessary.
|
|
@@ -98,6 +98,12 @@ For deeper reference material, read:
|
|
|
98
98
|
|
|
99
99
|
The reason is simple: these files are where Cabloy already encodes its real workflows.
|
|
100
100
|
|
|
101
|
+
### Parallel worktree environment setup
|
|
102
|
+
|
|
103
|
+
When a request involves a second worktree, concurrent Vona/Zova development, isolated ordinary tests, or managed clean E2E, classify it as fullstack workflow setup. Read [Parallel Worktree Environment](../../../cabloy-docs/fullstack/parallel-worktree-environment.md) for the canonical Cabloy Basic recipe.
|
|
104
|
+
|
|
105
|
+
Before applying the broad `.env.local` recipe, check for more-specific `.env.*.local` overrides. Keep Vona and Zova `APP_NAME` values aligned, use the required matching API target, and add database, Redis, external-service, mock, or SSR-preview isolation only when the work actually uses those shared resources. For Cabloy Start, inspect the active Start repository rather than reusing the Basic recipe unchanged.
|
|
106
|
+
|
|
101
107
|
## Step 4: Prefer CLI-first workflows
|
|
102
108
|
|
|
103
109
|
Whenever the task maps to an existing generator, initializer, refactor, or metadata command, prefer the CLI.
|
|
@@ -30,6 +30,12 @@
|
|
|
30
30
|
"prompt": "I want to update the public guidance for Cabloy contributors about using CLI generators first, but I also think Claude should follow the same rule automatically. Where should each part of that knowledge live?",
|
|
31
31
|
"expected_output": "Splits the guidance across public docs and Claude rules/skills appropriately, keeping maintainer rationale out of public docs unless needed.",
|
|
32
32
|
"files": []
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"id": 6,
|
|
36
|
+
"prompt": "I created a second Cabloy Basic worktree and need to run Vona, Zova, and test:e2e:basic:clean in parallel with the first worktree. Which environment files and exact variables should I configure without changing shared defaults?",
|
|
37
|
+
"expected_output": "Classifies this as fullstack parallel-worktree environment setup and routes to the canonical Parallel Worktree Environment guide. Checks for more-specific local overrides, uses Vona vona/env/.env.local with APP_NAME and SERVER_LISTEN_PORT, and Zova zova/env/.env.local with the same APP_NAME plus API_BASE_URL pointing to that Vona port, DEV_SERVER_PORT, and DEV_SERVER_HMR_PORT. Keeps SSR_API_BASE_URL inherited from API_BASE_URL unless a more-specific override changes it, and adds database, Redis, external-service, mock, or SSR-preview settings only when those resources are actually used.",
|
|
38
|
+
"files": []
|
|
33
39
|
}
|
|
34
40
|
]
|
|
35
41
|
}
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 5.1.124
|
|
4
|
+
|
|
5
|
+
### Improvements
|
|
6
|
+
|
|
7
|
+
- Refresh the Zova lockfile and core patch dependencies.
|
|
8
|
+
|
|
9
|
+
## 5.1.123
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
- Add payment payload handling and A-Pay integration updates.
|
|
14
|
+
- Add OpenAPI configuration support.
|
|
15
|
+
- Add configurable E2E test port support.
|
|
16
|
+
- Update payment scene and session view capabilities.
|
|
17
|
+
|
|
18
|
+
### Bug Fixes
|
|
19
|
+
|
|
20
|
+
- Import `VNode` as a type in `zova-core`.
|
|
21
|
+
|
|
22
|
+
### Improvements
|
|
23
|
+
|
|
24
|
+
- Align commerce documentation with the acceptance gate.
|
|
25
|
+
- Update application components, SSR menu configuration, package metadata, and dependencies.
|
|
26
|
+
|
|
3
27
|
## 5.1.122
|
|
4
28
|
|
|
5
29
|
### Features
|
package/CLAUDE.md
CHANGED
|
@@ -58,7 +58,7 @@ Before inventing a custom implementation path:
|
|
|
58
58
|
- Default to establishing such query state during render. Use `disableSuspenseOnInit: true` only for relatively stable query-backed state when you want to skip the init-time `query.suspense()` kick; it does not prevent query creation, fetches, or hydration-time rendering. If strict readiness is needed later, wait explicitly at the interaction boundary.
|
|
59
59
|
- In SSR, keep server HTML and the client's hydration-time initial render equivalent. When server rendering intentionally omits private, cookie-unavailable, or browser-only state, keep the same neutral shell or placeholder through hydration and defer its query/load/render branch to an explicit post-hydration, admission, mounted, or interaction boundary.
|
|
60
60
|
- Keep repo-wide AI rules in `CLAUDE.md` short and durable; put branching Zova analysis workflows in `.claude/skills/`.
|
|
61
|
-
- Do not modify
|
|
61
|
+
- Do not modify shared environment identity or ports merely to bypass a busy resource. For intentional parallel worktree setup, follow `cabloy-docs/fullstack/parallel-worktree-environment.md`; otherwise wait for the shared resource or ask the user.
|
|
62
62
|
- For SSR theme-sensitive frontend work, detect the active edition marker and UI library before making assumptions. Cabloy Basic currently means DaisyUI + Tailwind CSS assumptions; Cabloy Start currently means Vuetify assumptions.
|
|
63
63
|
- In Web SSR without cookie-backed theme resolution, do not treat server reads of `$theme.dark`, `$theme.darkMode`, or `$token` as final browser truth. Keep theme-sensitive SSR branching hydration-tolerant or defer final theme-sensitive decisions to the client.
|
|
64
64
|
- Do not assume Cabloy Basic and Cabloy Start use the same adapter-level SSR theme handoff. Verify the active theme handler and client hydration path before changing SSR theme behavior.
|
|
@@ -75,6 +75,10 @@ const fullstackGroups = [
|
|
|
75
75
|
text: 'Tooling & Workflow',
|
|
76
76
|
items: [
|
|
77
77
|
{ text: 'CLI', link: '/fullstack/cli' },
|
|
78
|
+
{
|
|
79
|
+
text: 'Parallel Worktree Environment',
|
|
80
|
+
link: '/fullstack/parallel-worktree-environment',
|
|
81
|
+
},
|
|
78
82
|
{ text: 'VS Code Extensions', link: '/fullstack/vscode-extensions' },
|
|
79
83
|
],
|
|
80
84
|
},
|
|
@@ -7,6 +7,27 @@ This guide covers the **structural** layout contract authored in DTO metadata an
|
|
|
7
7
|
> [!TIP]
|
|
8
8
|
> Cabloy Basic implements the renderer described here with DaisyUI and Tailwind CSS. The `formLayout` contract and its resolver are shared Zova surfaces, but group, Grid, flow, and tab presentation are Basic-specific. Do not assume Cabloy Start uses identical markup or styling.
|
|
9
9
|
|
|
10
|
+
## Choose the layout from the business form
|
|
11
|
+
|
|
12
|
+
Start with the user's task, information hierarchy, and audience—not with the available layout node types or the number of fields. The generated CRUD layout is a valid baseline to review and refine, not a requirement to preserve unchanged.
|
|
13
|
+
|
|
14
|
+
Choose the smallest structure that communicates the business form:
|
|
15
|
+
|
|
16
|
+
| Business shape | Recommended structure |
|
|
17
|
+
| ------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ |
|
|
18
|
+
| A short, conventional form whose schema order is already clear | No explicit `formLayout`, or a flat field list when placement must be explicit |
|
|
19
|
+
| One meaningful business subsection | A `group` with a title that explains the boundary |
|
|
20
|
+
| Related fields users complete or compare together and that need responsive density or spans | A Grid `section`, normally inside the relevant group |
|
|
21
|
+
| Compact scan-and-act controls, especially a list filter with Search/Reset | A `section` with `layout: 'flow'` and one embedded filter-actions block |
|
|
22
|
+
| Genuinely separate business domains or workflows | `tabs` with one `tab` per independent area |
|
|
23
|
+
| A nested detail collection | One normal `field`; its field renderer owns the detail UI |
|
|
24
|
+
|
|
25
|
+
Do not select tabs merely because a form has many fields, and do not add a structural tree merely because the API supports one. A `group` communicates a semantic boundary; a `section` solves Grid or flow placement. Field renderer and wrapper requirements remain separate concerns, as explained in the next section.
|
|
26
|
+
|
|
27
|
+
Create, update, and view can reuse one layout when they present the same information hierarchy. When their tasks differ—for example, a focused creation workflow versus a review-oriented view—author scene-specific DTO layouts instead of forcing a shared tree. Likewise, choose entry-form and filter layouts independently: a compact filter is not a smaller entry form.
|
|
28
|
+
|
|
29
|
+
When the business grouping is unknown, keep the simpler layout or clarify the grouping before introducing groups or tabs. See the [complete entry-form example](#complete-entry-form-example) for a justified tabbed business form and the [complete filter-form example](#complete-filter-form-example) for the maintained compact filter convention.
|
|
30
|
+
|
|
10
31
|
## The layout layers are different
|
|
11
32
|
|
|
12
33
|
Several APIs contain the word “layout,” but they own different concerns:
|
|
@@ -330,13 +351,14 @@ Here `formFieldLayout.inline: true` controls how each field wrapper is presented
|
|
|
330
351
|
|
|
331
352
|
## Authoring checklist
|
|
332
353
|
|
|
333
|
-
1.
|
|
334
|
-
2.
|
|
335
|
-
3. Use
|
|
336
|
-
4.
|
|
337
|
-
5.
|
|
338
|
-
6.
|
|
339
|
-
7.
|
|
354
|
+
1. Identify the audience, task, and meaningful field groupings for the operation-specific DTO before choosing a structural tree.
|
|
355
|
+
2. Start with DTO or resource metadata; do not hand-patch generated `.zova-rest` artifacts.
|
|
356
|
+
3. Use no structural layout when schema order is sufficient. Otherwise use the smallest layout that communicates the business structure; reserve tabs for genuinely separate business domains or workflows.
|
|
357
|
+
4. Use `formLayout` when the requirement is field placement, Grid or flow structure, groups, or tabs.
|
|
358
|
+
5. Use `layout`, `formFieldLayout`, `options`, or provider behaviors when the requirement is one field's wrapper or renderer.
|
|
359
|
+
6. Keep entry actions in page-entry toolbar blocks. Keep filter action semantics in `basic-page:blockFilterActions`; place that block inside Form Layout when the actions must share structural Grid or flow placement with fields.
|
|
360
|
+
7. For maintained Cabloy Basic list filters, prefer one inline flow section that explicitly lists every real filter-schema field in schema order and ends with one embedded `basic-page:blockFilterActions` block. Do not add virtual request fields, alter filter transforms, or combine it with a sibling action block.
|
|
361
|
+
8. Review field names against the scene-specific schema. Unlisted visible fields are appended; unknown and duplicate declarations are silently pruned from the rendered plan.
|
|
340
362
|
|
|
341
363
|
## Source-reading and verification path
|
|
342
364
|
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Parallel Worktree Environment
|
|
2
|
+
|
|
3
|
+
Use worktree-local environment overrides when two Cabloy Basic worktrees need to run ordinary local development or managed E2E checks at the same time.
|
|
4
|
+
|
|
5
|
+
This workflow creates an isolated local runtime without changing committed environment defaults. It covers normal Vona and Zova development, `npm run test`, and `npm run test:e2e:XXX:clean`. It does not automatically isolate every external dependency.
|
|
6
|
+
|
|
7
|
+
## Before creating local overrides
|
|
8
|
+
|
|
9
|
+
1. Confirm that the checkout is a separate worktree.
|
|
10
|
+
2. Check `vona/env/` and `zova/env/` for applicable, more-specific `.env.*.local` files. A more-specific local override can take precedence over `.env.local`.
|
|
11
|
+
3. Choose one unique worktree name and unused Vona, Zova, and HMR ports.
|
|
12
|
+
|
|
13
|
+
The repository ignores `**/env/.env*.local`, so these files remain local to the worktree and must not be committed.
|
|
14
|
+
|
|
15
|
+
## Minimum configuration
|
|
16
|
+
|
|
17
|
+
Create these files in the new worktree.
|
|
18
|
+
|
|
19
|
+
### Vona
|
|
20
|
+
|
|
21
|
+
`vona/env/.env.local`
|
|
22
|
+
|
|
23
|
+
```dotenv
|
|
24
|
+
APP_NAME = cabloy-basic-my-worktree
|
|
25
|
+
SERVER_LISTEN_PORT = 7113
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Zova
|
|
29
|
+
|
|
30
|
+
`zova/env/.env.local`
|
|
31
|
+
|
|
32
|
+
```dotenv
|
|
33
|
+
APP_NAME = cabloy-basic-my-worktree
|
|
34
|
+
API_BASE_URL = http://localhost:7113
|
|
35
|
+
DEV_SERVER_PORT = 9013
|
|
36
|
+
DEV_SERVER_HMR_PORT = 24693
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Keep these invariants:
|
|
40
|
+
|
|
41
|
+
- Vona and Zova use the same unique `APP_NAME`.
|
|
42
|
+
- `API_BASE_URL` points to the selected Vona `SERVER_LISTEN_PORT`.
|
|
43
|
+
- `SERVER_LISTEN_PORT`, `DEV_SERVER_PORT`, and `DEV_SERVER_HMR_PORT` are unique among concurrently running worktrees.
|
|
44
|
+
|
|
45
|
+
The base Zova environment defines `SSR_API_BASE_URL = $API_BASE_URL`, so SSR uses the same Vona target in the normal baseline. Add an explicit local `SSR_API_BASE_URL` only if an applicable, more-specific environment file changes that relationship.
|
|
46
|
+
|
|
47
|
+
## What this isolates
|
|
48
|
+
|
|
49
|
+
A unique `APP_NAME` separates the application identity used by ordinary framework-managed local resources, including managed test database names and Redis-related key prefixes. Worktree-local generated files, runtime files, build output, and coverage output are already separated by their worktree paths.
|
|
50
|
+
|
|
51
|
+
The selected Vona, Zova, and HMR ports let the worktrees run their ordinary local processes concurrently. The matching Zova API URL prevents the frontend in one worktree from calling the Vona process in another.
|
|
52
|
+
|
|
53
|
+
This is sufficient for the normal local workflows:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
npm run dev
|
|
57
|
+
npm run dev:zova:admin
|
|
58
|
+
npm run dev:zova:web
|
|
59
|
+
npm run test
|
|
60
|
+
npm run test:e2e:basic:clean
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
The managed clean E2E workflow reads Vona's effective local `SERVER_LISTEN_PORT`, then resets, starts, and targets that local runtime.
|
|
64
|
+
|
|
65
|
+
## Add configuration only when the work uses it
|
|
66
|
+
|
|
67
|
+
Do not add isolation settings preemptively. Extend the local overrides only when the selected workflow actually shares one of these resources:
|
|
68
|
+
|
|
69
|
+
- an explicitly named database or a separately configured Redis target
|
|
70
|
+
- mail, payment, webhook, object-storage, or other external providers
|
|
71
|
+
- a standalone mock-build process, using `MOCK_BUILD_PORT`
|
|
72
|
+
- an SSR preview or production process, using `SSR_PROD_PORT`
|
|
73
|
+
|
|
74
|
+
For example, `APP_NAME` namespaces ordinary framework Redis keys, but it does not create a separate Redis server or automatically isolate custom, unprefixed keys. Likewise, an explicitly configured external database remains shared until it is configured separately.
|
|
75
|
+
|
|
76
|
+
## Edition-aware note
|
|
77
|
+
|
|
78
|
+
This page describes the current Cabloy Basic workflow. For Cabloy Start, detect the active edition first and inspect the Start repository's current scripts, flavors, environment files, and generated-output paths before applying this recipe.
|
|
79
|
+
|
|
80
|
+
## Read together with
|
|
81
|
+
|
|
82
|
+
- [Quick Start](/fullstack/quickstart)
|
|
83
|
+
- [Vona + Zova Integration](/fullstack/vona-zova-integration)
|
|
84
|
+
- [Runtime Environments and Flavors](/backend/runtime-and-flavors)
|
|
85
|
+
- [Environment and Config Guide](/frontend/environment-config-guide)
|
|
86
|
+
- [SSR Environment Variables](/frontend/ssr-env)
|
|
87
|
+
- [Mock Guide](/frontend/mock-guide)
|
package/e2e/scripts/e2e.ts
CHANGED
|
@@ -1,8 +1,20 @@
|
|
|
1
|
+
import * as dotenv from '@cabloy/dotenv';
|
|
1
2
|
import { dirname, resolve } from 'node:path';
|
|
2
3
|
import { fileURLToPath } from 'node:url';
|
|
3
4
|
|
|
4
5
|
export const E2E_ROOT_DIR = resolve(dirname(fileURLToPath(import.meta.url)), '..', '..');
|
|
5
|
-
|
|
6
|
+
|
|
7
|
+
const vonaEnv = dotenv.loadEnvs(
|
|
8
|
+
{ flavor: 'normal', mode: 'dev', local: 'local' },
|
|
9
|
+
resolve(E2E_ROOT_DIR, 'vona', 'env'),
|
|
10
|
+
'.env',
|
|
11
|
+
);
|
|
12
|
+
const e2ePort = Number(vonaEnv?.SERVER_LISTEN_PORT);
|
|
13
|
+
if (!Number.isInteger(e2ePort) || e2ePort <= 0 || e2ePort > 65535) {
|
|
14
|
+
throw new Error('Missing or invalid SERVER_LISTEN_PORT for local E2E target');
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const E2E_PORT = e2ePort;
|
|
6
18
|
export const E2E_LOCAL_BASE_URL = `http://127.0.0.1:${E2E_PORT}`;
|
|
7
19
|
|
|
8
20
|
const E2E_CONFIG_DIR = resolve(E2E_ROOT_DIR, 'e2e', 'config');
|
|
@@ -1,11 +1,14 @@
|
|
|
1
|
+
import type { ChildProcess } from 'node:child_process';
|
|
2
|
+
|
|
1
3
|
import { spawn } from 'node:child_process';
|
|
2
4
|
|
|
3
5
|
import { E2E_ROOT_DIR } from './e2e.ts';
|
|
4
6
|
|
|
5
|
-
const child = spawn('npm', ['run', 'dev:one'], {
|
|
7
|
+
const child: ChildProcess = spawn('npm', ['run', 'dev:one'], {
|
|
6
8
|
cwd: E2E_ROOT_DIR,
|
|
7
9
|
detached: process.platform !== 'win32',
|
|
8
10
|
stdio: 'inherit',
|
|
11
|
+
env: process.env,
|
|
9
12
|
});
|
|
10
13
|
|
|
11
14
|
const gracefulShutdownTimeout = 7000;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { APIRequestContext, Browser, Page, TestInfo } from '@playwright/test';
|
|
1
|
+
import type { APIRequestContext, Browser, Locator, Page, TestInfo } from '@playwright/test';
|
|
2
2
|
|
|
3
3
|
import { expect, test } from '@playwright/test';
|
|
4
4
|
|
|
@@ -35,6 +35,10 @@ function waitForApiResponse(page: Page, method: string, path: string | RegExp) {
|
|
|
35
35
|
});
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
function expectTableIdentity(value: unknown) {
|
|
39
|
+
expect(['string', 'number']).toContain(typeof value);
|
|
40
|
+
}
|
|
41
|
+
|
|
38
42
|
function waitForAddressResponse(page: Page, method: string, path: string | RegExp) {
|
|
39
43
|
return waitForApiResponse(page, method, path);
|
|
40
44
|
}
|
|
@@ -43,6 +47,12 @@ function waitForAddressMine(page: Page) {
|
|
|
43
47
|
return waitForAddressResponse(page, 'GET', addressMinePath);
|
|
44
48
|
}
|
|
45
49
|
|
|
50
|
+
async function getAdminOrderRow(page: Page, orderId: number): Promise<Locator> {
|
|
51
|
+
const row = page.locator(`tr:has(td:first-child:text-is("${orderId}"))`);
|
|
52
|
+
await expect(row).toHaveCount(1);
|
|
53
|
+
return row;
|
|
54
|
+
}
|
|
55
|
+
|
|
46
56
|
async function login(
|
|
47
57
|
page: Page,
|
|
48
58
|
path: string,
|
|
@@ -63,7 +73,14 @@ async function login(
|
|
|
63
73
|
await expect(usernameInput).toHaveValue(username);
|
|
64
74
|
await expect(passwordInput).toHaveValue(password);
|
|
65
75
|
await expect(page.getByPlaceholder('Please input captcha')).not.toHaveValue('');
|
|
76
|
+
const loginResponse = waitForApiResponse(page, 'POST', '/api/home/user/passport/login');
|
|
66
77
|
await page.getByRole('button', { name: 'Login', exact: true }).click();
|
|
78
|
+
const loginResponseValue = await loginResponse;
|
|
79
|
+
if (!loginResponseValue.ok()) {
|
|
80
|
+
throw new Error(
|
|
81
|
+
`login failed: ${loginResponseValue.status()} ${await loginResponseValue.text()}`,
|
|
82
|
+
);
|
|
83
|
+
}
|
|
67
84
|
await expect(page).not.toHaveURL(/\/login(?:\?|$)/);
|
|
68
85
|
}
|
|
69
86
|
}
|
|
@@ -383,38 +400,43 @@ test(
|
|
|
383
400
|
const checkoutResponseValue = await checkoutResponse;
|
|
384
401
|
expect(checkoutResponseValue.ok()).toBeTruthy();
|
|
385
402
|
const checkout = (await checkoutResponseValue.json()).data;
|
|
386
|
-
|
|
387
|
-
|
|
403
|
+
expectTableIdentity(checkout.orderId);
|
|
404
|
+
expectTableIdentity(checkout.paymentAttemptId);
|
|
405
|
+
expectTableIdentity(checkout.paymentSessionId);
|
|
388
406
|
expect(checkout.state).toBe('awaiting_payment');
|
|
389
407
|
expect(checkout.paymentAttemptState).toBe('created');
|
|
390
408
|
expect(checkout.currency).toBe('USD');
|
|
391
409
|
expect(checkout.payableTotalCents).toBe(4599);
|
|
392
410
|
await expect(page).toHaveURL(
|
|
393
|
-
new RegExp(`/commerce/payment/${checkout.
|
|
411
|
+
new RegExp(`/commerce/payment/${checkout.paymentSessionId}/${checkout.orderId}(?:/|$)`),
|
|
394
412
|
);
|
|
395
|
-
await expect(page.getByRole('heading', { name: '
|
|
413
|
+
await expect(page.getByRole('heading', { name: 'Payment', exact: true })).toBeVisible();
|
|
396
414
|
|
|
397
|
-
const
|
|
415
|
+
const startResponse = waitForApiResponse(
|
|
416
|
+
page,
|
|
417
|
+
'POST',
|
|
418
|
+
new RegExp(`/api/payment-session/${checkout.paymentSessionId}/start$`),
|
|
419
|
+
);
|
|
420
|
+
await page.getByRole('button', { name: 'Start payment', exact: true }).click();
|
|
421
|
+
expect((await startResponse).ok()).toBeTruthy();
|
|
422
|
+
await expect(page.getByText('Payment is being prepared.')).toBeVisible();
|
|
423
|
+
await expect(page.getByRole('heading', { name: 'Mock payment simulator' })).toBeVisible();
|
|
424
|
+
const completeResponse = waitForApiResponse(
|
|
398
425
|
page,
|
|
399
426
|
'POST',
|
|
400
|
-
new RegExp(`/api/
|
|
427
|
+
new RegExp(`/api/pay/mock/payment-session/${checkout.paymentSessionId}/complete$`),
|
|
401
428
|
);
|
|
429
|
+
await page.getByRole('button', { name: 'Payment succeeded', exact: true }).click();
|
|
430
|
+
expect((await completeResponse).ok()).toBeTruthy();
|
|
431
|
+
await expect(page).toHaveURL(new RegExp(`/commerce/order/${checkout.orderId}(?:/|$)`), {
|
|
432
|
+
timeout: 40_000,
|
|
433
|
+
});
|
|
402
434
|
const orderDetailResponse = waitForApiResponse(
|
|
403
435
|
page,
|
|
404
436
|
'GET',
|
|
405
|
-
new RegExp(
|
|
437
|
+
new RegExp(`/api/commerce/trade/order/viewMine/${checkout.orderId}$`),
|
|
406
438
|
);
|
|
407
|
-
await page.
|
|
408
|
-
const paymentResponseValue = await paymentResponse;
|
|
409
|
-
expect(paymentResponseValue.ok()).toBeTruthy();
|
|
410
|
-
const payment = (await paymentResponseValue.json()).data;
|
|
411
|
-
expect(payment.orderId).toBe(checkout.orderId);
|
|
412
|
-
expect(payment.paymentAttemptId).toBe(checkout.paymentAttemptId);
|
|
413
|
-
expect(payment.orderState).toBe('paid');
|
|
414
|
-
expect(payment.paymentAttemptState).toBe('succeeded');
|
|
415
|
-
expect(payment.currency).toBe('USD');
|
|
416
|
-
expect(payment.payableTotalCents).toBe(4599);
|
|
417
|
-
await expect(page).toHaveURL(new RegExp(`/commerce/order/${checkout.orderId}(?:/|$)`));
|
|
439
|
+
await page.reload({ waitUntil: 'load' });
|
|
418
440
|
const orderDetailResponseValue = await orderDetailResponse;
|
|
419
441
|
expect(orderDetailResponseValue.ok()).toBeTruthy();
|
|
420
442
|
const order = (await orderDetailResponseValue.json()).data;
|
|
@@ -459,9 +481,7 @@ test(
|
|
|
459
481
|
'data-zova-hydrated',
|
|
460
482
|
'commerceAdmin',
|
|
461
483
|
);
|
|
462
|
-
const orderRow = adminPage
|
|
463
|
-
.getByRole('cell', { name: String(checkout.orderId), exact: true })
|
|
464
|
-
.locator('..');
|
|
484
|
+
const orderRow = await getAdminOrderRow(adminPage, checkout.orderId);
|
|
465
485
|
await expect(orderRow).toBeVisible();
|
|
466
486
|
const carrierInput = orderRow.getByPlaceholder('Carrier');
|
|
467
487
|
const trackingNumberInput = orderRow.getByPlaceholder('Tracking number');
|
|
@@ -525,6 +545,70 @@ test(
|
|
|
525
545
|
},
|
|
526
546
|
);
|
|
527
547
|
|
|
548
|
+
test(
|
|
549
|
+
'Payment cancellation: customer observes the cancelled order after verified provider confirmation',
|
|
550
|
+
{ tag: ['@web', '@flow', '@payment'] },
|
|
551
|
+
async ({ browser, request }, testInfo) => {
|
|
552
|
+
test.setTimeout(60_000);
|
|
553
|
+
const { context, fixture, page, pageErrors } = await createAddressThroughCustomerPage(
|
|
554
|
+
browser,
|
|
555
|
+
request,
|
|
556
|
+
testInfo,
|
|
557
|
+
);
|
|
558
|
+
try {
|
|
559
|
+
await page.goto('/commerce', { waitUntil: 'load' });
|
|
560
|
+
await expect(page.locator('html')).toHaveAttribute('data-zova-hydrated', 'commerce');
|
|
561
|
+
const productLink = page.getByRole('link', { name: 'Pour-Over Coffee Set', exact: true });
|
|
562
|
+
await expect(productLink).toBeVisible();
|
|
563
|
+
await productLink.click();
|
|
564
|
+
await expect(page).toHaveURL(/\/commerce\/product\/\d+(?:\/|$)/);
|
|
565
|
+
await expect(page.getByRole('heading', { name: 'Pour-Over Coffee Set' })).toBeVisible();
|
|
566
|
+
const addResponse = waitForApiResponse(page, 'POST', '/api/commerce/trade/cart/items');
|
|
567
|
+
await page.getByRole('button', { name: 'Add to cart', exact: true }).click();
|
|
568
|
+
expect((await addResponse).ok()).toBeTruthy();
|
|
569
|
+
await page.getByRole('link', { name: /^Cart/ }).click();
|
|
570
|
+
await expect(page).toHaveURL(/\/commerce\/cart(?:\/|$)/);
|
|
571
|
+
await page.getByRole('link', { name: 'Checkout', exact: true }).click();
|
|
572
|
+
await expect(page).toHaveURL(/\/commerce\/checkout(?:\/|$)/);
|
|
573
|
+
const addressChoice = page.getByRole('radio', { name: new RegExp(fixture.recipientName) });
|
|
574
|
+
await expect(addressChoice).toBeVisible();
|
|
575
|
+
await addressChoice.check();
|
|
576
|
+
await page.getByRole('radio', { name: 'No coupon', exact: true }).check();
|
|
577
|
+
const checkoutResponse = waitForApiResponse(page, 'POST', '/api/commerce/trade/checkout');
|
|
578
|
+
await page.getByRole('button', { name: 'Create order', exact: true }).click();
|
|
579
|
+
const checkoutResponseValue = await checkoutResponse;
|
|
580
|
+
expect(checkoutResponseValue.ok()).toBeTruthy();
|
|
581
|
+
const checkout = (await checkoutResponseValue.json()).data;
|
|
582
|
+
expectTableIdentity(checkout.orderId);
|
|
583
|
+
expectTableIdentity(checkout.paymentSessionId);
|
|
584
|
+
const startResponse = waitForApiResponse(
|
|
585
|
+
page,
|
|
586
|
+
'POST',
|
|
587
|
+
new RegExp(`/api/payment-session/${checkout.paymentSessionId}/start$`),
|
|
588
|
+
);
|
|
589
|
+
await page.getByRole('button', { name: 'Start payment', exact: true }).click();
|
|
590
|
+
expect((await startResponse).ok()).toBeTruthy();
|
|
591
|
+
await expect(page.getByText('Payment is being prepared.')).toBeVisible();
|
|
592
|
+
await expect(page.getByRole('heading', { name: 'Mock payment simulator' })).toBeVisible();
|
|
593
|
+
const cancelResponse = waitForApiResponse(
|
|
594
|
+
page,
|
|
595
|
+
'POST',
|
|
596
|
+
new RegExp(`/api/pay/mock/payment-session/${checkout.paymentSessionId}/complete$`),
|
|
597
|
+
);
|
|
598
|
+
await page.getByRole('button', { name: 'Cancel payment', exact: true }).click();
|
|
599
|
+
expect((await cancelResponse).ok()).toBeTruthy();
|
|
600
|
+
await expect(page).toHaveURL(new RegExp(`/commerce/order/${checkout.orderId}(?:/|$)`), {
|
|
601
|
+
timeout: 40_000,
|
|
602
|
+
});
|
|
603
|
+
await expect(page.getByText('cancelled · $45.99')).toBeVisible();
|
|
604
|
+
await expect(page.getByRole('alert')).toHaveCount(0);
|
|
605
|
+
expect(pageErrors).toEqual([]);
|
|
606
|
+
} finally {
|
|
607
|
+
await context.close().catch(() => {});
|
|
608
|
+
}
|
|
609
|
+
},
|
|
610
|
+
);
|
|
611
|
+
|
|
528
612
|
test(
|
|
529
613
|
'Phase 60: customer requests and operator executes a whole-order refund',
|
|
530
614
|
{ tag: ['@web', '@admin', '@flow', '@payment', '@refund'] },
|
|
@@ -558,15 +642,30 @@ test(
|
|
|
558
642
|
await page.getByRole('radio', { name: 'No coupon', exact: true }).check();
|
|
559
643
|
const checkoutResponse = waitForApiResponse(page, 'POST', '/api/commerce/trade/checkout');
|
|
560
644
|
await page.getByRole('button', { name: 'Create order', exact: true }).click();
|
|
561
|
-
const
|
|
562
|
-
|
|
645
|
+
const checkoutResponseValue = await checkoutResponse;
|
|
646
|
+
expect(checkoutResponseValue.ok()).toBeTruthy();
|
|
647
|
+
const checkout = (await checkoutResponseValue.json()).data;
|
|
648
|
+
expectTableIdentity(checkout.orderId);
|
|
649
|
+
expectTableIdentity(checkout.paymentAttemptId);
|
|
650
|
+
expectTableIdentity(checkout.paymentSessionId);
|
|
651
|
+
await expect(page.getByRole('heading', { name: 'Payment', exact: true })).toBeVisible();
|
|
652
|
+
const startResponse = waitForApiResponse(
|
|
563
653
|
page,
|
|
564
654
|
'POST',
|
|
565
|
-
new RegExp(`/api/
|
|
655
|
+
new RegExp(`/api/payment-session/${checkout.paymentSessionId}/start$`),
|
|
656
|
+
);
|
|
657
|
+
await page.getByRole('button', { name: 'Start payment', exact: true }).click();
|
|
658
|
+
expect((await startResponse).ok()).toBeTruthy();
|
|
659
|
+
await expect(page.getByText('Payment is being prepared.')).toBeVisible();
|
|
660
|
+
await expect(page.getByRole('heading', { name: 'Mock payment simulator' })).toBeVisible();
|
|
661
|
+
const completeResponse = waitForApiResponse(
|
|
662
|
+
page,
|
|
663
|
+
'POST',
|
|
664
|
+
new RegExp(`/api/pay/mock/payment-session/${checkout.paymentSessionId}/complete$`),
|
|
566
665
|
);
|
|
567
666
|
await page.getByRole('button', { name: 'Payment succeeded', exact: true }).click();
|
|
568
|
-
expect((await
|
|
569
|
-
await expect(page.getByText('paid · $45.99')).toBeVisible();
|
|
667
|
+
expect((await completeResponse).ok()).toBeTruthy();
|
|
668
|
+
await expect(page.getByText('paid · $45.99')).toBeVisible({ timeout: 40_000 });
|
|
570
669
|
|
|
571
670
|
const requestResponse = waitForApiResponse(
|
|
572
671
|
page,
|
|
@@ -591,9 +690,7 @@ test(
|
|
|
591
690
|
'data-zova-hydrated',
|
|
592
691
|
'commerceAdmin',
|
|
593
692
|
);
|
|
594
|
-
const orderRow = adminPage
|
|
595
|
-
.getByRole('cell', { name: String(checkout.orderId), exact: true })
|
|
596
|
-
.locator('..');
|
|
693
|
+
const orderRow = await getAdminOrderRow(adminPage, checkout.orderId);
|
|
597
694
|
await expect(orderRow).toBeVisible();
|
|
598
695
|
await orderRow.getByPlaceholder('Decision reason').fill('E2E approval');
|
|
599
696
|
await orderRow.getByRole('checkbox').check();
|
|
@@ -722,7 +819,7 @@ test(
|
|
|
722
819
|
async ({ page, request }) => {
|
|
723
820
|
const routes = [
|
|
724
821
|
['/commerce/checkout', '/checkout'],
|
|
725
|
-
['/commerce/payment/1', '/payment/1'],
|
|
822
|
+
['/commerce/payment/1/1', '/payment/1/1'],
|
|
726
823
|
['/commerce/orders', '/orders'],
|
|
727
824
|
['/commerce/order/1', '/order/1'],
|
|
728
825
|
] as const;
|
|
@@ -736,7 +833,7 @@ test(
|
|
|
736
833
|
expect(html, path).not.toContain('Payment succeeded');
|
|
737
834
|
expect(html, path).not.toContain('Order #');
|
|
738
835
|
expect(html, path).not.toContain('Checkout');
|
|
739
|
-
expect(html, path).not.toContain('Mock payment');
|
|
836
|
+
expect(html, path).not.toContain('Mock payment simulator');
|
|
740
837
|
expect(html, path).not.toContain('My orders');
|
|
741
838
|
|
|
742
839
|
const pageErrors = collectPageErrors(page);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cabloy",
|
|
3
|
-
"version": "5.1.
|
|
3
|
+
"version": "5.1.124",
|
|
4
4
|
"gitHead": "2c5c19284bab738e492856189acb6fad74b8a7b7",
|
|
5
5
|
"description": "A Node.js fullstack framework",
|
|
6
6
|
"keywords": [
|
|
@@ -77,6 +77,7 @@
|
|
|
77
77
|
"prepare": "husky"
|
|
78
78
|
},
|
|
79
79
|
"devDependencies": {
|
|
80
|
+
"@cabloy/dotenv": "^1.2.8",
|
|
80
81
|
"@cabloy/lint": "^5.1.27",
|
|
81
82
|
"@cabloy/process-helper": "^3.1.3",
|
|
82
83
|
"@playwright/test": "^1.61.1",
|