@nextsparkjs/core 0.1.0-beta.39 → 0.1.0-beta.40

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 (57) hide show
  1. package/dist/styles/classes.json +1 -1
  2. package/dist/templates/contents/themes/starter/tests/cypress/e2e/uat/entities/tasks/tasks-crud.bdd.md +278 -0
  3. package/dist/templates/contents/themes/starter/tests/cypress/e2e/uat/entities/tasks/tasks-crud.cy.ts +22 -14
  4. package/dist/templates/contents/themes/starter/tests/cypress/src/components/DevKeyringPOM.ts +160 -0
  5. package/dist/templates/contents/themes/starter/tests/cypress/src/components/EntityForm.ts +375 -0
  6. package/dist/templates/contents/themes/starter/tests/cypress/src/components/EntityList.ts +389 -0
  7. package/dist/templates/contents/themes/starter/tests/cypress/src/components/TeamSwitcherPOM.ts +450 -0
  8. package/dist/templates/contents/themes/starter/tests/cypress/src/components/index.ts +13 -0
  9. package/dist/templates/contents/themes/starter/tests/cypress/src/core/BlockEditorBasePOM.ts +576 -0
  10. package/dist/templates/contents/themes/starter/tests/cypress/src/core/index.ts +2 -0
  11. package/dist/templates/contents/themes/starter/tests/cypress/{e2e/uat/entities/tasks → src/entities}/TasksPOM.ts +1 -1
  12. package/dist/templates/contents/themes/starter/tests/cypress/src/entities/index.ts +10 -0
  13. package/dist/templates/contents/themes/starter/tests/cypress/src/features/BillingPOM.ts +385 -0
  14. package/dist/templates/contents/themes/starter/tests/cypress/src/features/DashboardPOM.ts +245 -0
  15. package/dist/templates/contents/themes/starter/tests/cypress/src/features/DevtoolsPOM.ts +750 -0
  16. package/dist/templates/contents/themes/starter/tests/cypress/src/features/ScheduledActionsPOM.ts +463 -0
  17. package/dist/templates/contents/themes/starter/tests/cypress/src/features/SettingsPOM.ts +362 -0
  18. package/dist/templates/contents/themes/starter/tests/cypress/src/features/SuperadminPOM.ts +331 -0
  19. package/dist/templates/contents/themes/starter/tests/cypress/src/features/index.ts +18 -0
  20. package/dist/templates/contents/themes/starter/tests/cypress/src/index.ts +88 -0
  21. package/dist/templates/contents/themes/starter/tests/cypress/src/session-helpers.ts +332 -88
  22. package/dist/templates/contents/themes/starter/tests/cypress.config.ts +4 -1
  23. package/package.json +1 -1
  24. package/scripts/test/jest-theme.mjs +7 -3
  25. package/templates/contents/themes/starter/tests/cypress/e2e/uat/entities/tasks/tasks-crud.bdd.md +278 -0
  26. package/templates/contents/themes/starter/tests/cypress/e2e/uat/entities/tasks/tasks-crud.cy.ts +22 -14
  27. package/templates/contents/themes/starter/tests/cypress/src/components/DevKeyringPOM.ts +160 -0
  28. package/templates/contents/themes/starter/tests/cypress/src/components/EntityForm.ts +375 -0
  29. package/templates/contents/themes/starter/tests/cypress/src/components/EntityList.ts +389 -0
  30. package/templates/contents/themes/starter/tests/cypress/src/components/TeamSwitcherPOM.ts +450 -0
  31. package/templates/contents/themes/starter/tests/cypress/src/components/index.ts +13 -0
  32. package/templates/contents/themes/starter/tests/cypress/src/core/BlockEditorBasePOM.ts +576 -0
  33. package/templates/contents/themes/starter/tests/cypress/src/core/index.ts +2 -0
  34. package/templates/contents/themes/starter/tests/cypress/{e2e/uat/entities/tasks → src/entities}/TasksPOM.ts +1 -1
  35. package/templates/contents/themes/starter/tests/cypress/src/entities/index.ts +10 -0
  36. package/templates/contents/themes/starter/tests/cypress/src/features/BillingPOM.ts +385 -0
  37. package/templates/contents/themes/starter/tests/cypress/src/features/DashboardPOM.ts +245 -0
  38. package/templates/contents/themes/starter/tests/cypress/src/features/DevtoolsPOM.ts +750 -0
  39. package/templates/contents/themes/starter/tests/cypress/src/features/ScheduledActionsPOM.ts +463 -0
  40. package/templates/contents/themes/starter/tests/cypress/src/features/SettingsPOM.ts +362 -0
  41. package/templates/contents/themes/starter/tests/cypress/src/features/SuperadminPOM.ts +331 -0
  42. package/templates/contents/themes/starter/tests/cypress/src/features/index.ts +18 -0
  43. package/templates/contents/themes/starter/tests/cypress/src/index.ts +88 -0
  44. package/templates/contents/themes/starter/tests/cypress/src/session-helpers.ts +332 -88
  45. package/templates/contents/themes/starter/tests/cypress.config.ts +4 -1
  46. package/dist/templates/contents/themes/starter/tests/cypress/e2e/_utils/selectors/pages-editor.bdd.md +0 -207
  47. package/dist/templates/contents/themes/starter/tests/cypress/e2e/_utils/selectors/pages-editor.cy.ts +0 -211
  48. package/dist/templates/contents/themes/starter/tests/cypress/e2e/_utils/selectors/posts-editor.bdd.md +0 -184
  49. package/dist/templates/contents/themes/starter/tests/cypress/e2e/_utils/selectors/posts-editor.cy.ts +0 -350
  50. package/dist/templates/contents/themes/starter/tests/cypress/e2e/_utils/selectors/public.cy.ts +0 -112
  51. package/dist/templates/contents/themes/starter/tests/cypress/e2e/_utils/selectors/taxonomies.cy.ts +0 -126
  52. package/templates/contents/themes/starter/tests/cypress/e2e/_utils/selectors/pages-editor.bdd.md +0 -207
  53. package/templates/contents/themes/starter/tests/cypress/e2e/_utils/selectors/pages-editor.cy.ts +0 -211
  54. package/templates/contents/themes/starter/tests/cypress/e2e/_utils/selectors/posts-editor.bdd.md +0 -184
  55. package/templates/contents/themes/starter/tests/cypress/e2e/_utils/selectors/posts-editor.cy.ts +0 -350
  56. package/templates/contents/themes/starter/tests/cypress/e2e/_utils/selectors/public.cy.ts +0 -112
  57. package/templates/contents/themes/starter/tests/cypress/e2e/_utils/selectors/taxonomies.cy.ts +0 -126
