@nextsparkjs/theme-default 0.1.0-beta.44 → 0.1.0-beta.45

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 (48) hide show
  1. package/components/ai-chat/ChatPanel.tsx +7 -7
  2. package/components/ai-chat/Message.tsx +2 -2
  3. package/components/ai-chat/MessageInput.tsx +3 -3
  4. package/components/ai-chat/MessageList.tsx +3 -3
  5. package/components/ai-chat/TypingIndicator.tsx +2 -2
  6. package/entities/customers/api/docs.md +107 -0
  7. package/entities/customers/api/presets.ts +80 -0
  8. package/entities/pages/api/docs.md +114 -0
  9. package/entities/pages/api/presets.ts +72 -0
  10. package/entities/posts/api/docs.md +120 -0
  11. package/entities/posts/api/presets.ts +74 -0
  12. package/entities/tasks/api/docs.md +126 -0
  13. package/entities/tasks/api/presets.ts +84 -0
  14. package/lib/selectors.ts +2 -2
  15. package/messages/de/admin.json +45 -0
  16. package/messages/en/admin.json +45 -0
  17. package/messages/es/admin.json +45 -0
  18. package/messages/fr/admin.json +45 -0
  19. package/messages/it/admin.json +45 -0
  20. package/messages/pt/admin.json +45 -0
  21. package/package.json +3 -3
  22. package/styles/globals.css +24 -0
  23. package/tests/cypress/e2e/_utils/selectors/block-editor.bdd.md +491 -0
  24. package/tests/cypress/e2e/_utils/selectors/block-editor.cy.ts +475 -0
  25. package/tests/cypress/e2e/_utils/selectors/dashboard-container.cy.ts +52 -0
  26. package/tests/cypress/e2e/_utils/selectors/dashboard-mobile.cy.ts +14 -14
  27. package/tests/cypress/e2e/_utils/selectors/dashboard-navigation.cy.ts +3 -3
  28. package/tests/cypress/e2e/_utils/selectors/dashboard-sidebar.bdd.md +38 -73
  29. package/tests/cypress/e2e/_utils/selectors/dashboard-sidebar.cy.ts +21 -42
  30. package/tests/cypress/e2e/_utils/selectors/dashboard-topnav.bdd.md +117 -38
  31. package/tests/cypress/e2e/_utils/selectors/dashboard-topnav.cy.ts +35 -12
  32. package/tests/cypress/e2e/_utils/selectors/settings-layout.bdd.md +50 -59
  33. package/tests/cypress/e2e/_utils/selectors/settings-layout.cy.ts +15 -23
  34. package/tests/cypress/e2e/_utils/selectors/tasks.bdd.md +395 -155
  35. package/tests/cypress/e2e/_utils/selectors/tasks.cy.ts +795 -174
  36. package/tests/cypress/e2e/api/_core/teams/teams-security.cy.ts +415 -0
  37. package/tests/cypress/e2e/uat/_core/teams/inline-edit.cy.ts +278 -0
  38. package/tests/cypress/src/core/BlockEditorBasePOM.ts +269 -99
  39. package/tests/cypress/src/core/DashboardEntityPOM.ts +1 -1
  40. package/tests/cypress/src/features/DashboardPOM.ts +49 -28
  41. package/tests/cypress/src/features/PageBuilderPOM.ts +20 -0
  42. package/tests/cypress/src/features/SettingsPOM.ts +511 -166
  43. package/tests/cypress/src/features/SuperadminPOM.ts +679 -159
  44. package/tests/cypress/src/features/index.ts +10 -10
  45. package/tests/cypress/e2e/_utils/selectors/pages-editor.bdd.md +0 -207
  46. package/tests/cypress/e2e/_utils/selectors/pages-editor.cy.ts +0 -211
  47. package/tests/cypress/e2e/_utils/selectors/posts-editor.bdd.md +0 -184
  48. package/tests/cypress/e2e/_utils/selectors/posts-editor.cy.ts +0 -350
@@ -3,19 +3,30 @@
3
3
  *
4
4
  * Handles Superadmin Panel pages:
5
5
  * - Dashboard with system stats (/superadmin)
6
- * - All users management (/superadmin/users)
7
- * - All teams management (/superadmin/teams)
6
+ * - All users management (/superadmin/users, /superadmin/users/[id])
7
+ * - All teams management (/superadmin/teams, /superadmin/teams/[id])
8
+ * - Team Roles - RBAC & Plan Features (/superadmin/team-roles)
8
9
  * - Subscriptions overview (/superadmin/subscriptions)
9
- * - System configuration (/superadmin/system)
10
+ * - Admin documentation (/superadmin/docs, /superadmin/docs/[section]/[page])
10
11
  *
11
- * Uses selectors from centralized selectors.ts
12
+ * Selector Structure (8 first-level keys):
13
+ * - container: Main wrapper
14
+ * - sidebar: Navigation sidebar (collapsible)
15
+ * - dashboard: Dashboard overview page
16
+ * - users: Users management (list + detail)
17
+ * - teams: Teams management (list + detail)
18
+ * - subscriptions: Subscriptions overview
19
+ * - teamRoles: RBAC Matrix and Plan Features
20
+ * - docs: Admin documentation pages
12
21
  *
13
- * NOTE: For /superadmin/team-roles (permissions matrix), use SuperadminTeamRolesPOM instead.
22
+ * Uses selectors from centralized selectors.ts
14
23
  */
15
24
 
16
25
  import { BasePOM } from '../core/BasePOM'
17
26
  import { cySelector } from '../selectors'
18
27
 
