@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,425 @@
1
+ /// <reference types="cypress" />
2
+
3
+ /**
4
+ * Pages API - CRUD Tests
5
+ *
6
+ * Basic CRUD operations for /api/v1/pages endpoints.
7
+ * Tests page creation, reading, updating, and deletion.
8
+ *
9
+ * Tags: @api, @feat-pages, @crud, @page-builder
10
+ */
11
+
12
+ import * as allure from 'allure-cypress'
13
+
14
+ describe('Pages API - CRUD Operations', {
15
+ tags: ['@api', '@feat-pages', '@crud', '@page-builder']
16
+ }, () => {
17
+ // Superadmin API key for testing
18
+ const SUPERADMIN_API_KEY = 'test_api_key_for_testing_purposes_only_not_a_real_secret_key_abc123'
19
+ const BASE_URL = Cypress.config('baseUrl') || 'http://localhost:5173'
20
+ const API_PAGES = `${BASE_URL}/api/v1/pages`
21
+
22
+ // Track created pages for cleanup
23
+ let createdPages: string[] = []
24
+
25
+ // Helper to make authenticated requests
26
+ const apiRequest = (method: string, url: string, body?: object) => {
27
+ return cy.request({
28
+ method,
29
+ url,
30
+ headers: {
31
+ 'x-api-key': SUPERADMIN_API_KEY,
32
+ 'Content-Type': 'application/json'
33
+ },
34
+ body,
35
+ failOnStatusCode: false
36
+ })
37
+ }
38
+
39
+ beforeEach(() => {
40
+ allure.epic('API')
41
+ allure.feature('Pages')
42
+ })
43
+
44
+ afterEach(() => {
45
+ // Cleanup: Delete pages created during tests
46
+ createdPages.forEach((pageId) => {
47
+ apiRequest('DELETE', `${API_PAGES}/${pageId}`)
48
+ })
49
+ createdPages = []
50
+ })
51
+
52
+ // ============================================================
53
+ // GET /api/v1/pages - List Pages
54
+ // ============================================================
55
+ describe('GET /api/v1/pages - List Pages', () => {
56
+ it('PB_API_001: Should list pages with valid API key', { tags: '@smoke' }, () => {
57
+ allure.story('CRUD Operations')
58
+ allure.severity('critical')
59
+
60
+ apiRequest('GET', API_PAGES).then((response) => {
61
+ expect(response.status).to.eq(200)
62
+ expect(response.body.success).to.be.true
63
+ expect(response.body.data).to.be.an('array')
64
+
65
+ cy.log(`Found ${response.body.data.length} pages`)
66
+ })
67
+ })
68
+
69
+ it('PB_API_002: Should return page with expected structure', () => {
70
+ apiRequest('GET', API_PAGES).then((response) => {
71
+ expect(response.status).to.eq(200)
72
+
73
+ if (response.body.data.length > 0) {
74
+ const page = response.body.data[0]
75
+
76
+ // Verify page structure
77
+ expect(page).to.have.property('id')
78
+ expect(page).to.have.property('title')
79
+ expect(page).to.have.property('slug')
80
+ expect(page).to.have.property('locale')
81
+ expect(page).to.have.property('published')
82
+ expect(page).to.have.property('blocks')
83
+ expect(page.blocks).to.be.an('array')
84
+
85
+ cy.log(`Page structure verified: ${page.title}`)
86
+ }
87
+ })
88
+ })
89
+
90
+ it('PB_API_003: Should reject request without API key', { tags: '@security' }, () => {
91
+ cy.request({
92
+ method: 'GET',
93
+ url: API_PAGES,
94
+ failOnStatusCode: false
95
+ }).then((response) => {
96
+ expect(response.status).to.eq(401)
97
+ expect(response.body.success).to.be.false
98
+ })
99
+ })
100
+ })
101
+
102
+ // ============================================================
103
+ // POST /api/v1/pages - Create Page
104
+ // ============================================================
105
+ describe('POST /api/v1/pages - Create Page', () => {
106
+ it('PB_API_004: Should create page with valid data', { tags: '@smoke' }, () => {
107
+ allure.story('CRUD Operations')
108
+ allure.severity('critical')
109
+
110
+ const pageData = {
111
+ title: `Test Page ${Date.now()}`,
112
+ slug: `test-page-${Date.now()}`,
113
+ locale: 'en',
114
+ published: false,
115
+ blocks: []
116
+ }
117
+
118
+ apiRequest('POST', API_PAGES, pageData).then((response) => {
119
+ expect(response.status).to.eq(201)
120
+ expect(response.body.success).to.be.true
121
+ expect(response.body.data).to.have.property('id')
122
+ expect(response.body.data.title).to.eq(pageData.title)
123
+ expect(response.body.data.slug).to.eq(pageData.slug)
124
+
125
+ // Track for cleanup
126
+ createdPages.push(response.body.data.id)
127
+ cy.log(`Created page: ${response.body.data.id}`)
128
+ })
129
+ })
130
+
131
+ it('PB_API_005: Should create page with blocks', () => {
132
+ const pageData = {
133
+ title: `Page With Blocks ${Date.now()}`,
134
+ slug: `page-with-blocks-${Date.now()}`,
135
+ locale: 'en',
136
+ published: false,
137
+ blocks: [
138
+ {
139
+ id: `block-${Date.now()}-1`,
140
+ blockSlug: 'hero',
141
+ props: {
142
+ title: 'Test Hero',
143
+ subtitle: 'Test Subtitle'
144
+ }
145
+ }
146
+ ]
147
+ }
148
+
149
+ apiRequest('POST', API_PAGES, pageData).then((response) => {
150
+ expect(response.status).to.eq(201)
151
+ expect(response.body.data.blocks).to.have.length(1)
152
+ expect(response.body.data.blocks[0].blockSlug).to.eq('hero')
153
+
154
+ createdPages.push(response.body.data.id)
155
+ cy.log(`Created page with ${response.body.data.blocks.length} blocks`)
156
+ })
157
+ })
158
+
159
+ it('PB_API_006: Should reject page with reserved slug', () => {
160
+ const pageData = {
161
+ title: 'Admin Page',
162
+ slug: 'admin', // Reserved slug
163
+ locale: 'en',
164
+ published: false,
165
+ blocks: []
166
+ }
167
+
168
+ apiRequest('POST', API_PAGES, pageData).then((response) => {
169
+ expect(response.status).to.be.oneOf([400, 422])
170
+ expect(response.body.success).to.be.false
171
+ })
172
+ })
173
+
174
+ it('PB_API_007: Should reject duplicate slug in same locale', () => {
175
+ const uniqueSlug = `unique-slug-${Date.now()}`
176
+
177
+ // Create first page
178
+ const pageData1 = {
179
+ title: 'First Page',
180
+ slug: uniqueSlug,
181
+ locale: 'en',
182
+ published: false,
183
+ blocks: []
184
+ }
185
+
186
+ apiRequest('POST', API_PAGES, pageData1).then((response1) => {
187
+ expect(response1.status).to.eq(201)
188
+ createdPages.push(response1.body.data.id)
189
+
190
+ // Try to create duplicate
191
+ const pageData2 = {
192
+ title: 'Second Page',
193
+ slug: uniqueSlug, // Same slug
194
+ locale: 'en', // Same locale
195
+ published: false,
196
+ blocks: []
197
+ }
198
+
199
+ apiRequest('POST', API_PAGES, pageData2).then((response2) => {
200
+ expect(response2.status).to.be.oneOf([400, 409, 422])
201
+ expect(response2.body.success).to.be.false
202
+ })
203
+ })
204
+ })
205
+ })
206
+
207
+ // ============================================================
208
+ // GET /api/v1/pages/{id} - Get Page by ID
209
+ // ============================================================
210
+ describe('GET /api/v1/pages/{id} - Get Page by ID', () => {
211
+ let testPageId: string
212
+
213
+ beforeEach(() => {
214
+ // Create a test page
215
+ const pageData = {
216
+ title: `Test Get By ID ${Date.now()}`,
217
+ slug: `test-get-${Date.now()}`,
218
+ locale: 'en',
219
+ published: false,
220
+ blocks: []
221
+ }
222
+
223
+ apiRequest('POST', API_PAGES, pageData).then((response) => {
224
+ testPageId = response.body.data.id
225
+ createdPages.push(testPageId)
226
+ })
227
+ })
228
+
229
+ it('PB_API_008: Should get page by valid ID', () => {
230
+ cy.then(() => {
231
+ apiRequest('GET', `${API_PAGES}/${testPageId}`).then((response) => {
232
+ expect(response.status).to.eq(200)
233
+ expect(response.body.success).to.be.true
234
+ expect(response.body.data.id).to.eq(testPageId)
235
+
236
+ cy.log(`Got page: ${response.body.data.title}`)
237
+ })
238
+ })
239
+ })
240
+
241
+ it('PB_API_009: Should return 404 for non-existent page', () => {
242
+ apiRequest('GET', `${API_PAGES}/non-existent-id-12345`).then((response) => {
243
+ expect(response.status).to.eq(404)
244
+ expect(response.body.success).to.be.false
245
+ })
246
+ })
247
+ })
248
+
249
+ // ============================================================
250
+ // PATCH /api/v1/pages/{id} - Update Page
251
+ // ============================================================
252
+ describe('PATCH /api/v1/pages/{id} - Update Page', () => {
253
+ let testPageId: string
254
+
255
+ beforeEach(() => {
256
+ const pageData = {
257
+ title: `Test Update ${Date.now()}`,
258
+ slug: `test-update-${Date.now()}`,
259
+ locale: 'en',
260
+ published: false,
261
+ blocks: []
262
+ }
263
+
264
+ apiRequest('POST', API_PAGES, pageData).then((response) => {
265
+ testPageId = response.body.data.id
266
+ createdPages.push(testPageId)
267
+ })
268
+ })
269
+
270
+ it('PB_API_010: Should update page title', () => {
271
+ const updateData = {
272
+ title: 'Updated Title'
273
+ }
274
+
275
+ cy.then(() => {
276
+ apiRequest('PATCH', `${API_PAGES}/${testPageId}`, updateData).then((response) => {
277
+ expect(response.status).to.eq(200)
278
+ expect(response.body.data.title).to.eq(updateData.title)
279
+
280
+ cy.log(`Updated page title to: ${updateData.title}`)
281
+ })
282
+ })
283
+ })
284
+
285
+ it('PB_API_011: Should update page blocks', () => {
286
+ const updateData = {
287
+ blocks: [
288
+ {
289
+ id: `block-${Date.now()}`,
290
+ blockSlug: 'cta-section',
291
+ props: {
292
+ title: 'New CTA',
293
+ description: 'Test description'
294
+ }
295
+ }
296
+ ]
297
+ }
298
+
299
+ cy.then(() => {
300
+ apiRequest('PATCH', `${API_PAGES}/${testPageId}`, updateData).then((response) => {
301
+ expect(response.status).to.eq(200)
302
+ expect(response.body.data.blocks).to.have.length(1)
303
+ expect(response.body.data.blocks[0].blockSlug).to.eq('cta-section')
304
+
305
+ cy.log(`Updated page with new blocks`)
306
+ })
307
+ })
308
+ })
309
+
310
+ it('PB_API_012: Should publish page', () => {
311
+ const updateData = {
312
+ published: true
313
+ }
314
+
315
+ cy.then(() => {
316
+ apiRequest('PATCH', `${API_PAGES}/${testPageId}`, updateData).then((response) => {
317
+ expect(response.status).to.eq(200)
318
+ expect(response.body.data.published).to.be.true
319
+
320
+ cy.log('Page published successfully')
321
+ })
322
+ })
323
+ })
324
+ })
325
+
326
+ // ============================================================
327
+ // DELETE /api/v1/pages/{id} - Delete Page
328
+ // ============================================================
329
+ describe('DELETE /api/v1/pages/{id} - Delete Page', () => {
330
+ it('PB_API_013: Should delete page by valid ID', () => {
331
+ // Create page to delete
332
+ const pageData = {
333
+ title: `Test Delete ${Date.now()}`,
334
+ slug: `test-delete-${Date.now()}`,
335
+ locale: 'en',
336
+ published: false,
337
+ blocks: []
338
+ }
339
+
340
+ apiRequest('POST', API_PAGES, pageData).then((createResponse) => {
341
+ const pageId = createResponse.body.data.id
342
+
343
+ // Delete the page
344
+ apiRequest('DELETE', `${API_PAGES}/${pageId}`).then((deleteResponse) => {
345
+ expect(deleteResponse.status).to.eq(200)
346
+ expect(deleteResponse.body.success).to.be.true
347
+
348
+ // Verify deletion
349
+ apiRequest('GET', `${API_PAGES}/${pageId}`).then((getResponse) => {
350
+ expect(getResponse.status).to.eq(404)
351
+ cy.log(`Deleted and verified: ${pageId}`)
352
+ })
353
+ })
354
+ })
355
+ })
356
+
357
+ it('PB_API_014: Should return 404 for non-existent page', () => {
358
+ apiRequest('DELETE', `${API_PAGES}/non-existent-id-12345`).then((response) => {
359
+ expect(response.status).to.eq(404)
360
+ expect(response.body.success).to.be.false
361
+ })
362
+ })
363
+ })
364
+
365
+ // ============================================================
366
+ // Integration Test - Complete CRUD Lifecycle
367
+ // ============================================================
368
+ describe('Integration - Complete CRUD Lifecycle', () => {
369
+ it('PB_API_100: Should complete full lifecycle: Create -> Read -> Update -> Delete', () => {
370
+ const timestamp = Date.now()
371
+ const pageData = {
372
+ title: `Lifecycle Test ${timestamp}`,
373
+ slug: `lifecycle-test-${timestamp}`,
374
+ locale: 'en',
375
+ published: false,
376
+ blocks: [
377
+ {
378
+ id: `block-${timestamp}`,
379
+ blockSlug: 'hero',
380
+ props: { title: 'Lifecycle Hero' }
381
+ }
382
+ ]
383
+ }
384
+
385
+ // 1. CREATE
386
+ apiRequest('POST', API_PAGES, pageData).then((createResponse) => {
387
+ expect(createResponse.status).to.eq(201)
388
+ const createdPage = createResponse.body.data
389
+ cy.log(`1. Created page: ${createdPage.id}`)
390
+
391
+ // 2. READ
392
+ apiRequest('GET', `${API_PAGES}/${createdPage.id}`).then((readResponse) => {
393
+ expect(readResponse.status).to.eq(200)
394
+ expect(readResponse.body.data.title).to.eq(pageData.title)
395
+ cy.log(`2. Read page: ${createdPage.id}`)
396
+
397
+ // 3. UPDATE
398
+ const updateData = {
399
+ title: 'Updated Lifecycle Page',
400
+ published: true
401
+ }
402
+ apiRequest('PATCH', `${API_PAGES}/${createdPage.id}`, updateData).then((updateResponse) => {
403
+ expect(updateResponse.status).to.eq(200)
404
+ expect(updateResponse.body.data.title).to.eq(updateData.title)
405
+ expect(updateResponse.body.data.published).to.be.true
406
+ cy.log(`3. Updated page: ${updateData.title}`)
407
+
408
+ // 4. DELETE
409
+ apiRequest('DELETE', `${API_PAGES}/${createdPage.id}`).then((deleteResponse) => {
410
+ expect(deleteResponse.status).to.eq(200)
411
+ cy.log(`4. Deleted page: ${createdPage.id}`)
412
+
413
+ // 5. VERIFY DELETION
414
+ apiRequest('GET', `${API_PAGES}/${createdPage.id}`).then((finalResponse) => {
415
+ expect(finalResponse.status).to.eq(404)
416
+ cy.log('5. Verified deletion: page not found (404)')
417
+ cy.log('Full CRUD lifecycle completed successfully')
418
+ })
419
+ })
420
+ })
421
+ })
422
+ })
423
+ })
424
+ })
425
+ })