@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,285 @@
1
+ /**
2
+ * SuperadminTeamRolesPOM - Page Object Model for Admin Team Roles Matrix
3
+ *
4
+ * Tests the consolidated permissions matrix that shows:
5
+ * - All team roles with hierarchy levels
6
+ * - Permissions grouped by category
7
+ * - Visual indicators for permission grants (checkmarks)
8
+ * - Dangerous permissions highlighted
9
+ *
10
+ * @version 3.0 - Uses centralized selectors from cySelector()
11
+ *
12
+ * @example
13
+ * // Verify matrix displays all roles
14
+ * SuperadminTeamRolesPOM.create()
15
+ * .visit()
16
+ * .verifyRolesDisplayed(['owner', 'admin', 'member', 'editor', 'viewer'])
17
+ *
18
+ * // Check editor permissions
19
+ * SuperadminTeamRolesPOM.create()
20
+ * .visit()
21
+ * .verifyHasPermission('editor', 'customers.list')
22
+ * .verifyNoPermission('editor', 'customers.create')
23
+ */
24
+
25
+ import { BasePOM } from '../core/BasePOM'
26
+ import { cySelector } from '../selectors'
27
+
28
+ export interface RoleHierarchy {
29
+ role: string
30
+ level: number
31
+ }
32
+
33
+ export class SuperadminTeamRolesPOM extends BasePOM {
34
+ // ============================================
35
+ // FACTORY METHOD
36
+ // ============================================
37
+
38
+ static create(): SuperadminTeamRolesPOM {
39
+ return new SuperadminTeamRolesPOM()
40
+ }
41
+
42
+ // ============================================
43
+ // SELECTORS using centralized cySelector()
44
+ // ============================================
45
+
46
+ get selectors() {
47
+ return {
48
+ // Page structure
49
+ pageTitle: 'h1',
50
+ backButton: cySelector('superadmin.teamRoles.backButton'),
51
+
52
+ // Stats cards (use contains since no specific data-cy)
53
+ statsCard: '.grid-cols-1 .border',
54
+
55
+ // Role cards in hierarchy section
56
+ roleCard: (role: string) => cySelector('superadmin.teamRoles.roleCard', { role }),
57
+ roleHierarchyBadge: '.font-semibold',
58
+
59
+ // Permissions matrix table
60
+ matrixTable: '.rounded-md.border table',
61
+ permissionRow: (permission: string) =>
62
+ cySelector('superadmin.permissions.row', { permission: permission.replace(/\./g, '-') }),
63
+
64
+ // Category headers
65
+ categoryHeader: '.bg-muted\\/50',
66
+
67
+ // Permission checkmarks and X marks (Lucide icons with Tailwind classes)
68
+ // Note: These are SVG elements with the class applied
69
+ checkmark: 'svg.lucide-check, .text-green-600',
70
+ xMark: 'svg.lucide-x',
71
+
72
+ // Dangerous permission badge (Badge component with variant="destructive")
73
+ dangerousBadge: '[class*="destructive"]',
74
+
75
+ // Legend section
76
+ legend: '.bg-muted\\/30',
77
+ }
78
+ }
79
+
80
+ // ============================================
81
+ // NAVIGATION
82
+ // ============================================
83
+
84
+ /**
85
+ * Navigate to Team Roles page
86
+ */
87
+ visit() {
88
+ cy.visit('/superadmin/team-roles')
89
+ this.waitForPageLoad()
90
+ return this
91
+ }
92
+
93
+ /**
94
+ * Wait for page to fully load
95
+ */
96
+ waitForPageLoad() {
97
+ cy.get(this.selectors.matrixTable, { timeout: 15000 }).should('be.visible')
98
+ return this
99
+ }
100
+
101
+ // ============================================
102
+ // ROLE CARDS (HIERARCHY SECTION)
103
+ // ============================================
104
+
105
+ /**
106
+ * Get a role card by role name
107
+ */
108
+ getRoleCard(role: string) {
109
+ return cy.get(this.selectors.roleCard(role))
110
+ }
111
+
112
+ /**
113
+ * Verify all expected roles are displayed
114
+ */
115
+ verifyRolesDisplayed(expectedRoles: string[]) {
116
+ for (const role of expectedRoles) {
117
+ this.getRoleCard(role).should('be.visible')
118
+ }
119
+ return this
120
+ }
121
+
122
+ /**
123
+ * Verify role hierarchy level
124
+ */
125
+ verifyRoleHierarchy(role: string, expectedLevel: number) {
126
+ this.getRoleCard(role)
127
+ .find('.font-semibold')
128
+ .first()
129
+ .should('contain', expectedLevel.toString())
130
+ return this
131
+ }
132
+
133
+ /**
134
+ * Get permission count text for a role
135
+ */
136
+ getPermissionCount(role: string) {
137
+ return this.getRoleCard(role).find('.text-muted-foreground')
138
+ }
139
+
140
+ /**
141
+ * Verify role has expected permission count
142
+ */
143
+ verifyPermissionCount(role: string, expectedCount: number) {
144
+ this.getPermissionCount(role).should('contain', `${expectedCount} permissions`)
145
+ return this
146
+ }
147
+
148
+ // ============================================
149
+ // PERMISSIONS MATRIX
150
+ // ============================================
151
+
152
+ /**
153
+ * Get a permission row by permission ID
154
+ */
155
+ getPermissionRow(permission: string) {
156
+ return cy.get(this.selectors.permissionRow(permission))
157
+ }
158
+
159
+ /**
160
+ * Get column index for a role in the matrix
161
+ * Roles are sorted by hierarchy: owner, admin, member, editor, viewer
162
+ */
163
+ private getRoleColumnIndex(role: string): number {
164
+ const roleOrder = ['owner', 'admin', 'member', 'editor', 'viewer']
165
+ const index = roleOrder.indexOf(role)
166
+ // +2 because first column is permission name
167
+ return index >= 0 ? index + 2 : -1
168
+ }
169
+
170
+ /**
171
+ * Verify a role has a specific permission (green checkmark)
172
+ */
173
+ verifyHasPermission(role: string, permission: string) {
174
+ const colIndex = this.getRoleColumnIndex(role)
175
+ this.getPermissionRow(permission)
176
+ .find(`td:nth-child(${colIndex})`)
177
+ .find(this.selectors.checkmark)
178
+ .should('exist')
179
+ return this
180
+ }
181
+
182
+ /**
183
+ * Verify a role does NOT have a specific permission (red X)
184
+ */
185
+ verifyNoPermission(role: string, permission: string) {
186
+ const colIndex = this.getRoleColumnIndex(role)
187
+ this.getPermissionRow(permission)
188
+ .find(`td:nth-child(${colIndex})`)
189
+ .find(this.selectors.xMark)
190
+ .should('exist')
191
+ return this
192
+ }
193
+
194
+ /**
195
+ * Verify a permission is marked as dangerous
196
+ * The dangerous badge contains text "dangerous" with destructive styling
197
+ */
198
+ verifyDangerousPermission(permission: string) {
199
+ this.getPermissionRow(permission)
200
+ .scrollIntoView()
201
+ .contains('dangerous')
202
+ .should('be.visible')
203
+ return this
204
+ }
205
+
206
+ /**
207
+ * Verify permission row shows permission ID with dangerous styling
208
+ */
209
+ verifyDangerousPermissionText(permission: string) {
210
+ this.getPermissionRow(permission)
211
+ .find('.text-red-600')
212
+ .should('contain', permission)
213
+ return this
214
+ }
215
+
216
+ // ============================================
217
+ // CATEGORY HEADERS
218
+ // ============================================
219
+
220
+ /**
221
+ * Get all category headers
222
+ */
223
+ getCategoryHeaders() {
224
+ return cy.get(this.selectors.categoryHeader)
225
+ }
226
+
227
+ /**
228
+ * Verify expected categories are present
229
+ */
230
+ verifyCategoriesPresent(categories: string[]) {
231
+ for (const category of categories) {
232
+ this.getCategoryHeaders().should('contain', category)
233
+ }
234
+ return this
235
+ }
236
+
237
+ // ============================================
238
+ // STATS CARDS
239
+ // ============================================
240
+
241
+ /**
242
+ * Verify stats card shows expected value
243
+ */
244
+ verifyStatsCard(title: string, value: string) {
245
+ cy.contains('.font-medium', title)
246
+ .parents('.border')
247
+ .find('.text-2xl')
248
+ .should('contain', value)
249
+ return this
250
+ }
251
+
252
+ // ============================================
253
+ // ASSERTIONS
254
+ // ============================================
255
+
256
+ /**
257
+ * Verify owner has all permissions (all checkmarks)
258
+ */
259
+ verifyOwnerHasAllPermissions() {
260
+ // Owner column should have no X marks
261
+ cy.get(this.selectors.matrixTable)
262
+ .find('tbody tr:not(.bg-muted\\/50)')
263
+ .each(($row) => {
264
+ cy.wrap($row)
265
+ .find('td:nth-child(2)') // Owner is first role column
266
+ .find(this.selectors.checkmark)
267
+ .should('exist')
268
+ })
269
+ return this
270
+ }
271
+
272
+ /**
273
+ * Verify editor has specific permission set
274
+ */
275
+ verifyEditorPermissions(expected: { permission: string; hasAccess: boolean }[]) {
276
+ for (const { permission, hasAccess } of expected) {
277
+ if (hasAccess) {
278
+ this.verifyHasPermission('editor', permission)
279
+ } else {
280
+ this.verifyNoPermission('editor', permission)
281
+ }
282
+ }
283
+ return this
284
+ }
285
+ }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Feature POM exports
3
+ *
4
+ * Specialized POMs for complex features:
5
+ * - PageBuilderPOM: Create/edit pages with blocks
6
+ * - PostEditorPOM: Create/edit posts with blocks
7
+ * - PublicPagePOM: Test public page rendering
8
+ * - PublicPostPOM: Test public post rendering
9
+ * - AdminTeamRolesPOM: Admin team roles matrix
10
+ * - DashboardPOM: Dashboard navigation and shell
11
+ * - SettingsPOM: Settings area (profile, team, billing)
12
+ * - AdminPOM: Superadmin area
13
+ * - BillingPOM: Billing settings
14
+ * - DevtoolsPOM: Developer tools area
15
+ */
16
+
17
+ export { PageBuilderPOM, type PageFormData, type BlockData as PageBlockData } from './PageBuilderPOM'
18
+ export { PostEditorPOM, type PostFormData, type BlockData as PostBlockData } from './PostEditorPOM'
19
+ export { AdminTeamRolesPOM, type RoleHierarchy } from './AdminTeamRolesPOM'
20
+ export { DashboardPOM } from './DashboardPOM'
21
+ export { SettingsPOM } from './SettingsPOM'
22
+ export { AdminPOM } from './AdminPOM'
23
+ export { BillingPOM } from './BillingPOM'
24
+ export { DevtoolsPOM } from './DevtoolsPOM'
25
+
26
+ // Re-export public POMs from components (until migrated)
27
+ export { PublicPagePOM } from '../components/PublicPagePOM'
28
+ export { PublicPostPOM } from '../components/PublicPostPOM'
@@ -0,0 +1,177 @@
1
+ /**
2
+ * ApiInterceptor - Helper para waits determinísticos en Cypress
3
+ *
4
+ * Reemplaza cy.wait(ms) poco fiables con waits basados en cy.intercept()
5
+ * que esperan respuestas reales de la API.
6
+ *
7
+ * Uso básico:
8
+ * const api = new ApiInterceptor('customers')
9
+ * api.setupCrudIntercepts()
10
+ * cy.visit('/dashboard/customers')
11
+ * api.waitForList()
12
+ *
13
+ * Uso con ruta custom:
14
+ * const api = new ApiInterceptor({
15
+ * slug: 'categories',
16
+ * customPath: '/api/v1/post-categories'
17
+ * })
18
+ */
19
+
20
+ export interface ApiInterceptorConfig {
21
+ /** Entity slug - usado para generar aliases */
22
+ slug: string
23
+ /** Ruta API custom (ej: '/api/v1/post-categories') */
24
+ customPath?: string
25
+ }
26
+
27
+ export class ApiInterceptor {
28
+ private slug: string
29
+ private endpoint: string
30
+
31
+ constructor(slugOrConfig: string | ApiInterceptorConfig) {
32
+ if (typeof slugOrConfig === 'string') {
33
+ this.slug = slugOrConfig
34
+ this.endpoint = `/api/v1/${slugOrConfig}`
35
+ } else {
36
+ this.slug = slugOrConfig.slug
37
+ this.endpoint = slugOrConfig.customPath || `/api/v1/${slugOrConfig.slug}`
38
+ }
39
+ }
40
+
41
+ // ============================================
42
+ // ACCESSORS
43
+ // ============================================
44
+
45
+ /** Get the API endpoint path */
46
+ get path(): string {
47
+ return this.endpoint
48
+ }
49
+
50
+ /** Get the entity slug */
51
+ get entitySlug(): string {
52
+ return this.slug
53
+ }
54
+
55
+ /** Get alias names for all operations */
56
+ get aliases() {
57
+ return {
58
+ list: `${this.slug}List`,
59
+ create: `${this.slug}Create`,
60
+ update: `${this.slug}Update`,
61
+ delete: `${this.slug}Delete`
62
+ }
63
+ }
64
+
65
+ // ============================================
66
+ // INTERCEPT SETUP
67
+ // ============================================
68
+
69
+ /**
70
+ * Setup intercepts for all CRUD operations
71
+ * Call this BEFORE navigation in beforeEach or at test start
72
+ *
73
+ * Note: We intercept both PUT and PATCH for updates since different
74
+ * APIs may use different HTTP methods for updates.
75
+ */
76
+ setupCrudIntercepts(): this {
77
+ cy.intercept('GET', `${this.endpoint}*`).as(this.aliases.list)
78
+ cy.intercept('POST', this.endpoint).as(this.aliases.create)
79
+ // Intercept both PUT and PATCH for updates (APIs may use either)
80
+ cy.intercept('PUT', `${this.endpoint}/*`).as(this.aliases.update)
81
+ cy.intercept('PATCH', `${this.endpoint}/*`).as(`${this.aliases.update}Patch`)
82
+ cy.intercept('DELETE', `${this.endpoint}/*`).as(this.aliases.delete)
83
+ return this
84
+ }
85
+
86
+ /**
87
+ * Setup only list + create intercepts
88
+ * Useful for list pages with inline create
89
+ */
90
+ setupListIntercepts(): this {
91
+ cy.intercept('GET', `${this.endpoint}*`).as(this.aliases.list)
92
+ cy.intercept('POST', this.endpoint).as(this.aliases.create)
93
+ return this
94
+ }
95
+
96
+ // ============================================
97
+ // WAIT METHODS
98
+ // ============================================
99
+
100
+ /**
101
+ * Wait for list response (GET)
102
+ * Use after navigation or after mutations to wait for refresh
103
+ */
104
+ waitForList(timeout = 10000): Cypress.Chainable {
105
+ return cy.wait(`@${this.aliases.list}`, { timeout })
106
+ }
107
+
108
+ /**
109
+ * Wait for create response (POST) and validate success status
110
+ */
111
+ waitForCreate(timeout = 10000): Cypress.Chainable {
112
+ return cy.wait(`@${this.aliases.create}`, { timeout })
113
+ .its('response.statusCode')
114
+ .should('be.oneOf', [200, 201])
115
+ }
116
+
117
+ /**
118
+ * Wait for update response (PATCH or PUT) and validate success status
119
+ * Waits for PATCH first (more common), falls back to PUT
120
+ */
121
+ waitForUpdate(timeout = 10000): Cypress.Chainable {
122
+ // Try PATCH first (more common in modern APIs), fall back to PUT
123
+ return cy.wait(`@${this.aliases.update}Patch`, { timeout })
124
+ .its('response.statusCode')
125
+ .should('be.oneOf', [200, 201])
126
+ }
127
+
128
+ /**
129
+ * Wait for delete response (DELETE) and validate success status
130
+ */
131
+ waitForDelete(timeout = 10000): Cypress.Chainable {
132
+ return cy.wait(`@${this.aliases.delete}`, { timeout })
133
+ .its('response.statusCode')
134
+ .should('be.oneOf', [200, 204])
135
+ }
136
+
137
+ // ============================================
138
+ // CONVENIENCE METHODS
139
+ // ============================================
140
+
141
+ /**
142
+ * Wait for list refresh (alias for waitForList)
143
+ * Semantic name for use after create/update/delete
144
+ */
145
+ waitForRefresh(timeout = 10000): Cypress.Chainable {
146
+ return this.waitForList(timeout)
147
+ }
148
+
149
+ /**
150
+ * Wait for create + list refresh
151
+ * Common pattern: create entity, wait for success, wait for list to refresh
152
+ */
153
+ waitForCreateAndRefresh(timeout = 10000): Cypress.Chainable {
154
+ this.waitForCreate(timeout)
155
+ return this.waitForList(timeout)
156
+ }
157
+
158
+ /**
159
+ * Wait for update + list refresh
160
+ * Common pattern: update entity, wait for success, wait for list to refresh
161
+ */
162
+ waitForUpdateAndRefresh(timeout = 10000): Cypress.Chainable {
163
+ this.waitForUpdate(timeout)
164
+ return this.waitForList(timeout)
165
+ }
166
+
167
+ /**
168
+ * Wait for delete + list refresh
169
+ * Common pattern: delete entity, wait for success, wait for list to refresh
170
+ */
171
+ waitForDeleteAndRefresh(timeout = 10000): Cypress.Chainable {
172
+ this.waitForDelete(timeout)
173
+ return this.waitForList(timeout)
174
+ }
175
+ }
176
+
177
+ export default ApiInterceptor
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Default Theme - Cypress POM Exports
3
+ *
4
+ * Centralized exports for all Default theme Page Object Models and helpers.
5
+ *
6
+ * Architecture (v2.0):
7
+ * - core/: Base classes (BasePOM, DashboardEntityPOM, BlockEditorBasePOM, AuthPOM)
8
+ * - entities/: Entity POMs extending DashboardEntityPOM (TasksPOM, CustomersPOM, etc.)
9
+ * - features/: Feature POMs for complex UIs (PageBuilderPOM, PostEditorPOM)
10
+ * - helpers/: Utility classes (ApiInterceptor)
11
+ *
12
+ * Usage:
13
+ * // New architecture (recommended)
14
+ * import { TasksPOM, CustomersPOM, AuthPOM, PageBuilderPOM } from '../src'
15
+ * const tasks = TasksPOM.create()
16
+ * tasks.visitList().waitForList().clickAdd()
17
+ *
18
+ * // Session helpers
19
+ * import { loginAsOwner, loginAsMember } from '../src'
20
+ */
21
+
22
+ // ============================================
23
+ // CORE - Base Classes
24
+ // ============================================
25
+ export {
26
+ BasePOM,
27
+ DashboardEntityPOM,
28
+ BlockEditorBasePOM,
29
+ AuthPOM,
30
+ type EntityConfig,
31
+ type SignupData
32
+ } from './core'
33
+
34
+ // ============================================
35
+ // ENTITIES - Entity POMs (extend DashboardEntityPOM)
36
+ // New instance-based POMs - use .create() factory method
37
+ // ============================================
38
+ export {
39
+ TasksPOM as TasksPOMv2,
40
+ CustomersPOM as CustomersPOMv2,
41
+ PostsPOM as PostsPOMv2,
42
+ PagesPOM as PagesPOMv2,
43
+ type TaskFormData,
44
+ type CustomerFormData,
45
+ type PostListFilters,
46
+ type PageListFilters
47
+ } from './entities'
48
+
49
+ // ============================================
50
+ // FEATURES - Feature POMs (block editors, public pages)
51
+ // New instance-based POMs - use .create() factory method
52
+ // ============================================
53
+ export {
54
+ PageBuilderPOM as PageBuilderPOMv2,
55
+ PostEditorPOM as PostEditorPOMv2,
56
+ AdminTeamRolesPOM,
57
+ PublicPagePOM,
58
+ PublicPostPOM,
59
+ type PageFormData,
60
+ type PostFormData,
61
+ type PageBlockData,
62
+ type PostBlockData,
63
+ type RoleHierarchy
64
+ } from './features'
65
+
66
+ // ============================================
67
+ // HELPERS
68
+ // ============================================
69
+ export { ApiInterceptor, type ApiInterceptorConfig } from './helpers/ApiInterceptor'
70
+
71
+ // ============================================
72
+ // SESSION HELPERS
73
+ // ============================================
74
+ export {
75
+ DEFAULT_THEME_USERS,
76
+ loginAsDefaultOwner,
77
+ loginAsDefaultAdmin,
78
+ loginAsDefaultMember,
79
+ loginAsDefaultEditor,
80
+ loginAsDefaultViewer,
81
+ loginAsOwner,
82
+ loginAsMember,
83
+ loginAsAdmin,
84
+ loginAsEditor,
85
+ loginAsViewer,
86
+ } from './session-helpers'
87
+
88
+ // ============================================
89
+ // LEGACY/STATIC POMs (backward compatible - use v2 for new code)
90
+ // These use static methods and work with existing tests
91
+ // ============================================
92
+ export { TasksPOM } from './components/TasksPOM'
93
+ export { CustomersPOM } from './components/CustomersPOM'
94
+ export { PageBuilderPOM } from './components/PageBuilderPOM'
95
+ export { PostEditorPOM } from './components/PostEditorPOM'
96
+ export { PostsListPOM } from './components/PostsListPOM'
97
+ export { CategoriesPOM } from './components/CategoriesPOM'
98
+
99
+ // Generic entity components
100
+ export { EntityList } from './components/EntityList'
101
+ export { EntityForm } from './components/EntityForm'