@nextsparkjs/theme-default 0.1.0-beta.20 → 0.1.0-beta.22
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 +1 -1
- package/tests/cypress/e2e/_devtools/access.bdd.md +262 -0
- package/tests/cypress/e2e/_devtools/access.cy.ts +171 -0
- package/tests/cypress/e2e/_devtools/navigation.bdd.md +261 -0
- package/tests/cypress/e2e/_devtools/navigation.cy.ts +157 -0
- package/tests/cypress/e2e/_devtools/pages.bdd.md +303 -0
- package/tests/cypress/e2e/_devtools/pages.cy.ts +184 -0
- package/tests/cypress/e2e/_docs/README.md +215 -0
- package/tests/cypress/e2e/_docs/tutorials/sector7-superadmin-teams.narration.json +155 -0
- package/tests/cypress/e2e/_docs/tutorials/sector7-superadmin.cy.ts +390 -0
- package/tests/cypress/e2e/_docs/tutorials/teams-system.doc.cy.ts +349 -0
- package/tests/cypress/e2e/_docs/tutorials/teams-system.narration.json +165 -0
- package/tests/cypress/e2e/_selectors/auth.cy.ts +306 -0
- package/tests/cypress/e2e/_selectors/billing.cy.ts +89 -0
- package/tests/cypress/e2e/_selectors/dashboard-mobile.cy.ts +113 -0
- package/tests/cypress/e2e/_selectors/dashboard-navigation.cy.ts +89 -0
- package/tests/cypress/e2e/_selectors/dashboard-sidebar.cy.ts +60 -0
- package/tests/cypress/e2e/_selectors/dashboard-topnav.cy.ts +146 -0
- package/tests/cypress/e2e/_selectors/devtools.cy.ts +210 -0
- package/tests/cypress/e2e/_selectors/global-search.cy.ts +88 -0
- package/tests/cypress/e2e/_selectors/pages-editor.cy.ts +179 -0
- package/tests/cypress/e2e/_selectors/posts-editor.cy.ts +282 -0
- package/tests/cypress/e2e/_selectors/public.cy.ts +112 -0
- package/tests/cypress/e2e/_selectors/settings-api-keys.cy.ts +228 -0
- package/tests/cypress/e2e/_selectors/settings-billing.cy.ts +105 -0
- package/tests/cypress/e2e/_selectors/settings-layout.cy.ts +119 -0
- package/tests/cypress/e2e/_selectors/settings-password.cy.ts +71 -0
- package/tests/cypress/e2e/_selectors/settings-profile.cy.ts +82 -0
- package/tests/cypress/e2e/_selectors/settings-teams.cy.ts +68 -0
- package/tests/cypress/e2e/_selectors/superadmin.cy.ts +185 -0
- package/tests/cypress/e2e/_selectors/tasks.cy.ts +242 -0
- package/tests/cypress/e2e/_selectors/taxonomies.cy.ts +126 -0
- package/tests/cypress/e2e/_selectors/teams.cy.ts +142 -0
- package/tests/cypress/e2e/_superadmin/all-teams.bdd.md +261 -0
- package/tests/cypress/e2e/_superadmin/all-teams.cy.ts +177 -0
- package/tests/cypress/e2e/_superadmin/all-users.bdd.md +406 -0
- package/tests/cypress/e2e/_superadmin/all-users.cy.ts +294 -0
- package/tests/cypress/e2e/_superadmin/dashboard.bdd.md +235 -0
- package/tests/cypress/e2e/_superadmin/dashboard.cy.ts +149 -0
- package/tests/cypress/e2e/_superadmin/subscriptions-overview.bdd.md +290 -0
- package/tests/cypress/e2e/_superadmin/subscriptions-overview.cy.ts +194 -0
- package/tests/cypress/e2e/ai/ai-usage.cy.ts +209 -0
- package/tests/cypress/e2e/ai/chat-api.cy.ts +107 -0
- package/tests/cypress/e2e/ai/guardrails.cy.ts +332 -0
- package/tests/cypress/e2e/api/billing/BillingAPIController.js +319 -0
- package/tests/cypress/e2e/api/billing/check-action.cy.ts +326 -0
- package/tests/cypress/e2e/api/billing/checkout.cy.ts +358 -0
- package/tests/cypress/e2e/api/billing/lifecycle.cy.ts +423 -0
- package/tests/cypress/e2e/api/billing/plans/README.md +345 -0
- package/tests/cypress/e2e/api/billing/plans/business.cy.ts +412 -0
- package/tests/cypress/e2e/api/billing/plans/downgrade.cy.ts +510 -0
- package/tests/cypress/e2e/api/billing/plans/fixtures/billing-plans.json +163 -0
- package/tests/cypress/e2e/api/billing/plans/free.cy.ts +500 -0
- package/tests/cypress/e2e/api/billing/plans/pro.cy.ts +497 -0
- package/tests/cypress/e2e/api/billing/plans/starter.cy.ts +342 -0
- package/tests/cypress/e2e/api/billing/portal.cy.ts +313 -0
- package/tests/cypress/e2e/api/devtools/registries.bdd.md +300 -0
- package/tests/cypress/e2e/api/devtools/registries.cy.ts +368 -0
- package/tests/cypress/e2e/api/entities/blocks-scope.cy.ts +396 -0
- package/tests/cypress/e2e/api/entities/customers-crud.cy.ts +648 -0
- package/tests/cypress/e2e/api/entities/customers-metas.cy.ts +839 -0
- package/tests/cypress/e2e/api/entities/pages-crud.cy.ts +425 -0
- package/tests/cypress/e2e/api/entities/pages-status.cy.ts +335 -0
- package/tests/cypress/e2e/api/entities/post-categories-crud.cy.ts +610 -0
- package/tests/cypress/e2e/api/entities/posts-crud.cy.ts +709 -0
- package/tests/cypress/e2e/api/entities/posts-status.cy.ts +396 -0
- package/tests/cypress/e2e/api/entities/tasks-crud.cy.ts +602 -0
- package/tests/cypress/e2e/api/entities/tasks-metas.cy.ts +878 -0
- package/tests/cypress/e2e/api/entities/users-crud.cy.ts +469 -0
- package/tests/cypress/e2e/api/entities/users-metas.cy.ts +913 -0
- package/tests/cypress/e2e/api/entities/users-security.cy.ts +375 -0
- package/tests/cypress/e2e/api/scheduled-actions/cron-endpoint.bdd.md +375 -0
- package/tests/cypress/e2e/api/scheduled-actions/cron-endpoint.cy.ts +346 -0
- package/tests/cypress/e2e/api/scheduled-actions/devtools-endpoint.bdd.md +451 -0
- package/tests/cypress/e2e/api/scheduled-actions/devtools-endpoint.cy.ts +447 -0
- package/tests/cypress/e2e/api/scheduled-actions/scheduling.bdd.md +649 -0
- package/tests/cypress/e2e/api/scheduled-actions/scheduling.cy.ts +333 -0
- package/tests/cypress/e2e/api/settings/api-keys.crud.cy.ts +923 -0
- package/tests/cypress/e2e/uat/auth/app-roles/developer-login.bdd.md +231 -0
- package/tests/cypress/e2e/uat/auth/app-roles/developer-login.cy.ts +144 -0
- package/tests/cypress/e2e/uat/auth/app-roles/superadmin-login.bdd.md +118 -0
- package/tests/cypress/e2e/uat/auth/app-roles/superadmin-login.cy.ts +84 -0
- package/tests/cypress/e2e/uat/auth/custom-roles/editor-login.bdd.md +288 -0
- package/tests/cypress/e2e/uat/auth/custom-roles/editor-login.cy.ts +188 -0
- package/tests/cypress/e2e/uat/auth/login-logout.bdd.md +160 -0
- package/tests/cypress/e2e/uat/auth/login-logout.cy.ts +116 -0
- package/tests/cypress/e2e/uat/auth/password-reset.bdd.md +289 -0
- package/tests/cypress/e2e/uat/auth/password-reset.cy.ts +200 -0
- package/tests/cypress/e2e/uat/auth/team-roles/admin-login.bdd.md +225 -0
- package/tests/cypress/e2e/uat/auth/team-roles/admin-login.cy.ts +148 -0
- package/tests/cypress/e2e/uat/auth/team-roles/member-login.bdd.md +251 -0
- package/tests/cypress/e2e/uat/auth/team-roles/member-login.cy.ts +163 -0
- package/tests/cypress/e2e/uat/auth/team-roles/owner-login.bdd.md +231 -0
- package/tests/cypress/e2e/uat/auth/team-roles/owner-login.cy.ts +141 -0
- package/tests/cypress/e2e/uat/billing/extended.bdd.md +273 -0
- package/tests/cypress/e2e/uat/billing/extended.cy.ts +209 -0
- package/tests/cypress/e2e/uat/billing/feature-gates.bdd.md +407 -0
- package/tests/cypress/e2e/uat/billing/feature-gates.cy.ts +307 -0
- package/tests/cypress/e2e/uat/billing/page.bdd.md +329 -0
- package/tests/cypress/e2e/uat/billing/page.cy.ts +250 -0
- package/tests/cypress/e2e/uat/billing/status.bdd.md +190 -0
- package/tests/cypress/e2e/uat/billing/status.cy.ts +145 -0
- package/tests/cypress/e2e/uat/billing/team-switch.bdd.md +156 -0
- package/tests/cypress/e2e/uat/billing/team-switch.cy.ts +122 -0
- package/tests/cypress/e2e/uat/billing/usage.bdd.md +218 -0
- package/tests/cypress/e2e/uat/billing/usage.cy.ts +176 -0
- package/tests/cypress/e2e/uat/blocks/hero.bdd.md +124 -0
- package/tests/cypress/e2e/uat/blocks/hero.cy.ts +56 -0
- package/tests/cypress/e2e/uat/devtools/api-tester.cy.ts +390 -0
- package/tests/cypress/e2e/uat/entities/customers/member.bdd.md +275 -0
- package/tests/cypress/e2e/uat/entities/customers/member.cy.ts +122 -0
- package/tests/cypress/e2e/uat/entities/customers/owner.bdd.md +243 -0
- package/tests/cypress/e2e/uat/entities/customers/owner.cy.ts +165 -0
- package/tests/cypress/e2e/uat/entities/pages/block-crud.bdd.md +476 -0
- package/tests/cypress/e2e/uat/entities/pages/block-crud.cy.ts +486 -0
- package/tests/cypress/e2e/uat/entities/pages/block-editor.bdd.md +460 -0
- package/tests/cypress/e2e/uat/entities/pages/block-editor.cy.ts +301 -0
- package/tests/cypress/e2e/uat/entities/pages/list.bdd.md +432 -0
- package/tests/cypress/e2e/uat/entities/pages/list.cy.ts +273 -0
- package/tests/cypress/e2e/uat/entities/pages/public-rendering.bdd.md +696 -0
- package/tests/cypress/e2e/uat/entities/pages/public-rendering.cy.ts +340 -0
- package/tests/cypress/e2e/uat/entities/posts/categories-api-aware.bdd.md +161 -0
- package/tests/cypress/e2e/uat/entities/posts/categories-api-aware.cy.ts +104 -0
- package/tests/cypress/e2e/uat/entities/posts/categories.bdd.md +375 -0
- package/tests/cypress/e2e/uat/entities/posts/categories.cy.ts +241 -0
- package/tests/cypress/e2e/uat/entities/posts/editor.bdd.md +429 -0
- package/tests/cypress/e2e/uat/entities/posts/editor.cy.ts +257 -0
- package/tests/cypress/e2e/uat/entities/posts/list.bdd.md +340 -0
- package/tests/cypress/e2e/uat/entities/posts/list.cy.ts +177 -0
- package/tests/cypress/e2e/uat/entities/posts/public.bdd.md +614 -0
- package/tests/cypress/e2e/uat/entities/posts/public.cy.ts +249 -0
- package/tests/cypress/e2e/uat/entities/tasks/member.bdd.md +222 -0
- package/tests/cypress/e2e/uat/entities/tasks/member.cy.ts +165 -0
- package/tests/cypress/e2e/uat/entities/tasks/owner.bdd.md +419 -0
- package/tests/cypress/e2e/uat/entities/tasks/owner.cy.ts +191 -0
- package/tests/cypress/e2e/uat/roles/editor-role.bdd.md +552 -0
- package/tests/cypress/e2e/uat/roles/editor-role.cy.ts +210 -0
- package/tests/cypress/e2e/uat/roles/member-restrictions.bdd.md +450 -0
- package/tests/cypress/e2e/uat/roles/member-restrictions.cy.ts +189 -0
- package/tests/cypress/e2e/uat/roles/owner-full-crud.bdd.md +530 -0
- package/tests/cypress/e2e/uat/roles/owner-full-crud.cy.ts +247 -0
- package/tests/cypress/e2e/uat/scheduled-actions/devtools-ui.bdd.md +736 -0
- package/tests/cypress/e2e/uat/scheduled-actions/devtools-ui.cy.ts +740 -0
- package/tests/cypress/e2e/uat/teams/roles-matrix.bdd.md +553 -0
- package/tests/cypress/e2e/uat/teams/roles-matrix.cy.ts +185 -0
- package/tests/cypress/e2e/uat/teams/switcher.bdd.md +1151 -0
- package/tests/cypress/e2e/uat/teams/switcher.cy.ts +497 -0
- package/tests/cypress/e2e/uat/teams/team-switcher.md +198 -0
- package/tests/cypress/fixtures/blocks.json +218 -0
- package/tests/cypress/fixtures/entities.json +78 -0
- package/tests/cypress/fixtures/page-builder.json +21 -0
- package/tests/cypress/src/components/CategoriesPOM.ts +382 -0
- package/tests/cypress/src/components/CustomersPOM.ts +439 -0
- package/tests/cypress/src/components/DevKeyringPOM.ts +160 -0
- package/tests/cypress/src/components/EntityForm.ts +375 -0
- package/tests/cypress/src/components/EntityList.ts +389 -0
- package/tests/cypress/src/components/PageBuilderPOM.ts +710 -0
- package/tests/cypress/src/components/PostEditorPOM.ts +370 -0
- package/tests/cypress/src/components/PostsListPOM.ts +223 -0
- package/tests/cypress/src/components/PublicPagePOM.ts +447 -0
- package/tests/cypress/src/components/PublicPostPOM.ts +146 -0
- package/tests/cypress/src/components/TasksPOM.ts +272 -0
- package/tests/cypress/src/components/TeamSwitcherPOM.ts +450 -0
- package/tests/cypress/src/components/index.ts +21 -0
- package/tests/cypress/src/controllers/ApiKeysAPIController.js +178 -0
- package/tests/cypress/src/controllers/BaseAPIController.js +317 -0
- package/tests/cypress/src/controllers/CustomerAPIController.js +251 -0
- package/tests/cypress/src/controllers/PagesAPIController.js +226 -0
- package/tests/cypress/src/controllers/PostsAPIController.js +250 -0
- package/tests/cypress/src/controllers/TaskAPIController.js +240 -0
- package/tests/cypress/src/controllers/UsersAPIController.js +242 -0
- package/tests/cypress/src/controllers/index.js +25 -0
- package/tests/cypress/src/core/AuthPOM.ts +450 -0
- package/tests/cypress/src/core/BasePOM.ts +86 -0
- package/tests/cypress/src/core/BlockEditorBasePOM.ts +576 -0
- package/tests/cypress/src/core/DashboardEntityPOM.ts +692 -0
- package/tests/cypress/src/core/index.ts +14 -0
- package/tests/cypress/src/entities/CustomersPOM.ts +172 -0
- package/tests/cypress/src/entities/PagesPOM.ts +137 -0
- package/tests/cypress/src/entities/PostsPOM.ts +137 -0
- package/tests/cypress/src/entities/TasksPOM.ts +176 -0
- package/tests/cypress/src/entities/index.ts +14 -0
- package/tests/cypress/src/features/BillingPOM.ts +385 -0
- package/tests/cypress/src/features/DashboardPOM.ts +245 -0
- package/tests/cypress/src/features/DevtoolsPOM.ts +739 -0
- package/tests/cypress/src/features/PageBuilderPOM.ts +263 -0
- package/tests/cypress/src/features/PostEditorPOM.ts +313 -0
- package/tests/cypress/src/features/ScheduledActionsPOM.ts +463 -0
- package/tests/cypress/src/features/SettingsPOM.ts +362 -0
- package/tests/cypress/src/features/SuperadminPOM.ts +331 -0
- package/tests/cypress/src/features/SuperadminTeamRolesPOM.ts +285 -0
- package/tests/cypress/src/features/index.ts +28 -0
- package/tests/cypress/src/helpers/ApiInterceptor.ts +177 -0
- package/tests/cypress/src/index.ts +101 -0
- package/tests/cypress/src/pages/dashboard/Dashboard.js +677 -0
- package/tests/cypress/src/pages/dashboard/DashboardPage.js +43 -0
- package/tests/cypress/src/pages/dashboard/DashboardStats.js +546 -0
- package/tests/cypress/src/pages/dashboard/index.js +6 -0
- package/tests/cypress/src/pages/index.js +5 -0
- package/tests/cypress/src/pages/public/FeaturesPage.js +28 -0
- package/tests/cypress/src/pages/public/LandingPage.js +69 -0
- package/tests/cypress/src/pages/public/PricingPage.js +33 -0
- package/tests/cypress/src/pages/public/index.js +6 -0
- package/tests/cypress/src/selectors.ts +46 -0
- package/tests/cypress/src/session-helpers.ts +500 -0
- package/tests/cypress/support/doc-commands.ts +260 -0
- package/tests/cypress/support/e2e.ts +89 -0
- package/tests/cypress.config.ts +165 -0
- package/tests/jest/components/post-header.test.tsx +377 -0
- package/tests/jest/config/role-config.test.ts +529 -0
- package/tests/jest/jest.config.ts +81 -0
- package/tests/jest/langchain/COVERAGE.md +372 -0
- package/tests/jest/langchain/guardrails.test.ts +465 -0
- package/tests/jest/langchain/streaming.test.ts +367 -0
- package/tests/jest/langchain/token-tracker.test.ts +455 -0
- package/tests/jest/langchain/tracer-callbacks.test.ts +881 -0
- package/tests/jest/langchain/tracer.test.ts +823 -0
- package/tests/jest/user-roles/role-helpers.test.ts +432 -0
- package/tests/jest/validation/categories.test.ts +429 -0
- package/tests/jest/validation/posts.test.ts +546 -0
- package/tests/tsconfig.json +15 -0
|
@@ -0,0 +1,648 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Customers API - CRUD Tests
|
|
3
|
+
*
|
|
4
|
+
* Comprehensive test suite for Customer API endpoints.
|
|
5
|
+
* Tests GET, POST, PATCH, DELETE operations.
|
|
6
|
+
*
|
|
7
|
+
* Entity characteristics:
|
|
8
|
+
* - Required fields: name, account (UNIQUE), office
|
|
9
|
+
* - Access: shared within team (all team members see all customers)
|
|
10
|
+
* - Team context: required (x-team-id header)
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/// <reference types="cypress" />
|
|
14
|
+
|
|
15
|
+
import * as allure from 'allure-cypress'
|
|
16
|
+
|
|
17
|
+
const CustomerAPIController = require('../../../src/controllers/CustomerAPIController.js')
|
|
18
|
+
|
|
19
|
+
describe('Customers API - CRUD Operations', {
|
|
20
|
+
tags: ['@api', '@feat-customers', '@crud', '@regression']
|
|
21
|
+
}, () => {
|
|
22
|
+
// Test constants
|
|
23
|
+
const SUPERADMIN_API_KEY = 'test_api_key_for_testing_purposes_only_not_a_real_secret_key_abc123'
|
|
24
|
+
const TEAM_ID = 'team-tmt-001'
|
|
25
|
+
const BASE_URL = Cypress.config('baseUrl') || 'http://localhost:5173'
|
|
26
|
+
|
|
27
|
+
// Controller instance
|
|
28
|
+
let customerAPI: InstanceType<typeof CustomerAPIController>
|
|
29
|
+
|
|
30
|
+
// Track created customers for cleanup
|
|
31
|
+
let createdCustomers: any[] = []
|
|
32
|
+
|
|
33
|
+
before(() => {
|
|
34
|
+
// Initialize controller with superadmin credentials
|
|
35
|
+
customerAPI = new CustomerAPIController(BASE_URL, SUPERADMIN_API_KEY, TEAM_ID)
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
beforeEach(() => {
|
|
39
|
+
allure.epic('API')
|
|
40
|
+
allure.feature('Customers')
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
afterEach(() => {
|
|
44
|
+
// Cleanup created customers after each test
|
|
45
|
+
createdCustomers.forEach((customer) => {
|
|
46
|
+
if (customer?.id) {
|
|
47
|
+
customerAPI.deleteCustomer(customer.id)
|
|
48
|
+
}
|
|
49
|
+
})
|
|
50
|
+
createdCustomers = []
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
// ============================================
|
|
54
|
+
// GET /api/v1/customers - List Customers
|
|
55
|
+
// ============================================
|
|
56
|
+
describe('GET /api/v1/customers - List Customers', () => {
|
|
57
|
+
it('CUST_API_001: Should list customers with valid API key', { tags: '@smoke' }, () => {
|
|
58
|
+
allure.story('CRUD Operations')
|
|
59
|
+
allure.severity('critical')
|
|
60
|
+
customerAPI.getCustomers().then((response: any) => {
|
|
61
|
+
customerAPI.validateSuccessResponse(response, 200)
|
|
62
|
+
expect(response.body.data).to.be.an('array')
|
|
63
|
+
expect(response.body.info).to.have.property('page')
|
|
64
|
+
expect(response.body.info).to.have.property('limit')
|
|
65
|
+
expect(response.body.info).to.have.property('total')
|
|
66
|
+
expect(response.body.info).to.have.property('totalPages')
|
|
67
|
+
|
|
68
|
+
cy.log(`Found ${response.body.data.length} customers`)
|
|
69
|
+
})
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
it('CUST_API_002: Should list customers with pagination', () => {
|
|
73
|
+
customerAPI.getCustomers({ page: 1, limit: 5 }).then((response: any) => {
|
|
74
|
+
customerAPI.validatePaginatedResponse(response)
|
|
75
|
+
expect(response.body.info.page).to.eq(1)
|
|
76
|
+
expect(response.body.info.limit).to.eq(5)
|
|
77
|
+
expect(response.body.data.length).to.be.at.most(5)
|
|
78
|
+
|
|
79
|
+
cy.log(`Page 1 with limit 5: ${response.body.data.length} customers`)
|
|
80
|
+
})
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
it('CUST_API_003: Should filter customers by office', () => {
|
|
84
|
+
// First create a customer with a specific office
|
|
85
|
+
const testOffice = `TestOffice-${Date.now()}`
|
|
86
|
+
const customerData = customerAPI.generateRandomCustomerData({ office: testOffice })
|
|
87
|
+
|
|
88
|
+
customerAPI.createCustomer(customerData).then((createResponse: any) => {
|
|
89
|
+
expect(createResponse.status).to.eq(201)
|
|
90
|
+
createdCustomers.push(createResponse.body.data)
|
|
91
|
+
|
|
92
|
+
// Now filter by that office
|
|
93
|
+
customerAPI.getCustomers({ office: testOffice }).then((response: any) => {
|
|
94
|
+
customerAPI.validateSuccessResponse(response, 200)
|
|
95
|
+
expect(response.body.data).to.be.an('array')
|
|
96
|
+
|
|
97
|
+
// All returned customers should have the specified office
|
|
98
|
+
response.body.data.forEach((customer: any) => {
|
|
99
|
+
expect(customer.office).to.eq(testOffice)
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
cy.log(`Found ${response.body.data.length} customers with office '${testOffice}'`)
|
|
103
|
+
})
|
|
104
|
+
})
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
it('CUST_API_004: Should filter customers by salesRep', () => {
|
|
108
|
+
// First create a customer with a specific salesRep
|
|
109
|
+
const testSalesRep = `SalesRep-${Date.now()}`
|
|
110
|
+
const customerData = customerAPI.generateRandomCustomerData({ salesRep: testSalesRep })
|
|
111
|
+
|
|
112
|
+
customerAPI.createCustomer(customerData).then((createResponse: any) => {
|
|
113
|
+
expect(createResponse.status).to.eq(201)
|
|
114
|
+
createdCustomers.push(createResponse.body.data)
|
|
115
|
+
|
|
116
|
+
// Now filter by that salesRep
|
|
117
|
+
customerAPI.getCustomers({ salesRep: testSalesRep }).then((response: any) => {
|
|
118
|
+
customerAPI.validateSuccessResponse(response, 200)
|
|
119
|
+
expect(response.body.data).to.be.an('array')
|
|
120
|
+
|
|
121
|
+
// All returned customers should have the specified salesRep
|
|
122
|
+
response.body.data.forEach((customer: any) => {
|
|
123
|
+
expect(customer.salesRep).to.eq(testSalesRep)
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
cy.log(`Found ${response.body.data.length} customers with salesRep '${testSalesRep}'`)
|
|
127
|
+
})
|
|
128
|
+
})
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
it('CUST_API_005: Should search customers by name/account', () => {
|
|
132
|
+
// Create a customer with a unique searchable term
|
|
133
|
+
const uniqueTerm = `SearchCustomer${Date.now()}`
|
|
134
|
+
const customerData = customerAPI.generateRandomCustomerData({
|
|
135
|
+
name: `Customer ${uniqueTerm} Corp`
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
customerAPI.createCustomer(customerData).then((createResponse: any) => {
|
|
139
|
+
expect(createResponse.status).to.eq(201)
|
|
140
|
+
createdCustomers.push(createResponse.body.data)
|
|
141
|
+
|
|
142
|
+
// Search for the unique term
|
|
143
|
+
customerAPI.getCustomers({ search: uniqueTerm }).then((response: any) => {
|
|
144
|
+
customerAPI.validateSuccessResponse(response, 200)
|
|
145
|
+
expect(response.body.data).to.be.an('array')
|
|
146
|
+
expect(response.body.data.length).to.be.greaterThan(0)
|
|
147
|
+
|
|
148
|
+
// Verify the found customer contains our search term
|
|
149
|
+
const foundCustomer = response.body.data.find(
|
|
150
|
+
(c: any) => c.id === createResponse.body.data.id
|
|
151
|
+
)
|
|
152
|
+
expect(foundCustomer).to.exist
|
|
153
|
+
expect(foundCustomer.name).to.include(uniqueTerm)
|
|
154
|
+
|
|
155
|
+
cy.log(`Search found ${response.body.data.length} customers matching '${uniqueTerm}'`)
|
|
156
|
+
})
|
|
157
|
+
})
|
|
158
|
+
})
|
|
159
|
+
|
|
160
|
+
it('CUST_API_006: Should return empty array for non-matching search', () => {
|
|
161
|
+
const nonExistentTerm = 'NonExistentCustomerSearchTerm123456789'
|
|
162
|
+
|
|
163
|
+
customerAPI.getCustomers({ search: nonExistentTerm }).then((response: any) => {
|
|
164
|
+
customerAPI.validateSuccessResponse(response, 200)
|
|
165
|
+
expect(response.body.data).to.be.an('array')
|
|
166
|
+
expect(response.body.data.length).to.eq(0)
|
|
167
|
+
|
|
168
|
+
cy.log('Search with non-matching term returns empty array')
|
|
169
|
+
})
|
|
170
|
+
})
|
|
171
|
+
|
|
172
|
+
it('CUST_API_007: Should reject request without API key', () => {
|
|
173
|
+
const noAuthAPI = new CustomerAPIController(BASE_URL, null, TEAM_ID)
|
|
174
|
+
|
|
175
|
+
noAuthAPI.getCustomers().then((response: any) => {
|
|
176
|
+
expect(response.status).to.eq(401)
|
|
177
|
+
expect(response.body).to.have.property('success', false)
|
|
178
|
+
|
|
179
|
+
cy.log('Request without API key rejected with 401')
|
|
180
|
+
})
|
|
181
|
+
})
|
|
182
|
+
|
|
183
|
+
it('CUST_API_008: Should reject request without x-team-id', () => {
|
|
184
|
+
const noTeamAPI = new CustomerAPIController(BASE_URL, SUPERADMIN_API_KEY, null)
|
|
185
|
+
|
|
186
|
+
noTeamAPI.getCustomers().then((response: any) => {
|
|
187
|
+
expect(response.status).to.eq(400)
|
|
188
|
+
expect(response.body).to.have.property('success', false)
|
|
189
|
+
expect(response.body).to.have.property('code', 'TEAM_CONTEXT_REQUIRED')
|
|
190
|
+
|
|
191
|
+
cy.log('Request without x-team-id rejected with TEAM_CONTEXT_REQUIRED')
|
|
192
|
+
})
|
|
193
|
+
})
|
|
194
|
+
})
|
|
195
|
+
|
|
196
|
+
// ============================================
|
|
197
|
+
// POST /api/v1/customers - Create Customer
|
|
198
|
+
// ============================================
|
|
199
|
+
describe('POST /api/v1/customers - Create Customer', () => {
|
|
200
|
+
it('CUST_API_010: Should create customer with valid data', { tags: '@smoke' }, () => {
|
|
201
|
+
allure.story('CRUD Operations')
|
|
202
|
+
allure.severity('critical')
|
|
203
|
+
const customerData = customerAPI.generateRandomCustomerData({
|
|
204
|
+
phone: '+1-555-1234',
|
|
205
|
+
salesRep: 'John Sales',
|
|
206
|
+
visitDays: ['lun', 'mie', 'vie'],
|
|
207
|
+
contactDays: ['mar', 'jue']
|
|
208
|
+
})
|
|
209
|
+
|
|
210
|
+
customerAPI.createCustomer(customerData).then((response: any) => {
|
|
211
|
+
customerAPI.validateSuccessResponse(response, 201)
|
|
212
|
+
createdCustomers.push(response.body.data)
|
|
213
|
+
|
|
214
|
+
const customer = response.body.data
|
|
215
|
+
customerAPI.validateCustomerObject(customer)
|
|
216
|
+
|
|
217
|
+
// Verify provided data
|
|
218
|
+
expect(customer.name).to.eq(customerData.name)
|
|
219
|
+
expect(Number(customer.account)).to.eq(customerData.account)
|
|
220
|
+
expect(customer.office).to.eq(customerData.office)
|
|
221
|
+
expect(customer.phone).to.eq(customerData.phone)
|
|
222
|
+
expect(customer.salesRep).to.eq(customerData.salesRep)
|
|
223
|
+
expect(customer.visitDays).to.deep.eq(customerData.visitDays)
|
|
224
|
+
expect(customer.contactDays).to.deep.eq(customerData.contactDays)
|
|
225
|
+
|
|
226
|
+
cy.log(`Created customer: ${customer.name} (ID: ${customer.id})`)
|
|
227
|
+
})
|
|
228
|
+
})
|
|
229
|
+
|
|
230
|
+
it('CUST_API_011: Should create customer with minimal data and default values', () => {
|
|
231
|
+
const minimalData = {
|
|
232
|
+
name: `Minimal Customer ${Date.now()}`,
|
|
233
|
+
account: customerAPI.generateUniqueAccount(),
|
|
234
|
+
office: 'Main Office'
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
customerAPI.createCustomer(minimalData).then((response: any) => {
|
|
238
|
+
customerAPI.validateSuccessResponse(response, 201)
|
|
239
|
+
createdCustomers.push(response.body.data)
|
|
240
|
+
|
|
241
|
+
const customer = response.body.data
|
|
242
|
+
customerAPI.validateCustomerObject(customer)
|
|
243
|
+
|
|
244
|
+
// Verify required fields
|
|
245
|
+
expect(customer.name).to.eq(minimalData.name)
|
|
246
|
+
expect(Number(customer.account)).to.eq(minimalData.account)
|
|
247
|
+
expect(customer.office).to.eq(minimalData.office)
|
|
248
|
+
|
|
249
|
+
// Verify defaults for optional fields
|
|
250
|
+
expect(customer.visitDays).to.deep.eq([])
|
|
251
|
+
expect(customer.contactDays).to.deep.eq([])
|
|
252
|
+
|
|
253
|
+
cy.log(`Created customer with minimal data: ${customer.id}`)
|
|
254
|
+
})
|
|
255
|
+
})
|
|
256
|
+
|
|
257
|
+
it('CUST_API_012: Should create customer with visitDays/contactDays', () => {
|
|
258
|
+
const customerData = customerAPI.generateRandomCustomerData({
|
|
259
|
+
visitDays: ['lun', 'mar', 'mie'],
|
|
260
|
+
contactDays: ['jue', 'vie']
|
|
261
|
+
})
|
|
262
|
+
|
|
263
|
+
customerAPI.createCustomer(customerData).then((response: any) => {
|
|
264
|
+
customerAPI.validateSuccessResponse(response, 201)
|
|
265
|
+
createdCustomers.push(response.body.data)
|
|
266
|
+
|
|
267
|
+
const customer = response.body.data
|
|
268
|
+
expect(customer.visitDays).to.be.an('array')
|
|
269
|
+
expect(customer.visitDays).to.deep.eq(['lun', 'mar', 'mie'])
|
|
270
|
+
expect(customer.contactDays).to.be.an('array')
|
|
271
|
+
expect(customer.contactDays).to.deep.eq(['jue', 'vie'])
|
|
272
|
+
|
|
273
|
+
cy.log(`Created customer with visitDays: ${JSON.stringify(customer.visitDays)}`)
|
|
274
|
+
})
|
|
275
|
+
})
|
|
276
|
+
|
|
277
|
+
it('CUST_API_013: Should reject creation without name', () => {
|
|
278
|
+
const invalidData = {
|
|
279
|
+
account: customerAPI.generateUniqueAccount(),
|
|
280
|
+
office: 'Test Office'
|
|
281
|
+
// Missing: name
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
customerAPI.createCustomer(invalidData).then((response: any) => {
|
|
285
|
+
customerAPI.validateErrorResponse(response, 400, 'VALIDATION_ERROR')
|
|
286
|
+
|
|
287
|
+
cy.log('Creation without name rejected with VALIDATION_ERROR')
|
|
288
|
+
})
|
|
289
|
+
})
|
|
290
|
+
|
|
291
|
+
it('CUST_API_014: Should reject creation without account', () => {
|
|
292
|
+
const invalidData = {
|
|
293
|
+
name: 'Test Customer',
|
|
294
|
+
office: 'Test Office'
|
|
295
|
+
// Missing: account
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
customerAPI.createCustomer(invalidData).then((response: any) => {
|
|
299
|
+
// Can be 400 (validation) or 500 (DB constraint for INTEGER NOT NULL)
|
|
300
|
+
expect(response.status).to.be.oneOf([400, 500])
|
|
301
|
+
expect(response.body).to.have.property('success', false)
|
|
302
|
+
|
|
303
|
+
cy.log('Creation without account rejected')
|
|
304
|
+
})
|
|
305
|
+
})
|
|
306
|
+
|
|
307
|
+
it('CUST_API_015: Should reject creation without office', () => {
|
|
308
|
+
const invalidData = {
|
|
309
|
+
name: 'Test Customer',
|
|
310
|
+
account: customerAPI.generateUniqueAccount()
|
|
311
|
+
// Missing: office
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
customerAPI.createCustomer(invalidData).then((response: any) => {
|
|
315
|
+
customerAPI.validateErrorResponse(response, 400, 'VALIDATION_ERROR')
|
|
316
|
+
|
|
317
|
+
cy.log('Creation without office rejected with VALIDATION_ERROR')
|
|
318
|
+
})
|
|
319
|
+
})
|
|
320
|
+
|
|
321
|
+
it('CUST_API_016: Should reject duplicate account number', () => {
|
|
322
|
+
// First create a customer
|
|
323
|
+
const customerData = customerAPI.generateRandomCustomerData()
|
|
324
|
+
|
|
325
|
+
customerAPI.createCustomer(customerData).then((createResponse: any) => {
|
|
326
|
+
expect(createResponse.status).to.eq(201)
|
|
327
|
+
createdCustomers.push(createResponse.body.data)
|
|
328
|
+
|
|
329
|
+
// Try to create another customer with the same account
|
|
330
|
+
const duplicateData = customerAPI.generateRandomCustomerData({
|
|
331
|
+
account: customerData.account // Same account number
|
|
332
|
+
})
|
|
333
|
+
|
|
334
|
+
customerAPI.createCustomer(duplicateData).then((response: any) => {
|
|
335
|
+
// Should fail due to UNIQUE constraint
|
|
336
|
+
expect(response.status).to.be.oneOf([400, 409, 500])
|
|
337
|
+
expect(response.body).to.have.property('success', false)
|
|
338
|
+
|
|
339
|
+
cy.log('Duplicate account number rejected')
|
|
340
|
+
})
|
|
341
|
+
})
|
|
342
|
+
})
|
|
343
|
+
|
|
344
|
+
it('CUST_API_017: Should reject creation without x-team-id', () => {
|
|
345
|
+
const noTeamAPI = new CustomerAPIController(BASE_URL, SUPERADMIN_API_KEY, null)
|
|
346
|
+
const customerData = noTeamAPI.generateRandomCustomerData()
|
|
347
|
+
|
|
348
|
+
noTeamAPI.createCustomer(customerData).then((response: any) => {
|
|
349
|
+
expect(response.status).to.eq(400)
|
|
350
|
+
expect(response.body).to.have.property('success', false)
|
|
351
|
+
expect(response.body).to.have.property('code', 'TEAM_CONTEXT_REQUIRED')
|
|
352
|
+
|
|
353
|
+
cy.log('Creation without x-team-id rejected with TEAM_CONTEXT_REQUIRED')
|
|
354
|
+
})
|
|
355
|
+
})
|
|
356
|
+
})
|
|
357
|
+
|
|
358
|
+
// ============================================
|
|
359
|
+
// GET /api/v1/customers/{id} - Get Customer by ID
|
|
360
|
+
// ============================================
|
|
361
|
+
describe('GET /api/v1/customers/{id} - Get Customer by ID', () => {
|
|
362
|
+
it('CUST_API_020: Should get customer by valid ID', () => {
|
|
363
|
+
// First create a customer
|
|
364
|
+
const customerData = customerAPI.generateRandomCustomerData()
|
|
365
|
+
|
|
366
|
+
customerAPI.createCustomer(customerData).then((createResponse: any) => {
|
|
367
|
+
expect(createResponse.status).to.eq(201)
|
|
368
|
+
createdCustomers.push(createResponse.body.data)
|
|
369
|
+
|
|
370
|
+
const customerId = createResponse.body.data.id
|
|
371
|
+
|
|
372
|
+
// Get the customer by ID
|
|
373
|
+
customerAPI.getCustomerById(customerId).then((response: any) => {
|
|
374
|
+
customerAPI.validateSuccessResponse(response, 200)
|
|
375
|
+
|
|
376
|
+
const customer = response.body.data
|
|
377
|
+
customerAPI.validateCustomerObject(customer)
|
|
378
|
+
expect(customer.id).to.eq(customerId)
|
|
379
|
+
expect(customer.name).to.eq(customerData.name)
|
|
380
|
+
|
|
381
|
+
cy.log(`Retrieved customer: ${customer.name}`)
|
|
382
|
+
})
|
|
383
|
+
})
|
|
384
|
+
})
|
|
385
|
+
|
|
386
|
+
it('CUST_API_021: Should return 404 for non-existent customer', () => {
|
|
387
|
+
const fakeId = 'non-existent-customer-id-12345'
|
|
388
|
+
|
|
389
|
+
customerAPI.getCustomerById(fakeId).then((response: any) => {
|
|
390
|
+
expect(response.status).to.eq(404)
|
|
391
|
+
expect(response.body).to.have.property('success', false)
|
|
392
|
+
|
|
393
|
+
cy.log('Non-existent customer returns 404')
|
|
394
|
+
})
|
|
395
|
+
})
|
|
396
|
+
|
|
397
|
+
// Note: No CUST_API_022 test for "access other user's record" because
|
|
398
|
+
// customers entity has shared: true - all team members can see all customers
|
|
399
|
+
})
|
|
400
|
+
|
|
401
|
+
// ============================================
|
|
402
|
+
// PATCH /api/v1/customers/{id} - Update Customer
|
|
403
|
+
// ============================================
|
|
404
|
+
describe('PATCH /api/v1/customers/{id} - Update Customer', () => {
|
|
405
|
+
it('CUST_API_030: Should update customer with valid data', () => {
|
|
406
|
+
// First create a customer
|
|
407
|
+
customerAPI.createTestCustomer().then((testCustomer: any) => {
|
|
408
|
+
createdCustomers.push(testCustomer)
|
|
409
|
+
|
|
410
|
+
const updateData = {
|
|
411
|
+
name: 'Updated Customer Name',
|
|
412
|
+
phone: '+1-555-9999'
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
customerAPI.updateCustomer(testCustomer.id, updateData).then((response: any) => {
|
|
416
|
+
customerAPI.validateSuccessResponse(response, 200)
|
|
417
|
+
|
|
418
|
+
const customer = response.body.data
|
|
419
|
+
expect(customer.name).to.eq(updateData.name)
|
|
420
|
+
expect(customer.phone).to.eq(updateData.phone)
|
|
421
|
+
// Original values should be preserved
|
|
422
|
+
expect(customer.office).to.eq(testCustomer.office)
|
|
423
|
+
|
|
424
|
+
cy.log(`Updated customer: ${customer.name}`)
|
|
425
|
+
})
|
|
426
|
+
})
|
|
427
|
+
})
|
|
428
|
+
|
|
429
|
+
it('CUST_API_031: Should update customer office', () => {
|
|
430
|
+
customerAPI.createTestCustomer().then((testCustomer: any) => {
|
|
431
|
+
createdCustomers.push(testCustomer)
|
|
432
|
+
|
|
433
|
+
const newOffice = 'New Branch Office'
|
|
434
|
+
|
|
435
|
+
customerAPI.updateCustomer(testCustomer.id, { office: newOffice }).then((response: any) => {
|
|
436
|
+
customerAPI.validateSuccessResponse(response, 200)
|
|
437
|
+
expect(response.body.data.office).to.eq(newOffice)
|
|
438
|
+
|
|
439
|
+
cy.log(`Updated office to: ${newOffice}`)
|
|
440
|
+
})
|
|
441
|
+
})
|
|
442
|
+
})
|
|
443
|
+
|
|
444
|
+
it('CUST_API_032: Should update customer salesRep', () => {
|
|
445
|
+
customerAPI.createTestCustomer().then((testCustomer: any) => {
|
|
446
|
+
createdCustomers.push(testCustomer)
|
|
447
|
+
|
|
448
|
+
const newSalesRep = 'New Sales Representative'
|
|
449
|
+
|
|
450
|
+
customerAPI
|
|
451
|
+
.updateCustomer(testCustomer.id, { salesRep: newSalesRep })
|
|
452
|
+
.then((response: any) => {
|
|
453
|
+
customerAPI.validateSuccessResponse(response, 200)
|
|
454
|
+
expect(response.body.data.salesRep).to.eq(newSalesRep)
|
|
455
|
+
|
|
456
|
+
cy.log(`Updated salesRep to: ${newSalesRep}`)
|
|
457
|
+
})
|
|
458
|
+
})
|
|
459
|
+
})
|
|
460
|
+
|
|
461
|
+
it('CUST_API_033: Should update customer visitDays/contactDays', () => {
|
|
462
|
+
customerAPI.createTestCustomer().then((testCustomer: any) => {
|
|
463
|
+
createdCustomers.push(testCustomer)
|
|
464
|
+
|
|
465
|
+
const updateData = {
|
|
466
|
+
visitDays: ['lun', 'vie'],
|
|
467
|
+
contactDays: ['mar', 'jue']
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
customerAPI.updateCustomer(testCustomer.id, updateData).then((response: any) => {
|
|
471
|
+
customerAPI.validateSuccessResponse(response, 200)
|
|
472
|
+
expect(response.body.data.visitDays).to.deep.eq(updateData.visitDays)
|
|
473
|
+
expect(response.body.data.contactDays).to.deep.eq(updateData.contactDays)
|
|
474
|
+
|
|
475
|
+
cy.log(`Updated visitDays and contactDays`)
|
|
476
|
+
})
|
|
477
|
+
})
|
|
478
|
+
})
|
|
479
|
+
|
|
480
|
+
it('CUST_API_034: Should reject update to duplicate account', () => {
|
|
481
|
+
// Create two customers
|
|
482
|
+
customerAPI.createTestCustomer().then((customer1: any) => {
|
|
483
|
+
createdCustomers.push(customer1)
|
|
484
|
+
|
|
485
|
+
customerAPI.createTestCustomer().then((customer2: any) => {
|
|
486
|
+
createdCustomers.push(customer2)
|
|
487
|
+
|
|
488
|
+
// Try to update customer2's account to customer1's account
|
|
489
|
+
customerAPI
|
|
490
|
+
.updateCustomer(customer2.id, { account: customer1.account })
|
|
491
|
+
.then((response: any) => {
|
|
492
|
+
// Should fail due to UNIQUE constraint
|
|
493
|
+
expect(response.status).to.be.oneOf([400, 409, 500])
|
|
494
|
+
expect(response.body).to.have.property('success', false)
|
|
495
|
+
|
|
496
|
+
cy.log('Update to duplicate account rejected')
|
|
497
|
+
})
|
|
498
|
+
})
|
|
499
|
+
})
|
|
500
|
+
})
|
|
501
|
+
|
|
502
|
+
it('CUST_API_035: Should return 404 for non-existent customer', () => {
|
|
503
|
+
const fakeId = 'non-existent-customer-id-12345'
|
|
504
|
+
|
|
505
|
+
customerAPI.updateCustomer(fakeId, { name: 'New Name' }).then((response: any) => {
|
|
506
|
+
expect(response.status).to.eq(404)
|
|
507
|
+
expect(response.body).to.have.property('success', false)
|
|
508
|
+
|
|
509
|
+
cy.log('Update non-existent customer returns 404')
|
|
510
|
+
})
|
|
511
|
+
})
|
|
512
|
+
|
|
513
|
+
it('CUST_API_036: Should reject empty update body', () => {
|
|
514
|
+
customerAPI.createTestCustomer().then((testCustomer: any) => {
|
|
515
|
+
createdCustomers.push(testCustomer)
|
|
516
|
+
|
|
517
|
+
customerAPI.updateCustomer(testCustomer.id, {}).then((response: any) => {
|
|
518
|
+
expect(response.status).to.eq(400)
|
|
519
|
+
expect(response.body).to.have.property('success', false)
|
|
520
|
+
// Error code can be NO_FIELDS or HTTP_400 depending on validation layer
|
|
521
|
+
expect(response.body.code).to.be.oneOf(['NO_FIELDS', 'HTTP_400'])
|
|
522
|
+
|
|
523
|
+
cy.log('Empty update body rejected')
|
|
524
|
+
})
|
|
525
|
+
})
|
|
526
|
+
})
|
|
527
|
+
})
|
|
528
|
+
|
|
529
|
+
// ============================================
|
|
530
|
+
// DELETE /api/v1/customers/{id} - Delete Customer
|
|
531
|
+
// ============================================
|
|
532
|
+
describe('DELETE /api/v1/customers/{id} - Delete Customer', () => {
|
|
533
|
+
it('CUST_API_040: Should delete customer by valid ID', () => {
|
|
534
|
+
// Create a customer to delete
|
|
535
|
+
const customerData = customerAPI.generateRandomCustomerData()
|
|
536
|
+
|
|
537
|
+
customerAPI.createCustomer(customerData).then((createResponse: any) => {
|
|
538
|
+
expect(createResponse.status).to.eq(201)
|
|
539
|
+
const customerId = createResponse.body.data.id
|
|
540
|
+
|
|
541
|
+
// Delete the customer
|
|
542
|
+
customerAPI.deleteCustomer(customerId).then((response: any) => {
|
|
543
|
+
customerAPI.validateSuccessResponse(response, 200)
|
|
544
|
+
expect(response.body.data).to.have.property('success', true)
|
|
545
|
+
expect(response.body.data).to.have.property('id', customerId)
|
|
546
|
+
|
|
547
|
+
cy.log(`Deleted customer: ${customerId}`)
|
|
548
|
+
})
|
|
549
|
+
})
|
|
550
|
+
})
|
|
551
|
+
|
|
552
|
+
it('CUST_API_041: Should return 404 for non-existent customer', () => {
|
|
553
|
+
const fakeId = 'non-existent-customer-id-12345'
|
|
554
|
+
|
|
555
|
+
customerAPI.deleteCustomer(fakeId).then((response: any) => {
|
|
556
|
+
expect(response.status).to.eq(404)
|
|
557
|
+
expect(response.body).to.have.property('success', false)
|
|
558
|
+
|
|
559
|
+
cy.log('Delete non-existent customer returns 404')
|
|
560
|
+
})
|
|
561
|
+
})
|
|
562
|
+
|
|
563
|
+
it('CUST_API_042: Should verify deletion persists', () => {
|
|
564
|
+
// Create a customer
|
|
565
|
+
const customerData = customerAPI.generateRandomCustomerData()
|
|
566
|
+
|
|
567
|
+
customerAPI.createCustomer(customerData).then((createResponse: any) => {
|
|
568
|
+
expect(createResponse.status).to.eq(201)
|
|
569
|
+
const customerId = createResponse.body.data.id
|
|
570
|
+
|
|
571
|
+
// Delete it
|
|
572
|
+
customerAPI.deleteCustomer(customerId).then((deleteResponse: any) => {
|
|
573
|
+
expect(deleteResponse.status).to.eq(200)
|
|
574
|
+
|
|
575
|
+
// Verify it's gone
|
|
576
|
+
customerAPI.getCustomerById(customerId).then((getResponse: any) => {
|
|
577
|
+
expect(getResponse.status).to.eq(404)
|
|
578
|
+
expect(getResponse.body).to.have.property('success', false)
|
|
579
|
+
|
|
580
|
+
cy.log('Deletion verified - customer no longer exists')
|
|
581
|
+
})
|
|
582
|
+
})
|
|
583
|
+
})
|
|
584
|
+
})
|
|
585
|
+
})
|
|
586
|
+
|
|
587
|
+
// ============================================
|
|
588
|
+
// Integration - Complete CRUD Lifecycle
|
|
589
|
+
// ============================================
|
|
590
|
+
describe('Integration - Complete CRUD Lifecycle', () => {
|
|
591
|
+
it('CUST_API_100: Should complete full lifecycle: Create -> Read -> Update -> Delete', () => {
|
|
592
|
+
// 1. CREATE
|
|
593
|
+
const customerData = customerAPI.generateRandomCustomerData({
|
|
594
|
+
phone: '+1-555-0000',
|
|
595
|
+
salesRep: 'Initial Rep',
|
|
596
|
+
visitDays: ['lun'],
|
|
597
|
+
contactDays: ['mar']
|
|
598
|
+
})
|
|
599
|
+
|
|
600
|
+
customerAPI.createCustomer(customerData).then((createResponse: any) => {
|
|
601
|
+
customerAPI.validateSuccessResponse(createResponse, 201)
|
|
602
|
+
const customerId = createResponse.body.data.id
|
|
603
|
+
|
|
604
|
+
cy.log(`1. Created customer: ${customerId}`)
|
|
605
|
+
|
|
606
|
+
// 2. READ
|
|
607
|
+
customerAPI.getCustomerById(customerId).then((readResponse: any) => {
|
|
608
|
+
customerAPI.validateSuccessResponse(readResponse, 200)
|
|
609
|
+
expect(readResponse.body.data.name).to.eq(customerData.name)
|
|
610
|
+
|
|
611
|
+
cy.log(`2. Read customer: ${readResponse.body.data.name}`)
|
|
612
|
+
|
|
613
|
+
// 3. UPDATE
|
|
614
|
+
const updateData = {
|
|
615
|
+
name: 'Updated Lifecycle Customer',
|
|
616
|
+
phone: '+1-555-9999',
|
|
617
|
+
salesRep: 'Updated Rep',
|
|
618
|
+
visitDays: ['lun', 'mie', 'vie']
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
customerAPI.updateCustomer(customerId, updateData).then((updateResponse: any) => {
|
|
622
|
+
customerAPI.validateSuccessResponse(updateResponse, 200)
|
|
623
|
+
expect(updateResponse.body.data.name).to.eq(updateData.name)
|
|
624
|
+
expect(updateResponse.body.data.phone).to.eq(updateData.phone)
|
|
625
|
+
|
|
626
|
+
cy.log(`3. Updated customer: ${updateResponse.body.data.name}`)
|
|
627
|
+
|
|
628
|
+
// 4. DELETE
|
|
629
|
+
customerAPI.deleteCustomer(customerId).then((deleteResponse: any) => {
|
|
630
|
+
customerAPI.validateSuccessResponse(deleteResponse, 200)
|
|
631
|
+
expect(deleteResponse.body.data).to.have.property('success', true)
|
|
632
|
+
|
|
633
|
+
cy.log(`4. Deleted customer: ${customerId}`)
|
|
634
|
+
|
|
635
|
+
// 5. VERIFY DELETION
|
|
636
|
+
customerAPI.getCustomerById(customerId).then((verifyResponse: any) => {
|
|
637
|
+
expect(verifyResponse.status).to.eq(404)
|
|
638
|
+
|
|
639
|
+
cy.log('5. Verified deletion - customer no longer exists')
|
|
640
|
+
cy.log('Full CRUD lifecycle completed successfully!')
|
|
641
|
+
})
|
|
642
|
+
})
|
|
643
|
+
})
|
|
644
|
+
})
|
|
645
|
+
})
|
|
646
|
+
})
|
|
647
|
+
})
|
|
648
|
+
})
|