@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.
Files changed (221) hide show
  1. package/package.json +1 -1
  2. package/tests/cypress/e2e/_devtools/access.bdd.md +262 -0
  3. package/tests/cypress/e2e/_devtools/access.cy.ts +171 -0
  4. package/tests/cypress/e2e/_devtools/navigation.bdd.md +261 -0
  5. package/tests/cypress/e2e/_devtools/navigation.cy.ts +157 -0
  6. package/tests/cypress/e2e/_devtools/pages.bdd.md +303 -0
  7. package/tests/cypress/e2e/_devtools/pages.cy.ts +184 -0
  8. package/tests/cypress/e2e/_docs/README.md +215 -0
  9. package/tests/cypress/e2e/_docs/tutorials/sector7-superadmin-teams.narration.json +155 -0
  10. package/tests/cypress/e2e/_docs/tutorials/sector7-superadmin.cy.ts +390 -0
  11. package/tests/cypress/e2e/_docs/tutorials/teams-system.doc.cy.ts +349 -0
  12. package/tests/cypress/e2e/_docs/tutorials/teams-system.narration.json +165 -0
  13. package/tests/cypress/e2e/_selectors/auth.cy.ts +306 -0
  14. package/tests/cypress/e2e/_selectors/billing.cy.ts +89 -0
  15. package/tests/cypress/e2e/_selectors/dashboard-mobile.cy.ts +113 -0
  16. package/tests/cypress/e2e/_selectors/dashboard-navigation.cy.ts +89 -0
  17. package/tests/cypress/e2e/_selectors/dashboard-sidebar.cy.ts +60 -0
  18. package/tests/cypress/e2e/_selectors/dashboard-topnav.cy.ts +146 -0
  19. package/tests/cypress/e2e/_selectors/devtools.cy.ts +210 -0
  20. package/tests/cypress/e2e/_selectors/global-search.cy.ts +88 -0
  21. package/tests/cypress/e2e/_selectors/pages-editor.cy.ts +179 -0
  22. package/tests/cypress/e2e/_selectors/posts-editor.cy.ts +282 -0
  23. package/tests/cypress/e2e/_selectors/public.cy.ts +112 -0
  24. package/tests/cypress/e2e/_selectors/settings-api-keys.cy.ts +228 -0
  25. package/tests/cypress/e2e/_selectors/settings-billing.cy.ts +105 -0
  26. package/tests/cypress/e2e/_selectors/settings-layout.cy.ts +119 -0
  27. package/tests/cypress/e2e/_selectors/settings-password.cy.ts +71 -0
  28. package/tests/cypress/e2e/_selectors/settings-profile.cy.ts +82 -0
  29. package/tests/cypress/e2e/_selectors/settings-teams.cy.ts +68 -0
  30. package/tests/cypress/e2e/_selectors/superadmin.cy.ts +185 -0
  31. package/tests/cypress/e2e/_selectors/tasks.cy.ts +242 -0
  32. package/tests/cypress/e2e/_selectors/taxonomies.cy.ts +126 -0
  33. package/tests/cypress/e2e/_selectors/teams.cy.ts +142 -0
  34. package/tests/cypress/e2e/_superadmin/all-teams.bdd.md +261 -0
  35. package/tests/cypress/e2e/_superadmin/all-teams.cy.ts +177 -0
  36. package/tests/cypress/e2e/_superadmin/all-users.bdd.md +406 -0
  37. package/tests/cypress/e2e/_superadmin/all-users.cy.ts +294 -0
  38. package/tests/cypress/e2e/_superadmin/dashboard.bdd.md +235 -0
  39. package/tests/cypress/e2e/_superadmin/dashboard.cy.ts +149 -0
  40. package/tests/cypress/e2e/_superadmin/subscriptions-overview.bdd.md +290 -0
  41. package/tests/cypress/e2e/_superadmin/subscriptions-overview.cy.ts +194 -0
  42. package/tests/cypress/e2e/ai/ai-usage.cy.ts +209 -0
  43. package/tests/cypress/e2e/ai/chat-api.cy.ts +107 -0
  44. package/tests/cypress/e2e/ai/guardrails.cy.ts +332 -0
  45. package/tests/cypress/e2e/api/billing/BillingAPIController.js +319 -0
  46. package/tests/cypress/e2e/api/billing/check-action.cy.ts +326 -0
  47. package/tests/cypress/e2e/api/billing/checkout.cy.ts +358 -0
  48. package/tests/cypress/e2e/api/billing/lifecycle.cy.ts +423 -0
  49. package/tests/cypress/e2e/api/billing/plans/README.md +345 -0
  50. package/tests/cypress/e2e/api/billing/plans/business.cy.ts +412 -0
  51. package/tests/cypress/e2e/api/billing/plans/downgrade.cy.ts +510 -0
  52. package/tests/cypress/e2e/api/billing/plans/fixtures/billing-plans.json +163 -0
  53. package/tests/cypress/e2e/api/billing/plans/free.cy.ts +500 -0
  54. package/tests/cypress/e2e/api/billing/plans/pro.cy.ts +497 -0
  55. package/tests/cypress/e2e/api/billing/plans/starter.cy.ts +342 -0
  56. package/tests/cypress/e2e/api/billing/portal.cy.ts +313 -0
  57. package/tests/cypress/e2e/api/devtools/registries.bdd.md +300 -0
  58. package/tests/cypress/e2e/api/devtools/registries.cy.ts +368 -0
  59. package/tests/cypress/e2e/api/entities/blocks-scope.cy.ts +396 -0
  60. package/tests/cypress/e2e/api/entities/customers-crud.cy.ts +648 -0
  61. package/tests/cypress/e2e/api/entities/customers-metas.cy.ts +839 -0
  62. package/tests/cypress/e2e/api/entities/pages-crud.cy.ts +425 -0
  63. package/tests/cypress/e2e/api/entities/pages-status.cy.ts +335 -0
  64. package/tests/cypress/e2e/api/entities/post-categories-crud.cy.ts +610 -0
  65. package/tests/cypress/e2e/api/entities/posts-crud.cy.ts +709 -0
  66. package/tests/cypress/e2e/api/entities/posts-status.cy.ts +396 -0
  67. package/tests/cypress/e2e/api/entities/tasks-crud.cy.ts +602 -0
  68. package/tests/cypress/e2e/api/entities/tasks-metas.cy.ts +878 -0
  69. package/tests/cypress/e2e/api/entities/users-crud.cy.ts +469 -0
  70. package/tests/cypress/e2e/api/entities/users-metas.cy.ts +913 -0
  71. package/tests/cypress/e2e/api/entities/users-security.cy.ts +375 -0
  72. package/tests/cypress/e2e/api/scheduled-actions/cron-endpoint.bdd.md +375 -0
  73. package/tests/cypress/e2e/api/scheduled-actions/cron-endpoint.cy.ts +346 -0
  74. package/tests/cypress/e2e/api/scheduled-actions/devtools-endpoint.bdd.md +451 -0
  75. package/tests/cypress/e2e/api/scheduled-actions/devtools-endpoint.cy.ts +447 -0
  76. package/tests/cypress/e2e/api/scheduled-actions/scheduling.bdd.md +649 -0
  77. package/tests/cypress/e2e/api/scheduled-actions/scheduling.cy.ts +333 -0
  78. package/tests/cypress/e2e/api/settings/api-keys.crud.cy.ts +923 -0
  79. package/tests/cypress/e2e/uat/auth/app-roles/developer-login.bdd.md +231 -0
  80. package/tests/cypress/e2e/uat/auth/app-roles/developer-login.cy.ts +144 -0
  81. package/tests/cypress/e2e/uat/auth/app-roles/superadmin-login.bdd.md +118 -0
  82. package/tests/cypress/e2e/uat/auth/app-roles/superadmin-login.cy.ts +84 -0
  83. package/tests/cypress/e2e/uat/auth/custom-roles/editor-login.bdd.md +288 -0
  84. package/tests/cypress/e2e/uat/auth/custom-roles/editor-login.cy.ts +188 -0
  85. package/tests/cypress/e2e/uat/auth/login-logout.bdd.md +160 -0
  86. package/tests/cypress/e2e/uat/auth/login-logout.cy.ts +116 -0
  87. package/tests/cypress/e2e/uat/auth/password-reset.bdd.md +289 -0
  88. package/tests/cypress/e2e/uat/auth/password-reset.cy.ts +200 -0
  89. package/tests/cypress/e2e/uat/auth/team-roles/admin-login.bdd.md +225 -0
  90. package/tests/cypress/e2e/uat/auth/team-roles/admin-login.cy.ts +148 -0
  91. package/tests/cypress/e2e/uat/auth/team-roles/member-login.bdd.md +251 -0
  92. package/tests/cypress/e2e/uat/auth/team-roles/member-login.cy.ts +163 -0
  93. package/tests/cypress/e2e/uat/auth/team-roles/owner-login.bdd.md +231 -0
  94. package/tests/cypress/e2e/uat/auth/team-roles/owner-login.cy.ts +141 -0
  95. package/tests/cypress/e2e/uat/billing/extended.bdd.md +273 -0
  96. package/tests/cypress/e2e/uat/billing/extended.cy.ts +209 -0
  97. package/tests/cypress/e2e/uat/billing/feature-gates.bdd.md +407 -0
  98. package/tests/cypress/e2e/uat/billing/feature-gates.cy.ts +307 -0
  99. package/tests/cypress/e2e/uat/billing/page.bdd.md +329 -0
  100. package/tests/cypress/e2e/uat/billing/page.cy.ts +250 -0
  101. package/tests/cypress/e2e/uat/billing/status.bdd.md +190 -0
  102. package/tests/cypress/e2e/uat/billing/status.cy.ts +145 -0
  103. package/tests/cypress/e2e/uat/billing/team-switch.bdd.md +156 -0
  104. package/tests/cypress/e2e/uat/billing/team-switch.cy.ts +122 -0
  105. package/tests/cypress/e2e/uat/billing/usage.bdd.md +218 -0
  106. package/tests/cypress/e2e/uat/billing/usage.cy.ts +176 -0
  107. package/tests/cypress/e2e/uat/blocks/hero.bdd.md +124 -0
  108. package/tests/cypress/e2e/uat/blocks/hero.cy.ts +56 -0
  109. package/tests/cypress/e2e/uat/devtools/api-tester.cy.ts +390 -0
  110. package/tests/cypress/e2e/uat/entities/customers/member.bdd.md +275 -0
  111. package/tests/cypress/e2e/uat/entities/customers/member.cy.ts +122 -0
  112. package/tests/cypress/e2e/uat/entities/customers/owner.bdd.md +243 -0
  113. package/tests/cypress/e2e/uat/entities/customers/owner.cy.ts +165 -0
  114. package/tests/cypress/e2e/uat/entities/pages/block-crud.bdd.md +476 -0
  115. package/tests/cypress/e2e/uat/entities/pages/block-crud.cy.ts +486 -0
  116. package/tests/cypress/e2e/uat/entities/pages/block-editor.bdd.md +460 -0
  117. package/tests/cypress/e2e/uat/entities/pages/block-editor.cy.ts +301 -0
  118. package/tests/cypress/e2e/uat/entities/pages/list.bdd.md +432 -0
  119. package/tests/cypress/e2e/uat/entities/pages/list.cy.ts +273 -0
  120. package/tests/cypress/e2e/uat/entities/pages/public-rendering.bdd.md +696 -0
  121. package/tests/cypress/e2e/uat/entities/pages/public-rendering.cy.ts +340 -0
  122. package/tests/cypress/e2e/uat/entities/posts/categories-api-aware.bdd.md +161 -0
  123. package/tests/cypress/e2e/uat/entities/posts/categories-api-aware.cy.ts +104 -0
  124. package/tests/cypress/e2e/uat/entities/posts/categories.bdd.md +375 -0
  125. package/tests/cypress/e2e/uat/entities/posts/categories.cy.ts +241 -0
  126. package/tests/cypress/e2e/uat/entities/posts/editor.bdd.md +429 -0
  127. package/tests/cypress/e2e/uat/entities/posts/editor.cy.ts +257 -0
  128. package/tests/cypress/e2e/uat/entities/posts/list.bdd.md +340 -0
  129. package/tests/cypress/e2e/uat/entities/posts/list.cy.ts +177 -0
  130. package/tests/cypress/e2e/uat/entities/posts/public.bdd.md +614 -0
  131. package/tests/cypress/e2e/uat/entities/posts/public.cy.ts +249 -0
  132. package/tests/cypress/e2e/uat/entities/tasks/member.bdd.md +222 -0
  133. package/tests/cypress/e2e/uat/entities/tasks/member.cy.ts +165 -0
  134. package/tests/cypress/e2e/uat/entities/tasks/owner.bdd.md +419 -0
  135. package/tests/cypress/e2e/uat/entities/tasks/owner.cy.ts +191 -0
  136. package/tests/cypress/e2e/uat/roles/editor-role.bdd.md +552 -0
  137. package/tests/cypress/e2e/uat/roles/editor-role.cy.ts +210 -0
  138. package/tests/cypress/e2e/uat/roles/member-restrictions.bdd.md +450 -0
  139. package/tests/cypress/e2e/uat/roles/member-restrictions.cy.ts +189 -0
  140. package/tests/cypress/e2e/uat/roles/owner-full-crud.bdd.md +530 -0
  141. package/tests/cypress/e2e/uat/roles/owner-full-crud.cy.ts +247 -0
  142. package/tests/cypress/e2e/uat/scheduled-actions/devtools-ui.bdd.md +736 -0
  143. package/tests/cypress/e2e/uat/scheduled-actions/devtools-ui.cy.ts +740 -0
  144. package/tests/cypress/e2e/uat/teams/roles-matrix.bdd.md +553 -0
  145. package/tests/cypress/e2e/uat/teams/roles-matrix.cy.ts +185 -0
  146. package/tests/cypress/e2e/uat/teams/switcher.bdd.md +1151 -0
  147. package/tests/cypress/e2e/uat/teams/switcher.cy.ts +497 -0
  148. package/tests/cypress/e2e/uat/teams/team-switcher.md +198 -0
  149. package/tests/cypress/fixtures/blocks.json +218 -0
  150. package/tests/cypress/fixtures/entities.json +78 -0
  151. package/tests/cypress/fixtures/page-builder.json +21 -0
  152. package/tests/cypress/src/components/CategoriesPOM.ts +382 -0
  153. package/tests/cypress/src/components/CustomersPOM.ts +439 -0
  154. package/tests/cypress/src/components/DevKeyringPOM.ts +160 -0
  155. package/tests/cypress/src/components/EntityForm.ts +375 -0
  156. package/tests/cypress/src/components/EntityList.ts +389 -0
  157. package/tests/cypress/src/components/PageBuilderPOM.ts +710 -0
  158. package/tests/cypress/src/components/PostEditorPOM.ts +370 -0
  159. package/tests/cypress/src/components/PostsListPOM.ts +223 -0
  160. package/tests/cypress/src/components/PublicPagePOM.ts +447 -0
  161. package/tests/cypress/src/components/PublicPostPOM.ts +146 -0
  162. package/tests/cypress/src/components/TasksPOM.ts +272 -0
  163. package/tests/cypress/src/components/TeamSwitcherPOM.ts +450 -0
  164. package/tests/cypress/src/components/index.ts +21 -0
  165. package/tests/cypress/src/controllers/ApiKeysAPIController.js +178 -0
  166. package/tests/cypress/src/controllers/BaseAPIController.js +317 -0
  167. package/tests/cypress/src/controllers/CustomerAPIController.js +251 -0
  168. package/tests/cypress/src/controllers/PagesAPIController.js +226 -0
  169. package/tests/cypress/src/controllers/PostsAPIController.js +250 -0
  170. package/tests/cypress/src/controllers/TaskAPIController.js +240 -0
  171. package/tests/cypress/src/controllers/UsersAPIController.js +242 -0
  172. package/tests/cypress/src/controllers/index.js +25 -0
  173. package/tests/cypress/src/core/AuthPOM.ts +450 -0
  174. package/tests/cypress/src/core/BasePOM.ts +86 -0
  175. package/tests/cypress/src/core/BlockEditorBasePOM.ts +576 -0
  176. package/tests/cypress/src/core/DashboardEntityPOM.ts +692 -0
  177. package/tests/cypress/src/core/index.ts +14 -0
  178. package/tests/cypress/src/entities/CustomersPOM.ts +172 -0
  179. package/tests/cypress/src/entities/PagesPOM.ts +137 -0
  180. package/tests/cypress/src/entities/PostsPOM.ts +137 -0
  181. package/tests/cypress/src/entities/TasksPOM.ts +176 -0
  182. package/tests/cypress/src/entities/index.ts +14 -0
  183. package/tests/cypress/src/features/BillingPOM.ts +385 -0
  184. package/tests/cypress/src/features/DashboardPOM.ts +245 -0
  185. package/tests/cypress/src/features/DevtoolsPOM.ts +739 -0
  186. package/tests/cypress/src/features/PageBuilderPOM.ts +263 -0
  187. package/tests/cypress/src/features/PostEditorPOM.ts +313 -0
  188. package/tests/cypress/src/features/ScheduledActionsPOM.ts +463 -0
  189. package/tests/cypress/src/features/SettingsPOM.ts +362 -0
  190. package/tests/cypress/src/features/SuperadminPOM.ts +331 -0
  191. package/tests/cypress/src/features/SuperadminTeamRolesPOM.ts +285 -0
  192. package/tests/cypress/src/features/index.ts +28 -0
  193. package/tests/cypress/src/helpers/ApiInterceptor.ts +177 -0
  194. package/tests/cypress/src/index.ts +101 -0
  195. package/tests/cypress/src/pages/dashboard/Dashboard.js +677 -0
  196. package/tests/cypress/src/pages/dashboard/DashboardPage.js +43 -0
  197. package/tests/cypress/src/pages/dashboard/DashboardStats.js +546 -0
  198. package/tests/cypress/src/pages/dashboard/index.js +6 -0
  199. package/tests/cypress/src/pages/index.js +5 -0
  200. package/tests/cypress/src/pages/public/FeaturesPage.js +28 -0
  201. package/tests/cypress/src/pages/public/LandingPage.js +69 -0
  202. package/tests/cypress/src/pages/public/PricingPage.js +33 -0
  203. package/tests/cypress/src/pages/public/index.js +6 -0
  204. package/tests/cypress/src/selectors.ts +46 -0
  205. package/tests/cypress/src/session-helpers.ts +500 -0
  206. package/tests/cypress/support/doc-commands.ts +260 -0
  207. package/tests/cypress/support/e2e.ts +89 -0
  208. package/tests/cypress.config.ts +165 -0
  209. package/tests/jest/components/post-header.test.tsx +377 -0
  210. package/tests/jest/config/role-config.test.ts +529 -0
  211. package/tests/jest/jest.config.ts +81 -0
  212. package/tests/jest/langchain/COVERAGE.md +372 -0
  213. package/tests/jest/langchain/guardrails.test.ts +465 -0
  214. package/tests/jest/langchain/streaming.test.ts +367 -0
  215. package/tests/jest/langchain/token-tracker.test.ts +455 -0
  216. package/tests/jest/langchain/tracer-callbacks.test.ts +881 -0
  217. package/tests/jest/langchain/tracer.test.ts +823 -0
  218. package/tests/jest/user-roles/role-helpers.test.ts +432 -0
  219. package/tests/jest/validation/categories.test.ts +429 -0
  220. package/tests/jest/validation/posts.test.ts +546 -0
  221. 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
+ }