@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,576 @@
1
+ /**
2
+ * BlockEditorBasePOM - Base class for Page and Post builder POMs
3
+ *
4
+ * Provides common functionality for the block-based editor:
5
+ * - Editor navigation and setup
6
+ * - Title and slug management
7
+ * - Block picker interactions
8
+ * - Block manipulation (add, remove, reorder)
9
+ * - Settings panel interactions
10
+ * - Status management
11
+ * - Save operations
12
+ *
13
+ * @example
14
+ * class PageBuilderPOM extends BlockEditorBasePOM {
15
+ * protected entitySlug = 'pages'
16
+ *
17
+ * publishPage() {
18
+ * this.setStatus('published')
19
+ * this.save()
20
+ * return this
21
+ * }
22
+ * }
23
+ */
24
+
25
+ import { BasePOM } from './BasePOM'
26
+ import { cySelector } from '../selectors'
27
+ import { ApiInterceptor } from '../helpers/ApiInterceptor'
28
+
29
+ export abstract class BlockEditorBasePOM extends BasePOM {
30
+ /**
31
+ * Entity slug - must be defined by subclass
32
+ */
33
+ protected abstract entitySlug: string
34
+
35
+ protected _api: ApiInterceptor | null = null
36
+
37
+ // ============================================
38
+ // API INTERCEPTOR
39
+ // ============================================
40
+
41
+ get api(): ApiInterceptor {
42
+ if (!this._api) {
43
+ this._api = new ApiInterceptor(this.entitySlug)
44
+ }
45
+ return this._api
46
+ }
47
+
48
+ setupApiIntercepts() {
49
+ this.api.setupCrudIntercepts()
50
+ return this
51
+ }
52
+
53
+ // ============================================
54
+ // SELECTORS (from centralized selectors.ts)
55
+ // ============================================
56
+
57
+ get editorSelectors() {
58
+ return {
59
+ // Editor main
60
+ container: cySelector('blockEditor.container'),
61
+ titleInput: cySelector('blockEditor.titleInput'),
62
+ slugInput: cySelector('blockEditor.slugInput'),
63
+ saveButton: cySelector('blockEditor.saveButton'),
64
+ statusBadge: cySelector('blockEditor.statusBadge'),
65
+ leftSidebarToggle: cySelector('blockEditor.leftSidebarToggle'),
66
+ viewModeToggle: cySelector('blockEditor.viewModeToggle'),
67
+
68
+ // Block Picker
69
+ blockPicker: cySelector('blockEditor.blockPicker.container'),
70
+ blockSearch: cySelector('blockEditor.blockPicker.searchInput'),
71
+ categoryAll: cySelector('blockEditor.blockPicker.categoryAll'),
72
+ category: (category: string) =>
73
+ cySelector('blockEditor.blockPicker.category', { category }),
74
+ blockItem: (slug: string) => cySelector('blockEditor.blockPicker.blockItem', { slug }),
75
+ addBlock: (slug: string) => cySelector('blockEditor.blockPicker.addBlock', { slug }),
76
+
77
+ // Block Canvas
78
+ blockCanvas: cySelector('blockEditor.blockCanvas.container'),
79
+ blockCanvasEmpty: cySelector('blockEditor.blockCanvas.empty'),
80
+
81
+ // Preview Canvas
82
+ previewCanvas: cySelector('blockEditor.previewCanvas.container'),
83
+ previewCanvasEmpty: cySelector('blockEditor.previewCanvas.empty'),
84
+ previewBlock: (id: string) => cySelector('blockEditor.previewCanvas.block', { id }),
85
+ previewMoveUp: (id: string) => cySelector('blockEditor.previewCanvas.moveUp', { id }),
86
+ previewMoveDown: (id: string) => cySelector('blockEditor.previewCanvas.moveDown', { id }),
87
+
88
+ // Sortable Block
89
+ sortableBlock: (id: string) => cySelector('blockEditor.sortableBlock.container', { id }),
90
+ dragHandle: (id: string) => cySelector('blockEditor.sortableBlock.dragHandle', { id }),
91
+ duplicateBlock: (id: string) => cySelector('blockEditor.sortableBlock.duplicate', { id }),
92
+ removeBlock: (id: string) => cySelector('blockEditor.sortableBlock.remove', { id }),
93
+ blockError: (id: string) => cySelector('blockEditor.sortableBlock.error', { id }),
94
+
95
+ // Settings Panel
96
+ settingsPanel: cySelector('blockEditor.settingsPanel.container'),
97
+ settingsPanelEmpty: cySelector('blockEditor.settingsPanel.empty'),
98
+ settingsPanelError: cySelector('blockEditor.settingsPanel.error'),
99
+ resetProps: cySelector('blockEditor.settingsPanel.resetProps'),
100
+ removeBlockSettings: cySelector('blockEditor.settingsPanel.removeBlock'),
101
+ tabContent: cySelector('blockEditor.settingsPanel.tabContent'),
102
+ tabDesign: cySelector('blockEditor.settingsPanel.tabDesign'),
103
+ tabAdvanced: cySelector('blockEditor.settingsPanel.tabAdvanced'),
104
+
105
+ // Page Settings
106
+ pageSettings: cySelector('blockEditor.pageSettings.container'),
107
+ seoTrigger: cySelector('blockEditor.pageSettings.seoTrigger'),
108
+ metaTitle: cySelector('blockEditor.pageSettings.metaTitle'),
109
+ metaDescription: cySelector('blockEditor.pageSettings.metaDescription'),
110
+ metaKeywords: cySelector('blockEditor.pageSettings.metaKeywords'),
111
+ ogImage: cySelector('blockEditor.pageSettings.ogImage'),
112
+ customFieldsTrigger: cySelector('blockEditor.pageSettings.customFieldsTrigger'),
113
+ customFieldKey: (index: number) =>
114
+ cySelector('blockEditor.pageSettings.customFieldKey', { index }),
115
+ customFieldValue: (index: number) =>
116
+ cySelector('blockEditor.pageSettings.customFieldValue', { index }),
117
+ customFieldRemove: (index: number) =>
118
+ cySelector('blockEditor.pageSettings.customFieldRemove', { index }),
119
+ addCustomField: cySelector('blockEditor.pageSettings.addCustomField'),
120
+
121
+ // Status Selector
122
+ statusSelector: cySelector('blockEditor.statusSelector.trigger'),
123
+ statusOption: (value: string) =>
124
+ cySelector('blockEditor.statusSelector.option', { value }),
125
+
126
+ // Dynamic Form
127
+ dynamicForm: cySelector('blockEditor.dynamicForm.container'),
128
+ dynamicField: (name: string) =>
129
+ cySelector('blockEditor.dynamicForm.field', { name }),
130
+ fieldGroup: (id: string) =>
131
+ cySelector('blockEditor.dynamicForm.fieldGroup', { id }),
132
+ arrayGroup: (name: string) =>
133
+ cySelector('blockEditor.dynamicForm.arrayGroup', { name }),
134
+
135
+ // Array Field
136
+ arrayFieldContainer: (name: string) =>
137
+ cySelector('blockEditor.arrayField.container', { name }),
138
+ arrayFieldItem: (name: string, index: number, field: string) =>
139
+ cySelector('blockEditor.arrayField.item', { name, index, field }),
140
+ arrayFieldMoveUp: (name: string, index: number) =>
141
+ cySelector('blockEditor.arrayField.moveUp', { name, index }),
142
+ arrayFieldMoveDown: (name: string, index: number) =>
143
+ cySelector('blockEditor.arrayField.moveDown', { name, index }),
144
+ arrayFieldRemove: (name: string, index: number) =>
145
+ cySelector('blockEditor.arrayField.remove', { name, index }),
146
+ arrayFieldAdd: (name: string) =>
147
+ cySelector('blockEditor.arrayField.add', { name }),
148
+
149
+ // Entity Fields Sidebar
150
+ entityFieldsSidebar: cySelector('blockEditor.entityFieldsSidebar.container'),
151
+ entityField: (name: string) =>
152
+ cySelector('blockEditor.entityFieldsSidebar.field', { name }),
153
+ entityCategory: (slug: string) =>
154
+ cySelector('blockEditor.entityFieldsSidebar.category', { slug })
155
+ }
156
+ }
157
+
158
+ // ============================================
159
+ // NAVIGATION
160
+ // ============================================
161
+
162
+ visitList() {
163
+ cy.visit(`/dashboard/${this.entitySlug}`)
164
+ return this
165
+ }
166
+
167
+ visitCreate() {
168
+ cy.visit(`/dashboard/${this.entitySlug}/create`)
169
+ return this
170
+ }
171
+
172
+ visitEdit(id: string) {
173
+ cy.visit(`/dashboard/${this.entitySlug}/${id}/edit`)
174
+ return this
175
+ }
176
+
177
+ // ============================================
178
+ // WAITS
179
+ // ============================================
180
+
181
+ waitForEditor() {
182
+ cy.get(this.editorSelectors.container, { timeout: 15000 }).should('be.visible')
183
+ return this
184
+ }
185
+
186
+ waitForSave() {
187
+ this.api.waitForUpdate()
188
+ return this
189
+ }
190
+
191
+ // ============================================
192
+ // EDITOR ACTIONS
193
+ // ============================================
194
+
195
+ /**
196
+ * Set the page/post title
197
+ */
198
+ setTitle(title: string) {
199
+ cy.get(this.editorSelectors.titleInput).clear().type(title)
200
+ return this
201
+ }
202
+
203
+ /**
204
+ * Set the page/post slug
205
+ */
206
+ setSlug(slug: string) {
207
+ cy.get(this.editorSelectors.slugInput).clear().type(slug)
208
+ return this
209
+ }
210
+
211
+ /**
212
+ * Save the page/post
213
+ */
214
+ save() {
215
+ cy.get(this.editorSelectors.saveButton).click()
216
+ return this
217
+ }
218
+
219
+ /**
220
+ * Save with API wait
221
+ */
222
+ saveWithWait() {
223
+ this.setupApiIntercepts()
224
+ this.save()
225
+ this.api.waitForUpdate()
226
+ return this
227
+ }
228
+
229
+ /**
230
+ * Set the status using the status selector
231
+ */
232
+ setStatus(status: string) {
233
+ cy.get(this.editorSelectors.statusSelector).click()
234
+ cy.get(this.editorSelectors.statusOption(status)).click()
235
+ return this
236
+ }
237
+
238
+ /**
239
+ * Toggle left sidebar
240
+ */
241
+ toggleLeftSidebar() {
242
+ cy.get(this.editorSelectors.leftSidebarToggle).click()
243
+ return this
244
+ }
245
+
246
+ /**
247
+ * Toggle view mode (edit/preview)
248
+ */
249
+ toggleViewMode() {
250
+ cy.get(this.editorSelectors.viewModeToggle).click()
251
+ return this
252
+ }
253
+
254
+ // ============================================
255
+ // BLOCK PICKER ACTIONS
256
+ // ============================================
257
+
258
+ /**
259
+ * Search for a block in the picker
260
+ */
261
+ searchBlock(term: string) {
262
+ cy.get(this.editorSelectors.blockSearch).clear().type(term)
263
+ return this
264
+ }
265
+
266
+ /**
267
+ * Clear block search
268
+ */
269
+ clearBlockSearch() {
270
+ cy.get(this.editorSelectors.blockSearch).clear()
271
+ return this
272
+ }
273
+
274
+ /**
275
+ * Select a block category
276
+ */
277
+ selectCategory(category: string) {
278
+ cy.get(this.editorSelectors.category(category)).click()
279
+ return this
280
+ }
281
+
282
+ /**
283
+ * Select "All" category
284
+ */
285
+ selectAllCategories() {
286
+ cy.get(this.editorSelectors.categoryAll).click()
287
+ return this
288
+ }
289
+
290
+ /**
291
+ * Add a block by clicking its add button
292
+ */
293
+ addBlock(blockSlug: string) {
294
+ cy.get(this.editorSelectors.addBlock(blockSlug)).click()
295
+ return this
296
+ }
297
+
298
+ /**
299
+ * Click on a block item in the picker
300
+ */
301
+ clickBlockItem(blockSlug: string) {
302
+ cy.get(this.editorSelectors.blockItem(blockSlug)).click()
303
+ return this
304
+ }
305
+
306
+ // ============================================
307
+ // BLOCK MANIPULATION
308
+ // ============================================
309
+
310
+ /**
311
+ * Remove a block from the canvas
312
+ */
313
+ removeBlock(blockId: string) {
314
+ cy.get(this.editorSelectors.removeBlock(blockId)).click()
315
+ return this
316
+ }
317
+
318
+ /**
319
+ * Duplicate a block
320
+ */
321
+ duplicateBlock(blockId: string) {
322
+ cy.get(this.editorSelectors.duplicateBlock(blockId)).click()
323
+ return this
324
+ }
325
+
326
+ /**
327
+ * Click on a sortable block to select it
328
+ */
329
+ selectBlock(blockId: string) {
330
+ cy.get(this.editorSelectors.sortableBlock(blockId)).click()
331
+ return this
332
+ }
333
+
334
+ /**
335
+ * Move block up in preview
336
+ */
337
+ moveBlockUp(blockId: string) {
338
+ cy.get(this.editorSelectors.previewMoveUp(blockId)).click()
339
+ return this
340
+ }
341
+
342
+ /**
343
+ * Move block down in preview
344
+ */
345
+ moveBlockDown(blockId: string) {
346
+ cy.get(this.editorSelectors.previewMoveDown(blockId)).click()
347
+ return this
348
+ }
349
+
350
+ // ============================================
351
+ // SETTINGS PANEL ACTIONS
352
+ // ============================================
353
+
354
+ /**
355
+ * Switch to Content tab in settings panel
356
+ */
357
+ openContentTab() {
358
+ cy.get(this.editorSelectors.tabContent).click()
359
+ return this
360
+ }
361
+
362
+ /**
363
+ * Switch to Design tab in settings panel
364
+ */
365
+ openDesignTab() {
366
+ cy.get(this.editorSelectors.tabDesign).click()
367
+ return this
368
+ }
369
+
370
+ /**
371
+ * Switch to Advanced tab in settings panel
372
+ */
373
+ openAdvancedTab() {
374
+ cy.get(this.editorSelectors.tabAdvanced).click()
375
+ return this
376
+ }
377
+
378
+ /**
379
+ * Reset block props to defaults
380
+ */
381
+ resetBlockProps() {
382
+ cy.get(this.editorSelectors.resetProps).click()
383
+ return this
384
+ }
385
+
386
+ /**
387
+ * Remove block from settings panel
388
+ */
389
+ removeBlockFromSettings() {
390
+ cy.get(this.editorSelectors.removeBlockSettings).click()
391
+ return this
392
+ }
393
+
394
+ /**
395
+ * Fill a dynamic form field
396
+ */
397
+ fillDynamicField(name: string, value: string) {
398
+ cy.get(this.editorSelectors.dynamicField(name)).find('input, textarea').clear().type(value)
399
+ return this
400
+ }
401
+
402
+ // ============================================
403
+ // SEO/PAGE SETTINGS
404
+ // ============================================
405
+
406
+ /**
407
+ * Open SEO settings section
408
+ */
409
+ openSeoSettings() {
410
+ cy.get(this.editorSelectors.seoTrigger).click()
411
+ return this
412
+ }
413
+
414
+ /**
415
+ * Set meta title
416
+ */
417
+ setMetaTitle(title: string) {
418
+ cy.get(this.editorSelectors.metaTitle).clear().type(title)
419
+ return this
420
+ }
421
+
422
+ /**
423
+ * Set meta description
424
+ */
425
+ setMetaDescription(description: string) {
426
+ cy.get(this.editorSelectors.metaDescription).clear().type(description)
427
+ return this
428
+ }
429
+
430
+ /**
431
+ * Set meta keywords
432
+ */
433
+ setMetaKeywords(keywords: string) {
434
+ cy.get(this.editorSelectors.metaKeywords).clear().type(keywords)
435
+ return this
436
+ }
437
+
438
+ /**
439
+ * Open custom fields section
440
+ */
441
+ openCustomFields() {
442
+ cy.get(this.editorSelectors.customFieldsTrigger).click()
443
+ return this
444
+ }
445
+
446
+ /**
447
+ * Add a custom field
448
+ */
449
+ addCustomField() {
450
+ cy.get(this.editorSelectors.addCustomField).click()
451
+ return this
452
+ }
453
+
454
+ /**
455
+ * Fill a custom field
456
+ */
457
+ fillCustomField(index: number, key: string, value: string) {
458
+ cy.get(this.editorSelectors.customFieldKey(index)).clear().type(key)
459
+ cy.get(this.editorSelectors.customFieldValue(index)).clear().type(value)
460
+ return this
461
+ }
462
+
463
+ /**
464
+ * Remove a custom field
465
+ */
466
+ removeCustomField(index: number) {
467
+ cy.get(this.editorSelectors.customFieldRemove(index)).click()
468
+ return this
469
+ }
470
+
471
+ // ============================================
472
+ // ARRAY FIELDS
473
+ // ============================================
474
+
475
+ /**
476
+ * Add an item to an array field
477
+ */
478
+ addArrayItem(name: string) {
479
+ cy.get(this.editorSelectors.arrayFieldAdd(name)).click()
480
+ return this
481
+ }
482
+
483
+ /**
484
+ * Remove an item from an array field
485
+ */
486
+ removeArrayItem(name: string, index: number) {
487
+ cy.get(this.editorSelectors.arrayFieldRemove(name, index)).click()
488
+ return this
489
+ }
490
+
491
+ /**
492
+ * Fill an array field item
493
+ */
494
+ fillArrayItem(name: string, index: number, field: string, value: string) {
495
+ cy.get(this.editorSelectors.arrayFieldItem(name, index, field)).clear().type(value)
496
+ return this
497
+ }
498
+
499
+ /**
500
+ * Move array item up
501
+ */
502
+ moveArrayItemUp(name: string, index: number) {
503
+ cy.get(this.editorSelectors.arrayFieldMoveUp(name, index)).click()
504
+ return this
505
+ }
506
+
507
+ /**
508
+ * Move array item down
509
+ */
510
+ moveArrayItemDown(name: string, index: number) {
511
+ cy.get(this.editorSelectors.arrayFieldMoveDown(name, index)).click()
512
+ return this
513
+ }
514
+
515
+ // ============================================
516
+ // ASSERTIONS
517
+ // ============================================
518
+
519
+ /**
520
+ * Assert editor is visible
521
+ */
522
+ assertEditorVisible() {
523
+ cy.get(this.editorSelectors.container).should('be.visible')
524
+ return this
525
+ }
526
+
527
+ /**
528
+ * Assert canvas is empty
529
+ */
530
+ assertCanvasEmpty() {
531
+ cy.get(this.editorSelectors.blockCanvasEmpty).should('be.visible')
532
+ return this
533
+ }
534
+
535
+ /**
536
+ * Assert block exists in canvas
537
+ */
538
+ assertBlockExists(blockId: string) {
539
+ cy.get(this.editorSelectors.sortableBlock(blockId)).should('exist')
540
+ return this
541
+ }
542
+
543
+ /**
544
+ * Assert block does not exist
545
+ */
546
+ assertBlockNotExists(blockId: string) {
547
+ cy.get(this.editorSelectors.sortableBlock(blockId)).should('not.exist')
548
+ return this
549
+ }
550
+
551
+ /**
552
+ * Assert status badge shows specific status
553
+ */
554
+ assertStatus(status: string) {
555
+ cy.get(this.editorSelectors.statusBadge).should('contain.text', status)
556
+ return this
557
+ }
558
+
559
+ /**
560
+ * Assert settings panel is visible
561
+ */
562
+ assertSettingsPanelVisible() {
563
+ cy.get(this.editorSelectors.settingsPanel).should('be.visible')
564
+ return this
565
+ }
566
+
567
+ /**
568
+ * Assert settings panel shows empty state
569
+ */
570
+ assertSettingsPanelEmpty() {
571
+ cy.get(this.editorSelectors.settingsPanelEmpty).should('be.visible')
572
+ return this
573
+ }
574
+ }
575
+
576
+ export default BlockEditorBasePOM
@@ -4,9 +4,11 @@
4
4
  * Base classes for building Page Object Models:
