@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,251 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CustomerAPIController - Controller for interacting with the Customers API
|
|
3
|
+
* Encapsulates all CRUD operations for /api/v1/customers endpoints
|
|
4
|
+
*
|
|
5
|
+
* Requires:
|
|
6
|
+
* - API Key with customers:read, customers:write scopes (or superadmin with *)
|
|
7
|
+
* - x-team-id header for team context
|
|
8
|
+
*/
|
|
9
|
+
const BaseAPIController = require('./BaseAPIController')
|
|
10
|
+
const entitiesConfig = require('../../fixtures/entities.json')
|
|
11
|
+
|
|
12
|
+
const { slug } = entitiesConfig.entities.customers
|
|
13
|
+
|
|
14
|
+
class CustomerAPIController extends BaseAPIController {
|
|
15
|
+
/**
|
|
16
|
+
* @param {string} baseUrl - Base URL for API requests
|
|
17
|
+
* @param {string|null} apiKey - API key for authentication
|
|
18
|
+
* @param {string|null} teamId - Team ID for x-team-id header
|
|
19
|
+
*/
|
|
20
|
+
constructor(baseUrl = 'http://localhost:5173', apiKey = null, teamId = null) {
|
|
21
|
+
super(baseUrl, apiKey, teamId, { slug })
|
|
22
|
+
// Counter for generating unique account numbers
|
|
23
|
+
this.accountCounter = Date.now()
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// ============================================================
|
|
27
|
+
// SEMANTIC ALIASES (for backward compatibility)
|
|
28
|
+
// ============================================================
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* GET /api/v1/customers - Get list of customers
|
|
32
|
+
* @param {Object} options - Query options
|
|
33
|
+
* @param {number} [options.page] - Page number
|
|
34
|
+
* @param {number} [options.limit] - Results per page
|
|
35
|
+
* @param {string} [options.office] - Filter by office
|
|
36
|
+
* @param {string} [options.salesRep] - Filter by salesRep
|
|
37
|
+
* @param {string} [options.metas] - Metadata parameter ('all', 'key1,key2', etc.)
|
|
38
|
+
* @param {string} [options.search] - Search in name/account/office
|
|
39
|
+
* @param {Object} [options.headers] - Additional headers
|
|
40
|
+
* @returns {Cypress.Chainable} Cypress response
|
|
41
|
+
*/
|
|
42
|
+
getCustomers(options = {}) {
|
|
43
|
+
return this.list(options)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* GET /api/v1/customers/{id} - Get specific customer by ID
|
|
48
|
+
* @param {string} id - Customer ID
|
|
49
|
+
* @param {Object} options - Additional options
|
|
50
|
+
* @returns {Cypress.Chainable} Cypress response
|
|
51
|
+
*/
|
|
52
|
+
getCustomerById(id, options = {}) {
|
|
53
|
+
return this.getById(id, options)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* POST /api/v1/customers - Create new customer
|
|
58
|
+
* @param {Object} customerData - Customer data
|
|
59
|
+
* @param {string} customerData.name - Customer name (required)
|
|
60
|
+
* @param {number} customerData.account - Account number (required, must be unique)
|
|
61
|
+
* @param {string} customerData.office - Customer office (required)
|
|
62
|
+
* @param {string} [customerData.phone] - Phone number
|
|
63
|
+
* @param {string} [customerData.salesRep] - Sales representative
|
|
64
|
+
* @param {string[]} [customerData.visitDays] - Array of visit days
|
|
65
|
+
* @param {string[]} [customerData.contactDays] - Array of contact days
|
|
66
|
+
* @param {Object} [customerData.metas] - Metadata object
|
|
67
|
+
* @param {Object} options - Additional options
|
|
68
|
+
* @returns {Cypress.Chainable} Cypress response
|
|
69
|
+
*/
|
|
70
|
+
createCustomer(customerData, options = {}) {
|
|
71
|
+
return this.create(customerData, options)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* PATCH /api/v1/customers/{id} - Update customer
|
|
76
|
+
* @param {string} id - Customer ID
|
|
77
|
+
* @param {Object} updateData - Data to update
|
|
78
|
+
* @param {Object} options - Additional options
|
|
79
|
+
* @returns {Cypress.Chainable} Cypress response
|
|
80
|
+
*/
|
|
81
|
+
updateCustomer(id, updateData, options = {}) {
|
|
82
|
+
return this.update(id, updateData, options)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* DELETE /api/v1/customers/{id} - Delete customer
|
|
87
|
+
* @param {string} id - Customer ID
|
|
88
|
+
* @param {Object} options - Additional options
|
|
89
|
+
* @returns {Cypress.Chainable} Cypress response
|
|
90
|
+
*/
|
|
91
|
+
deleteCustomer(id, options = {}) {
|
|
92
|
+
return this.delete(id, options)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// ============================================================
|
|
96
|
+
// DATA GENERATORS
|
|
97
|
+
// ============================================================
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Generate a unique account number
|
|
101
|
+
* Uses timestamp + counter to ensure uniqueness
|
|
102
|
+
* @returns {number} Unique account number
|
|
103
|
+
*/
|
|
104
|
+
generateUniqueAccount() {
|
|
105
|
+
this.accountCounter++
|
|
106
|
+
// Use last 9 digits to stay within INTEGER range
|
|
107
|
+
return parseInt(String(this.accountCounter).slice(-9))
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Generate random customer data for testing
|
|
112
|
+
* @param {Object} overrides - Specific data to override
|
|
113
|
+
* @returns {Object} Generated customer data
|
|
114
|
+
*/
|
|
115
|
+
generateRandomData(overrides = {}) {
|
|
116
|
+
return this.generateRandomCustomerData(overrides)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Generate random customer data for testing
|
|
121
|
+
* @param {Object} overrides - Specific data to override
|
|
122
|
+
* @returns {Object} Generated customer data
|
|
123
|
+
*/
|
|
124
|
+
generateRandomCustomerData(overrides = {}) {
|
|
125
|
+
const timestamp = Date.now()
|
|
126
|
+
const randomId = Math.random().toString(36).substring(2, 8)
|
|
127
|
+
|
|
128
|
+
return {
|
|
129
|
+
name: `Test Customer ${randomId} - ${timestamp}`,
|
|
130
|
+
account: this.generateUniqueAccount(),
|
|
131
|
+
office: `Office-${randomId}`,
|
|
132
|
+
phone: `+1-555-${Math.floor(1000 + Math.random() * 9000)}`,
|
|
133
|
+
salesRep: `Sales Rep ${randomId}`,
|
|
134
|
+
visitDays: [],
|
|
135
|
+
contactDays: [],
|
|
136
|
+
...overrides
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Create a test customer and return its data
|
|
142
|
+
* @param {Object} customerData - Customer data (optional)
|
|
143
|
+
* @returns {Cypress.Chainable} Promise resolving with created customer data
|
|
144
|
+
*/
|
|
145
|
+
createTestCustomer(customerData = {}) {
|
|
146
|
+
return this.createTestEntity(customerData)
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Clean up a test customer (delete it)
|
|
151
|
+
* @param {string} id - Customer ID
|
|
152
|
+
* @returns {Cypress.Chainable} Delete response
|
|
153
|
+
*/
|
|
154
|
+
cleanupTestCustomer(id) {
|
|
155
|
+
return this.cleanup(id)
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// ============================================================
|
|
159
|
+
// ENTITY-SPECIFIC VALIDATORS
|
|
160
|
+
// ============================================================
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Validate customer object structure
|
|
164
|
+
* @param {Object} customer - Customer object
|
|
165
|
+
* @param {boolean} allowMetas - If metas property is allowed
|
|
166
|
+
*/
|
|
167
|
+
validateCustomerObject(customer, allowMetas = false) {
|
|
168
|
+
// Base fields
|
|
169
|
+
this.validateBaseEntityFields(customer)
|
|
170
|
+
|
|
171
|
+
// Required entity fields
|
|
172
|
+
expect(customer).to.have.property('name')
|
|
173
|
+
expect(customer.name).to.be.a('string')
|
|
174
|
+
|
|
175
|
+
expect(customer).to.have.property('account')
|
|
176
|
+
// Account can be number or string depending on how PostgreSQL returns it
|
|
177
|
+
expect(typeof customer.account === 'number' || typeof customer.account === 'string').to.be.true
|
|
178
|
+
|
|
179
|
+
expect(customer).to.have.property('office')
|
|
180
|
+
expect(customer.office).to.be.a('string')
|
|
181
|
+
|
|
182
|
+
// Optional fields that can be null
|
|
183
|
+
if (customer.phone !== null && customer.phone !== undefined) {
|
|
184
|
+
expect(customer.phone).to.be.a('string')
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (customer.salesRep !== null && customer.salesRep !== undefined) {
|
|
188
|
+
expect(customer.salesRep).to.be.a('string')
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// JSONB array fields
|
|
192
|
+
expect(customer).to.have.property('visitDays')
|
|
193
|
+
expect(customer.visitDays).to.be.an('array')
|
|
194
|
+
|
|
195
|
+
expect(customer).to.have.property('contactDays')
|
|
196
|
+
expect(customer.contactDays).to.be.an('array')
|
|
197
|
+
|
|
198
|
+
// Validate metas if present
|
|
199
|
+
if (allowMetas && customer.hasOwnProperty('metas')) {
|
|
200
|
+
expect(customer.metas).to.be.an('object')
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// ============================================================
|
|
205
|
+
// METADATA HELPERS
|
|
206
|
+
// ============================================================
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Generate sample metadata for testing
|
|
210
|
+
* @param {string} type - Type of metadata ('contactPreferences', 'billing', 'notes')
|
|
211
|
+
* @returns {Object} Sample metadata
|
|
212
|
+
*/
|
|
213
|
+
generateSampleMetadata(type = 'contactPreferences') {
|
|
214
|
+
const sampleMetas = {
|
|
215
|
+
contactPreferences: {
|
|
216
|
+
preferredTime: 'morning',
|
|
217
|
+
preferredChannel: 'phone',
|
|
218
|
+
language: 'es',
|
|
219
|
+
doNotContact: false
|
|
220
|
+
},
|
|
221
|
+
billing: {
|
|
222
|
+
paymentTerms: 'net30',
|
|
223
|
+
creditLimit: 50000,
|
|
224
|
+
taxExempt: false,
|
|
225
|
+
currency: 'USD'
|
|
226
|
+
},
|
|
227
|
+
notes: {
|
|
228
|
+
lastContact: '2025-12-01T10:00:00Z',
|
|
229
|
+
nextFollowUp: '2025-12-15T10:00:00Z',
|
|
230
|
+
accountManager: 'John Doe',
|
|
231
|
+
priority: 'high'
|
|
232
|
+
},
|
|
233
|
+
customFields: {
|
|
234
|
+
industry: 'Technology',
|
|
235
|
+
segment: 'Enterprise',
|
|
236
|
+
referralSource: 'Website',
|
|
237
|
+
loyaltyTier: 'Gold'
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
return { [type]: sampleMetas[type] || sampleMetas.contactPreferences }
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// Export class for use in tests
|
|
246
|
+
module.exports = CustomerAPIController
|
|
247
|
+
|
|
248
|
+
// For global use in Cypress
|
|
249
|
+
if (typeof window !== 'undefined') {
|
|
250
|
+
window.CustomerAPIController = CustomerAPIController
|
|
251
|
+
}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PagesAPIController - Controller for interacting with the Pages API
|
|
3
|
+
* Encapsulates all CRUD operations for /api/v1/pages endpoints
|
|
4
|
+
*
|
|
5
|
+
* Requires:
|
|
6
|
+
* - API Key with pages:read, pages:write scopes (or superadmin with *)
|
|
7
|
+
* - x-team-id header for team context
|
|
8
|
+
*
|
|
9
|
+
* Entity characteristics:
|
|
10
|
+
* - Required fields: slug, title, blocks, locale
|
|
11
|
+
* - Optional fields: SEO fields
|
|
12
|
+
* - Unique constraint: slug + locale
|
|
13
|
+
* - Status system: draft, published, scheduled, archived
|
|
14
|
+
* - Uses PATCH for updates
|
|
15
|
+
*/
|
|
16
|
+
const BaseAPIController = require('./BaseAPIController')
|
|
17
|
+
const entitiesConfig = require('../../fixtures/entities.json')
|
|
18
|
+
|
|
19
|
+
const { slug } = entitiesConfig.entities.pages
|
|
20
|
+
|
|
21
|
+
class PagesAPIController extends BaseAPIController {
|
|
22
|
+
/**
|
|
23
|
+
* @param {string} baseUrl - Base URL for API requests
|
|
24
|
+
* @param {string|null} apiKey - API key for authentication
|
|
25
|
+
* @param {string|null} teamId - Team ID for x-team-id header
|
|
26
|
+
*/
|
|
27
|
+
constructor(baseUrl = 'http://localhost:5173', apiKey = null, teamId = null) {
|
|
28
|
+
super(baseUrl, apiKey, teamId, { slug })
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// ============================================================
|
|
32
|
+
// SEMANTIC ALIASES (for better readability in tests)
|
|
33
|
+
// ============================================================
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* GET /api/v1/pages - List pages
|
|
37
|
+
* @param {Object} options - Query options
|
|
38
|
+
* @param {number} [options.page] - Page number
|
|
39
|
+
* @param {number} [options.limit] - Results per page
|
|
40
|
+
* @param {string} [options.status] - Filter by status (draft, published, scheduled, archived)
|
|
41
|
+
* @param {string} [options.locale] - Filter by locale
|
|
42
|
+
* @param {string} [options.search] - Search in title
|
|
43
|
+
* @param {string} [options.metas] - Metadata parameter
|
|
44
|
+
* @returns {Cypress.Chainable} Cypress response
|
|
45
|
+
*/
|
|
46
|
+
getPages(options = {}) {
|
|
47
|
+
return this.list(options)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* GET /api/v1/pages/{id} - Get page by ID
|
|
52
|
+
* @param {string} id - Page ID
|
|
53
|
+
* @param {Object} options - Additional options
|
|
54
|
+
* @returns {Cypress.Chainable} Cypress response
|
|
55
|
+
*/
|
|
56
|
+
getPageById(id, options = {}) {
|
|
57
|
+
return this.getById(id, options)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* POST /api/v1/pages - Create page
|
|
62
|
+
* @param {Object} pageData - Page data
|
|
63
|
+
* @param {string} pageData.slug - Page slug (required)
|
|
64
|
+
* @param {string} pageData.title - Page title (required)
|
|
65
|
+
* @param {string} pageData.locale - Page locale (required)
|
|
66
|
+
* @param {Array} pageData.blocks - Page blocks (required)
|
|
67
|
+
* @param {string} [pageData.status] - Status (draft, published, scheduled, archived)
|
|
68
|
+
* @param {string} [pageData.seoTitle] - SEO title
|
|
69
|
+
* @param {string} [pageData.seoDescription] - SEO description
|
|
70
|
+
* @param {Object} [pageData.metas] - Metadata object
|
|
71
|
+
* @returns {Cypress.Chainable} Cypress response
|
|
72
|
+
*/
|
|
73
|
+
createPage(pageData, options = {}) {
|
|
74
|
+
return this.create(pageData, options)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* PATCH /api/v1/pages/{id} - Update page
|
|
79
|
+
* @param {string} id - Page ID
|
|
80
|
+
* @param {Object} updateData - Data to update
|
|
81
|
+
* @returns {Cypress.Chainable} Cypress response
|
|
82
|
+
*/
|
|
83
|
+
updatePage(id, updateData, options = {}) {
|
|
84
|
+
return this.update(id, updateData, options)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* DELETE /api/v1/pages/{id} - Delete page
|
|
89
|
+
* @param {string} id - Page ID
|
|
90
|
+
* @returns {Cypress.Chainable} Cypress response
|
|
91
|
+
*/
|
|
92
|
+
deletePage(id, options = {}) {
|
|
93
|
+
return this.delete(id, options)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// ============================================================
|
|
97
|
+
// DATA GENERATORS
|
|
98
|
+
// ============================================================
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Generate random page data for testing
|
|
102
|
+
* @param {Object} overrides - Specific data to override
|
|
103
|
+
* @returns {Object} Generated page data
|
|
104
|
+
*/
|
|
105
|
+
generateRandomData(overrides = {}) {
|
|
106
|
+
return PagesAPIController.generateRandomPageData(overrides)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Static method to generate random page data
|
|
111
|
+
* @param {Object} overrides - Specific data to override
|
|
112
|
+
* @returns {Object} Generated page data
|
|
113
|
+
*/
|
|
114
|
+
static generateRandomPageData(overrides = {}) {
|
|
115
|
+
const timestamp = Date.now()
|
|
116
|
+
const randomId = Math.random().toString(36).substring(2, 8)
|
|
117
|
+
|
|
118
|
+
return {
|
|
119
|
+
slug: `test-page-${randomId}-${timestamp}`,
|
|
120
|
+
title: `Test Page ${randomId}`,
|
|
121
|
+
locale: 'en',
|
|
122
|
+
status: 'draft',
|
|
123
|
+
blocks: [],
|
|
124
|
+
...overrides
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Create a test page and return its data
|
|
130
|
+
* @param {Object} overrides - Data overrides
|
|
131
|
+
* @returns {Cypress.Chainable} Promise resolving with created page data
|
|
132
|
+
*/
|
|
133
|
+
createTestPage(overrides = {}) {
|
|
134
|
+
return this.createTestEntity(overrides)
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Clean up a test page
|
|
139
|
+
* @param {string} id - Page ID
|
|
140
|
+
* @returns {Cypress.Chainable} Delete response
|
|
141
|
+
*/
|
|
142
|
+
cleanupTestPage(id) {
|
|
143
|
+
return this.cleanup(id)
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// ============================================================
|
|
147
|
+
// ENTITY-SPECIFIC VALIDATORS
|
|
148
|
+
// ============================================================
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Validate page object structure
|
|
152
|
+
* @param {Object} page - Page object
|
|
153
|
+
* @param {boolean} allowMetas - If metas property is allowed
|
|
154
|
+
*/
|
|
155
|
+
validatePageObject(page, allowMetas = false) {
|
|
156
|
+
// Base fields
|
|
157
|
+
this.validateBaseEntityFields(page)
|
|
158
|
+
|
|
159
|
+
// Required page fields
|
|
160
|
+
expect(page).to.have.property('slug')
|
|
161
|
+
expect(page.slug).to.be.a('string')
|
|
162
|
+
|
|
163
|
+
expect(page).to.have.property('title')
|
|
164
|
+
expect(page.title).to.be.a('string')
|
|
165
|
+
|
|
166
|
+
expect(page).to.have.property('locale')
|
|
167
|
+
expect(page.locale).to.be.a('string')
|
|
168
|
+
|
|
169
|
+
expect(page).to.have.property('blocks')
|
|
170
|
+
expect(page.blocks).to.be.an('array')
|
|
171
|
+
|
|
172
|
+
// Status field (if present)
|
|
173
|
+
if (page.hasOwnProperty('status') && page.status !== null) {
|
|
174
|
+
expect(page.status).to.be.oneOf(['draft', 'published', 'scheduled', 'archived'])
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Metas if allowed
|
|
178
|
+
if (allowMetas && page.hasOwnProperty('metas')) {
|
|
179
|
+
expect(page.metas).to.be.an('object')
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// ============================================================
|
|
184
|
+
// METADATA HELPERS
|
|
185
|
+
// ============================================================
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Generate sample metadata for testing
|
|
189
|
+
* @param {string} type - Type of metadata ('seo', 'layout', 'settings')
|
|
190
|
+
* @returns {Object} Sample metadata
|
|
191
|
+
*/
|
|
192
|
+
generateSampleMetadata(type = 'seo') {
|
|
193
|
+
const sampleMetas = {
|
|
194
|
+
seo: {
|
|
195
|
+
seoTitle: 'Custom Page SEO Title',
|
|
196
|
+
seoDescription: 'Custom SEO description for this page',
|
|
197
|
+
seoKeywords: 'test, page, cypress',
|
|
198
|
+
noindex: false,
|
|
199
|
+
nofollow: false,
|
|
200
|
+
ogImage: '/images/og-page.jpg'
|
|
201
|
+
},
|
|
202
|
+
layout: {
|
|
203
|
+
headerStyle: 'transparent',
|
|
204
|
+
footerVisible: true,
|
|
205
|
+
sidebarEnabled: false,
|
|
206
|
+
fullWidth: true
|
|
207
|
+
},
|
|
208
|
+
settings: {
|
|
209
|
+
cacheEnabled: true,
|
|
210
|
+
cacheTTL: 3600,
|
|
211
|
+
authRequired: false,
|
|
212
|
+
analyticsEnabled: true
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
return { [type]: sampleMetas[type] || sampleMetas.seo }
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Export for CommonJS
|
|
221
|
+
module.exports = PagesAPIController
|
|
222
|
+
|
|
223
|
+
// For global use in Cypress
|
|
224
|
+
if (typeof window !== 'undefined') {
|
|
225
|
+
window.PagesAPIController = PagesAPIController
|
|
226
|
+
}
|