@open-mercato/core 0.4.5-develop-2e9903a57a → 0.4.5-develop-eeccf7adf4
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/package.json +2 -2
- package/dist/modules/auth/__integration__/TC-AUTH-001.spec.js +0 -9
- package/dist/modules/auth/__integration__/TC-AUTH-001.spec.js.map +0 -7
- package/dist/modules/auth/__integration__/TC-AUTH-002.spec.js +0 -22
- package/dist/modules/auth/__integration__/TC-AUTH-002.spec.js.map +0 -7
- package/dist/modules/auth/__integration__/TC-AUTH-003.spec.js +0 -21
- package/dist/modules/auth/__integration__/TC-AUTH-003.spec.js.map +0 -7
- package/dist/modules/auth/__integration__/TC-AUTH-004.spec.js +0 -15
- package/dist/modules/auth/__integration__/TC-AUTH-004.spec.js.map +0 -7
- package/dist/modules/auth/__integration__/TC-AUTH-005.spec.js +0 -11
- package/dist/modules/auth/__integration__/TC-AUTH-005.spec.js.map +0 -7
- package/dist/modules/auth/__integration__/TC-AUTH-006.spec.js +0 -11
- package/dist/modules/auth/__integration__/TC-AUTH-006.spec.js.map +0 -7
- package/dist/modules/auth/__integration__/TC-AUTH-007.spec.js +0 -14
- package/dist/modules/auth/__integration__/TC-AUTH-007.spec.js.map +0 -7
- package/dist/modules/auth/__integration__/TC-AUTH-008.spec.js +0 -26
- package/dist/modules/auth/__integration__/TC-AUTH-008.spec.js.map +0 -7
- package/dist/modules/auth/__integration__/TC-AUTH-009.spec.js +0 -16
- package/dist/modules/auth/__integration__/TC-AUTH-009.spec.js.map +0 -7
- package/dist/modules/auth/__integration__/TC-AUTH-010.spec.js +0 -32
- package/dist/modules/auth/__integration__/TC-AUTH-010.spec.js.map +0 -7
- package/dist/modules/auth/__integration__/TC-AUTH-011.spec.js +0 -26
- package/dist/modules/auth/__integration__/TC-AUTH-011.spec.js.map +0 -7
- package/dist/modules/auth/__integration__/TC-AUTH-012.spec.js +0 -30
- package/dist/modules/auth/__integration__/TC-AUTH-012.spec.js.map +0 -7
- package/dist/modules/auth/__integration__/TC-AUTH-013.spec.js +0 -41
- package/dist/modules/auth/__integration__/TC-AUTH-013.spec.js.map +0 -7
- package/dist/modules/auth/__integration__/TC-AUTH-014.spec.js +0 -25
- package/dist/modules/auth/__integration__/TC-AUTH-014.spec.js.map +0 -7
- package/dist/modules/auth/__integration__/TC-AUTH-015.spec.js +0 -20
- package/dist/modules/auth/__integration__/TC-AUTH-015.spec.js.map +0 -7
- package/dist/modules/auth/__integration__/TC-AUTH-016.spec.js +0 -76
- package/dist/modules/auth/__integration__/TC-AUTH-016.spec.js.map +0 -7
- package/dist/modules/catalog/__integration__/TC-CAT-001.spec.js +0 -20
- package/dist/modules/catalog/__integration__/TC-CAT-001.spec.js.map +0 -7
- package/dist/modules/catalog/__integration__/TC-CAT-002.spec.js +0 -12
- package/dist/modules/catalog/__integration__/TC-CAT-002.spec.js.map +0 -7
- package/dist/modules/catalog/__integration__/TC-CAT-003.spec.js +0 -28
- package/dist/modules/catalog/__integration__/TC-CAT-003.spec.js.map +0 -7
- package/dist/modules/catalog/__integration__/TC-CAT-004.spec.js +0 -33
- package/dist/modules/catalog/__integration__/TC-CAT-004.spec.js.map +0 -7
- package/dist/modules/catalog/__integration__/TC-CAT-005.spec.js +0 -30
- package/dist/modules/catalog/__integration__/TC-CAT-005.spec.js.map +0 -7
- package/dist/modules/catalog/__integration__/TC-CAT-006.spec.js +0 -31
- package/dist/modules/catalog/__integration__/TC-CAT-006.spec.js.map +0 -7
- package/dist/modules/catalog/__integration__/TC-CAT-007.spec.js +0 -31
- package/dist/modules/catalog/__integration__/TC-CAT-007.spec.js.map +0 -7
- package/dist/modules/catalog/__integration__/TC-CAT-008.spec.js +0 -65
- package/dist/modules/catalog/__integration__/TC-CAT-008.spec.js.map +0 -7
- package/dist/modules/catalog/__integration__/TC-CAT-009.spec.js +0 -31
- package/dist/modules/catalog/__integration__/TC-CAT-009.spec.js.map +0 -7
- package/dist/modules/catalog/__integration__/TC-CAT-010.spec.js +0 -28
- package/dist/modules/catalog/__integration__/TC-CAT-010.spec.js.map +0 -7
- package/dist/modules/catalog/__integration__/TC-CAT-011.spec.js +0 -34
- package/dist/modules/catalog/__integration__/TC-CAT-011.spec.js.map +0 -7
- package/dist/modules/catalog/__integration__/TC-CAT-012.spec.js +0 -27
- package/dist/modules/catalog/__integration__/TC-CAT-012.spec.js.map +0 -7
- package/dist/modules/core/__integration__/admin/TC-ADMIN-001.spec.js +0 -44
- package/dist/modules/core/__integration__/admin/TC-ADMIN-001.spec.js.map +0 -7
- package/dist/modules/core/__integration__/admin/TC-ADMIN-002.spec.js +0 -53
- package/dist/modules/core/__integration__/admin/TC-ADMIN-002.spec.js.map +0 -7
- package/dist/modules/core/__integration__/admin/TC-ADMIN-003.spec.js +0 -26
- package/dist/modules/core/__integration__/admin/TC-ADMIN-003.spec.js.map +0 -7
- package/dist/modules/core/__integration__/admin/TC-ADMIN-004.spec.js +0 -47
- package/dist/modules/core/__integration__/admin/TC-ADMIN-004.spec.js.map +0 -7
- package/dist/modules/core/__integration__/admin/TC-ADMIN-005.spec.js +0 -33
- package/dist/modules/core/__integration__/admin/TC-ADMIN-005.spec.js.map +0 -7
- package/dist/modules/core/__integration__/admin/TC-ADMIN-006.spec.js +0 -30
- package/dist/modules/core/__integration__/admin/TC-ADMIN-006.spec.js.map +0 -7
- package/dist/modules/core/__integration__/admin/TC-ADMIN-007.spec.js +0 -36
- package/dist/modules/core/__integration__/admin/TC-ADMIN-007.spec.js.map +0 -7
- package/dist/modules/core/__integration__/admin/TC-ADMIN-008.spec.js +0 -113
- package/dist/modules/core/__integration__/admin/TC-ADMIN-008.spec.js.map +0 -7
- package/dist/modules/core/__integration__/admin/TC-ADMIN-009.spec.js +0 -25
- package/dist/modules/core/__integration__/admin/TC-ADMIN-009.spec.js.map +0 -7
- package/dist/modules/core/__integration__/admin/TC-ADMIN-010.spec.js +0 -35
- package/dist/modules/core/__integration__/admin/TC-ADMIN-010.spec.js.map +0 -7
- package/dist/modules/core/__integration__/helpers/api.js +0 -64
- package/dist/modules/core/__integration__/helpers/api.js.map +0 -7
- package/dist/modules/core/__integration__/helpers/auth.js +0 -98
- package/dist/modules/core/__integration__/helpers/auth.js.map +0 -7
- package/dist/modules/core/__integration__/helpers/authUi.js +0 -31
- package/dist/modules/core/__integration__/helpers/authUi.js.map +0 -7
- package/dist/modules/core/__integration__/helpers/catalogFixtures.js +0 -49
- package/dist/modules/core/__integration__/helpers/catalogFixtures.js.map +0 -7
- package/dist/modules/core/__integration__/helpers/crmFixtures.js +0 -73
- package/dist/modules/core/__integration__/helpers/crmFixtures.js.map +0 -7
- package/dist/modules/core/__integration__/helpers/salesFixtures.js +0 -63
- package/dist/modules/core/__integration__/helpers/salesFixtures.js.map +0 -7
- package/dist/modules/core/__integration__/helpers/salesUi.js +0 -464
- package/dist/modules/core/__integration__/helpers/salesUi.js.map +0 -7
- package/dist/modules/core/__integration__/integration/TC-INT-001.spec.js +0 -26
- package/dist/modules/core/__integration__/integration/TC-INT-001.spec.js.map +0 -7
- package/dist/modules/core/__integration__/integration/TC-INT-002.spec.js +0 -60
- package/dist/modules/core/__integration__/integration/TC-INT-002.spec.js.map +0 -7
- package/dist/modules/core/__integration__/integration/TC-INT-003.spec.js +0 -36
- package/dist/modules/core/__integration__/integration/TC-INT-003.spec.js.map +0 -7
- package/dist/modules/core/__integration__/integration/TC-INT-004.spec.js +0 -74
- package/dist/modules/core/__integration__/integration/TC-INT-004.spec.js.map +0 -7
- package/dist/modules/core/__integration__/integration/TC-INT-005.spec.js +0 -21
- package/dist/modules/core/__integration__/integration/TC-INT-005.spec.js.map +0 -7
- package/dist/modules/customers/__integration__/TC-CRM-001.spec.js +0 -32
- package/dist/modules/customers/__integration__/TC-CRM-001.spec.js.map +0 -7
- package/dist/modules/customers/__integration__/TC-CRM-002.spec.js +0 -35
- package/dist/modules/customers/__integration__/TC-CRM-002.spec.js.map +0 -7
- package/dist/modules/customers/__integration__/TC-CRM-003.spec.js +0 -40
- package/dist/modules/customers/__integration__/TC-CRM-003.spec.js.map +0 -7
- package/dist/modules/customers/__integration__/TC-CRM-004.spec.js +0 -40
- package/dist/modules/customers/__integration__/TC-CRM-004.spec.js.map +0 -7
- package/dist/modules/customers/__integration__/TC-CRM-005.spec.js +0 -37
- package/dist/modules/customers/__integration__/TC-CRM-005.spec.js.map +0 -7
- package/dist/modules/customers/__integration__/TC-CRM-006.spec.js +0 -42
- package/dist/modules/customers/__integration__/TC-CRM-006.spec.js.map +0 -7
- package/dist/modules/customers/__integration__/TC-CRM-007.spec.js +0 -44
- package/dist/modules/customers/__integration__/TC-CRM-007.spec.js.map +0 -7
- package/dist/modules/customers/__integration__/TC-CRM-008.spec.js +0 -50
- package/dist/modules/customers/__integration__/TC-CRM-008.spec.js.map +0 -7
- package/dist/modules/customers/__integration__/TC-CRM-009.spec.js +0 -33
- package/dist/modules/customers/__integration__/TC-CRM-009.spec.js.map +0 -7
- package/dist/modules/customers/__integration__/TC-CRM-010.spec.js +0 -39
- package/dist/modules/customers/__integration__/TC-CRM-010.spec.js.map +0 -7
- package/dist/modules/customers/__integration__/TC-CRM-011.spec.js +0 -37
- package/dist/modules/customers/__integration__/TC-CRM-011.spec.js.map +0 -7
- package/dist/modules/customers/__integration__/TC-CRM-012.spec.js +0 -38
- package/dist/modules/customers/__integration__/TC-CRM-012.spec.js.map +0 -7
- package/dist/modules/customers/__integration__/TC-CRM-013.spec.js +0 -43
- package/dist/modules/customers/__integration__/TC-CRM-013.spec.js.map +0 -7
- package/dist/modules/customers/__integration__/TC-CRM-014.spec.js +0 -23
- package/dist/modules/customers/__integration__/TC-CRM-014.spec.js.map +0 -7
- package/dist/modules/customers/__integration__/TC-CRM-015.spec.js +0 -63
- package/dist/modules/customers/__integration__/TC-CRM-015.spec.js.map +0 -7
- package/dist/modules/customers/__integration__/TC-CRM-016.spec.js +0 -46
- package/dist/modules/customers/__integration__/TC-CRM-016.spec.js.map +0 -7
- package/dist/modules/customers/__integration__/TC-CRM-017.spec.js +0 -29
- package/dist/modules/customers/__integration__/TC-CRM-017.spec.js.map +0 -7
- package/dist/modules/customers/__integration__/TC-CRM-018.spec.js +0 -52
- package/dist/modules/customers/__integration__/TC-CRM-018.spec.js.map +0 -7
- package/dist/modules/customers/__integration__/TC-CRM-019.spec.js +0 -37
- package/dist/modules/customers/__integration__/TC-CRM-019.spec.js.map +0 -7
- package/dist/modules/customers/__integration__/TC-CRM-020.spec.js +0 -65
- package/dist/modules/customers/__integration__/TC-CRM-020.spec.js.map +0 -7
- package/dist/modules/progress/__integration__/TC-PROG-001.spec.js +0 -51
- package/dist/modules/progress/__integration__/TC-PROG-001.spec.js.map +0 -7
- package/dist/modules/resources/__integration__/TC-INT-007.spec.js +0 -88
- package/dist/modules/resources/__integration__/TC-INT-007.spec.js.map +0 -7
- package/dist/modules/resources/__integration__/helpers/resourcesFixtures.js +0 -45
- package/dist/modules/resources/__integration__/helpers/resourcesFixtures.js.map +0 -7
- package/dist/modules/sales/__integration__/TC-SALES-001.spec.js +0 -20
- package/dist/modules/sales/__integration__/TC-SALES-001.spec.js.map +0 -7
- package/dist/modules/sales/__integration__/TC-SALES-002.spec.js +0 -31
- package/dist/modules/sales/__integration__/TC-SALES-002.spec.js.map +0 -7
- package/dist/modules/sales/__integration__/TC-SALES-003.spec.js +0 -13
- package/dist/modules/sales/__integration__/TC-SALES-003.spec.js.map +0 -7
- package/dist/modules/sales/__integration__/TC-SALES-004.spec.js +0 -14
- package/dist/modules/sales/__integration__/TC-SALES-004.spec.js.map +0 -7
- package/dist/modules/sales/__integration__/TC-SALES-005.spec.js +0 -15
- package/dist/modules/sales/__integration__/TC-SALES-005.spec.js.map +0 -7
- package/dist/modules/sales/__integration__/TC-SALES-006.spec.js +0 -20
- package/dist/modules/sales/__integration__/TC-SALES-006.spec.js.map +0 -7
- package/dist/modules/sales/__integration__/TC-SALES-007.spec.js +0 -19
- package/dist/modules/sales/__integration__/TC-SALES-007.spec.js.map +0 -7
- package/dist/modules/sales/__integration__/TC-SALES-008.spec.js +0 -7
- package/dist/modules/sales/__integration__/TC-SALES-008.spec.js.map +0 -7
- package/dist/modules/sales/__integration__/TC-SALES-009.spec.js +0 -7
- package/dist/modules/sales/__integration__/TC-SALES-009.spec.js.map +0 -7
- package/dist/modules/sales/__integration__/TC-SALES-010.spec.js +0 -16
- package/dist/modules/sales/__integration__/TC-SALES-010.spec.js.map +0 -7
- package/dist/modules/sales/__integration__/TC-SALES-011.spec.js +0 -20
- package/dist/modules/sales/__integration__/TC-SALES-011.spec.js.map +0 -7
- package/dist/modules/sales/__integration__/TC-SALES-012.spec.js +0 -7
- package/dist/modules/sales/__integration__/TC-SALES-012.spec.js.map +0 -7
- package/dist/modules/sales/__integration__/TC-SALES-013.spec.js +0 -66
- package/dist/modules/sales/__integration__/TC-SALES-013.spec.js.map +0 -7
- package/dist/modules/sales/__integration__/TC-SALES-014.spec.js +0 -13
- package/dist/modules/sales/__integration__/TC-SALES-014.spec.js.map +0 -7
- package/dist/modules/sales/__integration__/TC-SALES-015.spec.js +0 -13
- package/dist/modules/sales/__integration__/TC-SALES-015.spec.js.map +0 -7
- package/dist/modules/sales/__integration__/TC-SALES-016.spec.js +0 -13
- package/dist/modules/sales/__integration__/TC-SALES-016.spec.js.map +0 -7
- package/dist/modules/sales/__integration__/TC-SALES-017.spec.js +0 -44
- package/dist/modules/sales/__integration__/TC-SALES-017.spec.js.map +0 -7
- package/dist/modules/sales/__integration__/TC-SALES-018.spec.js +0 -18
- package/dist/modules/sales/__integration__/TC-SALES-018.spec.js.map +0 -7
- package/dist/modules/sales/__integration__/TC-SALES-019.spec.js +0 -16
- package/dist/modules/sales/__integration__/TC-SALES-019.spec.js.map +0 -7
- package/dist/modules/sales/__integration__/TC-SALES-020.spec.js +0 -75
- package/dist/modules/sales/__integration__/TC-SALES-020.spec.js.map +0 -7
- package/dist/modules/staff/__integration__/TC-INT-006.spec.js +0 -64
- package/dist/modules/staff/__integration__/TC-INT-006.spec.js.map +0 -7
- package/dist/modules/translations/__integration__/TC-TRANS-001.spec.js +0 -48
- package/dist/modules/translations/__integration__/TC-TRANS-001.spec.js.map +0 -7
- package/dist/modules/translations/__integration__/TC-TRANS-002.spec.js +0 -94
- package/dist/modules/translations/__integration__/TC-TRANS-002.spec.js.map +0 -7
- package/dist/modules/translations/__integration__/TC-TRANS-003.spec.js +0 -61
- package/dist/modules/translations/__integration__/TC-TRANS-003.spec.js.map +0 -7
- package/dist/modules/translations/__integration__/TC-TRANS-004.spec.js +0 -52
- package/dist/modules/translations/__integration__/TC-TRANS-004.spec.js.map +0 -7
- package/dist/modules/translations/__integration__/TC-TRANS-005.spec.js +0 -106
- package/dist/modules/translations/__integration__/TC-TRANS-005.spec.js.map +0 -7
- package/dist/modules/translations/__integration__/TC-TRANS-006.spec.js +0 -94
- package/dist/modules/translations/__integration__/TC-TRANS-006.spec.js.map +0 -7
- package/dist/modules/translations/__integration__/TC-TRANS-007.spec.js +0 -62
- package/dist/modules/translations/__integration__/TC-TRANS-007.spec.js.map +0 -7
- package/dist/modules/translations/__integration__/TC-TRANS-008.spec.js +0 -168
- package/dist/modules/translations/__integration__/TC-TRANS-008.spec.js.map +0 -7
- package/dist/modules/translations/__integration__/helpers/translationFixtures.js +0 -63
- package/dist/modules/translations/__integration__/helpers/translationFixtures.js.map +0 -7
- package/dist/modules/workflows/__integration__/TC-WF-001.spec.js +0 -73
- package/dist/modules/workflows/__integration__/TC-WF-001.spec.js.map +0 -7
- package/src/__tests__/module-decoupling.test.ts +0 -356
- package/src/modules/api_keys/api/__tests__/keys.route.test.ts +0 -244
- package/src/modules/attachments/api/__tests__/attachments.api.test.ts +0 -240
- package/src/modules/attachments/components/__tests__/AttachmentContentPreview.test.tsx +0 -45
- package/src/modules/attachments/data/__tests__/entities-ocr.test.ts +0 -15
- package/src/modules/attachments/lib/__tests__/ocr-config.test.ts +0 -27
- package/src/modules/attachments/lib/__tests__/textExtraction.test.ts +0 -64
- package/src/modules/audit_logs/api/__tests__/access.route.test.ts +0 -118
- package/src/modules/audit_logs/api/__tests__/redo.route.test.ts +0 -131
- package/src/modules/audit_logs/api/__tests__/undo.route.test.ts +0 -103
- package/src/modules/audit_logs/services/__tests__/actionLogService.test.ts +0 -26
- package/src/modules/auth/__integration__/TC-AUTH-001.spec.ts +0 -13
- package/src/modules/auth/__integration__/TC-AUTH-002.spec.ts +0 -30
- package/src/modules/auth/__integration__/TC-AUTH-003.spec.ts +0 -28
- package/src/modules/auth/__integration__/TC-AUTH-004.spec.ts +0 -21
- package/src/modules/auth/__integration__/TC-AUTH-005.spec.ts +0 -17
- package/src/modules/auth/__integration__/TC-AUTH-006.spec.ts +0 -17
- package/src/modules/auth/__integration__/TC-AUTH-007.spec.ts +0 -19
- package/src/modules/auth/__integration__/TC-AUTH-008.spec.ts +0 -31
- package/src/modules/auth/__integration__/TC-AUTH-009.spec.ts +0 -22
- package/src/modules/auth/__integration__/TC-AUTH-010.spec.ts +0 -39
- package/src/modules/auth/__integration__/TC-AUTH-011.spec.ts +0 -35
- package/src/modules/auth/__integration__/TC-AUTH-012.spec.ts +0 -36
- package/src/modules/auth/__integration__/TC-AUTH-013.spec.ts +0 -48
- package/src/modules/auth/__integration__/TC-AUTH-014.spec.ts +0 -31
- package/src/modules/auth/__integration__/TC-AUTH-015.spec.ts +0 -28
- package/src/modules/auth/__integration__/TC-AUTH-016.spec.ts +0 -109
- package/src/modules/auth/__tests__/cli-rotate-encryption.test.ts +0 -97
- package/src/modules/auth/__tests__/cli-setup-acl.test.ts +0 -148
- package/src/modules/auth/api/__tests__/feature-check.test.ts +0 -65
- package/src/modules/auth/api/__tests__/login.test.ts +0 -47
- package/src/modules/auth/commands/__tests__/roles.custom-fields.test.ts +0 -126
- package/src/modules/auth/commands/__tests__/users.custom-fields.test.ts +0 -147
- package/src/modules/auth/lib/__tests__/rateLimitCheck.test.ts +0 -224
- package/src/modules/auth/services/__tests__/authService.test.ts +0 -32
- package/src/modules/auth/services/__tests__/rbacService.test.ts +0 -814
- package/src/modules/business_rules/api/__tests__/execute.route.test.ts +0 -311
- package/src/modules/business_rules/api/__tests__/logs-detail.route.test.ts +0 -181
- package/src/modules/business_rules/api/__tests__/logs.route.test.ts +0 -261
- package/src/modules/business_rules/api/__tests__/rules-detail.route.test.ts +0 -115
- package/src/modules/business_rules/api/__tests__/rules.route.test.ts +0 -746
- package/src/modules/business_rules/api/__tests__/sets-detail.route.test.ts +0 -169
- package/src/modules/business_rules/api/__tests__/sets-members.route.test.ts +0 -367
- package/src/modules/business_rules/api/__tests__/sets.route.test.ts +0 -361
- package/src/modules/business_rules/api/__tests__/test-helpers.ts +0 -42
- package/src/modules/business_rules/components/utils/__tests__/formHelpers.test.ts +0 -69
- package/src/modules/business_rules/data/__tests__/validators.test.ts +0 -637
- package/src/modules/business_rules/lib/__tests__/action-executor.test.ts +0 -728
- package/src/modules/business_rules/lib/__tests__/expression-evaluator.test.ts +0 -592
- package/src/modules/business_rules/lib/__tests__/rule-engine.test.ts +0 -805
- package/src/modules/business_rules/lib/__tests__/rule-evaluator.test.ts +0 -436
- package/src/modules/catalog/__integration__/TC-CAT-001.spec.ts +0 -32
- package/src/modules/catalog/__integration__/TC-CAT-002.spec.ts +0 -19
- package/src/modules/catalog/__integration__/TC-CAT-003.spec.ts +0 -39
- package/src/modules/catalog/__integration__/TC-CAT-004.spec.ts +0 -41
- package/src/modules/catalog/__integration__/TC-CAT-005.spec.ts +0 -37
- package/src/modules/catalog/__integration__/TC-CAT-006.spec.ts +0 -40
- package/src/modules/catalog/__integration__/TC-CAT-007.spec.ts +0 -37
- package/src/modules/catalog/__integration__/TC-CAT-008.spec.ts +0 -76
- package/src/modules/catalog/__integration__/TC-CAT-009.spec.ts +0 -39
- package/src/modules/catalog/__integration__/TC-CAT-010.spec.ts +0 -36
- package/src/modules/catalog/__integration__/TC-CAT-011.spec.ts +0 -44
- package/src/modules/catalog/__integration__/TC-CAT-012.spec.ts +0 -35
- package/src/modules/catalog/api/__tests__/offers.route.test.ts +0 -161
- package/src/modules/catalog/api/__tests__/prices.route.test.ts +0 -39
- package/src/modules/catalog/api/__tests__/products.route.test.ts +0 -91
- package/src/modules/catalog/api/__tests__/utils.test.ts +0 -36
- package/src/modules/catalog/api/__tests__/variants.route.test.ts +0 -44
- package/src/modules/catalog/backend/catalog/products/__tests__/ProductsDataTable.test.tsx +0 -172
- package/src/modules/catalog/commands/__tests__/products.delete.test.ts +0 -146
- package/src/modules/catalog/commands/__tests__/products.update.test.ts +0 -142
- package/src/modules/catalog/commands/__tests__/registration.test.ts +0 -54
- package/src/modules/catalog/commands/__tests__/shared.test.ts +0 -129
- package/src/modules/catalog/components/__tests__/catalogComponentsRender.test.tsx +0 -373
- package/src/modules/catalog/components/products/__tests__/ProductImageCell.test.tsx +0 -51
- package/src/modules/catalog/components/products/__tests__/productForm.test.ts +0 -32
- package/src/modules/catalog/lib/__tests__/pricing.test.ts +0 -150
- package/src/modules/catalog/services/__tests__/catalogPricingService.test.ts +0 -21
- package/src/modules/configs/components/__tests__/CachePanel.test.tsx +0 -134
- package/src/modules/configs/components/__tests__/SystemStatusPanel.test.tsx +0 -93
- package/src/modules/configs/lib/__tests__/system-status.test.ts +0 -55
- package/src/modules/configs/lib/__tests__/upgrade-actions.test.ts +0 -135
- package/src/modules/core/__integration__/admin/TC-ADMIN-001.spec.ts +0 -70
- package/src/modules/core/__integration__/admin/TC-ADMIN-002.spec.ts +0 -83
- package/src/modules/core/__integration__/admin/TC-ADMIN-003.spec.ts +0 -50
- package/src/modules/core/__integration__/admin/TC-ADMIN-004.spec.ts +0 -77
- package/src/modules/core/__integration__/admin/TC-ADMIN-005.spec.ts +0 -49
- package/src/modules/core/__integration__/admin/TC-ADMIN-006.spec.ts +0 -59
- package/src/modules/core/__integration__/admin/TC-ADMIN-007.spec.ts +0 -68
- package/src/modules/core/__integration__/admin/TC-ADMIN-008.spec.ts +0 -127
- package/src/modules/core/__integration__/admin/TC-ADMIN-009.spec.ts +0 -48
- package/src/modules/core/__integration__/admin/TC-ADMIN-010.spec.ts +0 -57
- package/src/modules/core/__integration__/helpers/api.ts +0 -84
- package/src/modules/core/__integration__/helpers/auth.ts +0 -110
- package/src/modules/core/__integration__/helpers/authUi.ts +0 -33
- package/src/modules/core/__integration__/helpers/catalogFixtures.ts +0 -73
- package/src/modules/core/__integration__/helpers/crmFixtures.ts +0 -101
- package/src/modules/core/__integration__/helpers/salesFixtures.ts +0 -89
- package/src/modules/core/__integration__/helpers/salesUi.ts +0 -528
- package/src/modules/core/__integration__/integration/TC-INT-001.spec.ts +0 -34
- package/src/modules/core/__integration__/integration/TC-INT-002.spec.ts +0 -74
- package/src/modules/core/__integration__/integration/TC-INT-003.spec.ts +0 -43
- package/src/modules/core/__integration__/integration/TC-INT-004.spec.ts +0 -82
- package/src/modules/core/__integration__/integration/TC-INT-005.spec.ts +0 -29
- package/src/modules/currencies/backend/exchange-rates/__tests__/formatDateTimeLocal.test.ts +0 -78
- package/src/modules/currencies/data/__tests__/validators.test.ts +0 -100
- package/src/modules/currencies/services/__tests__/exchangeRateService.test.ts +0 -666
- package/src/modules/currencies/services/__tests__/rateFetchingService.basic.test.ts +0 -398
- package/src/modules/currencies/services/__tests__/rateFetchingService.errors.test.ts +0 -296
- package/src/modules/currencies/services/__tests__/rateFetchingService.providers.test.ts +0 -350
- package/src/modules/currencies/services/__tests__/rateFetchingService.setup.ts +0 -188
- package/src/modules/customers/__integration__/TC-CRM-001.spec.ts +0 -42
- package/src/modules/customers/__integration__/TC-CRM-002.spec.ts +0 -47
- package/src/modules/customers/__integration__/TC-CRM-003.spec.ts +0 -55
- package/src/modules/customers/__integration__/TC-CRM-004.spec.ts +0 -57
- package/src/modules/customers/__integration__/TC-CRM-005.spec.ts +0 -50
- package/src/modules/customers/__integration__/TC-CRM-006.spec.ts +0 -60
- package/src/modules/customers/__integration__/TC-CRM-007.spec.ts +0 -57
- package/src/modules/customers/__integration__/TC-CRM-008.spec.ts +0 -62
- package/src/modules/customers/__integration__/TC-CRM-009.spec.ts +0 -46
- package/src/modules/customers/__integration__/TC-CRM-010.spec.ts +0 -49
- package/src/modules/customers/__integration__/TC-CRM-011.spec.ts +0 -47
- package/src/modules/customers/__integration__/TC-CRM-012.spec.ts +0 -49
- package/src/modules/customers/__integration__/TC-CRM-013.spec.ts +0 -61
- package/src/modules/customers/__integration__/TC-CRM-014.spec.ts +0 -31
- package/src/modules/customers/__integration__/TC-CRM-015.spec.ts +0 -89
- package/src/modules/customers/__integration__/TC-CRM-016.spec.ts +0 -55
- package/src/modules/customers/__integration__/TC-CRM-017.spec.ts +0 -37
- package/src/modules/customers/__integration__/TC-CRM-018.spec.ts +0 -62
- package/src/modules/customers/__integration__/TC-CRM-019.spec.ts +0 -44
- package/src/modules/customers/__integration__/TC-CRM-020.spec.ts +0 -73
- package/src/modules/customers/api/__tests__/utils.test.ts +0 -61
- package/src/modules/customers/api/dashboard/widgets/new-deals/__tests__/route.test.ts +0 -54
- package/src/modules/customers/commands/__tests__/shared.test.ts +0 -263
- package/src/modules/customers/commands/__tests__/undo.custom-fields.test.ts +0 -1184
- package/src/modules/customers/components/detail/__tests__/ActivityForm.validation.test.ts +0 -37
- package/src/modules/customers/components/detail/__tests__/DealForm.validation.test.ts +0 -45
- package/src/modules/customers/components/detail/__tests__/InlineEditors.test.tsx +0 -166
- package/src/modules/customers/components/detail/__tests__/TaskForm.submit.test.ts +0 -21
- package/src/modules/customers/components/detail/hooks/__tests__/useCustomerDictionary.test.ts +0 -97
- package/src/modules/customers/lib/__tests__/customFieldRouting.test.ts +0 -107
- package/src/modules/customers/utils/__tests__/addressFormat.test.ts +0 -105
- package/src/modules/customers/utils/__tests__/phoneDuplicates.test.ts +0 -98
- package/src/modules/dashboards/__tests__/widgets.test.ts +0 -70
- package/src/modules/dashboards/lib/__tests__/aggregations.test.ts +0 -328
- package/src/modules/dashboards/lib/__tests__/formatters.test.ts +0 -128
- package/src/modules/directory/backend/directory/organizations/__tests__/create-submit.test.ts +0 -46
- package/src/modules/directory/backend/directory/organizations/__tests__/edit-submit.test.ts +0 -49
- package/src/modules/directory/components/__tests__/OrganizationSelect.test.tsx +0 -71
- package/src/modules/directory/components/__tests__/TenantSelect.test.tsx +0 -75
- package/src/modules/entities/__tests__/cli-decrypt-database.test.ts +0 -534
- package/src/modules/entities/__tests__/cli-rotate-encryption.test.ts +0 -123
- package/src/modules/entities/api/__tests__/encryption.api.test.ts +0 -57
- package/src/modules/entities/api/__tests__/records.get.custom-entity.test.ts +0 -43
- package/src/modules/entities/api/__tests__/records.validation.test.ts +0 -53
- package/src/modules/entities/backend/entities/user/__tests__/create-entity-submit.test.ts +0 -47
- package/src/modules/entities/backend/entities/user/__tests__/records-submit.test.ts +0 -104
- package/src/modules/feature_toggles/commands/__tests__/global.test.ts +0 -325
- package/src/modules/feature_toggles/commands/__tests__/overrides.test.ts +0 -186
- package/src/modules/feature_toggles/lib/__tests__/feature-flag-check.test.ts +0 -365
- package/src/modules/feature_toggles/lib/__tests__/queries.test.ts +0 -130
- package/src/modules/inbox_ops/api/emails/[id]/reprocess/__tests__/route.test.ts +0 -194
- package/src/modules/inbox_ops/api/proposals/[id]/__tests__/route.test.ts +0 -124
- package/src/modules/inbox_ops/api/proposals/[id]/accept-all/__tests__/route.test.ts +0 -154
- package/src/modules/inbox_ops/api/proposals/[id]/actions/[actionId]/__tests__/route.test.ts +0 -200
- package/src/modules/inbox_ops/api/proposals/[id]/actions/[actionId]/accept/__tests__/route.test.ts +0 -261
- package/src/modules/inbox_ops/api/proposals/[id]/actions/[actionId]/reject/__tests__/route.test.ts +0 -201
- package/src/modules/inbox_ops/api/proposals/[id]/reject/__tests__/route.test.ts +0 -123
- package/src/modules/inbox_ops/api/proposals/[id]/replies/[replyId]/send/__tests__/route.test.ts +0 -232
- package/src/modules/inbox_ops/api/proposals/[id]/translate/__tests__/route.test.ts +0 -173
- package/src/modules/inbox_ops/api/proposals/__tests__/route.test.ts +0 -185
- package/src/modules/inbox_ops/api/webhook/__tests__/inbound.test.ts +0 -317
- package/src/modules/inbox_ops/data/__tests__/validators.test.ts +0 -463
- package/src/modules/inbox_ops/lib/__tests__/catalogLookup.test.ts +0 -143
- package/src/modules/inbox_ops/lib/__tests__/contactMatcher.test.ts +0 -158
- package/src/modules/inbox_ops/lib/__tests__/emailParser.test.ts +0 -191
- package/src/modules/inbox_ops/lib/__tests__/executionEngine.test.ts +0 -1419
- package/src/modules/inbox_ops/lib/__tests__/extractionPrompt.test.ts +0 -151
- package/src/modules/inbox_ops/lib/__tests__/priceValidator.test.ts +0 -259
- package/src/modules/inbox_ops/lib/__tests__/translationProvider.test.ts +0 -99
- package/src/modules/inbox_ops/subscribers/__tests__/extractionWorker.test.ts +0 -803
- package/src/modules/notifications/__tests__/deliver-notification.test.ts +0 -285
- package/src/modules/notifications/__tests__/deliveryStrategies.test.ts +0 -19
- package/src/modules/notifications/__tests__/notificationService.test.ts +0 -248
- package/src/modules/planner/__tests__/availabilityMerge.test.ts +0 -99
- package/src/modules/planner/__tests__/plannerAvailabilityService.test.ts +0 -89
- package/src/modules/planner/data/__tests__/validators.test.ts +0 -78
- package/src/modules/progress/__integration__/TC-PROG-001.spec.ts +0 -67
- package/src/modules/progress/__tests__/progressService.test.ts +0 -377
- package/src/modules/query_index/__tests__/hybrid-engine.test.ts +0 -365
- package/src/modules/query_index/__tests__/indexer.test.ts +0 -175
- package/src/modules/resources/__integration__/TC-INT-007.spec.ts +0 -110
- package/src/modules/resources/__integration__/helpers/resourcesFixtures.ts +0 -50
- package/src/modules/resources/data/__tests__/validators.test.ts +0 -65
- package/src/modules/sales/__integration__/TC-SALES-001.spec.ts +0 -26
- package/src/modules/sales/__integration__/TC-SALES-002.spec.ts +0 -38
- package/src/modules/sales/__integration__/TC-SALES-003.spec.ts +0 -18
- package/src/modules/sales/__integration__/TC-SALES-004.spec.ts +0 -19
- package/src/modules/sales/__integration__/TC-SALES-005.spec.ts +0 -21
- package/src/modules/sales/__integration__/TC-SALES-006.spec.ts +0 -26
- package/src/modules/sales/__integration__/TC-SALES-007.spec.ts +0 -23
- package/src/modules/sales/__integration__/TC-SALES-008.spec.ts +0 -11
- package/src/modules/sales/__integration__/TC-SALES-009.spec.ts +0 -12
- package/src/modules/sales/__integration__/TC-SALES-010.spec.ts +0 -20
- package/src/modules/sales/__integration__/TC-SALES-011.spec.ts +0 -26
- package/src/modules/sales/__integration__/TC-SALES-012.spec.ts +0 -12
- package/src/modules/sales/__integration__/TC-SALES-013.spec.ts +0 -73
- package/src/modules/sales/__integration__/TC-SALES-014.spec.ts +0 -17
- package/src/modules/sales/__integration__/TC-SALES-015.spec.ts +0 -17
- package/src/modules/sales/__integration__/TC-SALES-016.spec.ts +0 -17
- package/src/modules/sales/__integration__/TC-SALES-017.spec.ts +0 -60
- package/src/modules/sales/__integration__/TC-SALES-018.spec.ts +0 -25
- package/src/modules/sales/__integration__/TC-SALES-019.spec.ts +0 -22
- package/src/modules/sales/__integration__/TC-SALES-020.spec.ts +0 -107
- package/src/modules/sales/api/__tests__/channels.route.test.ts +0 -50
- package/src/modules/sales/api/__tests__/document-history.test.ts +0 -146
- package/src/modules/sales/api/__tests__/documents.factory.test.ts +0 -98
- package/src/modules/sales/api/__tests__/documents.routes.test.ts +0 -149
- package/src/modules/sales/api/__tests__/quotes.acceptance.test.ts +0 -209
- package/src/modules/sales/api/__tests__/timeline.test.tsx +0 -165
- package/src/modules/sales/api/dashboard/widgets/new-orders/__tests__/route.test.ts +0 -112
- package/src/modules/sales/api/dashboard/widgets/new-quotes/__tests__/route.test.ts +0 -116
- package/src/modules/sales/commands/__tests__/documents.cache.test.ts +0 -126
- package/src/modules/sales/commands/__tests__/documents.undo.test.ts +0 -170
- package/src/modules/sales/commands/__tests__/registration.test.ts +0 -141
- package/src/modules/sales/components/__tests__/salesComponentsRender.test.tsx +0 -456
- package/src/modules/sales/lib/__tests__/calculations.test.ts +0 -210
- package/src/modules/sales/services/__tests__/salesCalculationService.test.ts +0 -181
- package/src/modules/sales/services/__tests__/taxCalculationService.test.ts +0 -79
- package/src/modules/sales/widgets/dashboard/new-orders/__tests__/config.test.ts +0 -47
- package/src/modules/sales/widgets/dashboard/new-quotes/__tests__/config.test.ts +0 -47
- package/src/modules/staff/__integration__/TC-INT-006.spec.ts +0 -71
- package/src/modules/staff/data/__tests__/validators.test.ts +0 -60
- package/src/modules/translations/__integration__/TC-TRANS-001.spec.ts +0 -57
- package/src/modules/translations/__integration__/TC-TRANS-002.spec.ts +0 -114
- package/src/modules/translations/__integration__/TC-TRANS-003.spec.ts +0 -71
- package/src/modules/translations/__integration__/TC-TRANS-004.spec.ts +0 -66
- package/src/modules/translations/__integration__/TC-TRANS-005.spec.ts +0 -135
- package/src/modules/translations/__integration__/TC-TRANS-006.spec.ts +0 -113
- package/src/modules/translations/__integration__/TC-TRANS-007.spec.ts +0 -80
- package/src/modules/translations/__integration__/TC-TRANS-008.spec.ts +0 -209
- package/src/modules/translations/__integration__/helpers/translationFixtures.ts +0 -95
- package/src/modules/translations/api/__tests__/locales.test.ts +0 -67
- package/src/modules/translations/data/__tests__/validators.test.ts +0 -143
- package/src/modules/translations/lib/__tests__/extract-record-id.test.ts +0 -75
- package/src/modules/translations/lib/__tests__/helpers.test.ts +0 -215
- package/src/modules/translations/lib/__tests__/locale.test.ts +0 -115
- package/src/modules/translations/lib/__tests__/resolve-field-list.test.ts +0 -176
- package/src/modules/translations/lib/__tests__/translatable-fields.test.ts +0 -79
- package/src/modules/translations/widgets/__tests__/injection-table.test.ts +0 -83
- package/src/modules/workflows/__integration__/TC-WF-001.spec.ts +0 -114
- package/src/modules/workflows/api/__tests__/definitions.route.test.ts +0 -762
- package/src/modules/workflows/api/__tests__/instances.route.test.ts +0 -869
- package/src/modules/workflows/data/__tests__/validators.test.ts +0 -707
- package/src/modules/workflows/lib/__tests__/activity-executor.test.ts +0 -1230
- package/src/modules/workflows/lib/__tests__/call-api.test.ts +0 -421
- package/src/modules/workflows/lib/__tests__/compensation.test.ts +0 -713
- package/src/modules/workflows/lib/__tests__/event-logger.test.ts +0 -615
- package/src/modules/workflows/lib/__tests__/integration.test.ts +0 -693
- package/src/modules/workflows/lib/__tests__/signals.test.ts +0 -566
- package/src/modules/workflows/lib/__tests__/step-handler.test.ts +0 -670
- package/src/modules/workflows/lib/__tests__/sub-workflow.test.ts +0 -934
- package/src/modules/workflows/lib/__tests__/transition-handler.test.ts +0 -925
- package/src/modules/workflows/lib/__tests__/workflow-executor.test.ts +0 -684
|
@@ -1,464 +0,0 @@
|
|
|
1
|
-
import { expect } from "@playwright/test";
|
|
2
|
-
import { apiRequest, getAuthToken } from "./api.js";
|
|
3
|
-
const TEST_WAIT_TIMEOUT_MS = 1e4;
|
|
4
|
-
function escapeRegExp(value) {
|
|
5
|
-
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
6
|
-
}
|
|
7
|
-
function parseCurrencyAmount(value) {
|
|
8
|
-
const normalized = value.replace(/,/g, "");
|
|
9
|
-
const matches = normalized.match(/-?\$[0-9]+(?:\.[0-9]{2})?/g);
|
|
10
|
-
const lastMatch = matches?.[matches.length - 1];
|
|
11
|
-
if (!lastMatch) {
|
|
12
|
-
throw new Error(`Could not parse currency from: ${value}`);
|
|
13
|
-
}
|
|
14
|
-
return Number.parseFloat(lastMatch.replace("$", ""));
|
|
15
|
-
}
|
|
16
|
-
function readId(payload, keys) {
|
|
17
|
-
if (!payload || typeof payload !== "object") return null;
|
|
18
|
-
const map = payload;
|
|
19
|
-
for (const key of keys) {
|
|
20
|
-
const value = map[key];
|
|
21
|
-
if (typeof value === "string" && value.length > 0) return value;
|
|
22
|
-
}
|
|
23
|
-
for (const value of Object.values(map)) {
|
|
24
|
-
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
25
|
-
const nested = readId(value, keys);
|
|
26
|
-
if (nested) return nested;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
return null;
|
|
30
|
-
}
|
|
31
|
-
async function ensureSalesDocumentFixtures(page, options) {
|
|
32
|
-
let customerQuery = options.customerQuery;
|
|
33
|
-
let channelQuery = options.channelQuery;
|
|
34
|
-
if (customerQuery && channelQuery) {
|
|
35
|
-
return { customerQuery, channelQuery };
|
|
36
|
-
}
|
|
37
|
-
const token = await getAuthToken(page.request, "admin").catch(() => null);
|
|
38
|
-
if (!token) {
|
|
39
|
-
if (!customerQuery) {
|
|
40
|
-
customerQuery = `QA Sales Customer ${Date.now()}`;
|
|
41
|
-
await page.goto("/backend/customers/companies/create");
|
|
42
|
-
await page.locator("form").getByRole("textbox").first().fill(customerQuery);
|
|
43
|
-
await page.getByPlaceholder("https://example.com").fill("https://example.com");
|
|
44
|
-
await page.locator("form").getByRole("button", { name: /Create Company/i }).click();
|
|
45
|
-
await expect(page).toHaveURL(/\/backend\/customers\/companies\/[0-9a-f-]{36}$/i);
|
|
46
|
-
}
|
|
47
|
-
if (!channelQuery) {
|
|
48
|
-
const timestamp = Date.now();
|
|
49
|
-
channelQuery = `QA Sales Channel ${timestamp}`;
|
|
50
|
-
const channelCode = `qa-sales-channel-${timestamp}`;
|
|
51
|
-
await page.goto("/backend/sales/channels");
|
|
52
|
-
await page.getByRole("link", { name: /Add channel/i }).click();
|
|
53
|
-
const createForm = page.locator("form").first();
|
|
54
|
-
await createForm.getByRole("textbox").nth(0).fill(channelQuery);
|
|
55
|
-
await createForm.getByRole("textbox").nth(1).fill(channelCode);
|
|
56
|
-
await page.getByRole("button", { name: /Create channel|Create/i }).last().click();
|
|
57
|
-
await expect(page).toHaveURL(/\/backend\/sales\/channels$/i);
|
|
58
|
-
}
|
|
59
|
-
return {
|
|
60
|
-
customerQuery,
|
|
61
|
-
channelQuery
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
if (!customerQuery) {
|
|
65
|
-
const companyName = `QA Sales Customer ${Date.now()}`;
|
|
66
|
-
const companyResponse = await apiRequest(page.request, "POST", "/api/customers/companies", {
|
|
67
|
-
token,
|
|
68
|
-
data: { displayName: companyName }
|
|
69
|
-
}).catch(() => null);
|
|
70
|
-
if (companyResponse && companyResponse.ok()) {
|
|
71
|
-
const companyBody = await companyResponse.json().catch(() => null);
|
|
72
|
-
const companyId = readId(companyBody, ["id", "entityId", "companyId"]);
|
|
73
|
-
if (companyId) {
|
|
74
|
-
await apiRequest(page.request, "POST", "/api/customers/addresses", {
|
|
75
|
-
token,
|
|
76
|
-
data: {
|
|
77
|
-
entityId: companyId,
|
|
78
|
-
name: "Primary",
|
|
79
|
-
purpose: "Shipping",
|
|
80
|
-
addressLine1: "100 QA Street",
|
|
81
|
-
city: "Austin",
|
|
82
|
-
postalCode: "78701",
|
|
83
|
-
country: "US",
|
|
84
|
-
isPrimary: true
|
|
85
|
-
}
|
|
86
|
-
}).catch(() => {
|
|
87
|
-
});
|
|
88
|
-
customerQuery = companyName;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
if (!customerQuery) {
|
|
92
|
-
customerQuery = "Copperleaf";
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
if (!channelQuery) {
|
|
96
|
-
const timestamp = Date.now();
|
|
97
|
-
const channelName = `QA Sales Channel ${timestamp}`;
|
|
98
|
-
const channelCode = `qa-sales-channel-${timestamp}`;
|
|
99
|
-
const channelResponse = await apiRequest(page.request, "POST", "/api/sales/channels", {
|
|
100
|
-
token,
|
|
101
|
-
data: {
|
|
102
|
-
name: channelName,
|
|
103
|
-
code: channelCode
|
|
104
|
-
}
|
|
105
|
-
}).catch(() => null);
|
|
106
|
-
if (channelResponse && channelResponse.ok()) {
|
|
107
|
-
channelQuery = channelName;
|
|
108
|
-
} else {
|
|
109
|
-
channelQuery = "online";
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
return {
|
|
113
|
-
customerQuery: customerQuery ?? "Copperleaf",
|
|
114
|
-
channelQuery: channelQuery ?? "online"
|
|
115
|
-
};
|
|
116
|
-
}
|
|
117
|
-
async function selectFirstAddressIfAvailable(page) {
|
|
118
|
-
const addressSelect = page.locator("select").filter({ has: page.locator("option", { hasText: "Select address" }) }).first();
|
|
119
|
-
if (await addressSelect.count() === 0) return;
|
|
120
|
-
if (!await addressSelect.isEnabled()) return;
|
|
121
|
-
const nextValue = await addressSelect.evaluate((element) => {
|
|
122
|
-
const select = element;
|
|
123
|
-
return select.options.length > 1 ? select.options[1]?.value ?? null : null;
|
|
124
|
-
});
|
|
125
|
-
if (nextValue) {
|
|
126
|
-
await addressSelect.selectOption(nextValue);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
async function createSalesDocument(page, options) {
|
|
130
|
-
const fixtureContext = await ensureSalesDocumentFixtures(page, options);
|
|
131
|
-
const customerQuery = fixtureContext.customerQuery;
|
|
132
|
-
const channelQuery = fixtureContext.channelQuery;
|
|
133
|
-
await page.goto(`/backend/sales/documents/create?kind=${options.kind}`);
|
|
134
|
-
await page.waitForLoadState("networkidle");
|
|
135
|
-
await page.waitForTimeout(500);
|
|
136
|
-
await page.getByText("Document type").click();
|
|
137
|
-
await page.getByRole("textbox", { name: /Search customers/i }).fill(customerQuery);
|
|
138
|
-
await page.waitForTimeout(500);
|
|
139
|
-
const selectButton = page.locator('[role="button"]').filter({ hasText: customerQuery }).getByRole("button", { name: "Select" });
|
|
140
|
-
await selectButton.scrollIntoViewIfNeeded();
|
|
141
|
-
await selectButton.click();
|
|
142
|
-
await page.getByRole("textbox", { name: /Select a channel/i }).fill(channelQuery);
|
|
143
|
-
try {
|
|
144
|
-
await page.getByRole("button", { name: /Select$/i }).filter({ hasText: new RegExp(escapeRegExp(channelQuery), "i") }).first().click({ timeout: 2e3 });
|
|
145
|
-
} catch {
|
|
146
|
-
await page.getByRole("button", { name: /Select$/i }).first().click();
|
|
147
|
-
}
|
|
148
|
-
await selectFirstAddressIfAvailable(page);
|
|
149
|
-
await page.getByRole("button", { name: /^Create$/i }).first().click();
|
|
150
|
-
await expect(page).toHaveURL(new RegExp(`/backend/sales/documents/[0-9a-f-]{36}\\?kind=${options.kind}$`, "i"));
|
|
151
|
-
const match = page.url().match(/\/backend\/sales\/documents\/([0-9a-f-]{36})\?kind=/i);
|
|
152
|
-
if (!match) {
|
|
153
|
-
throw new Error(`Could not resolve document id from URL: ${page.url()}`);
|
|
154
|
-
}
|
|
155
|
-
return match[1];
|
|
156
|
-
}
|
|
157
|
-
function lineDialog(page) {
|
|
158
|
-
return page.getByRole("dialog", { name: /Add line|Edit line/i });
|
|
159
|
-
}
|
|
160
|
-
async function selectFirstOption(container, rowNamePattern) {
|
|
161
|
-
const optionRow = container.getByRole("button", { name: rowNamePattern }).first();
|
|
162
|
-
await optionRow.waitFor({ state: "visible", timeout: 4e3 }).catch(() => {
|
|
163
|
-
});
|
|
164
|
-
if (await optionRow.count() === 0) return;
|
|
165
|
-
const selectButton = optionRow.getByRole("button", { name: /^Select$/i }).first();
|
|
166
|
-
if (await selectButton.count() > 0) {
|
|
167
|
-
await selectButton.click();
|
|
168
|
-
return;
|
|
169
|
-
}
|
|
170
|
-
await optionRow.click();
|
|
171
|
-
}
|
|
172
|
-
async function selectShipmentMethod(dialog) {
|
|
173
|
-
const shippingMethodInput = dialog.getByPlaceholder(/Select method/i).first();
|
|
174
|
-
if (await shippingMethodInput.count() === 0) return;
|
|
175
|
-
await shippingMethodInput.click().catch(() => {
|
|
176
|
-
});
|
|
177
|
-
await shippingMethodInput.press("ControlOrMeta+a").catch(() => {
|
|
178
|
-
});
|
|
179
|
-
await shippingMethodInput.type("Standard", { delay: 20 }).catch(() => {
|
|
180
|
-
});
|
|
181
|
-
await shippingMethodInput.press("Enter").catch(() => {
|
|
182
|
-
});
|
|
183
|
-
await selectFirstOption(dialog, /standard ground|express air|select/i);
|
|
184
|
-
}
|
|
185
|
-
async function selectShipmentStatus(dialog) {
|
|
186
|
-
const statusInput = dialog.getByPlaceholder(/Select shipment status/i).first();
|
|
187
|
-
if (await statusInput.count() > 0) {
|
|
188
|
-
await statusInput.click().catch(() => {
|
|
189
|
-
});
|
|
190
|
-
await statusInput.press("ControlOrMeta+a").catch(() => {
|
|
191
|
-
});
|
|
192
|
-
await statusInput.type("Shipped", { delay: 20 }).catch(() => {
|
|
193
|
-
});
|
|
194
|
-
await statusInput.press("Enter").catch(() => {
|
|
195
|
-
});
|
|
196
|
-
}
|
|
197
|
-
await selectFirstOption(dialog, /shipped.*select|in transit.*select|packed.*select|select/i);
|
|
198
|
-
}
|
|
199
|
-
async function selectShipmentAddress(dialog) {
|
|
200
|
-
const addressInput = dialog.getByPlaceholder(/Select address/i).first();
|
|
201
|
-
if (await addressInput.count() === 0) return;
|
|
202
|
-
const currentValue = await addressInput.inputValue().catch(() => "");
|
|
203
|
-
if (currentValue.trim().length > 0) return;
|
|
204
|
-
if (await addressInput.count() > 0) {
|
|
205
|
-
await addressInput.click().catch(() => {
|
|
206
|
-
});
|
|
207
|
-
await addressInput.press("Enter").catch(() => {
|
|
208
|
-
});
|
|
209
|
-
}
|
|
210
|
-
await selectFirstOption(dialog, /shipping address|select/i);
|
|
211
|
-
}
|
|
212
|
-
async function fillShipmentQuantity(dialog) {
|
|
213
|
-
const quantityInputs = dialog.getByRole("spinbutton");
|
|
214
|
-
const count = await quantityInputs.count();
|
|
215
|
-
for (let index = 0; index < count; index += 1) {
|
|
216
|
-
const input = quantityInputs.nth(index);
|
|
217
|
-
const isVisible = await input.isVisible().catch(() => false);
|
|
218
|
-
const isEnabled = await input.isEnabled().catch(() => false);
|
|
219
|
-
if (!isVisible || !isEnabled) continue;
|
|
220
|
-
await input.click().catch(() => {
|
|
221
|
-
});
|
|
222
|
-
await input.press("ControlOrMeta+a").catch(() => {
|
|
223
|
-
});
|
|
224
|
-
await input.type("1", { delay: 20 }).catch(() => {
|
|
225
|
-
});
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
async function selectShipmentRequiredOptions(dialog) {
|
|
229
|
-
for (let attempt = 0; attempt < 6; attempt += 1) {
|
|
230
|
-
const pendingSelect = dialog.getByRole("button", { name: /^Select$/i }).first();
|
|
231
|
-
if (await pendingSelect.count() === 0) return;
|
|
232
|
-
if (!await pendingSelect.isVisible().catch(() => false)) return;
|
|
233
|
-
await pendingSelect.click().catch(() => {
|
|
234
|
-
});
|
|
235
|
-
await dialog.getByText(/Searching…|Searching\.\.\./i).first().waitFor({ state: "hidden", timeout: 3e3 }).catch(() => {
|
|
236
|
-
});
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
async function fillShipmentDates(dialog) {
|
|
240
|
-
const now = /* @__PURE__ */ new Date();
|
|
241
|
-
const day = String(now.getDate()).padStart(2, "0");
|
|
242
|
-
const month = String(now.getMonth() + 1).padStart(2, "0");
|
|
243
|
-
const year = String(now.getFullYear());
|
|
244
|
-
const shippedDateValue = `${day}/${month}/${year}`;
|
|
245
|
-
const shippedDateInput = dialog.getByLabel(/Shipped date/i).first();
|
|
246
|
-
if (await shippedDateInput.count() > 0) {
|
|
247
|
-
const currentValue = await shippedDateInput.inputValue().catch(() => "");
|
|
248
|
-
if (currentValue.trim().length === 0) {
|
|
249
|
-
await shippedDateInput.fill(shippedDateValue).catch(() => {
|
|
250
|
-
});
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
async function fillShipmentNumber(dialog, shipmentNumber) {
|
|
255
|
-
const shipmentNumberInput = dialog.getByRole("textbox").first();
|
|
256
|
-
if (await shipmentNumberInput.count() === 0) return;
|
|
257
|
-
await shipmentNumberInput.click().catch(() => {
|
|
258
|
-
});
|
|
259
|
-
await shipmentNumberInput.press("ControlOrMeta+a").catch(() => {
|
|
260
|
-
});
|
|
261
|
-
await shipmentNumberInput.type(shipmentNumber, { delay: 20 }).catch(() => {
|
|
262
|
-
});
|
|
263
|
-
await shipmentNumberInput.press("Tab").catch(() => {
|
|
264
|
-
});
|
|
265
|
-
}
|
|
266
|
-
async function addCustomLine(page, options) {
|
|
267
|
-
await page.getByRole("button", { name: /^Items$/i }).click();
|
|
268
|
-
await page.getByRole("button", { name: /Add item/i }).first().click();
|
|
269
|
-
const dialog = lineDialog(page);
|
|
270
|
-
await expect(dialog).toBeVisible();
|
|
271
|
-
await dialog.getByRole("button", { name: /Custom line/i }).click();
|
|
272
|
-
await dialog.getByRole("textbox", { name: /Optional line name/i }).fill(options.name);
|
|
273
|
-
await dialog.getByRole("textbox", { name: "0.00" }).fill(String(options.unitPriceGross));
|
|
274
|
-
await dialog.getByRole("textbox", { name: "1" }).fill(String(options.quantity));
|
|
275
|
-
if (options.taxClassName) {
|
|
276
|
-
const taxClassSelect = dialog.locator("select").filter({ has: dialog.locator("option", { hasText: /No tax class selected/i }) }).first();
|
|
277
|
-
if (await taxClassSelect.count() > 0) {
|
|
278
|
-
await taxClassSelect.selectOption({ label: options.taxClassName });
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
await dialog.getByRole("button", { name: /Add item/i }).click();
|
|
282
|
-
await expect(page.getByRole("row", { name: new RegExp(escapeRegExp(options.name), "i") })).toBeVisible();
|
|
283
|
-
}
|
|
284
|
-
async function updateLineQuantity(page, lineName, quantity) {
|
|
285
|
-
await page.getByRole("button", { name: /^Items$/i }).click();
|
|
286
|
-
const row = page.getByRole("row", { name: new RegExp(escapeRegExp(lineName), "i") });
|
|
287
|
-
await row.click();
|
|
288
|
-
const dialog = page.getByRole("dialog", { name: /Edit line/i });
|
|
289
|
-
await expect(dialog).toBeVisible();
|
|
290
|
-
await dialog.getByRole("textbox", { name: "1" }).fill(String(quantity));
|
|
291
|
-
await dialog.getByRole("button", { name: /Save changes/i }).click();
|
|
292
|
-
await expect(page.getByRole("row", { name: new RegExp(`${escapeRegExp(lineName)}.*\\b${quantity}\\b`, "i") })).toBeVisible();
|
|
293
|
-
}
|
|
294
|
-
async function deleteLine(page, lineName) {
|
|
295
|
-
await page.getByRole("button", { name: /^Items$/i }).click();
|
|
296
|
-
const row = page.getByRole("row", { name: new RegExp(escapeRegExp(lineName), "i") });
|
|
297
|
-
await expect(row).toBeVisible();
|
|
298
|
-
await row.locator("button").last().click();
|
|
299
|
-
const confirmDialog = page.getByRole("alertdialog");
|
|
300
|
-
if (await confirmDialog.isVisible().catch(() => false)) {
|
|
301
|
-
await confirmDialog.getByRole("button", { name: /^Delete$/i }).first().click();
|
|
302
|
-
await expect(confirmDialog).toBeHidden();
|
|
303
|
-
}
|
|
304
|
-
await expect(page.getByRole("row", { name: new RegExp(escapeRegExp(lineName), "i") })).toHaveCount(0);
|
|
305
|
-
}
|
|
306
|
-
async function addAdjustment(page, options) {
|
|
307
|
-
await page.getByRole("button", { name: /^Adjustments$/i }).click();
|
|
308
|
-
await page.getByRole("button", { name: /Add adjustment/i }).first().click();
|
|
309
|
-
const dialog = page.getByRole("dialog", { name: /Add adjustment/i });
|
|
310
|
-
await expect(dialog).toBeVisible();
|
|
311
|
-
const fillAdjustmentForm = async () => {
|
|
312
|
-
const labelInput = dialog.getByRole("textbox", { name: /e\.g\. Shipping fee/i }).first();
|
|
313
|
-
if (await labelInput.count() > 0) {
|
|
314
|
-
await labelInput.fill(options.label);
|
|
315
|
-
} else {
|
|
316
|
-
await dialog.locator('input[placeholder="e.g. Shipping fee"]').first().fill(options.label);
|
|
317
|
-
}
|
|
318
|
-
const kindSelect = dialog.getByRole("combobox").first();
|
|
319
|
-
if (await kindSelect.count() > 0) {
|
|
320
|
-
await kindSelect.selectOption({ label: options.kindLabel ?? "Surcharge" }).catch(async () => {
|
|
321
|
-
await kindSelect.selectOption({ label: "Custom" });
|
|
322
|
-
});
|
|
323
|
-
}
|
|
324
|
-
const enabledAmountInputs = dialog.locator('input[placeholder="0.00"]:not([disabled])');
|
|
325
|
-
if (await enabledAmountInputs.count() > 0) {
|
|
326
|
-
await enabledAmountInputs.first().fill(String(options.netAmount));
|
|
327
|
-
}
|
|
328
|
-
if (await enabledAmountInputs.count() > 1) {
|
|
329
|
-
await enabledAmountInputs.nth(1).fill(String(options.netAmount));
|
|
330
|
-
}
|
|
331
|
-
};
|
|
332
|
-
let saved = false;
|
|
333
|
-
for (let attempt = 0; attempt < 3; attempt += 1) {
|
|
334
|
-
await fillAdjustmentForm();
|
|
335
|
-
await dialog.getByRole("button", { name: /Add adjustment/i }).click();
|
|
336
|
-
saved = await dialog.waitFor({ state: "hidden", timeout: 3e3 }).then(() => true).catch(() => false);
|
|
337
|
-
if (saved) break;
|
|
338
|
-
}
|
|
339
|
-
await expect(dialog).toBeHidden({ timeout: 8e3 });
|
|
340
|
-
await page.getByRole("button", { name: /^Adjustments$/i }).click();
|
|
341
|
-
await expect(page.getByText(new RegExp(escapeRegExp(options.label), "i")).first()).toBeVisible({ timeout: 8e3 });
|
|
342
|
-
}
|
|
343
|
-
async function addPayment(page, amount) {
|
|
344
|
-
await page.getByRole("button", { name: /^Payments$/i }).click();
|
|
345
|
-
const amountLabel = amount.toFixed(2);
|
|
346
|
-
const amountInputValue = String(Math.max(1, Math.round(amount)));
|
|
347
|
-
await page.getByRole("button", { name: /Add payment/i }).click();
|
|
348
|
-
const dialog = page.getByRole("dialog", { name: /Add payment/i });
|
|
349
|
-
await expect(dialog).toBeVisible();
|
|
350
|
-
const setAmount = async () => {
|
|
351
|
-
const amountInput = dialog.getByRole("spinbutton").first();
|
|
352
|
-
await amountInput.click();
|
|
353
|
-
await amountInput.press("ControlOrMeta+a");
|
|
354
|
-
await amountInput.type(amountInputValue, { delay: 20 });
|
|
355
|
-
await amountInput.press("Tab");
|
|
356
|
-
};
|
|
357
|
-
await setAmount();
|
|
358
|
-
await dialog.getByText(/Loading payment methods/i).waitFor({ state: "hidden", timeout: TEST_WAIT_TIMEOUT_MS }).catch(() => {
|
|
359
|
-
});
|
|
360
|
-
const paymentMethodOption = dialog.getByRole("button", { name: /bank transfer|credit card|cash on delivery/i }).first();
|
|
361
|
-
if (await paymentMethodOption.count() > 0) {
|
|
362
|
-
const methodSelectButton = paymentMethodOption.getByRole("button", { name: /^Select$/i }).first();
|
|
363
|
-
if (await methodSelectButton.count() > 0) {
|
|
364
|
-
await methodSelectButton.click();
|
|
365
|
-
} else {
|
|
366
|
-
await paymentMethodOption.click();
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
const paymentStatusOption = dialog.getByRole("button", { name: /pending.*select|captured.*select/i }).first();
|
|
370
|
-
if (await paymentStatusOption.count() > 0) {
|
|
371
|
-
const statusSelectButton = paymentStatusOption.getByRole("button", { name: /^Select$/i }).first();
|
|
372
|
-
if (await statusSelectButton.count() > 0) {
|
|
373
|
-
await statusSelectButton.click();
|
|
374
|
-
} else {
|
|
375
|
-
await paymentStatusOption.click();
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
const saveButton = dialog.getByRole("button", { name: /Save/i }).first();
|
|
379
|
-
const operationMessage = page.getByText(/Last operation:\s*Create payment/i).first();
|
|
380
|
-
for (let attempt = 0; attempt < 3; attempt += 1) {
|
|
381
|
-
await setAmount();
|
|
382
|
-
await saveButton.click();
|
|
383
|
-
const closed = await dialog.waitFor({ state: "hidden", timeout: 4e3 }).then(() => true).catch(() => false);
|
|
384
|
-
if (closed) {
|
|
385
|
-
break;
|
|
386
|
-
}
|
|
387
|
-
const operationVisible = await operationMessage.isVisible().catch(() => false);
|
|
388
|
-
if (operationVisible) {
|
|
389
|
-
break;
|
|
390
|
-
}
|
|
391
|
-
const hasRequiredFieldError = await dialog.getByText(/This field is required/i).isVisible().catch(() => false);
|
|
392
|
-
if (!hasRequiredFieldError) {
|
|
393
|
-
await page.waitForTimeout(200);
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
if (await dialog.isVisible().catch(() => false)) {
|
|
397
|
-
await dialog.press("Escape").catch(() => {
|
|
398
|
-
});
|
|
399
|
-
await dialog.waitFor({ state: "hidden", timeout: 4e3 }).catch(() => {
|
|
400
|
-
});
|
|
401
|
-
}
|
|
402
|
-
await operationMessage.waitFor({ state: "visible", timeout: TEST_WAIT_TIMEOUT_MS }).catch(() => {
|
|
403
|
-
});
|
|
404
|
-
const added = await operationMessage.isVisible().catch(() => false);
|
|
405
|
-
return { amountLabel, added };
|
|
406
|
-
}
|
|
407
|
-
async function addShipment(page) {
|
|
408
|
-
await page.getByRole("button", { name: /^Shipments$/i }).click();
|
|
409
|
-
const trackingNumber = `SHIP-${Date.now()}`;
|
|
410
|
-
const shipmentNumber = String(Date.now());
|
|
411
|
-
await page.getByRole("button", { name: /Add shipment/i }).click();
|
|
412
|
-
const dialog = page.getByRole("dialog", { name: /Add shipment/i });
|
|
413
|
-
await expect(dialog).toBeVisible();
|
|
414
|
-
await fillShipmentNumber(dialog, shipmentNumber);
|
|
415
|
-
const trackingInput = dialog.getByLabel(/Tracking numbers/i).first();
|
|
416
|
-
if (await trackingInput.count() > 0) {
|
|
417
|
-
await trackingInput.fill(trackingNumber);
|
|
418
|
-
} else {
|
|
419
|
-
await dialog.getByPlaceholder(/One per line or comma separated/i).first().fill(trackingNumber);
|
|
420
|
-
}
|
|
421
|
-
await selectShipmentMethod(dialog);
|
|
422
|
-
await selectShipmentStatus(dialog);
|
|
423
|
-
await selectShipmentAddress(dialog);
|
|
424
|
-
await fillShipmentQuantity(dialog);
|
|
425
|
-
await fillShipmentDates(dialog);
|
|
426
|
-
await selectShipmentRequiredOptions(dialog);
|
|
427
|
-
await fillShipmentNumber(dialog, shipmentNumber);
|
|
428
|
-
await dialog.getByText(/Searching…|Searching\.\.\./i).first().waitFor({ state: "hidden", timeout: TEST_WAIT_TIMEOUT_MS }).catch(() => {
|
|
429
|
-
});
|
|
430
|
-
const saveButton = dialog.getByRole("button", { name: /^Save\b/i }).first();
|
|
431
|
-
const canClickSave = await saveButton.count() > 0 && await saveButton.isVisible().catch(() => false);
|
|
432
|
-
if (canClickSave) {
|
|
433
|
-
await saveButton.click({ timeout: TEST_WAIT_TIMEOUT_MS }).catch(() => {
|
|
434
|
-
});
|
|
435
|
-
} else {
|
|
436
|
-
await dialog.press("ControlOrMeta+Enter").catch(() => {
|
|
437
|
-
});
|
|
438
|
-
}
|
|
439
|
-
const closed = await dialog.waitFor({ state: "hidden", timeout: TEST_WAIT_TIMEOUT_MS }).then(() => true).catch(() => false);
|
|
440
|
-
if (!closed) {
|
|
441
|
-
return { trackingNumber, shipmentNumber, added: false };
|
|
442
|
-
}
|
|
443
|
-
await page.getByRole("button", { name: /^Shipments$/i }).click();
|
|
444
|
-
const shipmentLabel = page.getByText(new RegExp(`Shipment\\s+${escapeRegExp(shipmentNumber)}`, "i")).first();
|
|
445
|
-
const added = await shipmentLabel.waitFor({ state: "visible", timeout: TEST_WAIT_TIMEOUT_MS }).then(() => true).catch(() => false);
|
|
446
|
-
return { trackingNumber, shipmentNumber, added };
|
|
447
|
-
}
|
|
448
|
-
async function readGrandTotalGross(page) {
|
|
449
|
-
const row = page.getByRole("row", { name: /Grand total \(gross\)/i }).first();
|
|
450
|
-
await expect(row).toBeVisible();
|
|
451
|
-
const text = (await row.innerText()).trim();
|
|
452
|
-
return parseCurrencyAmount(text);
|
|
453
|
-
}
|
|
454
|
-
export {
|
|
455
|
-
addAdjustment,
|
|
456
|
-
addCustomLine,
|
|
457
|
-
addPayment,
|
|
458
|
-
addShipment,
|
|
459
|
-
createSalesDocument,
|
|
460
|
-
deleteLine,
|
|
461
|
-
readGrandTotalGross,
|
|
462
|
-
updateLineQuantity
|
|
463
|
-
};
|
|
464
|
-
//# sourceMappingURL=salesUi.js.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../../../src/modules/core/__integration__/helpers/salesUi.ts"],
|
|
4
|
-
"sourcesContent": ["import { expect, type Locator, type Page } from '@playwright/test';\nimport { apiRequest, getAuthToken } from './api';\n\ntype DocumentKind = 'quote' | 'order';\n\ntype CreateDocumentOptions = {\n kind: DocumentKind;\n customerQuery?: string;\n channelQuery?: string;\n};\n\ntype AddLineOptions = {\n name: string;\n quantity: number;\n unitPriceGross: number;\n taxClassName?: string;\n};\n\ntype AddAdjustmentOptions = {\n label: string;\n kindLabel?: string;\n netAmount: number;\n};\n\nconst TEST_WAIT_TIMEOUT_MS = 10_000;\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nfunction parseCurrencyAmount(value: string): number {\n const normalized = value.replace(/,/g, '');\n const matches = normalized.match(/-?\\$[0-9]+(?:\\.[0-9]{2})?/g);\n const lastMatch = matches?.[matches.length - 1];\n if (!lastMatch) {\n throw new Error(`Could not parse currency from: ${value}`);\n }\n return Number.parseFloat(lastMatch.replace('$', ''));\n}\n\nfunction readId(payload: unknown, keys: string[]): string | null {\n if (!payload || typeof payload !== 'object') return null;\n const map = payload as Record<string, unknown>;\n for (const key of keys) {\n const value = map[key];\n if (typeof value === 'string' && value.length > 0) return value;\n }\n for (const value of Object.values(map)) {\n if (value && typeof value === 'object' && !Array.isArray(value)) {\n const nested = readId(value, keys);\n if (nested) return nested;\n }\n }\n return null;\n}\n\nasync function ensureSalesDocumentFixtures(\n page: Page,\n options: CreateDocumentOptions,\n): Promise<{ customerQuery: string; channelQuery: string }> {\n let customerQuery = options.customerQuery;\n let channelQuery = options.channelQuery;\n\n if (customerQuery && channelQuery) {\n return { customerQuery, channelQuery };\n }\n\n const token = await getAuthToken(page.request, 'admin').catch(() => null);\n if (!token) {\n if (!customerQuery) {\n customerQuery = `QA Sales Customer ${Date.now()}`;\n await page.goto('/backend/customers/companies/create');\n await page.locator('form').getByRole('textbox').first().fill(customerQuery);\n await page.getByPlaceholder('https://example.com').fill('https://example.com');\n await page.locator('form').getByRole('button', { name: /Create Company/i }).click();\n await expect(page).toHaveURL(/\\/backend\\/customers\\/companies\\/[0-9a-f-]{36}$/i);\n }\n if (!channelQuery) {\n const timestamp = Date.now();\n channelQuery = `QA Sales Channel ${timestamp}`;\n const channelCode = `qa-sales-channel-${timestamp}`;\n await page.goto('/backend/sales/channels');\n await page.getByRole('link', { name: /Add channel/i }).click();\n const createForm = page.locator('form').first();\n await createForm.getByRole('textbox').nth(0).fill(channelQuery);\n await createForm.getByRole('textbox').nth(1).fill(channelCode);\n await page.getByRole('button', { name: /Create channel|Create/i }).last().click();\n await expect(page).toHaveURL(/\\/backend\\/sales\\/channels$/i);\n }\n return {\n customerQuery,\n channelQuery,\n };\n }\n\n if (!customerQuery) {\n const companyName = `QA Sales Customer ${Date.now()}`;\n const companyResponse = await apiRequest(page.request, 'POST', '/api/customers/companies', {\n token,\n data: { displayName: companyName },\n }).catch(() => null);\n if (companyResponse && companyResponse.ok()) {\n const companyBody = (await companyResponse.json().catch(() => null)) as unknown;\n const companyId = readId(companyBody, ['id', 'entityId', 'companyId']);\n if (companyId) {\n await apiRequest(page.request, 'POST', '/api/customers/addresses', {\n token,\n data: {\n entityId: companyId,\n name: 'Primary',\n purpose: 'Shipping',\n addressLine1: '100 QA Street',\n city: 'Austin',\n postalCode: '78701',\n country: 'US',\n isPrimary: true,\n },\n }).catch(() => {});\n customerQuery = companyName;\n }\n }\n if (!customerQuery) {\n customerQuery = 'Copperleaf';\n }\n }\n\n if (!channelQuery) {\n const timestamp = Date.now();\n const channelName = `QA Sales Channel ${timestamp}`;\n const channelCode = `qa-sales-channel-${timestamp}`;\n const channelResponse = await apiRequest(page.request, 'POST', '/api/sales/channels', {\n token,\n data: {\n name: channelName,\n code: channelCode,\n },\n }).catch(() => null);\n if (channelResponse && channelResponse.ok()) {\n channelQuery = channelName;\n } else {\n channelQuery = 'online';\n }\n }\n\n return {\n customerQuery: customerQuery ?? 'Copperleaf',\n channelQuery: channelQuery ?? 'online',\n };\n}\n\nasync function selectFirstAddressIfAvailable(page: Page): Promise<void> {\n const addressSelect = page\n .locator('select')\n .filter({ has: page.locator('option', { hasText: 'Select address' }) })\n .first();\n if ((await addressSelect.count()) === 0) return;\n if (!(await addressSelect.isEnabled())) return;\n\n const nextValue = await addressSelect.evaluate((element) => {\n const select = element as HTMLSelectElement;\n return select.options.length > 1 ? select.options[1]?.value ?? null : null;\n });\n if (nextValue) {\n await addressSelect.selectOption(nextValue);\n }\n}\n\nexport async function createSalesDocument(page: Page, options: CreateDocumentOptions): Promise<string> {\n const fixtureContext = await ensureSalesDocumentFixtures(page, options);\n const customerQuery = fixtureContext.customerQuery;\n const channelQuery = fixtureContext.channelQuery;\n\n await page.goto(`/backend/sales/documents/create?kind=${options.kind}`);\n \n await page.waitForLoadState('networkidle');\n await page.waitForTimeout(500);\n\n\n await page.getByText('Document type').click();\n await page.getByRole('textbox', { name: /Search customers/i }).fill(customerQuery);\n await page.waitForTimeout(500);\n\n const selectButton = page\n .locator('[role=\"button\"]')\n .filter({ hasText: customerQuery })\n .getByRole('button', { name: 'Select' });\n\n await selectButton.scrollIntoViewIfNeeded();\n await selectButton.click();\n// Channel selection\nawait page.getByRole('textbox', { name: /Select a channel/i }).fill(channelQuery);\ntry {\n await page\n .getByRole('button', { name: /Select$/i })\n .filter({ hasText: new RegExp(escapeRegExp(channelQuery), 'i') })\n .first()\n .click({ timeout: 2000 });\n} catch {\n await page.getByRole('button', { name: /Select$/i }).first().click();\n}\n\n await selectFirstAddressIfAvailable(page);\n\n await page.getByRole('button', { name: /^Create$/i }).first().click();\n await expect(page).toHaveURL(new RegExp(`/backend/sales/documents/[0-9a-f-]{36}\\\\?kind=${options.kind}$`, 'i'));\n\n const match = page.url().match(/\\/backend\\/sales\\/documents\\/([0-9a-f-]{36})\\?kind=/i);\n if (!match) {\n throw new Error(`Could not resolve document id from URL: ${page.url()}`);\n }\n return match[1];\n}\n\nfunction lineDialog(page: Page): Locator {\n return page.getByRole('dialog', { name: /Add line|Edit line/i });\n}\n\nasync function selectFirstOption(container: Locator, rowNamePattern: RegExp): Promise<void> {\n const optionRow = container.getByRole('button', { name: rowNamePattern }).first();\n await optionRow.waitFor({ state: 'visible', timeout: 4_000 }).catch(() => {});\n if ((await optionRow.count()) === 0) return;\n\n const selectButton = optionRow.getByRole('button', { name: /^Select$/i }).first();\n if ((await selectButton.count()) > 0) {\n await selectButton.click();\n return;\n }\n await optionRow.click();\n}\n\nasync function selectShipmentMethod(dialog: Locator): Promise<void> {\n const shippingMethodInput = dialog.getByPlaceholder(/Select method/i).first();\n if ((await shippingMethodInput.count()) === 0) return;\n await shippingMethodInput.click().catch(() => {});\n await shippingMethodInput.press('ControlOrMeta+a').catch(() => {});\n await shippingMethodInput.type('Standard', { delay: 20 }).catch(() => {});\n await shippingMethodInput.press('Enter').catch(() => {});\n await selectFirstOption(dialog, /standard ground|express air|select/i);\n}\n\nasync function selectShipmentStatus(dialog: Locator): Promise<void> {\n const statusInput = dialog.getByPlaceholder(/Select shipment status/i).first();\n if ((await statusInput.count()) > 0) {\n await statusInput.click().catch(() => {});\n await statusInput.press('ControlOrMeta+a').catch(() => {});\n await statusInput.type('Shipped', { delay: 20 }).catch(() => {});\n await statusInput.press('Enter').catch(() => {});\n }\n await selectFirstOption(dialog, /shipped.*select|in transit.*select|packed.*select|select/i);\n}\n\nasync function selectShipmentAddress(dialog: Locator): Promise<void> {\n const addressInput = dialog.getByPlaceholder(/Select address/i).first();\n if ((await addressInput.count()) === 0) return;\n const currentValue = await addressInput.inputValue().catch(() => '');\n if (currentValue.trim().length > 0) return;\n if ((await addressInput.count()) > 0) {\n await addressInput.click().catch(() => {});\n await addressInput.press('Enter').catch(() => {});\n }\n await selectFirstOption(dialog, /shipping address|select/i);\n}\n\nasync function fillShipmentQuantity(dialog: Locator): Promise<void> {\n const quantityInputs = dialog.getByRole('spinbutton');\n const count = await quantityInputs.count();\n for (let index = 0; index < count; index += 1) {\n const input = quantityInputs.nth(index);\n const isVisible = await input.isVisible().catch(() => false);\n const isEnabled = await input.isEnabled().catch(() => false);\n if (!isVisible || !isEnabled) continue;\n await input.click().catch(() => {});\n await input.press('ControlOrMeta+a').catch(() => {});\n await input.type('1', { delay: 20 }).catch(() => {});\n }\n}\n\nasync function selectShipmentRequiredOptions(dialog: Locator): Promise<void> {\n for (let attempt = 0; attempt < 6; attempt += 1) {\n const pendingSelect = dialog.getByRole('button', { name: /^Select$/i }).first();\n if ((await pendingSelect.count()) === 0) return;\n if (!(await pendingSelect.isVisible().catch(() => false))) return;\n await pendingSelect.click().catch(() => {});\n await dialog.getByText(/Searching\u2026|Searching\\.\\.\\./i).first().waitFor({ state: 'hidden', timeout: 3_000 }).catch(() => {});\n }\n}\n\nasync function fillShipmentDates(dialog: Locator): Promise<void> {\n const now = new Date();\n const day = String(now.getDate()).padStart(2, '0');\n const month = String(now.getMonth() + 1).padStart(2, '0');\n const year = String(now.getFullYear());\n const shippedDateValue = `${day}/${month}/${year}`;\n\n const shippedDateInput = dialog.getByLabel(/Shipped date/i).first();\n if ((await shippedDateInput.count()) > 0) {\n const currentValue = await shippedDateInput.inputValue().catch(() => '');\n if (currentValue.trim().length === 0) {\n await shippedDateInput.fill(shippedDateValue).catch(() => {});\n }\n }\n}\n\nasync function fillShipmentNumber(dialog: Locator, shipmentNumber: string): Promise<void> {\n const shipmentNumberInput = dialog.getByRole('textbox').first();\n if ((await shipmentNumberInput.count()) === 0) return;\n await shipmentNumberInput.click().catch(() => {});\n await shipmentNumberInput.press('ControlOrMeta+a').catch(() => {});\n await shipmentNumberInput.type(shipmentNumber, { delay: 20 }).catch(() => {});\n await shipmentNumberInput.press('Tab').catch(() => {});\n}\n\nexport async function addCustomLine(page: Page, options: AddLineOptions): Promise<void> {\n await page.getByRole('button', { name: /^Items$/i }).click();\n await page.getByRole('button', { name: /Add item/i }).first().click();\n\n const dialog = lineDialog(page);\n await expect(dialog).toBeVisible();\n\n await dialog.getByRole('button', { name: /Custom line/i }).click();\n await dialog.getByRole('textbox', { name: /Optional line name/i }).fill(options.name);\n await dialog.getByRole('textbox', { name: '0.00' }).fill(String(options.unitPriceGross));\n await dialog.getByRole('textbox', { name: '1' }).fill(String(options.quantity));\n\n if (options.taxClassName) {\n const taxClassSelect = dialog\n .locator('select')\n .filter({ has: dialog.locator('option', { hasText: /No tax class selected/i }) })\n .first();\n if ((await taxClassSelect.count()) > 0) {\n await taxClassSelect.selectOption({ label: options.taxClassName });\n }\n }\n\n await dialog.getByRole('button', { name: /Add item/i }).click();\n await expect(page.getByRole('row', { name: new RegExp(escapeRegExp(options.name), 'i') })).toBeVisible();\n}\n\nexport async function updateLineQuantity(page: Page, lineName: string, quantity: number): Promise<void> {\n await page.getByRole('button', { name: /^Items$/i }).click();\n const row = page.getByRole('row', { name: new RegExp(escapeRegExp(lineName), 'i') });\n await row.click();\n\n const dialog = page.getByRole('dialog', { name: /Edit line/i });\n await expect(dialog).toBeVisible();\n await dialog.getByRole('textbox', { name: '1' }).fill(String(quantity));\n await dialog.getByRole('button', { name: /Save changes/i }).click();\n\n await expect(page.getByRole('row', { name: new RegExp(`${escapeRegExp(lineName)}.*\\\\b${quantity}\\\\b`, 'i') })).toBeVisible();\n}\n\nexport async function deleteLine(page: Page, lineName: string): Promise<void> {\n await page.getByRole('button', { name: /^Items$/i }).click();\n const row = page.getByRole('row', { name: new RegExp(escapeRegExp(lineName), 'i') });\n await expect(row).toBeVisible();\n await row.locator('button').last().click();\n\n const confirmDialog = page.getByRole('alertdialog');\n if (await confirmDialog.isVisible().catch(() => false)) {\n await confirmDialog.getByRole('button', { name: /^Delete$/i }).first().click();\n await expect(confirmDialog).toBeHidden();\n }\n\n await expect(page.getByRole('row', { name: new RegExp(escapeRegExp(lineName), 'i') })).toHaveCount(0);\n}\n\nexport async function addAdjustment(page: Page, options: AddAdjustmentOptions): Promise<void> {\n await page.getByRole('button', { name: /^Adjustments$/i }).click();\n await page.getByRole('button', { name: /Add adjustment/i }).first().click();\n\n const dialog = page.getByRole('dialog', { name: /Add adjustment/i });\n await expect(dialog).toBeVisible();\n const fillAdjustmentForm = async (): Promise<void> => {\n const labelInput = dialog.getByRole('textbox', { name: /e\\.g\\. Shipping fee/i }).first();\n if ((await labelInput.count()) > 0) {\n await labelInput.fill(options.label);\n } else {\n await dialog.locator('input[placeholder=\"e.g. Shipping fee\"]').first().fill(options.label);\n }\n\n const kindSelect = dialog.getByRole('combobox').first();\n if ((await kindSelect.count()) > 0) {\n await kindSelect.selectOption({ label: options.kindLabel ?? 'Surcharge' }).catch(async () => {\n await kindSelect.selectOption({ label: 'Custom' });\n });\n }\n\n const enabledAmountInputs = dialog.locator('input[placeholder=\"0.00\"]:not([disabled])');\n if ((await enabledAmountInputs.count()) > 0) {\n await enabledAmountInputs.first().fill(String(options.netAmount));\n }\n if ((await enabledAmountInputs.count()) > 1) {\n await enabledAmountInputs.nth(1).fill(String(options.netAmount));\n }\n };\n\n let saved = false;\n for (let attempt = 0; attempt < 3; attempt += 1) {\n await fillAdjustmentForm();\n await dialog.getByRole('button', { name: /Add adjustment/i }).click();\n saved = await dialog.waitFor({ state: 'hidden', timeout: 3_000 }).then(() => true).catch(() => false);\n if (saved) break;\n }\n\n await expect(dialog).toBeHidden({ timeout: 8_000 });\n await page.getByRole('button', { name: /^Adjustments$/i }).click();\n await expect(page.getByText(new RegExp(escapeRegExp(options.label), 'i')).first()).toBeVisible({ timeout: 8_000 });\n}\n\nexport async function addPayment(page: Page, amount: number): Promise<{ amountLabel: string; added: boolean }> {\n await page.getByRole('button', { name: /^Payments$/i }).click();\n const amountLabel = amount.toFixed(2);\n const amountInputValue = String(Math.max(1, Math.round(amount)));\n await page.getByRole('button', { name: /Add payment/i }).click();\n\n const dialog = page.getByRole('dialog', { name: /Add payment/i });\n await expect(dialog).toBeVisible();\n const setAmount = async (): Promise<void> => {\n const amountInput = dialog.getByRole('spinbutton').first();\n await amountInput.click();\n await amountInput.press('ControlOrMeta+a');\n await amountInput.type(amountInputValue, { delay: 20 });\n await amountInput.press('Tab');\n };\n await setAmount();\n\n await dialog.getByText(/Loading payment methods/i).waitFor({ state: 'hidden', timeout: TEST_WAIT_TIMEOUT_MS }).catch(() => {});\n const paymentMethodOption = dialog.getByRole('button', { name: /bank transfer|credit card|cash on delivery/i }).first();\n if ((await paymentMethodOption.count()) > 0) {\n const methodSelectButton = paymentMethodOption.getByRole('button', { name: /^Select$/i }).first();\n if ((await methodSelectButton.count()) > 0) {\n await methodSelectButton.click();\n } else {\n await paymentMethodOption.click();\n }\n }\n const paymentStatusOption = dialog.getByRole('button', { name: /pending.*select|captured.*select/i }).first();\n if ((await paymentStatusOption.count()) > 0) {\n const statusSelectButton = paymentStatusOption.getByRole('button', { name: /^Select$/i }).first();\n if ((await statusSelectButton.count()) > 0) {\n await statusSelectButton.click();\n } else {\n await paymentStatusOption.click();\n }\n }\n const saveButton = dialog.getByRole('button', { name: /Save/i }).first();\n const operationMessage = page.getByText(/Last operation:\\s*Create payment/i).first();\n for (let attempt = 0; attempt < 3; attempt += 1) {\n await setAmount();\n await saveButton.click();\n const closed = await dialog.waitFor({ state: 'hidden', timeout: 4_000 }).then(() => true).catch(() => false);\n if (closed) {\n break;\n }\n const operationVisible = await operationMessage.isVisible().catch(() => false);\n if (operationVisible) {\n break;\n }\n const hasRequiredFieldError = await dialog.getByText(/This field is required/i).isVisible().catch(() => false);\n if (!hasRequiredFieldError) {\n await page.waitForTimeout(200);\n }\n }\n if (await dialog.isVisible().catch(() => false)) {\n await dialog.press('Escape').catch(() => {});\n await dialog.waitFor({ state: 'hidden', timeout: 4_000 }).catch(() => {});\n }\n await operationMessage.waitFor({ state: 'visible', timeout: TEST_WAIT_TIMEOUT_MS }).catch(() => {});\n const added = await operationMessage.isVisible().catch(() => false);\n return { amountLabel, added };\n}\n\nexport async function addShipment(page: Page): Promise<{ trackingNumber: string; shipmentNumber: string; added: boolean }> {\n await page.getByRole('button', { name: /^Shipments$/i }).click();\n const trackingNumber = `SHIP-${Date.now()}`;\n const shipmentNumber = String(Date.now());\n await page.getByRole('button', { name: /Add shipment/i }).click();\n\n const dialog = page.getByRole('dialog', { name: /Add shipment/i });\n await expect(dialog).toBeVisible();\n await fillShipmentNumber(dialog, shipmentNumber);\n const trackingInput = dialog.getByLabel(/Tracking numbers/i).first();\n if ((await trackingInput.count()) > 0) {\n await trackingInput.fill(trackingNumber);\n } else {\n await dialog.getByPlaceholder(/One per line or comma separated/i).first().fill(trackingNumber);\n }\n await selectShipmentMethod(dialog);\n await selectShipmentStatus(dialog);\n await selectShipmentAddress(dialog);\n await fillShipmentQuantity(dialog);\n await fillShipmentDates(dialog);\n await selectShipmentRequiredOptions(dialog);\n await fillShipmentNumber(dialog, shipmentNumber);\n\n await dialog.getByText(/Searching\u2026|Searching\\.\\.\\./i).first().waitFor({ state: 'hidden', timeout: TEST_WAIT_TIMEOUT_MS }).catch(() => {});\n const saveButton = dialog.getByRole('button', { name: /^Save\\b/i }).first();\n const canClickSave = (await saveButton.count()) > 0 && (await saveButton.isVisible().catch(() => false));\n if (canClickSave) {\n await saveButton.click({ timeout: TEST_WAIT_TIMEOUT_MS }).catch(() => {});\n } else {\n await dialog.press('ControlOrMeta+Enter').catch(() => {});\n }\n\n const closed = await dialog\n .waitFor({ state: 'hidden', timeout: TEST_WAIT_TIMEOUT_MS })\n .then(() => true)\n .catch(() => false);\n\n if (!closed) {\n return { trackingNumber, shipmentNumber, added: false };\n }\n\n await page.getByRole('button', { name: /^Shipments$/i }).click();\n const shipmentLabel = page.getByText(new RegExp(`Shipment\\\\s+${escapeRegExp(shipmentNumber)}`, 'i')).first();\n const added = await shipmentLabel\n .waitFor({ state: 'visible', timeout: TEST_WAIT_TIMEOUT_MS })\n .then(() => true)\n .catch(() => false);\n return { trackingNumber, shipmentNumber, added };\n}\n\nexport async function readGrandTotalGross(page: Page): Promise<number> {\n const row = page.getByRole('row', { name: /Grand total \\(gross\\)/i }).first();\n await expect(row).toBeVisible();\n const text = (await row.innerText()).trim();\n return parseCurrencyAmount(text);\n}"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { expect, test } from "@playwright/test";
|
|
2
|
-
import { login } from "@open-mercato/core/modules/core/__integration__/helpers/auth";
|
|
3
|
-
import { addCustomLine, addPayment, addShipment, createSalesDocument } from "@open-mercato/core/modules/core/__integration__/helpers/salesUi";
|
|
4
|
-
test.describe("TC-INT-001: Quote to Order to Invoice to Payment", () => {
|
|
5
|
-
test("should progress quote to order and record fulfillment/payment actions", async ({ page }) => {
|
|
6
|
-
await login(page, "admin");
|
|
7
|
-
await createSalesDocument(page, { kind: "quote" });
|
|
8
|
-
await addCustomLine(page, { name: `QA INT-001 ${Date.now()}`, quantity: 1, unitPriceGross: 50 });
|
|
9
|
-
await page.getByRole("button", { name: /^Actions$/i }).click();
|
|
10
|
-
const convertToOrder = page.getByRole("menuitem", { name: /Convert to order/i });
|
|
11
|
-
if (await convertToOrder.count() === 0) {
|
|
12
|
-
test.skip(true, "Quote to order conversion is unavailable in this environment.");
|
|
13
|
-
}
|
|
14
|
-
await convertToOrder.first().click();
|
|
15
|
-
const confirm = page.getByRole("button", { name: /Convert|Create order|Continue/i }).last();
|
|
16
|
-
if (await confirm.isVisible().catch(() => false)) await confirm.click();
|
|
17
|
-
await expect(page).toHaveURL(/kind=order$/i);
|
|
18
|
-
const shipmentResult = await addShipment(page);
|
|
19
|
-
await addPayment(page, 50);
|
|
20
|
-
await page.getByRole("button", { name: /^Shipments$/i }).click();
|
|
21
|
-
await expect(page.getByText(new RegExp(`Shipment\\s+${shipmentResult.shipmentNumber}`, "i")).first()).toBeVisible();
|
|
22
|
-
await page.getByRole("button", { name: /^Payments$/i }).click();
|
|
23
|
-
await expect(page.getByText(/\$50\.00|50\.00/).first()).toBeVisible();
|
|
24
|
-
});
|
|
25
|
-
});
|
|
26
|
-
//# sourceMappingURL=TC-INT-001.spec.js.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../../../src/modules/core/__integration__/integration/TC-INT-001.spec.ts"],
|
|
4
|
-
"sourcesContent": ["import { expect, test } from '@playwright/test';\nimport { login } from '@open-mercato/core/modules/core/__integration__/helpers/auth';\nimport { addCustomLine, addPayment, addShipment, createSalesDocument } from '@open-mercato/core/modules/core/__integration__/helpers/salesUi';\n\n/**\n * TC-INT-001: Quote to Order to Invoice to Payment\n * Source: .ai/qa/scenarios/TC-INT-001-quote-to-order-to-invoice.md\n */\ntest.describe('TC-INT-001: Quote to Order to Invoice to Payment', () => {\n test('should progress quote to order and record fulfillment/payment actions', async ({ page }) => {\n await login(page, 'admin');\n await createSalesDocument(page, { kind: 'quote' });\n await addCustomLine(page, { name: `QA INT-001 ${Date.now()}`, quantity: 1, unitPriceGross: 50 });\n\n await page.getByRole('button', { name: /^Actions$/i }).click();\n const convertToOrder = page.getByRole('menuitem', { name: /Convert to order/i });\n if ((await convertToOrder.count()) === 0) {\n test.skip(true, 'Quote to order conversion is unavailable in this environment.');\n }\n await convertToOrder.first().click();\n\n const confirm = page.getByRole('button', { name: /Convert|Create order|Continue/i }).last();\n if (await confirm.isVisible().catch(() => false)) await confirm.click();\n await expect(page).toHaveURL(/kind=order$/i);\n\n const shipmentResult = await addShipment(page);\n await addPayment(page, 50);\n\n await page.getByRole('button', { name: /^Shipments$/i }).click();\n await expect(page.getByText(new RegExp(`Shipment\\\\s+${shipmentResult.shipmentNumber}`, 'i')).first()).toBeVisible();\n await page.getByRole('button', { name: /^Payments$/i }).click();\n await expect(page.getByText(/\\$50\\.00|50\\.00/).first()).toBeVisible();\n });\n});\n"],
|
|
5
|
-
"mappings": "AAAA,SAAS,QAAQ,YAAY;AAC7B,SAAS,aAAa;AACtB,SAAS,eAAe,YAAY,aAAa,2BAA2B;AAM5E,KAAK,SAAS,oDAAoD,MAAM;AACtE,OAAK,yEAAyE,OAAO,EAAE,KAAK,MAAM;AAChG,UAAM,MAAM,MAAM,OAAO;AACzB,UAAM,oBAAoB,MAAM,EAAE,MAAM,QAAQ,CAAC;AACjD,UAAM,cAAc,MAAM,EAAE,MAAM,cAAc,KAAK,IAAI,CAAC,IAAI,UAAU,GAAG,gBAAgB,GAAG,CAAC;AAE/F,UAAM,KAAK,UAAU,UAAU,EAAE,MAAM,aAAa,CAAC,EAAE,MAAM;AAC7D,UAAM,iBAAiB,KAAK,UAAU,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAC/E,QAAK,MAAM,eAAe,MAAM,MAAO,GAAG;AACxC,WAAK,KAAK,MAAM,+DAA+D;AAAA,IACjF;AACA,UAAM,eAAe,MAAM,EAAE,MAAM;AAEnC,UAAM,UAAU,KAAK,UAAU,UAAU,EAAE,MAAM,iCAAiC,CAAC,EAAE,KAAK;AAC1F,QAAI,MAAM,QAAQ,UAAU,EAAE,MAAM,MAAM,KAAK,EAAG,OAAM,QAAQ,MAAM;AACtE,UAAM,OAAO,IAAI,EAAE,UAAU,cAAc;AAE3C,UAAM,iBAAiB,MAAM,YAAY,IAAI;AAC7C,UAAM,WAAW,MAAM,EAAE;AAEzB,UAAM,KAAK,UAAU,UAAU,EAAE,MAAM,eAAe,CAAC,EAAE,MAAM;AAC/D,UAAM,OAAO,KAAK,UAAU,IAAI,OAAO,eAAe,eAAe,cAAc,IAAI,GAAG,CAAC,EAAE,MAAM,CAAC,EAAE,YAAY;AAClH,UAAM,KAAK,UAAU,UAAU,EAAE,MAAM,cAAc,CAAC,EAAE,MAAM;AAC9D,UAAM,OAAO,KAAK,UAAU,iBAAiB,EAAE,MAAM,CAAC,EAAE,YAAY;AAAA,EACtE,CAAC;AACH,CAAC;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|