@@ -0,0 +1,450 @@
1
+ /**
2
+ * TeamSwitcherPOM - Page Object Model for TeamSwitcherCompact component
3
+ *
4
+ * POM for the team switcher in multi-tenant mode.
5
+ * Used in sidebar footer and mobile MobileMoreSheet.
6
+ *
7
+ * @version 3.0 - Uses centralized selectors from cySelector()
8
+ */
9
+ import { BasePOM } from '../core/BasePOM'
10
+ import { cySelector } from '../selectors'
11
+
12
+ export class TeamSwitcherPOM extends BasePOM {
13
+ /**
14
+ * Selectors using centralized cySelector()
15
+ */
16
+ get selectors() {
17
+ return {
18
+ // TeamSwitcherCompact selectors
19
+ trigger: cySelector('teams.switcher.compact'),
20
+ dropdown: cySelector('teams.switcher.dropdown'),
21
+ // Prefix selector for all team options
22
+ teamOption: '[data-cy^="team-option-"]',
23
+ teamOptionBySlug: (slug: string) => cySelector('teams.switcher.option', { slug }),
24
+ manageTeamsLink: cySelector('teams.switcher.manageLink'),
25
+
26
+ // TeamSwitchModal selectors
27
+ switchModal: cySelector('teams.switchModal.container'),
28
+
29
+ // Sidebar selectors (toggle is in TopNavbar, not sidebar)
30
+ sidebar: cySelector('dashboard.sidebar.main'),
31
+ sidebarToggle: cySelector('dashboard.topnav.sidebarToggle'),
32
+
33
+ // Mobile selectors
34
+ mobileMoreButton: cySelector('dashboard.mobile.bottomNav.item', { id: 'more' }),
35
+ mobileMoreSheet: cySelector('dashboard.mobile.moreSheet.content'),
36
+ mobileTeamSwitcher: cySelector('dashboard.mobile.moreSheet.teamSwitcher'),
37
+
38
+ // Permission selectors
39
+ permissionDenied: cySelector('common.permissionDenied'),
40
+
41
+ // Internal elements (CSS classes, used for validation)
42
+ teamName: '.text-sm.font-medium',
43
+ teamRole: '.text-xs.text-muted-foreground.capitalize',
44
+ checkIcon: 'svg.lucide-check',
45
+ avatar: '[class*="avatar"]',
46
+ }
47
+ }
48
+
49
+ /**
50
+ * Factory method - creates a new instance
51
+ */
52
+ static create(): TeamSwitcherPOM {
53
+ return new TeamSwitcherPOM()
54
+ }
55
+
56
+ // ============================================
57
+ // Sidebar Methods
58
+ // ============================================
59
+
60
+ /**
61
+ * Ensure sidebar is expanded (required for TeamSwitcher to be visible)
62
+ * The TeamSwitcherCompact only renders when sidebar is NOT collapsed
63
+ */
64
+ ensureSidebarExpanded(): this {
65
+ // Wait for dashboard to be fully loaded
66
+ cy.url().should('include', '/dashboard')
67
+
68
+ // First check if sidebar exists and wait for it to be visible
69
+ cy.get(this.selectors.sidebar, { timeout: 15000 }).should('be.visible')
70
+
71
+ // Check if collapsed and expand if needed
72
+ cy.get(this.selectors.sidebar).then($sidebar => {
73
+ const isCollapsed = $sidebar.attr('data-collapsed')
74
+ if (isCollapsed === 'true') {
75
+ // Click toggle to expand
76
+ cy.get(this.selectors.sidebarToggle, { timeout: 5000 })
77
+ .should('be.visible')
78
+ .click({ force: true })
79
+ // Wait for expansion animation
80
+ cy.get(this.selectors.sidebar, { timeout: 5000 })
81
+ .should('have.attr', 'data-collapsed', 'false')
82
+ // Wait for team switcher to render
83
+ cy.wait(300)
84
+ }
85
+ })
86
+
87
+ // Final assertion that sidebar is expanded
88
+ cy.get(this.selectors.sidebar).should('have.attr', 'data-collapsed', 'false')
89
+ return this
90
+ }
91
+
92
+ /**
93
+ * Validate sidebar is visible and expanded
94
+ */
95
+ validateSidebarExpanded(): this {
96
+ cy.get(this.selectors.sidebar)
97
+ .should('be.visible')
98
+ .and('have.attr', 'data-collapsed', 'false')
99
+ return this
100
+ }
101
+
102
+ /**
103
+ * Validate sidebar is collapsed
104
+ */
105
+ validateSidebarCollapsed(): this {
106
+ cy.get(this.selectors.sidebar)
107
+ .should('be.visible')
108
+ .and('have.attr', 'data-collapsed', 'true')
109
+ return this
110
+ }
111
+
112
+ /**
113
+ * Click sidebar toggle button to collapse/expand
114
+ */
115
+ toggleSidebar(): this {
116
+ cy.get(this.selectors.sidebarToggle).click()
117
+ return this
118
+ }
119
+
120
+ /**
121
+ * Collapse sidebar and wait for animation
122
+ */
123
+ collapseSidebar(): this {
124
+ cy.get(this.selectors.sidebar).then($sidebar => {
125
+ if ($sidebar.attr('data-collapsed') === 'false') {
126
+ this.toggleSidebar()
127
+ cy.get(this.selectors.sidebar).should('have.attr', 'data-collapsed', 'true')
128
+ }
129
+ })
130
+ return this
131
+ }
132
+
133
+ /**
134
+ * Expand sidebar and wait for animation
135
+ */
136
+ expandSidebar(): this {
137
+ cy.get(this.selectors.sidebar).then($sidebar => {
138
+ if ($sidebar.attr('data-collapsed') === 'true') {
139
+ this.toggleSidebar()
140
+ cy.get(this.selectors.sidebar).should('have.attr', 'data-collapsed', 'false')
141
+ }
142
+ })
143
+ return this
144
+ }
145
+
146
+ // ============================================
147
+ // Team Switcher Core Methods
148
+ // ============================================
149
+
150
+ /**
151
+ * Validate team switcher is visible
152
+ */
153
+ validateSwitcherVisible(): this {
154
+ this.ensureSidebarExpanded()
155
+ cy.get(this.selectors.trigger).should('be.visible')
156
+ return this
157
+ }
158
+
159
+ /**
160
+ * Validate team switcher is NOT visible
161
+ */
162
+ validateSwitcherNotVisible(): this {
163
+ cy.get(this.selectors.trigger).should('not.exist')
164
+ return this
165
+ }
166
+
167
+ /**
168
+ * Open the team switcher dropdown (idempotent)
169
+ */
170
+ open(): this {
171
+ this.ensureSidebarExpanded()
172
+ cy.get('body').then($body => {
173
+ if ($body.find(this.selectors.dropdown).length === 0) {
174
+ cy.get(this.selectors.trigger).click()
175
+ }
176
+ cy.get(this.selectors.dropdown).should('be.visible')
177
+ })
178
+ return this
179
+ }
180
+
181
+ /**
182
+ * Close the team switcher dropdown
183
+ */
184
+ close(): this {
185
+ cy.get('body').click(0, 0)
186
+ cy.get(this.selectors.dropdown).should('not.exist')
187
+ return this
188
+ }
189
+
190
+ /**
191
+ * Get the current team name displayed in the trigger button
192
+ */
193
+ getCurrentTeamName(): Cypress.Chainable<string> {
194
+ this.ensureSidebarExpanded()
195
+ return cy.get(this.selectors.trigger)
196
+ .find(this.selectors.teamName)
197
+ .invoke('text')
198
+ }
199
+
200
+ /**
201
+ * Validate current team name in trigger button
202
+ */
203
+ validateCurrentTeamName(teamName: string): this {
204
+ this.ensureSidebarExpanded()
205
+ cy.get(this.selectors.trigger)
206
+ .find(this.selectors.teamName)
207
+ .should('contain', teamName)
208
+ return this
209
+ }
210
+
211
+ // ============================================
212
+ // Team Selection Methods
213
+ // ============================================
214
+
215
+ /**
216
+ * Select a specific team by slug (opens dropdown, clicks team)
217
+ */
218
+ selectTeam(teamSlug: string): this {
219
+ this.open()
220
+ cy.get(this.selectors.teamOptionBySlug(teamSlug)).click()
221
+ return this
222
+ }
223
+
224
+ /**
225
+ * Select a team and wait for switch to complete
226
+ */
227
+ switchToTeam(teamSlug: string): this {
228
+ this.selectTeam(teamSlug)
229
+ this.waitForSwitchComplete()
230
+ return this
231
+ }
232
+
233
+ /**
234
+ * Wait for the switch modal to appear and complete
235
+ */
236
+ waitForSwitchComplete(): this {
237
+ cy.get(this.selectors.switchModal, { timeout: 5000 }).should('be.visible')
238
+ cy.get(this.selectors.switchModal, { timeout: 10000 }).should('not.exist')
239
+ cy.url().should('include', '/dashboard')
240
+ return this
241
+ }
242
+
243
+ /**
244
+ * Validate the switch modal is visible
245
+ */
246
+ validateSwitchModalVisible(): this {
247
+ cy.get(this.selectors.switchModal).should('be.visible')
248
+ return this
249
+ }
250
+
251
+ // ============================================
252
+ // Team Validation Methods
253
+ // ============================================
254
+
255
+ /**
256
+ * Get the count of teams in the dropdown
257
+ */
258
+ getTeamCount(): Cypress.Chainable<number> {
259
+ this.open()
260
+ return cy.get(this.selectors.teamOption).its('length')
261
+ }
262
+
263
+ /**
264
+ * Validate number of teams in dropdown
265
+ */
266
+ validateTeamCount(count: number): this {
267
+ this.open()
268
+ cy.get(this.selectors.teamOption).should('have.length', count)
269
+ return this
270
+ }
271
+
272
+ /**
273
+ * Validate team exists in the list
274
+ */
275
+ validateTeamInList(teamSlug: string): this {
276
+ this.open()
277
+ cy.get(this.selectors.teamOptionBySlug(teamSlug)).should('exist')
278
+ return this
279
+ }
280
+
281
+ /**
282
+ * Validate team is NOT in the list
283
+ */
284
+ validateTeamNotInList(teamSlug: string): this {
285
+ this.open()
286
+ cy.get(this.selectors.teamOptionBySlug(teamSlug)).should('not.exist')
287
+ return this
288
+ }
289
+
290
+ /**
291
+ * Validate a team option shows the checkmark (is active)
292
+ */
293
+ validateTeamHasCheckmark(teamSlug: string): this {
294
+ this.open()
295
+ cy.get(this.selectors.teamOptionBySlug(teamSlug))
296
+ .find(this.selectors.checkIcon)
297
+ .should('exist')
298
+ return this
299
+ }
300
+
301
+ /**
302
+ * Validate a team option does NOT show the checkmark
303
+ */
304
+ validateTeamNoCheckmark(teamSlug: string): this {
305
+ this.open()
306
+ cy.get(this.selectors.teamOptionBySlug(teamSlug))
307
+ .find(this.selectors.checkIcon)
308
+ .should('not.exist')
309
+ return this
310
+ }
311
+
312
+ /**
313
+ * Validate the role displayed for a team
314
+ */
315
+ validateRoleDisplayed(teamSlug: string, role: string): this {
316
+ this.open()
317
+ cy.get(this.selectors.teamOptionBySlug(teamSlug))
318
+ .find('.text-xs.text-muted-foreground')
319
+ .should('contain.text', role)
320
+ return this
321
+ }
322
+
323
+ /**
324
+ * Validate team has an avatar or initials displayed
325
+ */
326
+ validateTeamHasAvatar(teamSlug: string): this {
327
+ this.open()
328
+ cy.get(this.selectors.teamOptionBySlug(teamSlug))
329
+ .find(this.selectors.avatar)
330
+ .should('exist')
331
+ return this
332
+ }
333
+
334
+ /**
335
+ * Get all team names from the dropdown
336
+ */
337
+ getTeamNames(): Cypress.Chainable<string[]> {
338
+ this.open()
339
+ return cy.get(this.selectors.teamOption)
340
+ .find('.truncate')
341
+ .then($elements => {
342
+ return Cypress._.map($elements, el => el.innerText)
343
+ })
344
+ }
345
+
346
+ // ============================================
347
+ // Manage Teams Methods
348
+ // ============================================
349
+
350
+ /**
351
+ * Click Manage Teams link
352
+ */
353
+ clickManageTeams(): this {
354
+ this.open()
355
+ cy.get(this.selectors.manageTeamsLink).click()
356
+ return this
357
+ }
358
+
359
+ /**
360
+ * Validate Manage Teams link is visible
361
+ */
362
+ validateManageTeamsVisible(): this {
363
+ this.open()
364
+ cy.get(this.selectors.manageTeamsLink).should('be.visible')
365
+ return this
366
+ }
367
+
368
+ /**
369
+ * Navigate to Manage Teams and validate URL
370
+ */
371
+ goToManageTeams(): this {
372
+ this.clickManageTeams()
373
+ cy.url().should('include', '/dashboard/settings/teams')
374
+ return this
375
+ }
376
+
377
+ // ============================================
378
+ // Mobile Methods
379
+ // ============================================
380
+
381
+ /**
382
+ * Open the mobile more sheet
383
+ */
384
+ openMobileMoreSheet(): this {
385
+ cy.get(this.selectors.mobileMoreButton).click()
386
+ cy.get(this.selectors.mobileMoreSheet).should('be.visible')
387
+ return this
388
+ }
389
+
390
+ /**
391
+ * Validate mobile more sheet is visible
392
+ */
393
+ validateMobileMoreSheetVisible(): this {
394
+ cy.get(this.selectors.mobileMoreSheet).should('be.visible')
395
+ return this
396
+ }
397
+
398
+ /**
399
+ * Validate team switcher is visible in mobile more sheet
400
+ */
401
+ validateMobileTeamSwitcherVisible(): this {
402
+ cy.get(this.selectors.mobileMoreSheet).within(() => {
403
+ cy.get(this.selectors.trigger).should('be.visible')
404
+ })
405
+ return this
406
+ }
407
+
408
+ /**
409
+ * Open team dropdown from mobile more sheet
410
+ */
411
+ openMobileTeamDropdown(): this {
412
+ cy.get(this.selectors.mobileMoreSheet).within(() => {
413
+ cy.get(this.selectors.trigger).click()
414
+ })
415
+ return this
416
+ }
417
+
418
+ /**
419
+ * Switch team from mobile view
420
+ */
421
+ switchToTeamMobile(teamSlug: string): this {
422
+ this.openMobileMoreSheet()
423
+ this.openMobileTeamDropdown()
424
+ cy.get(this.selectors.teamOptionBySlug(teamSlug)).click()
425
+ this.waitForSwitchComplete()
426
+ return this
427
+ }
428
+
429
+ // ============================================
430
+ // Permission Methods
431
+ // ============================================
432
+
433
+ /**
434
+ * Validate permission denied page is visible
435
+ */
436
+ validatePermissionDenied(): this {
437
+ cy.get(this.selectors.permissionDenied).should('be.visible')
438
+ return this
439
+ }
440
+
441
+ /**
442
+ * Validate permission denied page is NOT visible
443
+ */
444
+ validateNoPermissionDenied(): this {
445
+ cy.get(this.selectors.permissionDenied).should('not.exist')
446
+ return this
447
+ }
448
+ }
449
+
450
+ export default TeamSwitcherPOM
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Starter Theme - Components Index
3
+ *
4
+ * Export all POM components for the Starter theme.
5
+ */
6
+
7
+ // Generic POMs (entity-agnostic)
8
+ export { EntityList, type EntityConfig as EntityListConfig } from './EntityList'
9
+ export { EntityForm, type EntityConfig as EntityFormConfig } from './EntityForm'
10
+
11
+ // Feature Component POMs (multi-tenant, auth)
12
+ export { TeamSwitcherPOM } from './TeamSwitcherPOM'
13
+ export { DevKeyringPOM } from './DevKeyringPOM'