5
5
  * - BasePOM: Utility methods for all POMs
6
6
  * - DashboardEntityPOM: Base for entity CRUD POMs
7
+ * - BlockEditorBasePOM: Base for block editor POMs
7
8
  * - AuthPOM: Authentication pages POM
8
9
  */
9
10
 
10
11
  export { BasePOM } from './BasePOM'
11
12
  export { DashboardEntityPOM, type EntityConfig } from './DashboardEntityPOM'
13
+ export { BlockEditorBasePOM } from './BlockEditorBasePOM'
12
14
  export { AuthPOM, type SignupData } from './AuthPOM'
@@ -22,7 +22,7 @@
22
22
  * })
23
23
  */
24
24
 
25
- import { DashboardEntityPOM } from '../../src/core/DashboardEntityPOM'
25
+ import { DashboardEntityPOM } from '../core/DashboardEntityPOM'
26
26
  import entitiesConfig from '../../fixtures/entities.json'
27
27
 
28
28
  export interface TaskFormData {
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Starter Theme - Entity POM exports
3
+ *
4
+ * Page Object Models for specific entities:
5
+ * - TasksPOM: Tasks CRUD operations
6
+ *
7
+ * Add more entity POMs as you create new entities.
8
+ */
9
+
10
+ export { TasksPOM, type TaskFormData } from './TasksPOM'