@nextsparkjs/theme-default 0.1.0-beta.20 → 0.1.0-beta.21

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 (220) 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.config.ts +150 -0
  208. package/tests/jest/components/post-header.test.tsx +377 -0
  209. package/tests/jest/config/role-config.test.ts +529 -0
  210. package/tests/jest/jest.config.ts +81 -0
  211. package/tests/jest/langchain/COVERAGE.md +372 -0
  212. package/tests/jest/langchain/guardrails.test.ts +465 -0
  213. package/tests/jest/langchain/streaming.test.ts +367 -0
  214. package/tests/jest/langchain/token-tracker.test.ts +455 -0
  215. package/tests/jest/langchain/tracer-callbacks.test.ts +881 -0
  216. package/tests/jest/langchain/tracer.test.ts +823 -0
  217. package/tests/jest/user-roles/role-helpers.test.ts +432 -0
  218. package/tests/jest/validation/categories.test.ts +429 -0
  219. package/tests/jest/validation/posts.test.ts +546 -0
  220. package/tests/tsconfig.json +15 -0
@@ -0,0 +1,469 @@
1
+ /// <reference types="cypress" />
2
+
3
+ /**
4
+ * Users API - CRUD Tests
5
+ *
6
+ * Basic CRUD operations for /api/v1/users endpoints
7
+ * Uses superadmin API key for full access
8
+ */
9
+
10
+ import * as allure from 'allure-cypress'
11
+
12
+ const UsersAPIController = require('../../../src/controllers/UsersAPIController.js')
13
+
14
+ describe('Users API - CRUD Operations', {
15
+ tags: ['@api', '@feat-users', '@crud', '@regression']
16
+ }, () => {
17
+ let userAPI: any
18
+ let createdUsers: any[] = []
19
+
20
+ // Superadmin API key for testing
21
+ const SUPERADMIN_API_KEY = 'test_api_key_for_testing_purposes_only_not_a_real_secret_key_abc123'
22
+ const BASE_URL = Cypress.config('baseUrl') || 'http://localhost:5173'
23
+
24
+ before(() => {
25
+ // Initialize API controller with superadmin API key (global entity - no teamId required)
26
+ userAPI = new UsersAPIController(BASE_URL, SUPERADMIN_API_KEY)
27
+ cy.log('UsersAPIController initialized (global entity - no team required)')
28
+ cy.log(`Base URL: ${BASE_URL}`)
29
+ })
30
+
31
+ beforeEach(() => {
32
+ allure.epic('API')
33
+ allure.feature('Users')
34
+ allure.story('CRUD Operations')
35
+ })
36
+
37
+ afterEach(() => {
38
+ // Cleanup: Delete users created during tests
39
+ if (createdUsers.length > 0) {
40
+ createdUsers.forEach((user: any) => {
41
+ if (user && user.id) {
42
+ userAPI.deleteUser(user.id)
43
+ }
44
+ })
45
+ createdUsers = []
46
+ }
47
+ })
48
+
49
+ // ============================================================
50
+ // GET /api/v1/users - List Users
51
+ // ============================================================
52
+ describe('GET /api/v1/users - List Users', () => {
53
+ it('USERS_API_001: Should list all users with valid API key', { tags: '@smoke' }, () => {
54
+ allure.severity('critical')
55
+ userAPI.getUsers().then((response: any) => {
56
+ userAPI.validateSuccessResponse(response, 200)
57
+ userAPI.validatePaginatedResponse(response)
58
+ expect(response.body.data).to.be.an('array')
59
+
60
+ cy.log(`Found ${response.body.data.length} users`)
61
+ cy.log(`Total users: ${response.body.info.total}`)
62
+ })
63
+ })
64
+
65
+ it('USERS_API_002: Should list users with pagination', () => {
66
+ userAPI.getUsers({ page: 1, limit: 5 }).then((response: any) => {
67
+ userAPI.validatePaginatedResponse(response)
68
+ expect(response.body.info.page).to.eq(1)
69
+ expect(response.body.info.limit).to.eq(5)
70
+ expect(response.body.data.length).to.be.at.most(5)
71
+
72
+ cy.log(`Page 1, Limit 5: Got ${response.body.data.length} users`)
73
+ })
74
+ })
75
+
76
+ it('USERS_API_003: Should filter users by role', () => {
77
+ userAPI.getUsers({ role: 'member' }).then((response: any) => {
78
+ userAPI.validateSuccessResponse(response, 200)
79
+
80
+ // All returned users should have role 'member'
81
+ response.body.data.forEach((user: any) => {
82
+ expect(user.role).to.eq('member')
83
+ })
84
+
85
+ cy.log(`Found ${response.body.data.length} users with role 'member'`)
86
+ })
87
+ })
88
+
89
+ it('USERS_API_004: Should reject request without API key', () => {
90
+ const originalApiKey = userAPI.apiKey
91
+ userAPI.setApiKey(null)
92
+
93
+ userAPI.getUsers().then((response: any) => {
94
+ expect(response.status).to.eq(401)
95
+ expect(response.body.success).to.be.false
96
+ })
97
+
98
+ userAPI.setApiKey(originalApiKey)
99
+ })
100
+
101
+ it('USERS_API_005: Should reject request with invalid API key', () => {
102
+ const originalApiKey = userAPI.apiKey
103
+ userAPI.setApiKey('sk_invalid_key_12345')
104
+
105
+ userAPI.getUsers().then((response: any) => {
106
+ expect(response.status).to.eq(401)
107
+ expect(response.body.success).to.be.false
108
+ })
109
+
110
+ userAPI.setApiKey(originalApiKey)
111
+ })
112
+ })
113
+
114
+ // ============================================================
115
+ // POST /api/v1/users - Create User
116
+ // ============================================================
117
+ describe('POST /api/v1/users - Create User', () => {
118
+ it('USERS_API_010: Should create user with valid data', { tags: '@smoke' }, () => {
119
+ allure.severity('critical')
120
+ const userData = userAPI.generateRandomUserData({
121
+ firstName: 'TestCreate',
122
+ lastName: 'CypressUser',
123
+ role: 'member'
124
+ })
125
+
126
+ userAPI.createUser(userData).then((response: any) => {
127
+ userAPI.validateSuccessResponse(response, 201)
128
+ userAPI.validateUserObject(response.body.data)
129
+
130
+ expect(response.body.data.email).to.eq(userData.email)
131
+ expect(response.body.data.firstName).to.eq(userData.firstName)
132
+ expect(response.body.data.lastName).to.eq(userData.lastName)
133
+ expect(response.body.data.role).to.eq(userData.role)
134
+
135
+ // Save for cleanup
136
+ createdUsers.push(response.body.data)
137
+
138
+ cy.log(`Created user: ${response.body.data.email}`)
139
+ })
140
+ })
141
+
142
+ it('USERS_API_011: Should create user with minimal data and default values', () => {
143
+ const userData = userAPI.generateRandomUserData({
144
+ firstName: 'MinimalUser'
145
+ })
146
+ delete userData.role // Should default to 'member'
147
+
148
+ userAPI.createUser(userData).then((response: any) => {
149
+ userAPI.validateSuccessResponse(response, 201)
150
+ userAPI.validateUserObject(response.body.data)
151
+
152
+ // Verify default values
153
+ expect(response.body.data.role).to.eq('member')
154
+ expect(response.body.data.language).to.eq('en')
155
+ expect(response.body.data.timezone).to.eq('UTC')
156
+
157
+ // Verify auto-generated name
158
+ expect(response.body.data.name).to.eq(`${userData.firstName} ${userData.lastName}`)
159
+
160
+ createdUsers.push(response.body.data)
161
+ cy.log(`Created user with defaults: ${response.body.data.email}`)
162
+ })
163
+ })
164
+
165
+ it('USERS_API_012: Should reject creation with invalid email format', () => {
166
+ const userData = userAPI.generateRandomUserData({
167
+ email: 'invalid-email-format'
168
+ })
169
+
170
+ userAPI.createUser(userData).then((response: any) => {
171
+ expect(response.status).to.eq(400)
172
+ expect(response.body.success).to.be.false
173
+ })
174
+ })
175
+
176
+ it('USERS_API_013: Should reject creation without required fields', () => {
177
+ const userData = {
178
+ email: `test_${Date.now()}@nextspark.dev`
179
+ // Missing firstName, lastName, country
180
+ }
181
+
182
+ userAPI.createUser(userData).then((response: any) => {
183
+ expect(response.status).to.eq(400)
184
+ expect(response.body.success).to.be.false
185
+ })
186
+ })
187
+
188
+ it('USERS_API_014: Should reject duplicate email', () => {
189
+ const userData = userAPI.generateRandomUserData()
190
+
191
+ // Create first user
192
+ userAPI.createUser(userData).then((firstResponse: any) => {
193
+ expect(firstResponse.status).to.eq(201)
194
+ createdUsers.push(firstResponse.body.data)
195
+
196
+ // Try to create second user with same email
197
+ userAPI.createUser(userData).then((secondResponse: any) => {
198
+ expect(secondResponse.status).to.eq(409)
199
+ expect(secondResponse.body.success).to.be.false
200
+ })
201
+ })
202
+ })
203
+ })
204
+
205
+ // ============================================================
206
+ // GET /api/v1/users/{id} - Get User by ID
207
+ // ============================================================
208
+ describe('GET /api/v1/users/{id} - Get User by ID', () => {
209
+ let testUser: any
210
+
211
+ beforeEach(() => {
212
+ // Create a test user for each test
213
+ const userData = userAPI.generateRandomUserData({
214
+ firstName: 'TestGetById'
215
+ })
216
+
217
+ userAPI.createUser(userData).then((response: any) => {
218
+ testUser = response.body.data
219
+ createdUsers.push(testUser)
220
+ })
221
+ })
222
+
223
+ it('USERS_API_020: Should get user by valid ID', () => {
224
+ cy.then(() => {
225
+ userAPI.getUserById(testUser.id).then((response: any) => {
226
+ userAPI.validateSuccessResponse(response, 200)
227
+ userAPI.validateUserObject(response.body.data)
228
+
229
+ expect(response.body.data.id).to.eq(testUser.id)
230
+ expect(response.body.data.email).to.eq(testUser.email)
231
+
232
+ cy.log(`Got user by ID: ${testUser.id}`)
233
+ })
234
+ })
235
+ })
236
+
237
+ it('USERS_API_021: Should get user by valid email', () => {
238
+ cy.then(() => {
239
+ userAPI.getUserById(testUser.email).then((response: any) => {
240
+ userAPI.validateSuccessResponse(response, 200)
241
+ userAPI.validateUserObject(response.body.data)
242
+
243
+ expect(response.body.data.id).to.eq(testUser.id)
244
+ expect(response.body.data.email).to.eq(testUser.email)
245
+
246
+ cy.log(`Got user by email: ${testUser.email}`)
247
+ })
248
+ })
249
+ })
250
+
251
+ it('USERS_API_022: Should return 404 for non-existent user', () => {
252
+ const nonExistentId = 'non-existent-user-id-12345'
253
+
254
+ userAPI.getUserById(nonExistentId).then((response: any) => {
255
+ expect(response.status).to.eq(404)
256
+ expect(response.body.success).to.be.false
257
+ })
258
+ })
259
+ })
260
+
261
+ // ============================================================
262
+ // PATCH /api/v1/users/{id} - Update User
263
+ // ============================================================
264
+ describe('PATCH /api/v1/users/{id} - Update User', () => {
265
+ let testUser: any
266
+
267
+ beforeEach(() => {
268
+ // Create a test user for each test
269
+ const userData = userAPI.generateRandomUserData({
270
+ firstName: 'TestUpdate'
271
+ })
272
+
273
+ userAPI.createUser(userData).then((response: any) => {
274
+ testUser = response.body.data
275
+ createdUsers.push(testUser)
276
+ })
277
+ })
278
+
279
+ it('USERS_API_030: Should update user with valid data', () => {
280
+ const updateData = {
281
+ firstName: 'UpdatedFirstName',
282
+ lastName: 'UpdatedLastName'
283
+ }
284
+
285
+ cy.then(() => {
286
+ userAPI.updateUser(testUser.id, updateData).then((response: any) => {
287
+ userAPI.validateSuccessResponse(response, 200)
288
+ userAPI.validateUserObject(response.body.data)
289
+
290
+ expect(response.body.data.firstName).to.eq(updateData.firstName)
291
+ expect(response.body.data.lastName).to.eq(updateData.lastName)
292
+ expect(response.body.data.id).to.eq(testUser.id)
293
+
294
+ // Name should be auto-updated
295
+ expect(response.body.data.name).to.eq(`${updateData.firstName} ${updateData.lastName}`)
296
+
297
+ cy.log(`Updated user: ${testUser.id}`)
298
+ })
299
+ })
300
+ })
301
+
302
+ it('USERS_API_031: Should update user by email', () => {
303
+ const updateData = {
304
+ firstName: 'UpdatedViaEmail'
305
+ }
306
+
307
+ cy.then(() => {
308
+ userAPI.updateUser(testUser.email, updateData).then((response: any) => {
309
+ userAPI.validateSuccessResponse(response, 200)
310
+
311
+ expect(response.body.data.firstName).to.eq(updateData.firstName)
312
+ expect(response.body.data.email).to.eq(testUser.email)
313
+
314
+ cy.log(`Updated user by email: ${testUser.email}`)
315
+ })
316
+ })
317
+ })
318
+
319
+ it('USERS_API_032: Should update user role', () => {
320
+ // Note: User-level roles are only 'member' or 'superadmin'
321
+ // Team-specific roles (admin, collaborator, etc.) are managed via team_members API
322
+ const updateData = {
323
+ role: 'superadmin'
324
+ }
325
+
326
+ cy.then(() => {
327
+ userAPI.updateUser(testUser.id, updateData).then((response: any) => {
328
+ userAPI.validateSuccessResponse(response, 200)
329
+ expect(response.body.data.role).to.eq(updateData.role)
330
+
331
+ cy.log(`Updated user role to: ${updateData.role}`)
332
+ })
333
+ })
334
+ })
335
+
336
+ it('USERS_API_033: Should return 404 for non-existent user', () => {
337
+ const nonExistentId = 'non-existent-user-id-12345'
338
+ const updateData = { firstName: 'Updated' }
339
+
340
+ userAPI.updateUser(nonExistentId, updateData).then((response: any) => {
341
+ expect(response.status).to.eq(404)
342
+ expect(response.body.success).to.be.false
343
+ })
344
+ })
345
+
346
+ it('USERS_API_034: Should reject empty update body', () => {
347
+ cy.then(() => {
348
+ userAPI.updateUser(testUser.id, {}).then((response: any) => {
349
+ expect(response.status).to.eq(400)
350
+ expect(response.body.success).to.be.false
351
+ })
352
+ })
353
+ })
354
+ })
355
+
356
+ // ============================================================
357
+ // DELETE /api/v1/users/{id} - Delete User
358
+ // ============================================================
359
+ describe('DELETE /api/v1/users/{id} - Delete User', () => {
360
+ let testUser: any
361
+
362
+ beforeEach(() => {
363
+ // Create a test user for each test
364
+ const userData = userAPI.generateRandomUserData({
365
+ firstName: 'TestDelete'
366
+ })
367
+
368
+ userAPI.createUser(userData).then((response: any) => {
369
+ testUser = response.body.data
370
+ // Don't add to createdUsers - we'll delete manually
371
+ })
372
+ })
373
+
374
+ it('USERS_API_040: Should delete user by valid ID', () => {
375
+ cy.then(() => {
376
+ userAPI.deleteUser(testUser.id).then((response: any) => {
377
+ userAPI.validateSuccessResponse(response, 200)
378
+ expect(response.body.data.deleted).to.be.true
379
+ expect(response.body.data.id).to.exist
380
+
381
+ cy.log(`Deleted user: ${testUser.id}`)
382
+
383
+ // Verify user was deleted
384
+ userAPI.getUserById(testUser.id).then((getResponse: any) => {
385
+ expect(getResponse.status).to.eq(404)
386
+ })
387
+ })
388
+ })
389
+ })
390
+
391
+ it('USERS_API_041: Should delete user by valid email', () => {
392
+ cy.then(() => {
393
+ userAPI.deleteUser(testUser.email).then((response: any) => {
394
+ userAPI.validateSuccessResponse(response, 200)
395
+ expect(response.body.data.deleted).to.be.true
396
+
397
+ cy.log(`Deleted user by email: ${testUser.email}`)
398
+
399
+ // Verify user was deleted
400
+ userAPI.getUserById(testUser.email).then((getResponse: any) => {
401
+ expect(getResponse.status).to.eq(404)
402
+ })
403
+ })
404
+ })
405
+ })
406
+
407
+ it('USERS_API_042: Should return 404 for non-existent user', () => {
408
+ const nonExistentId = 'non-existent-user-id-12345'
409
+
410
+ userAPI.deleteUser(nonExistentId).then((response: any) => {
411
+ expect(response.status).to.eq(404)
412
+ expect(response.body.success).to.be.false
413
+ })
414
+
415
+ // Add testUser to cleanup since we didn't delete it
416
+ createdUsers.push(testUser)
417
+ })
418
+ })
419
+
420
+ // ============================================================
421
+ // Integration Test - Complete CRUD Lifecycle
422
+ // ============================================================
423
+ describe('Integration - Complete CRUD Lifecycle', () => {
424
+ it('USERS_API_100: Should complete full lifecycle: Create -> Read -> Update -> Delete', () => {
425
+ const userData = userAPI.generateRandomUserData({
426
+ firstName: 'Lifecycle',
427
+ lastName: 'TestUser',
428
+ role: 'member'
429
+ })
430
+
431
+ // 1. CREATE
432
+ userAPI.createUser(userData).then((createResponse: any) => {
433
+ userAPI.validateSuccessResponse(createResponse, 201)
434
+ const createdUser = createResponse.body.data
435
+ cy.log(`1. Created user: ${createdUser.email}`)
436
+
437
+ // 2. READ
438
+ userAPI.getUserById(createdUser.id).then((readResponse: any) => {
439
+ userAPI.validateSuccessResponse(readResponse, 200)
440
+ expect(readResponse.body.data.id).to.eq(createdUser.id)
441
+ expect(readResponse.body.data.email).to.eq(userData.email)
442
+ cy.log(`2. Read user: ${createdUser.id}`)
443
+
444
+ // 3. UPDATE
445
+ const updateData = { firstName: 'UpdatedLifecycle' }
446
+ userAPI.updateUser(createdUser.id, updateData).then((updateResponse: any) => {
447
+ userAPI.validateSuccessResponse(updateResponse, 200)
448
+ expect(updateResponse.body.data.firstName).to.eq(updateData.firstName)
449
+ cy.log(`3. Updated user firstName to: ${updateData.firstName}`)
450
+
451
+ // 4. DELETE
452
+ userAPI.deleteUser(createdUser.id).then((deleteResponse: any) => {
453
+ userAPI.validateSuccessResponse(deleteResponse, 200)
454
+ expect(deleteResponse.body.data.deleted).to.be.true
455
+ cy.log(`4. Deleted user: ${createdUser.id}`)
456
+
457
+ // 5. VERIFY DELETION
458
+ userAPI.getUserById(createdUser.id).then((finalResponse: any) => {
459
+ expect(finalResponse.status).to.eq(404)
460
+ cy.log(`5. Verified deletion: user not found (404)`)
461
+ cy.log('Full CRUD lifecycle completed successfully')
462
+ })
463
+ })
464
+ })
465
+ })
466
+ })
467
+ })
468
+ })
469
+ })