28
+ type PaginationContext = 'users' | 'teams' | 'subscriptions'
29
+
19
30
  export class SuperadminPOM extends BasePOM {
20
31
  // ============================================
21
32
  // FACTORY METHOD
@@ -31,115 +42,450 @@ export class SuperadminPOM extends BasePOM {
31
42
 
32
43
  get selectors() {
33
44
  return {
34
- // Navigation
35
- navContainer: cySelector('superadmin.container'),
36
- navDashboard: cySelector('superadmin.navigation.dashboard'),
37
- navUsers: cySelector('superadmin.navigation.users'),
38
- navTeams: cySelector('superadmin.navigation.teams'),
39
- navTeamRoles: cySelector('superadmin.navigation.teamRoles'),
40
- navSubscriptions: cySelector('superadmin.navigation.subscriptions'),
41
- exitToDashboard: cySelector('superadmin.navigation.exitToDashboard'),
42
-
43
- // Dashboard
44
- dashboardContainer: cySelector('superadmin.dashboard.container'),
45
-
46
- // Users
47
- usersContainer: cySelector('superadmin.users.container'),
48
- usersTable: cySelector('superadmin.users.table'),
49
- usersSearch: cySelector('superadmin.users.search'),
50
- userRow: (id: string) => cySelector('superadmin.users.row', { id }),
51
- userView: (id: string) => cySelector('superadmin.users.viewButton', { id }),
52
- userEdit: (id: string) => cySelector('superadmin.users.editButton', { id }),
53
- userBan: (id: string) => cySelector('superadmin.users.banButton', { id }),
54
- userDelete: (id: string) => cySelector('superadmin.users.deleteButton', { id }),
55
- userImpersonate: (id: string) => cySelector('superadmin.users.impersonateButton', { id }),
56
-
57
- // Teams
58
- teamsContainer: cySelector('superadmin.teams.container'),
59
- teamsTable: cySelector('superadmin.teams.table'),
60
- teamsSearch: cySelector('superadmin.teams.search'),
61
- teamRow: (id: string) => cySelector('superadmin.teams.row', { id }),
62
- teamActionsButton: (id: string) => cySelector('superadmin.teams.actionsButton', { id }),
63
- teamView: (id: string) => cySelector('superadmin.teams.viewButton', { id }),
64
- teamEdit: (id: string) => cySelector('superadmin.teams.editButton', { id }),
65
- teamDelete: (id: string) => cySelector('superadmin.teams.deleteButton', { id }),
66
-
67
- // Pagination (shared across superadmin pages)
68
- paginationPageSize: cySelector('superadmin.pagination.pageSize'),
69
- paginationFirst: cySelector('superadmin.pagination.first'),
70
- paginationPrev: cySelector('superadmin.pagination.prev'),
71
- paginationNext: cySelector('superadmin.pagination.next'),
72
- paginationLast: cySelector('superadmin.pagination.last'),
73
-
74
- // Permissions (team-roles page)
75
- permissionRow: (permission: string) => cySelector('superadmin.permissions.row', { permission: permission.replace(/\./g, '-') }),
76
-
77
- // Subscriptions
78
- subscriptionsContainer: cySelector('superadmin.subscriptions.container'),
79
- subscriptionsMrr: cySelector('superadmin.subscriptions.mrr'),
80
- subscriptionsPlanDistribution: cySelector('superadmin.subscriptions.planDistribution'),
81
- subscriptionsPlanCount: (plan: string) => cySelector('superadmin.subscriptions.planCount', { plan }),
82
- subscriptionsActiveCount: cySelector('superadmin.subscriptions.activeCount'),
45
+ // Main container
46
+ container: cySelector('superadmin.container'),
47
+
48
+ // ─────────────────────────────────────────
49
+ // SIDEBAR - Navigation sidebar (collapsible)
50
+ // ─────────────────────────────────────────
51
+ sidebar: {
52
+ container: cySelector('superadmin.sidebar.container'),
53
+ header: cySelector('superadmin.sidebar.header'),
54
+ collapseButton: cySelector('superadmin.sidebar.collapseButton'),
55
+ securityNotice: cySelector('superadmin.sidebar.securityNotice'),
56
+ nav: {
57
+ dashboard: cySelector('superadmin.sidebar.nav.dashboard'),
58
+ users: cySelector('superadmin.sidebar.nav.users'),
59
+ teams: cySelector('superadmin.sidebar.nav.teams'),
60
+ teamRoles: cySelector('superadmin.sidebar.nav.teamRoles'),
61
+ docs: cySelector('superadmin.sidebar.nav.docs'),
62
+ subscriptions: cySelector('superadmin.sidebar.nav.subscriptions'),
63
+ analytics: cySelector('superadmin.sidebar.nav.analytics'),
64
+ config: cySelector('superadmin.sidebar.nav.config'),
65
+ },
66
+ exitButton: cySelector('superadmin.sidebar.exitButton'),
67
+ },
68
+
69
+ // ─────────────────────────────────────────
70
+ // DASHBOARD - Overview page
71
+ // ─────────────────────────────────────────
72
+ dashboard: {
73
+ container: cySelector('superadmin.dashboard.container'),
74
+ header: {
75
+ title: cySelector('superadmin.dashboard.header.title'),
76
+ badge: cySelector('superadmin.dashboard.header.badge'),
77
+ },
78
+ quickActions: {
79
+ container: cySelector('superadmin.dashboard.quickActions.container'),
80
+ users: cySelector('superadmin.dashboard.quickActions.users'),
81
+ analytics: cySelector('superadmin.dashboard.quickActions.analytics'),
82
+ config: cySelector('superadmin.dashboard.quickActions.config'),
83
+ },
84
+ systemStatus: {
85
+ container: cySelector('superadmin.dashboard.systemStatus.container'),
86
+ online: cySelector('superadmin.dashboard.systemStatus.online'),
87
+ version: cySelector('superadmin.dashboard.systemStatus.version'),
88
+ security: cySelector('superadmin.dashboard.systemStatus.security'),
89
+ },
90
+ },
91
+
92
+ // ─────────────────────────────────────────
93
+ // USERS - User management (list + detail)
94
+ // ─────────────────────────────────────────
95
+ users: {
96
+ container: cySelector('superadmin.users.container'),
97
+ header: {
98
+ backButton: cySelector('superadmin.users.header.backButton'),
99
+ title: cySelector('superadmin.users.header.title'),
100
+ refreshButton: cySelector('superadmin.users.header.refreshButton'),
101
+ },
102
+ stats: {
103
+ totalUsers: cySelector('superadmin.users.stats.totalUsers'),
104
+ workTeams: cySelector('superadmin.users.stats.workTeams'),
105
+ superadmins: cySelector('superadmin.users.stats.superadmins'),
106
+ distribution: cySelector('superadmin.users.stats.distribution'),
107
+ },
108
+ filters: {
109
+ search: cySelector('superadmin.users.filters.search'),
110
+ roleFilter: cySelector('superadmin.users.filters.roleFilter'),
111
+ statusFilter: cySelector('superadmin.users.filters.statusFilter'),
112
+ clearButton: cySelector('superadmin.users.filters.clearButton'),
113
+ },
114
+ tabs: {
115
+ container: cySelector('superadmin.users.tabs.container'),
116
+ regularUsers: cySelector('superadmin.users.tabs.regularUsers'),
117
+ superadmins: cySelector('superadmin.users.tabs.superadmins'),
118
+ },
119
+ table: {
120
+ element: cySelector('superadmin.users.table.element'),
121
+ row: (id: string) => cySelector('superadmin.users.table.row', { id }),
122
+ viewButton: (id: string) => cySelector('superadmin.users.table.viewButton', { id }),
123
+ editButton: (id: string) => cySelector('superadmin.users.table.editButton', { id }),
124
+ banButton: (id: string) => cySelector('superadmin.users.table.banButton', { id }),
125
+ deleteButton: (id: string) => cySelector('superadmin.users.table.deleteButton', { id }),
126
+ impersonateButton: (id: string) => cySelector('superadmin.users.table.impersonateButton', { id }),
127
+ },
128
+ pagination: {
129
+ container: cySelector('superadmin.users.pagination.container'),
130
+ pageSize: cySelector('superadmin.users.pagination.pageSize'),
131
+ first: cySelector('superadmin.users.pagination.first'),
132
+ prev: cySelector('superadmin.users.pagination.prev'),
133
+ next: cySelector('superadmin.users.pagination.next'),
134
+ last: cySelector('superadmin.users.pagination.last'),
135
+ },
136
+ detail: {
137
+ container: cySelector('superadmin.users.detail.container'),
138
+ info: {
139
+ email: cySelector('superadmin.users.detail.info.email'),
140
+ role: cySelector('superadmin.users.detail.info.role'),
141
+ status: cySelector('superadmin.users.detail.info.status'),
142
+ teams: cySelector('superadmin.users.detail.info.teams'),
143
+ activity: cySelector('superadmin.users.detail.info.activity'),
144
+ },
145
+ actions: cySelector('superadmin.users.detail.actions'),
146
+ metas: {
147
+ container: cySelector('superadmin.users.detail.metas.container'),
148
+ title: cySelector('superadmin.users.detail.metas.title'),
149
+ table: cySelector('superadmin.users.detail.metas.table'),
150
+ empty: cySelector('superadmin.users.detail.metas.empty'),
151
+ row: (key: string) => cySelector('superadmin.users.detail.metas.row', { key }),
152
+ key: (key: string) => cySelector('superadmin.users.detail.metas.key', { key }),
153
+ value: (key: string) => cySelector('superadmin.users.detail.metas.value', { key }),
154
+ type: (key: string) => cySelector('superadmin.users.detail.metas.type', { key }),
155
+ public: (key: string) => cySelector('superadmin.users.detail.metas.public', { key }),
156
+ searchable: (key: string) => cySelector('superadmin.users.detail.metas.searchable', { key }),
157
+ },
158
+ },
159
+ },
160
+
161
+ // ─────────────────────────────────────────
162
+ // TEAMS - Team management (list + detail)
163
+ // ─────────────────────────────────────────
164
+ teams: {
165
+ container: cySelector('superadmin.teams.container'),
166
+ header: {
167
+ backButton: cySelector('superadmin.teams.header.backButton'),
168
+ title: cySelector('superadmin.teams.header.title'),
169
+ refreshButton: cySelector('superadmin.teams.header.refreshButton'),
170
+ },
171
+ stats: {
172
+ totalTeams: cySelector('superadmin.teams.stats.totalTeams'),
173
+ },
174
+ filters: {
175
+ search: cySelector('superadmin.teams.filters.search'),
176
+ clearButton: cySelector('superadmin.teams.filters.clearButton'),
177
+ },
178
+ tabs: {
179
+ container: cySelector('superadmin.teams.tabs.container'),
180
+ userTeams: cySelector('superadmin.teams.tabs.userTeams'),
181
+ systemAdmin: cySelector('superadmin.teams.tabs.systemAdmin'),
182
+ },
183
+ table: {
184
+ element: cySelector('superadmin.teams.table.element'),
185
+ row: (id: string) => cySelector('superadmin.teams.table.row', { id }),
186
+ menuButton: (id: string) => cySelector('superadmin.teams.table.menuButton', { id }),
187
+ menuContent: (id: string) => cySelector('superadmin.teams.table.menuContent', { id }),
188
+ viewButton: (id: string) => cySelector('superadmin.teams.table.viewButton', { id }),
189
+ editButton: (id: string) => cySelector('superadmin.teams.table.editButton', { id }),
190
+ deleteButton: (id: string) => cySelector('superadmin.teams.table.deleteButton', { id }),
191
+ },
192
+ pagination: {
193
+ container: cySelector('superadmin.teams.pagination.container'),
194
+ pageSize: cySelector('superadmin.teams.pagination.pageSize'),
195
+ first: cySelector('superadmin.teams.pagination.first'),
196
+ prev: cySelector('superadmin.teams.pagination.prev'),
197
+ next: cySelector('superadmin.teams.pagination.next'),
198
+ last: cySelector('superadmin.teams.pagination.last'),
199
+ },
200
+ detail: {
201
+ container: cySelector('superadmin.teams.detail.container'),
202
+ info: {
203
+ name: cySelector('superadmin.teams.detail.info.name'),
204
+ owner: cySelector('superadmin.teams.detail.info.owner'),
205
+ members: cySelector('superadmin.teams.detail.info.members'),
206
+ },
207
+ membersTable: {
208
+ container: cySelector('superadmin.teams.detail.membersTable.container'),
209
+ row: (id: string) => cySelector('superadmin.teams.detail.membersTable.row', { id }),
210
+ },
211
+ subscription: {
212
+ container: cySelector('superadmin.teams.detail.subscription.container'),
213
+ plan: cySelector('superadmin.teams.detail.subscription.plan'),
214
+ status: cySelector('superadmin.teams.detail.subscription.status'),
215
+ period: cySelector('superadmin.teams.detail.subscription.period'),
216
+ stripeLink: cySelector('superadmin.teams.detail.subscription.stripeLink'),
217
+ },
218
+ billingHistory: {
219
+ container: cySelector('superadmin.teams.detail.billingHistory.container'),
220
+ row: (id: string) => cySelector('superadmin.teams.detail.billingHistory.row', { id }),
221
+ },
222
+ usage: {
223
+ container: cySelector('superadmin.teams.detail.usage.container'),
224
+ metric: (slug: string) => cySelector('superadmin.teams.detail.usage.metric', { slug }),
225
+ },
226
+ },
227
+ },
228
+
229
+ // ─────────────────────────────────────────
230
+ // SUBSCRIPTIONS - Subscriptions overview
231
+ // ─────────────────────────────────────────
232
+ subscriptions: {
233
+ container: cySelector('superadmin.subscriptions.container'),
234
+ header: {
235
+ backButton: cySelector('superadmin.subscriptions.header.backButton'),
236
+ title: cySelector('superadmin.subscriptions.header.title'),
237
+ refreshButton: cySelector('superadmin.subscriptions.header.refreshButton'),
238
+ },
239
+ stats: {
240
+ mrr: cySelector('superadmin.subscriptions.stats.mrr'),
241
+ arr: cySelector('superadmin.subscriptions.stats.arr'),
242
+ activeCount: cySelector('superadmin.subscriptions.stats.activeCount'),
243
+ totalCount: cySelector('superadmin.subscriptions.stats.totalCount'),
244
+ needsAttention: cySelector('superadmin.subscriptions.stats.needsAttention'),
245
+ planDistribution: cySelector('superadmin.subscriptions.stats.planDistribution'),
246
+ planCount: (plan: string) => cySelector('superadmin.subscriptions.stats.planCount', { plan }),
247
+ },
248
+ filters: {
249
+ search: cySelector('superadmin.subscriptions.filters.search'),
250
+ statusFilter: cySelector('superadmin.subscriptions.filters.statusFilter'),
251
+ planFilter: cySelector('superadmin.subscriptions.filters.planFilter'),
252
+ intervalFilter: cySelector('superadmin.subscriptions.filters.intervalFilter'),
253
+ clearButton: cySelector('superadmin.subscriptions.filters.clearButton'),
254
+ },
255
+ table: {
256
+ element: cySelector('superadmin.subscriptions.table.element'),
257
+ row: (id: string) => cySelector('superadmin.subscriptions.table.row', { id }),
258
+ viewTeamButton: (id: string) => cySelector('superadmin.subscriptions.table.viewTeamButton', { id }),
259
+ stripeLink: (id: string) => cySelector('superadmin.subscriptions.table.stripeLink', { id }),
260
+ },
261
+ pagination: {
262
+ container: cySelector('superadmin.subscriptions.pagination.container'),
263
+ pageSize: cySelector('superadmin.subscriptions.pagination.pageSize'),
264
+ first: cySelector('superadmin.subscriptions.pagination.first'),
265
+ prev: cySelector('superadmin.subscriptions.pagination.prev'),
266
+ next: cySelector('superadmin.subscriptions.pagination.next'),
267
+ last: cySelector('superadmin.subscriptions.pagination.last'),
268
+ },
269
+ },
270
+
271
+ // ─────────────────────────────────────────
272
+ // TEAM ROLES - RBAC Matrix and Plan Features
273
+ // ─────────────────────────────────────────
274
+ teamRoles: {
275
+ container: cySelector('superadmin.teamRoles.container'),
276
+ header: {
277
+ backButton: cySelector('superadmin.teamRoles.header.backButton'),
278
+ title: cySelector('superadmin.teamRoles.header.title'),
279
+ },
280
+ tabs: {
281
+ container: cySelector('superadmin.teamRoles.tabs.container'),
282
+ rbac: cySelector('superadmin.teamRoles.tabs.rbac'),
283
+ plans: cySelector('superadmin.teamRoles.tabs.plans'),
284
+ },
285
+ rbac: {
286
+ stats: {
287
+ roles: cySelector('superadmin.teamRoles.rbac.stats.roles'),
288
+ permissions: cySelector('superadmin.teamRoles.rbac.stats.permissions'),
289
+ protectedRole: cySelector('superadmin.teamRoles.rbac.stats.protectedRole'),
290
+ defaultRole: cySelector('superadmin.teamRoles.rbac.stats.defaultRole'),
291
+ },
292
+ hierarchy: {
293
+ container: cySelector('superadmin.teamRoles.rbac.hierarchy.container'),
294
+ roleCard: (role: string) => cySelector('superadmin.teamRoles.rbac.hierarchy.roleCard', { role }),
295
+ },
296
+ matrix: {
297
+ container: cySelector('superadmin.teamRoles.rbac.matrix.container'),
298
+ permissionRow: (permission: string) => cySelector('superadmin.teamRoles.rbac.matrix.permissionRow', { permission: permission.replace(/\./g, '-') }),
299
+ },
300
+ },
301
+ plans: {
302
+ stats: {
303
+ totalPlans: cySelector('superadmin.teamRoles.plans.stats.totalPlans'),
304
+ features: cySelector('superadmin.teamRoles.plans.stats.features'),
305
+ limits: cySelector('superadmin.teamRoles.plans.stats.limits'),
306
+ activeTheme: cySelector('superadmin.teamRoles.plans.stats.activeTheme'),
307
+ },
308
+ planCard: (slug: string) => cySelector('superadmin.teamRoles.plans.planCard', { slug }),
309
+ matrix: {
310
+ container: cySelector('superadmin.teamRoles.plans.matrix.container'),
311
+ featureRow: (slug: string) => cySelector('superadmin.teamRoles.plans.matrix.featureRow', { slug }),
312
+ limitRow: (slug: string) => cySelector('superadmin.teamRoles.plans.matrix.limitRow', { slug }),
313
+ },
314
+ },
315
+ },
316
+
317
+ // ─────────────────────────────────────────
318
+ // DOCS - Admin documentation pages
319
+ // ─────────────────────────────────────────
320
+ docs: {
321
+ container: cySelector('superadmin.docs.container'),
322
+ pageDetail: cySelector('superadmin.docs.pageDetail'),
323
+ sectionCard: (slug: string) => cySelector('superadmin.docs.sectionCard', { slug }),
324
+ pageLink: (slug: string) => cySelector('superadmin.docs.pageLink', { slug }),
325
+ },
326
+ }
327
+ }
328
+
329
+ // ============================================
330
+ // LEGACY SELECTOR ALIASES (for backward compatibility)
331
+ // These map old selector names to new structure
332
+ // TODO: Remove after updating all tests
333
+ // ============================================
334
+
335
+ get legacySelectors() {
336
+ return {
337
+ // Old navigation selectors → new sidebar.nav
338
+ navContainer: this.selectors.container,
339
+ navDashboard: this.selectors.sidebar.nav.dashboard,
340
+ navUsers: this.selectors.sidebar.nav.users,
341
+ navTeams: this.selectors.sidebar.nav.teams,
342
+ navTeamRoles: this.selectors.sidebar.nav.teamRoles,
343
+ navSubscriptions: this.selectors.sidebar.nav.subscriptions,
344
+ exitToDashboard: this.selectors.sidebar.exitButton,
345
+
346
+ // Old dashboard selectors
347
+ dashboardContainer: this.selectors.dashboard.container,
348
+
349
+ // Old users selectors
350
+ usersContainer: this.selectors.users.container,
351
+ usersTable: this.selectors.users.table.element,
352
+ usersSearch: this.selectors.users.filters.search,
353
+ userRow: this.selectors.users.table.row,
354
+ userView: this.selectors.users.table.viewButton,
355
+ userEdit: this.selectors.users.table.editButton,
356
+ userBan: this.selectors.users.table.banButton,
357
+ userDelete: this.selectors.users.table.deleteButton,
358
+ userImpersonate: this.selectors.users.table.impersonateButton,
359
+
360
+ // Old teams selectors
361
+ teamsContainer: this.selectors.teams.container,
362
+ teamsTable: this.selectors.teams.table.element,
363
+ teamsSearch: this.selectors.teams.filters.search,
364
+ teamRow: this.selectors.teams.table.row,
365
+ teamActionsButton: this.selectors.teams.table.menuButton,
366
+ teamView: this.selectors.teams.table.viewButton,
367
+ teamEdit: this.selectors.teams.table.editButton,
368
+ teamDelete: this.selectors.teams.table.deleteButton,
369
+
370
+ // Old subscriptions selectors
371
+ subscriptionsContainer: this.selectors.subscriptions.container,
372
+ subscriptionsMrr: this.selectors.subscriptions.stats.mrr,
373
+ subscriptionsPlanDistribution: this.selectors.subscriptions.stats.planDistribution,
374
+ subscriptionsPlanCount: this.selectors.subscriptions.stats.planCount,
375
+ subscriptionsActiveCount: this.selectors.subscriptions.stats.activeCount,
376
+
377
+ // Old permission selectors
378
+ permissionRow: this.selectors.teamRoles.rbac.matrix.permissionRow,
83
379
  }
84
380
  }
85
381
 
86
382
  // ============================================
87
- // NAVIGATION
383
+ // NAVIGATION - Visit Pages
88
384
  // ============================================
89
385
 
90
- /**
91
- * Navigate to Superadmin dashboard
92
- */
386
+ /** Navigate to Superadmin dashboard */
93
387
  visitDashboard() {
94
388
  cy.visit('/superadmin', { timeout: 60000 })
95
389
  return this
96
390
  }
97
391
 
98
- /**
99
- * Navigate to all users page
100
- */
392
+ /** Navigate to all users page */
101
393
  visitUsers() {
102
394
  cy.visit('/superadmin/users', { timeout: 60000 })
103
395
  return this
104
396
  }
105
397
 
106
- /**
107
- * Navigate to all teams page
108
- */
398
+ /** Navigate to user detail page */
399
+ visitUserDetail(id: string) {
400
+ cy.visit(`/superadmin/users/${id}`, { timeout: 60000 })
401
+ return this
402
+ }
403
+
404
+ /** Navigate to all teams page */
109
405
  visitTeams() {
110
406
  cy.visit('/superadmin/teams', { timeout: 60000 })
111
407
  return this
112
408
  }
113
409
 
114
- /**
115
- * Navigate to subscriptions overview
116
- */
410
+ /** Navigate to team detail page */
411
+ visitTeamDetail(id: string) {
412
+ cy.visit(`/superadmin/teams/${id}`, { timeout: 60000 })
413
+ return this
414
+ }
415
+
416
+ /** Navigate to subscriptions overview */
117
417
  visitSubscriptions() {
118
418
  cy.visit('/superadmin/subscriptions', { timeout: 60000 })
119
419
  return this
120
420
  }
121
421
 
122
- /**
123
- * Click nav link to dashboard
124
- */
422
+ /** Navigate to team roles (RBAC & Plans) */
423
+ visitTeamRoles() {
424
+ cy.visit('/superadmin/team-roles', { timeout: 60000 })
425
+ return this
426
+ }
427
+
428
+ /** Navigate to docs index */
429
+ visitDocs() {
430
+ cy.visit('/superadmin/docs', { timeout: 60000 })
431
+ return this
432
+ }
433
+
434
+ /** Navigate to a specific doc page */
435
+ visitDocPage(section: string, page: string) {
436
+ cy.visit(`/superadmin/docs/${section}/${page}`, { timeout: 60000 })
437
+ return this
438
+ }
439
+
440
+ // ============================================
441
+ // NAVIGATION - Sidebar Clicks
442
+ // ============================================
443
+
444
+ /** Click nav link to dashboard */
125
445
  clickNavDashboard() {
126
- cy.get(this.selectors.navDashboard).click()
446
+ cy.get(this.selectors.sidebar.nav.dashboard).click()
127
447
  return this
128
448
  }
129
449
 
130
- /**
131
- * Click nav link to users
132
- */
450
+ /** Click nav link to users */
133
451
  clickNavUsers() {
134
- cy.get(this.selectors.navUsers).click()
452
+ cy.get(this.selectors.sidebar.nav.users).click()
135
453
  return this
136
454
  }
137
455
 
138
- /**
139
- * Click nav link to teams
140
- */
456
+ /** Click nav link to teams */
141
457
  clickNavTeams() {
142
- cy.get(this.selectors.navTeams).click()
458
+ cy.get(this.selectors.sidebar.nav.teams).click()
459
+ return this
460
+ }
461
+
462
+ /** Click nav link to team roles */
463
+ clickNavTeamRoles() {
464
+ cy.get(this.selectors.sidebar.nav.teamRoles).click()
465
+ return this
466
+ }
467
+
468
+ /** Click nav link to subscriptions */
469
+ clickNavSubscriptions() {
470
+ cy.get(this.selectors.sidebar.nav.subscriptions).click()
471
+ return this
472
+ }
473
+
474
+ /** Click nav link to docs */
475
+ clickNavDocs() {
476
+ cy.get(this.selectors.sidebar.nav.docs).click()
477
+ return this
478
+ }
479
+
480
+ /** Click exit button to return to main dashboard */
481
+ clickExitButton() {
482
+ cy.get(this.selectors.sidebar.exitButton).click()
483
+ return this
484
+ }
485
+
486
+ /** Toggle sidebar collapse */
487
+ toggleSidebarCollapse() {
488
+ cy.get(this.selectors.sidebar.collapseButton).click()
143
489
  return this
144
490
  }
145
491
 
@@ -147,35 +493,57 @@ export class SuperadminPOM extends BasePOM {
147
493
  // USERS ACTIONS
148
494
  // ============================================
149
495
 
150
- /**
151
- * Search users
152
- */
496
+ /** Search users */
153
497
  searchUsers(query: string) {
154
- cy.get(this.selectors.usersSearch).clear().type(query)
498
+ cy.get(this.selectors.users.filters.search).clear().type(query)
155
499
  return this
156
500
  }
157
501
 
158
- /**
159
- * View user details
160
- */
502
+ /** Clear users search */
503
+ clearUsersSearch() {
504
+ cy.get(this.selectors.users.filters.search).clear()
505
+ return this
506
+ }
507
+
508
+ /** Clear all users filters */
509
+ clearUsersFilters() {
510
+ cy.get(this.selectors.users.filters.clearButton).click()
511
+ return this
512
+ }
513
+
514
+ /** Switch to regular users tab */
515
+ switchToRegularUsersTab() {
516
+ cy.get(this.selectors.users.tabs.regularUsers).click()
517
+ return this
518
+ }
519
+
520
+ /** Switch to superadmins tab */
521
+ switchToSuperadminsTab() {
522
+ cy.get(this.selectors.users.tabs.superadmins).click()
523
+ return this
524
+ }
525
+
526
+ /** Click on a user row to view details */
527
+ clickUserRow(id: string) {
528
+ cy.get(this.selectors.users.table.row(id)).click()
529
+ return this
530
+ }
531
+
532
+ /** View user details via button */
161
533
  viewUser(id: string) {
162
- cy.get(this.selectors.userView(id)).click()
534
+ cy.get(this.selectors.users.table.viewButton(id)).click()
163
535
  return this
164
536
  }
165
537
 
166
- /**
167
- * Ban a user
168
- */
538
+ /** Ban a user */
169
539
  banUser(id: string) {
170
- cy.get(this.selectors.userBan(id)).click()
540
+ cy.get(this.selectors.users.table.banButton(id)).click()
171
541
  return this
172
542
  }
173
543
 
174
- /**
175
- * Impersonate a user
176
- */
544
+ /** Impersonate a user */
177
545
  impersonateUser(id: string) {
178
- cy.get(this.selectors.userImpersonate(id)).click()
546
+ cy.get(this.selectors.users.table.impersonateButton(id)).click()
179
547
  return this
180
548
  }
181
549
 
@@ -183,19 +551,107 @@ export class SuperadminPOM extends BasePOM {
183
551
  // TEAMS ACTIONS
184
552
  // ============================================
185
553
 
186
- /**
187
- * Search teams
188
- */
554
+ /** Search teams */
189
555
  searchTeams(query: string) {
190
- cy.get(this.selectors.teamsSearch).clear().type(query)
556
+ cy.get(this.selectors.teams.filters.search).clear().type(query)
557
+ return this
558
+ }
559
+
560
+ /** Clear teams search */
561
+ clearTeamsSearch() {
562
+ cy.get(this.selectors.teams.filters.search).clear()
563
+ return this
564
+ }
565
+
566
+ /** Clear all teams filters */
567
+ clearTeamsFilters() {
568
+ cy.get(this.selectors.teams.filters.clearButton).click()
569
+ return this
570
+ }
571
+
572
+ /** Switch to user teams tab */
573
+ switchToUserTeamsTab() {
574
+ cy.get(this.selectors.teams.tabs.userTeams).click()
575
+ return this
576
+ }
577
+
578
+ /** Switch to system admin team tab */
579
+ switchToSystemAdminTab() {
580
+ cy.get(this.selectors.teams.tabs.systemAdmin).click()
581
+ return this
582
+ }
583
+
584
+ /** Click on a team row to view details */
585
+ clickTeamRow(id: string) {
586
+ cy.get(this.selectors.teams.table.row(id)).click()
587
+ return this
588
+ }
589
+
590
+ /** Open team actions menu */
591
+ openTeamMenu(id: string) {
592
+ cy.get(this.selectors.teams.table.menuButton(id)).click()
191
593
  return this
192
594
  }
193
595
 
194
- /**
195
- * View team details
196
- */
596
+ /** View team details via button */
197
597
  viewTeam(id: string) {
198
- cy.get(this.selectors.teamView(id)).click()
598
+ cy.get(this.selectors.teams.table.viewButton(id)).click()
599
+ return this
600
+ }
601
+
602
+ // ============================================
603
+ // TEAM ROLES ACTIONS
604
+ // ============================================
605
+
606
+ /** Switch to RBAC tab */
607
+ switchToRbacTab() {
608
+ cy.get(this.selectors.teamRoles.tabs.rbac).click()
609
+ return this
610
+ }
611
+
612
+ /** Switch to Plans tab */
613
+ switchToPlansTab() {
614
+ cy.get(this.selectors.teamRoles.tabs.plans).click()
615
+ return this
616
+ }
617
+
618
+ // ============================================
619
+ // PAGINATION (Contextual)
620
+ // ============================================
621
+
622
+ /** Get pagination selectors for a specific context */
623
+ getPaginationSelectors(context: PaginationContext) {
624
+ return this.selectors[context].pagination
625
+ }
626
+
627
+ /** Go to first page */
628
+ paginateFirst(context: PaginationContext) {
629
+ cy.get(this.selectors[context].pagination.first).click()
630
+ return this
631
+ }
632
+
633
+ /** Go to previous page */
634
+ paginatePrev(context: PaginationContext) {
635
+ cy.get(this.selectors[context].pagination.prev).click()
636
+ return this
637
+ }
638
+
639
+ /** Go to next page */
640
+ paginateNext(context: PaginationContext) {
641
+ cy.get(this.selectors[context].pagination.next).click()
642
+ return this
643
+ }
644
+
645
+ /** Go to last page */
646
+ paginateLast(context: PaginationContext) {
647
+ cy.get(this.selectors[context].pagination.last).click()
648
+ return this
649
+ }
650
+
651
+ /** Change page size */
652
+ changePageSize(context: PaginationContext, size: number) {
653
+ cy.get(this.selectors[context].pagination.pageSize).click()
654
+ cy.get(`[data-value="${size}"]`).click()
199
655
  return this
200
656
  }
201
657
 
@@ -203,82 +659,109 @@ export class SuperadminPOM extends BasePOM {
203
659
  // ASSERTIONS
204
660
  // ============================================
205
661
 
206
- /**
207
- * Assert on Superadmin area
208
- */
662
+ /** Assert on Superadmin area */
209
663
  assertOnSuperadmin() {
210
664
  cy.url().should('include', '/superadmin')
211
665
  return this
212
666
  }
213
667
 
214
- /**
215
- * Assert dashboard is visible
216
- */
668
+ /** Assert dashboard is visible */
217
669
  assertDashboardVisible() {
218
- cy.get(this.selectors.dashboardContainer).should('be.visible')
670
+ cy.get(this.selectors.dashboard.container).should('be.visible')
219
671
  return this
220
672
  }
221
673
 
222
- /**
223
- * Assert stats cards are visible
224
- */
225
- assertStatsVisible() {
226
- cy.get(this.selectors.statsUsers).should('be.visible')
227
- cy.get(this.selectors.statsTeams).should('be.visible')
674
+ /** Assert sidebar is visible */
675
+ assertSidebarVisible() {
676
+ cy.get(this.selectors.sidebar.nav.dashboard).should('be.visible')
228
677
  return this
229
678
  }
230
679
 
231
- /**
232
- * Assert users page is visible
233
- */
680
+ /** Assert users page is visible */
234
681
  assertUsersVisible() {
235
- cy.get(this.selectors.usersContainer).should('be.visible')
682
+ cy.get(this.selectors.users.container).should('be.visible')
236
683
  return this
237
684
  }
238
685
 
239
- /**
240
- * Assert users table is visible
241
- */
686
+ /** Assert users table is visible */
242
687
  assertUsersTableVisible() {
243
- cy.get(this.selectors.usersTable).should('be.visible')
688
+ cy.get(this.selectors.users.table.element).should('be.visible')
244
689
  return this
245
690
  }
246
691
 
247
- /**
248
- * Assert teams page is visible
249
- */
692
+ /** Assert user detail is visible */
693
+ assertUserDetailVisible() {
694
+ cy.get(this.selectors.users.detail.container).should('be.visible')
695
+ return this
696
+ }
697
+
698
+ /** Assert user metadata section is visible */
699
+ assertUserMetasVisible() {
700
+ cy.get(this.selectors.users.detail.metas.container).should('be.visible')
701
+ return this
702
+ }
703
+
704
+ /** Assert teams page is visible */
250
705
  assertTeamsVisible() {
251
- cy.get(this.selectors.teamsContainer).should('be.visible')
706
+ cy.get(this.selectors.teams.container).should('be.visible')
252
707
  return this
253
708
  }
254
709
 
255
- /**
256
- * Assert teams table is visible
257
- */
710
+ /** Assert teams table is visible */
258
711
  assertTeamsTableVisible() {
259
- cy.get(this.selectors.teamsTable).should('be.visible')
712
+ cy.get(this.selectors.teams.table.element).should('be.visible')
260
713
  return this
261
714
  }
262
715
 
263
- /**
264
- * Assert nav items are visible
265
- */
716
+ /** Assert team detail is visible */
717
+ assertTeamDetailVisible() {
718
+ cy.get(this.selectors.teams.detail.container).should('be.visible')
719
+ return this
720
+ }
721
+
722
+ /** Assert nav items are visible */
266
723
  assertNavVisible() {
267
- cy.get(this.selectors.navContainer).should('be.visible')
724
+ cy.get(this.selectors.container).should('be.visible')
268
725
  return this
269
726
  }
270
727
 
271
- /**
272
- * Assert subscriptions page is visible
273
- */
728
+ /** Assert subscriptions page is visible */
274
729
  assertSubscriptionsVisible() {
275
- cy.get(this.selectors.subscriptionsContainer).should('be.visible')
730
+ cy.get(this.selectors.subscriptions.container).should('be.visible')
731
+ return this
732
+ }
733
+
734
+ /** Assert team roles page is visible */
735
+ assertTeamRolesVisible() {
736
+ cy.get(this.selectors.teamRoles.container).should('be.visible')
737
+ return this
738
+ }
739
+
740
+ /** Assert RBAC matrix is visible */
741
+ assertRbacMatrixVisible() {
742
+ cy.get(this.selectors.teamRoles.rbac.matrix.container).should('be.visible')
743
+ return this
744
+ }
745
+
746
+ /** Assert Plans matrix is visible */
747
+ assertPlansMatrixVisible() {
748
+ cy.get(this.selectors.teamRoles.plans.matrix.container).should('be.visible')
276
749
  return this
277
750
  }
278
751
 
279
- /**
280
- * Assert access denied (redirect from superadmin)
281
- */
752
+ /** Assert docs index is visible */
753
+ assertDocsVisible() {
754
+ cy.get(this.selectors.docs.container).should('be.visible')
755
+ return this
756
+ }
757
+
758
+ /** Assert docs page detail is visible */
759
+ assertDocPageVisible() {
760
+ cy.get(this.selectors.docs.pageDetail).should('be.visible')
761
+ return this
762
+ }
763
+
764
+ /** Assert access denied (redirect from superadmin) */
282
765
  assertAccessDenied() {
283
766
  cy.url().should('not.include', '/superadmin')
284
767
  cy.url().should('satisfy', (url: string) => {
@@ -291,39 +774,76 @@ export class SuperadminPOM extends BasePOM {
291
774
  // WAITS
292
775
  // ============================================
293
776
 
294
- /**
295
- * Wait for Superadmin dashboard to load
296
- */
777
+ /** Wait for Superadmin dashboard to load */
297
778
  waitForDashboard() {
298
779
  cy.url().should('include', '/superadmin')
299
- cy.get(this.selectors.dashboardContainer, { timeout: 15000 }).should('be.visible')
780
+ cy.get(this.selectors.dashboard.container, { timeout: 15000 }).should('be.visible')
300
781
  return this
301
782
  }
302
783
 
303
- /**
304
- * Wait for users page to load
305
- */
784
+ /** Wait for users page to load */
306
785
  waitForUsers() {
307
786
  cy.url().should('include', '/superadmin/users')
308
- cy.get(this.selectors.usersContainer, { timeout: 15000 }).should('be.visible')
787
+ cy.get(this.selectors.users.container, { timeout: 15000 }).should('be.visible')
788
+ return this
789
+ }
790
+
791
+ /** Wait for user detail to load */
792
+ waitForUserDetail() {
793
+ cy.url().should('match', /\/superadmin\/users\/[^/]+$/)
794
+ cy.get(this.selectors.users.detail.container, { timeout: 15000 }).should('be.visible')
309
795
  return this
310
796
  }
311
797
 
312
- /**
313
- * Wait for teams page to load
314
- */
798
+ /** Wait for teams page to load */
315
799
  waitForTeams() {
316
800
  cy.url().should('include', '/superadmin/teams')
317
- cy.get(this.selectors.teamsContainer, { timeout: 15000 }).should('be.visible')
801
+ cy.get(this.selectors.teams.container, { timeout: 15000 }).should('be.visible')
318
802
  return this
319
803
  }
320
804
 
321
- /**
322
- * Wait for subscriptions page to load
323
- */
805
+ /** Wait for team detail to load */
806
+ waitForTeamDetail() {
807
+ cy.url().should('match', /\/superadmin\/teams\/[^/]+$/)
808
+ cy.get(this.selectors.teams.detail.container, { timeout: 15000 }).should('be.visible')
809
+ return this
810
+ }
811
+
812
+ /** Wait for subscriptions page to load */
324
813
  waitForSubscriptions() {
325
814
  cy.url().should('include', '/superadmin/subscriptions')
326
- cy.get(this.selectors.subscriptionsContainer, { timeout: 15000 }).should('be.visible')
815
+ cy.get(this.selectors.subscriptions.container, { timeout: 15000 }).should('be.visible')
816
+ return this
817
+ }
818
+
819
+ /** Wait for team roles page to load */
820
+ waitForTeamRoles() {
821
+ cy.url().should('include', '/superadmin/team-roles')
822
+ cy.get(this.selectors.teamRoles.container, { timeout: 15000 }).should('be.visible')
823
+ return this
824
+ }
825
+
826
+ /** Wait for docs index to load */
827
+ waitForDocs() {
828
+ cy.url().should('include', '/superadmin/docs')
829
+ cy.get(this.selectors.docs.container, { timeout: 15000 }).should('be.visible')
830
+ return this
831
+ }
832
+
833
+ /** Wait for doc page detail to load */
834
+ waitForDocPage() {
835
+ cy.url().should('match', /\/superadmin\/docs\/[^/]+\/[^/]+$/)
836
+ cy.get(this.selectors.docs.pageDetail, { timeout: 15000 }).should('be.visible')
837
+ return this
838
+ }
839
+
840
+ // ============================================
841
+ // DOCS ACTIONS
842
+ // ============================================
843
+
844
+ /** Click on a doc page link */
845
+ clickDocPageLink(slug: string) {
846
+ cy.get(this.selectors.docs.pageLink(slug)).click()
327
847
  return this
328
848
  }
329
849
  }