@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.
- package/package.json +1 -1
- package/tests/cypress/e2e/_devtools/access.bdd.md +262 -0
- package/tests/cypress/e2e/_devtools/access.cy.ts +171 -0
- package/tests/cypress/e2e/_devtools/navigation.bdd.md +261 -0
- package/tests/cypress/e2e/_devtools/navigation.cy.ts +157 -0
- package/tests/cypress/e2e/_devtools/pages.bdd.md +303 -0
- package/tests/cypress/e2e/_devtools/pages.cy.ts +184 -0
- package/tests/cypress/e2e/_docs/README.md +215 -0
- package/tests/cypress/e2e/_docs/tutorials/sector7-superadmin-teams.narration.json +155 -0
- package/tests/cypress/e2e/_docs/tutorials/sector7-superadmin.cy.ts +390 -0
- package/tests/cypress/e2e/_docs/tutorials/teams-system.doc.cy.ts +349 -0
- package/tests/cypress/e2e/_docs/tutorials/teams-system.narration.json +165 -0
- package/tests/cypress/e2e/_selectors/auth.cy.ts +306 -0
- package/tests/cypress/e2e/_selectors/billing.cy.ts +89 -0
- package/tests/cypress/e2e/_selectors/dashboard-mobile.cy.ts +113 -0
- package/tests/cypress/e2e/_selectors/dashboard-navigation.cy.ts +89 -0
- package/tests/cypress/e2e/_selectors/dashboard-sidebar.cy.ts +60 -0
- package/tests/cypress/e2e/_selectors/dashboard-topnav.cy.ts +146 -0
- package/tests/cypress/e2e/_selectors/devtools.cy.ts +210 -0
- package/tests/cypress/e2e/_selectors/global-search.cy.ts +88 -0
- package/tests/cypress/e2e/_selectors/pages-editor.cy.ts +179 -0
- package/tests/cypress/e2e/_selectors/posts-editor.cy.ts +282 -0
- package/tests/cypress/e2e/_selectors/public.cy.ts +112 -0
- package/tests/cypress/e2e/_selectors/settings-api-keys.cy.ts +228 -0
- package/tests/cypress/e2e/_selectors/settings-billing.cy.ts +105 -0
- package/tests/cypress/e2e/_selectors/settings-layout.cy.ts +119 -0
- package/tests/cypress/e2e/_selectors/settings-password.cy.ts +71 -0
- package/tests/cypress/e2e/_selectors/settings-profile.cy.ts +82 -0
- package/tests/cypress/e2e/_selectors/settings-teams.cy.ts +68 -0
- package/tests/cypress/e2e/_selectors/superadmin.cy.ts +185 -0
- package/tests/cypress/e2e/_selectors/tasks.cy.ts +242 -0
- package/tests/cypress/e2e/_selectors/taxonomies.cy.ts +126 -0
- package/tests/cypress/e2e/_selectors/teams.cy.ts +142 -0
- package/tests/cypress/e2e/_superadmin/all-teams.bdd.md +261 -0
- package/tests/cypress/e2e/_superadmin/all-teams.cy.ts +177 -0
- package/tests/cypress/e2e/_superadmin/all-users.bdd.md +406 -0
- package/tests/cypress/e2e/_superadmin/all-users.cy.ts +294 -0
- package/tests/cypress/e2e/_superadmin/dashboard.bdd.md +235 -0
- package/tests/cypress/e2e/_superadmin/dashboard.cy.ts +149 -0
- package/tests/cypress/e2e/_superadmin/subscriptions-overview.bdd.md +290 -0
- package/tests/cypress/e2e/_superadmin/subscriptions-overview.cy.ts +194 -0
- package/tests/cypress/e2e/ai/ai-usage.cy.ts +209 -0
- package/tests/cypress/e2e/ai/chat-api.cy.ts +107 -0
- package/tests/cypress/e2e/ai/guardrails.cy.ts +332 -0
- package/tests/cypress/e2e/api/billing/BillingAPIController.js +319 -0
- package/tests/cypress/e2e/api/billing/check-action.cy.ts +326 -0
- package/tests/cypress/e2e/api/billing/checkout.cy.ts +358 -0
- package/tests/cypress/e2e/api/billing/lifecycle.cy.ts +423 -0
- package/tests/cypress/e2e/api/billing/plans/README.md +345 -0
- package/tests/cypress/e2e/api/billing/plans/business.cy.ts +412 -0
- package/tests/cypress/e2e/api/billing/plans/downgrade.cy.ts +510 -0
- package/tests/cypress/e2e/api/billing/plans/fixtures/billing-plans.json +163 -0
- package/tests/cypress/e2e/api/billing/plans/free.cy.ts +500 -0
- package/tests/cypress/e2e/api/billing/plans/pro.cy.ts +497 -0
- package/tests/cypress/e2e/api/billing/plans/starter.cy.ts +342 -0
- package/tests/cypress/e2e/api/billing/portal.cy.ts +313 -0
- package/tests/cypress/e2e/api/devtools/registries.bdd.md +300 -0
- package/tests/cypress/e2e/api/devtools/registries.cy.ts +368 -0
- package/tests/cypress/e2e/api/entities/blocks-scope.cy.ts +396 -0
- package/tests/cypress/e2e/api/entities/customers-crud.cy.ts +648 -0
- package/tests/cypress/e2e/api/entities/customers-metas.cy.ts +839 -0
- package/tests/cypress/e2e/api/entities/pages-crud.cy.ts +425 -0
- package/tests/cypress/e2e/api/entities/pages-status.cy.ts +335 -0
- package/tests/cypress/e2e/api/entities/post-categories-crud.cy.ts +610 -0
- package/tests/cypress/e2e/api/entities/posts-crud.cy.ts +709 -0
- package/tests/cypress/e2e/api/entities/posts-status.cy.ts +396 -0
- package/tests/cypress/e2e/api/entities/tasks-crud.cy.ts +602 -0
- package/tests/cypress/e2e/api/entities/tasks-metas.cy.ts +878 -0
- package/tests/cypress/e2e/api/entities/users-crud.cy.ts +469 -0
- package/tests/cypress/e2e/api/entities/users-metas.cy.ts +913 -0
- package/tests/cypress/e2e/api/entities/users-security.cy.ts +375 -0
- package/tests/cypress/e2e/api/scheduled-actions/cron-endpoint.bdd.md +375 -0
- package/tests/cypress/e2e/api/scheduled-actions/cron-endpoint.cy.ts +346 -0
- package/tests/cypress/e2e/api/scheduled-actions/devtools-endpoint.bdd.md +451 -0
- package/tests/cypress/e2e/api/scheduled-actions/devtools-endpoint.cy.ts +447 -0
- package/tests/cypress/e2e/api/scheduled-actions/scheduling.bdd.md +649 -0
- package/tests/cypress/e2e/api/scheduled-actions/scheduling.cy.ts +333 -0
- package/tests/cypress/e2e/api/settings/api-keys.crud.cy.ts +923 -0
- package/tests/cypress/e2e/uat/auth/app-roles/developer-login.bdd.md +231 -0
- package/tests/cypress/e2e/uat/auth/app-roles/developer-login.cy.ts +144 -0
- package/tests/cypress/e2e/uat/auth/app-roles/superadmin-login.bdd.md +118 -0
- package/tests/cypress/e2e/uat/auth/app-roles/superadmin-login.cy.ts +84 -0
- package/tests/cypress/e2e/uat/auth/custom-roles/editor-login.bdd.md +288 -0
- package/tests/cypress/e2e/uat/auth/custom-roles/editor-login.cy.ts +188 -0
- package/tests/cypress/e2e/uat/auth/login-logout.bdd.md +160 -0
- package/tests/cypress/e2e/uat/auth/login-logout.cy.ts +116 -0
- package/tests/cypress/e2e/uat/auth/password-reset.bdd.md +289 -0
- package/tests/cypress/e2e/uat/auth/password-reset.cy.ts +200 -0
- package/tests/cypress/e2e/uat/auth/team-roles/admin-login.bdd.md +225 -0
- package/tests/cypress/e2e/uat/auth/team-roles/admin-login.cy.ts +148 -0
- package/tests/cypress/e2e/uat/auth/team-roles/member-login.bdd.md +251 -0
- package/tests/cypress/e2e/uat/auth/team-roles/member-login.cy.ts +163 -0
- package/tests/cypress/e2e/uat/auth/team-roles/owner-login.bdd.md +231 -0
- package/tests/cypress/e2e/uat/auth/team-roles/owner-login.cy.ts +141 -0
- package/tests/cypress/e2e/uat/billing/extended.bdd.md +273 -0
- package/tests/cypress/e2e/uat/billing/extended.cy.ts +209 -0
- package/tests/cypress/e2e/uat/billing/feature-gates.bdd.md +407 -0
- package/tests/cypress/e2e/uat/billing/feature-gates.cy.ts +307 -0
- package/tests/cypress/e2e/uat/billing/page.bdd.md +329 -0
- package/tests/cypress/e2e/uat/billing/page.cy.ts +250 -0
- package/tests/cypress/e2e/uat/billing/status.bdd.md +190 -0
- package/tests/cypress/e2e/uat/billing/status.cy.ts +145 -0
- package/tests/cypress/e2e/uat/billing/team-switch.bdd.md +156 -0
- package/tests/cypress/e2e/uat/billing/team-switch.cy.ts +122 -0
- package/tests/cypress/e2e/uat/billing/usage.bdd.md +218 -0
- package/tests/cypress/e2e/uat/billing/usage.cy.ts +176 -0
- package/tests/cypress/e2e/uat/blocks/hero.bdd.md +124 -0
- package/tests/cypress/e2e/uat/blocks/hero.cy.ts +56 -0
- package/tests/cypress/e2e/uat/devtools/api-tester.cy.ts +390 -0
- package/tests/cypress/e2e/uat/entities/customers/member.bdd.md +275 -0
- package/tests/cypress/e2e/uat/entities/customers/member.cy.ts +122 -0
- package/tests/cypress/e2e/uat/entities/customers/owner.bdd.md +243 -0
- package/tests/cypress/e2e/uat/entities/customers/owner.cy.ts +165 -0
- package/tests/cypress/e2e/uat/entities/pages/block-crud.bdd.md +476 -0
- package/tests/cypress/e2e/uat/entities/pages/block-crud.cy.ts +486 -0
- package/tests/cypress/e2e/uat/entities/pages/block-editor.bdd.md +460 -0
- package/tests/cypress/e2e/uat/entities/pages/block-editor.cy.ts +301 -0
- package/tests/cypress/e2e/uat/entities/pages/list.bdd.md +432 -0
- package/tests/cypress/e2e/uat/entities/pages/list.cy.ts +273 -0
- package/tests/cypress/e2e/uat/entities/pages/public-rendering.bdd.md +696 -0
- package/tests/cypress/e2e/uat/entities/pages/public-rendering.cy.ts +340 -0
- package/tests/cypress/e2e/uat/entities/posts/categories-api-aware.bdd.md +161 -0
- package/tests/cypress/e2e/uat/entities/posts/categories-api-aware.cy.ts +104 -0
- package/tests/cypress/e2e/uat/entities/posts/categories.bdd.md +375 -0
- package/tests/cypress/e2e/uat/entities/posts/categories.cy.ts +241 -0
- package/tests/cypress/e2e/uat/entities/posts/editor.bdd.md +429 -0
- package/tests/cypress/e2e/uat/entities/posts/editor.cy.ts +257 -0
- package/tests/cypress/e2e/uat/entities/posts/list.bdd.md +340 -0
- package/tests/cypress/e2e/uat/entities/posts/list.cy.ts +177 -0
- package/tests/cypress/e2e/uat/entities/posts/public.bdd.md +614 -0
- package/tests/cypress/e2e/uat/entities/posts/public.cy.ts +249 -0
- package/tests/cypress/e2e/uat/entities/tasks/member.bdd.md +222 -0
- package/tests/cypress/e2e/uat/entities/tasks/member.cy.ts +165 -0
- package/tests/cypress/e2e/uat/entities/tasks/owner.bdd.md +419 -0
- package/tests/cypress/e2e/uat/entities/tasks/owner.cy.ts +191 -0
- package/tests/cypress/e2e/uat/roles/editor-role.bdd.md +552 -0
- package/tests/cypress/e2e/uat/roles/editor-role.cy.ts +210 -0
- package/tests/cypress/e2e/uat/roles/member-restrictions.bdd.md +450 -0
- package/tests/cypress/e2e/uat/roles/member-restrictions.cy.ts +189 -0
- package/tests/cypress/e2e/uat/roles/owner-full-crud.bdd.md +530 -0
- package/tests/cypress/e2e/uat/roles/owner-full-crud.cy.ts +247 -0
- package/tests/cypress/e2e/uat/scheduled-actions/devtools-ui.bdd.md +736 -0
- package/tests/cypress/e2e/uat/scheduled-actions/devtools-ui.cy.ts +740 -0
- package/tests/cypress/e2e/uat/teams/roles-matrix.bdd.md +553 -0
- package/tests/cypress/e2e/uat/teams/roles-matrix.cy.ts +185 -0
- package/tests/cypress/e2e/uat/teams/switcher.bdd.md +1151 -0
- package/tests/cypress/e2e/uat/teams/switcher.cy.ts +497 -0
- package/tests/cypress/e2e/uat/teams/team-switcher.md +198 -0
- package/tests/cypress/fixtures/blocks.json +218 -0
- package/tests/cypress/fixtures/entities.json +78 -0
- package/tests/cypress/fixtures/page-builder.json +21 -0
- package/tests/cypress/src/components/CategoriesPOM.ts +382 -0
- package/tests/cypress/src/components/CustomersPOM.ts +439 -0
- package/tests/cypress/src/components/DevKeyringPOM.ts +160 -0
- package/tests/cypress/src/components/EntityForm.ts +375 -0
- package/tests/cypress/src/components/EntityList.ts +389 -0
- package/tests/cypress/src/components/PageBuilderPOM.ts +710 -0
- package/tests/cypress/src/components/PostEditorPOM.ts +370 -0
- package/tests/cypress/src/components/PostsListPOM.ts +223 -0
- package/tests/cypress/src/components/PublicPagePOM.ts +447 -0
- package/tests/cypress/src/components/PublicPostPOM.ts +146 -0
- package/tests/cypress/src/components/TasksPOM.ts +272 -0
- package/tests/cypress/src/components/TeamSwitcherPOM.ts +450 -0
- package/tests/cypress/src/components/index.ts +21 -0
- package/tests/cypress/src/controllers/ApiKeysAPIController.js +178 -0
- package/tests/cypress/src/controllers/BaseAPIController.js +317 -0
- package/tests/cypress/src/controllers/CustomerAPIController.js +251 -0
- package/tests/cypress/src/controllers/PagesAPIController.js +226 -0
- package/tests/cypress/src/controllers/PostsAPIController.js +250 -0
- package/tests/cypress/src/controllers/TaskAPIController.js +240 -0
- package/tests/cypress/src/controllers/UsersAPIController.js +242 -0
- package/tests/cypress/src/controllers/index.js +25 -0
- package/tests/cypress/src/core/AuthPOM.ts +450 -0
- package/tests/cypress/src/core/BasePOM.ts +86 -0
- package/tests/cypress/src/core/BlockEditorBasePOM.ts +576 -0
- package/tests/cypress/src/core/DashboardEntityPOM.ts +692 -0
- package/tests/cypress/src/core/index.ts +14 -0
- package/tests/cypress/src/entities/CustomersPOM.ts +172 -0
- package/tests/cypress/src/entities/PagesPOM.ts +137 -0
- package/tests/cypress/src/entities/PostsPOM.ts +137 -0
- package/tests/cypress/src/entities/TasksPOM.ts +176 -0
- package/tests/cypress/src/entities/index.ts +14 -0
- package/tests/cypress/src/features/BillingPOM.ts +385 -0
- package/tests/cypress/src/features/DashboardPOM.ts +245 -0
- package/tests/cypress/src/features/DevtoolsPOM.ts +739 -0
- package/tests/cypress/src/features/PageBuilderPOM.ts +263 -0
- package/tests/cypress/src/features/PostEditorPOM.ts +313 -0
- package/tests/cypress/src/features/ScheduledActionsPOM.ts +463 -0
- package/tests/cypress/src/features/SettingsPOM.ts +362 -0
- package/tests/cypress/src/features/SuperadminPOM.ts +331 -0
- package/tests/cypress/src/features/SuperadminTeamRolesPOM.ts +285 -0
- package/tests/cypress/src/features/index.ts +28 -0
- package/tests/cypress/src/helpers/ApiInterceptor.ts +177 -0
- package/tests/cypress/src/index.ts +101 -0
- package/tests/cypress/src/pages/dashboard/Dashboard.js +677 -0
- package/tests/cypress/src/pages/dashboard/DashboardPage.js +43 -0
- package/tests/cypress/src/pages/dashboard/DashboardStats.js +546 -0
- package/tests/cypress/src/pages/dashboard/index.js +6 -0
- package/tests/cypress/src/pages/index.js +5 -0
- package/tests/cypress/src/pages/public/FeaturesPage.js +28 -0
- package/tests/cypress/src/pages/public/LandingPage.js +69 -0
- package/tests/cypress/src/pages/public/PricingPage.js +33 -0
- package/tests/cypress/src/pages/public/index.js +6 -0
- package/tests/cypress/src/selectors.ts +46 -0
- package/tests/cypress/src/session-helpers.ts +500 -0
- package/tests/cypress/support/doc-commands.ts +260 -0
- package/tests/cypress.config.ts +150 -0
- package/tests/jest/components/post-header.test.tsx +377 -0
- package/tests/jest/config/role-config.test.ts +529 -0
- package/tests/jest/jest.config.ts +81 -0
- package/tests/jest/langchain/COVERAGE.md +372 -0
- package/tests/jest/langchain/guardrails.test.ts +465 -0
- package/tests/jest/langchain/streaming.test.ts +367 -0
- package/tests/jest/langchain/token-tracker.test.ts +455 -0
- package/tests/jest/langchain/tracer-callbacks.test.ts +881 -0
- package/tests/jest/langchain/tracer.test.ts +823 -0
- package/tests/jest/user-roles/role-helpers.test.ts +432 -0
- package/tests/jest/validation/categories.test.ts +429 -0
- package/tests/jest/validation/posts.test.ts +546 -0
- package/tests/tsconfig.json +15 -0
|
@@ -0,0 +1,710 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Page Builder POM
|
|
3
|
+
*
|
|
4
|
+
* Page Object Model for the Block Editor / Page Builder system.
|
|
5
|
+
* Covers admin UI workflows for creating and editing pages with blocks.
|
|
6
|
+
*
|
|
7
|
+
* Convention: block-editor-{component}-{detail}
|
|
8
|
+
* Based on 67+ existing data-cy attributes in dashboard components.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { ApiInterceptor } from '../helpers/ApiInterceptor'
|
|
12
|
+
|
|
13
|
+
export interface PageFormData {
|
|
14
|
+
title: string
|
|
15
|
+
slug: string
|
|
16
|
+
locale?: 'en' | 'es'
|
|
17
|
+
status?: 'draft' | 'published' | 'scheduled' | 'archived'
|
|
18
|
+
metaTitle?: string
|
|
19
|
+
metaDescription?: string
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface BlockData {
|
|
23
|
+
slug: string
|
|
24
|
+
props?: Record<string, unknown>
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export class PageBuilderPOM {
|
|
28
|
+
// ============================================
|
|
29
|
+
// STATIC CONFIG
|
|
30
|
+
// ============================================
|
|
31
|
+
|
|
32
|
+
static get slug() {
|
|
33
|
+
return 'pages'
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// ============================================
|
|
37
|
+
// API INTERCEPTOR (for deterministic waits)
|
|
38
|
+
// ============================================
|
|
39
|
+
|
|
40
|
+
private static _api: ApiInterceptor | null = null
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Get the API interceptor instance for pages
|
|
44
|
+
* Lazy-initialized on first access
|
|
45
|
+
*/
|
|
46
|
+
static get api(): ApiInterceptor {
|
|
47
|
+
if (!this._api) {
|
|
48
|
+
this._api = new ApiInterceptor(this.slug)
|
|
49
|
+
}
|
|
50
|
+
return this._api
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Setup API intercepts for CRUD operations
|
|
55
|
+
* Call this in beforeEach BEFORE navigation
|
|
56
|
+
*/
|
|
57
|
+
static setupApiIntercepts(): typeof PageBuilderPOM {
|
|
58
|
+
this.api.setupCrudIntercepts()
|
|
59
|
+
return this
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// ============================================
|
|
63
|
+
// SELECTORS - Pages List
|
|
64
|
+
// ============================================
|
|
65
|
+
|
|
66
|
+
static get listSelectors() {
|
|
67
|
+
// Using entity testing convention: {slug}-{component}
|
|
68
|
+
// Based on createCyId(entityConfig.slug, component) from testing-utils.ts
|
|
69
|
+
return {
|
|
70
|
+
page: '[data-cy="pages-page"]',
|
|
71
|
+
title: '[data-cy="pages-title"]',
|
|
72
|
+
table: '[data-cy="pages-table"], table',
|
|
73
|
+
createBtn: '[data-cy="pages-add"]',
|
|
74
|
+
searchContainer: '[data-cy="pages-search"]',
|
|
75
|
+
searchInput: '[data-cy="pages-search-input"]',
|
|
76
|
+
filterStatus: '[data-cy="pages-filter-status"]',
|
|
77
|
+
filterLocale: '[data-cy="pages-filter-locale"]',
|
|
78
|
+
row: (id: string) => `[data-cy="pages-row-${id}"]`,
|
|
79
|
+
rowGeneric: 'table tbody tr',
|
|
80
|
+
// Row menu actions (EntityTable patterns)
|
|
81
|
+
menuTrigger: (id: string) => `[data-cy="pages-menu-${id}"]`,
|
|
82
|
+
menuEdit: (id: string) => `[data-cy="pages-menu-edit-${id}"]`,
|
|
83
|
+
menuDelete: (id: string) => `[data-cy="pages-menu-delete-${id}"]`,
|
|
84
|
+
menuView: (id: string) => `[data-cy="pages-menu-view-${id}"]`,
|
|
85
|
+
confirmDelete: '[data-cy="pages-confirm-delete"], [role="dialog"]',
|
|
86
|
+
confirmDeleteBtn: '[data-cy="pages-confirm-delete-btn"], [role="dialog"] button:contains("Delete"), button.bg-destructive',
|
|
87
|
+
cancelDeleteBtn: '[data-cy="pages-cancel-delete-btn"], [role="dialog"] button:contains("Cancel"),[role="dialog"] button[type="button"]:not(.bg-destructive)',
|
|
88
|
+
emptyState: 'td:contains("No pages")',
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// ============================================
|
|
93
|
+
// SELECTORS - Block Editor
|
|
94
|
+
// ============================================
|
|
95
|
+
|
|
96
|
+
static get editorSelectors() {
|
|
97
|
+
return {
|
|
98
|
+
// Page container (builder-editor is the main editor wrapper)
|
|
99
|
+
editorPage: '[data-cy="builder-editor"]',
|
|
100
|
+
|
|
101
|
+
// Left sidebar toggle (expands/collapses block picker)
|
|
102
|
+
leftSidebarToggle: '[data-cy="left-sidebar-toggle"]',
|
|
103
|
+
|
|
104
|
+
// Mode toggles (wrapper and individual buttons)
|
|
105
|
+
viewModeToggle: '[data-cy="view-mode-toggle"]',
|
|
106
|
+
modeLayout: '[data-cy="mode-layout"]',
|
|
107
|
+
modePreview: '[data-cy="mode-preview"]',
|
|
108
|
+
|
|
109
|
+
// Block Picker (Left Panel)
|
|
110
|
+
blockPicker: '[data-cy="block-picker"]',
|
|
111
|
+
blockSearchInput: '[data-cy="block-search-input"]',
|
|
112
|
+
categoryTab: (cat: string) => `[data-cy="category-${cat}"]`,
|
|
113
|
+
blockItem: (slug: string) => `[data-cy="block-item-${slug}"]`,
|
|
114
|
+
addBlockBtn: (slug: string) => `[data-cy="add-block-${slug}"]`,
|
|
115
|
+
|
|
116
|
+
// Block Canvas (Center Panel - Edit Mode)
|
|
117
|
+
blockCanvas: '[data-cy="block-canvas"]',
|
|
118
|
+
blockCanvasEmpty: '[data-cy="block-canvas-empty"]',
|
|
119
|
+
sortableBlock: (id: string) => `[data-cy="sortable-block-${id}"]`,
|
|
120
|
+
dragHandle: (id: string) => `[data-cy="drag-handle-${id}"]`,
|
|
121
|
+
duplicateBlock: (id: string) => `[data-cy="duplicate-block-${id}"]`,
|
|
122
|
+
removeBlock: (id: string) => `[data-cy="remove-block-${id}"]`,
|
|
123
|
+
sortableBlockGeneric: '[data-cy^="sortable-block-"]',
|
|
124
|
+
|
|
125
|
+
// Preview Canvas (Center Panel - Preview Mode)
|
|
126
|
+
previewCanvas: '[data-cy="block-preview-canvas"]',
|
|
127
|
+
previewCanvasEmpty: '[data-cy="block-preview-canvas-empty"]',
|
|
128
|
+
previewBlock: (id: string) => `[data-cy="preview-block-${id}"]`,
|
|
129
|
+
moveUpBtn: (id: string) => `[data-cy="preview-block-${id}-move-up"]`,
|
|
130
|
+
moveDownBtn: (id: string) => `[data-cy="preview-block-${id}-move-down"]`,
|
|
131
|
+
previewBlockGeneric: '[data-cy^="preview-block-"]',
|
|
132
|
+
|
|
133
|
+
// Settings Panel (Right Panel)
|
|
134
|
+
settingsPanel: '[data-cy="block-settings-panel"]',
|
|
135
|
+
settingsEmpty: '[data-cy="settings-panel-empty"]',
|
|
136
|
+
resetPropsBtn: '[data-cy="reset-block-props"]',
|
|
137
|
+
removeBlockSettings: '[data-cy="remove-block-settings"]',
|
|
138
|
+
|
|
139
|
+
// Settings Tabs
|
|
140
|
+
tabContent: '[data-cy="tab-content"]',
|
|
141
|
+
tabDesign: '[data-cy="tab-design"]',
|
|
142
|
+
tabAdvanced: '[data-cy="tab-advanced"]',
|
|
143
|
+
|
|
144
|
+
// Field inputs in settings
|
|
145
|
+
fieldInput: (name: string) => `[data-cy="field-${name}"]`,
|
|
146
|
+
fieldTextarea: (name: string) => `[data-cy="field-${name}"] textarea`,
|
|
147
|
+
fieldSelect: (name: string) => `[data-cy="field-${name}"] [role="combobox"]`,
|
|
148
|
+
fieldCheckbox: (name: string) => `[data-cy="field-${name}"] input[type="checkbox"]`,
|
|
149
|
+
fieldArray: (name: string) => `[data-cy="field-${name}-array"]`,
|
|
150
|
+
|
|
151
|
+
// Array field controls
|
|
152
|
+
arrayAddItem: (name: string) => `[data-cy="field-${name}-add-item"]`,
|
|
153
|
+
arrayItem: (name: string, index: number) => `[data-cy="field-${name}-item-${index}"]`,
|
|
154
|
+
arrayItemRemove: (name: string, index: number) => `[data-cy="field-${name}-item-${index}-remove"]`,
|
|
155
|
+
arrayItemMoveUp: (name: string, index: number) => `[data-cy="field-${name}-item-${index}-move-up"]`,
|
|
156
|
+
arrayItemMoveDown: (name: string, index: number) => `[data-cy="field-${name}-item-${index}-move-down"]`,
|
|
157
|
+
|
|
158
|
+
// CTA group fields (collapsible)
|
|
159
|
+
ctaGroupTrigger: (name: string) => `[data-cy="cta-group-${name}"]`,
|
|
160
|
+
ctaGroupContent: (name: string) => `[data-cy="cta-group-${name}-content"]`,
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// ============================================
|
|
165
|
+
// SELECTORS - Page Settings
|
|
166
|
+
// ============================================
|
|
167
|
+
|
|
168
|
+
static get pageSettingsSelectors() {
|
|
169
|
+
return {
|
|
170
|
+
panel: '[data-cy="page-settings-panel"]',
|
|
171
|
+
// Note: In editor, these are in the top bar
|
|
172
|
+
titleInput: '[data-cy="editor-title-input"]',
|
|
173
|
+
slugInput: '[data-cy="editor-slug-input"]',
|
|
174
|
+
localeSelect: '[data-cy="locale-select"]',
|
|
175
|
+
|
|
176
|
+
// Status selector (dropdown)
|
|
177
|
+
statusSelector: '[data-cy="status-selector"]',
|
|
178
|
+
statusOption: (status: string) => `[data-cy="status-option-${status}"]`,
|
|
179
|
+
statusBadge: '[data-cy="status-badge"]',
|
|
180
|
+
|
|
181
|
+
// SEO Settings
|
|
182
|
+
seoTrigger: '[data-cy="seo-settings-trigger"]',
|
|
183
|
+
seoContent: '[data-cy="seo-settings-content"]',
|
|
184
|
+
metaTitle: '[data-cy="seo-meta-title"]',
|
|
185
|
+
metaDescription: '[data-cy="seo-meta-description"]',
|
|
186
|
+
|
|
187
|
+
// Action buttons
|
|
188
|
+
saveBtn: '[data-cy="save-btn"]',
|
|
189
|
+
previewBtn: '[data-cy="preview-page-btn"]',
|
|
190
|
+
deleteBtn: '[data-cy="delete-page-btn"]',
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// ============================================
|
|
195
|
+
// NAVIGATION
|
|
196
|
+
// ============================================
|
|
197
|
+
|
|
198
|
+
static visitList() {
|
|
199
|
+
cy.visit('/dashboard/pages')
|
|
200
|
+
return this
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
static visitCreate() {
|
|
204
|
+
cy.visit('/dashboard/pages/create')
|
|
205
|
+
return this
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
static visitEdit(id: string) {
|
|
209
|
+
cy.visit(`/dashboard/pages/${id}/edit`)
|
|
210
|
+
return this
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// ============================================
|
|
214
|
+
// API-AWARE NAVIGATION
|
|
215
|
+
// ============================================
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Visit list page with API intercepts and wait for data load
|
|
219
|
+
*/
|
|
220
|
+
static visitListWithApiWait(): typeof PageBuilderPOM {
|
|
221
|
+
this.setupApiIntercepts()
|
|
222
|
+
this.visitList()
|
|
223
|
+
this.api.waitForList()
|
|
224
|
+
return this
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Visit edit page with API intercepts
|
|
229
|
+
*/
|
|
230
|
+
static visitEditWithApiWait(id: string): typeof PageBuilderPOM {
|
|
231
|
+
this.setupApiIntercepts()
|
|
232
|
+
this.visitEdit(id)
|
|
233
|
+
return this
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// ============================================
|
|
237
|
+
// WAIT METHODS
|
|
238
|
+
// ============================================
|
|
239
|
+
|
|
240
|
+
static waitForListLoad() {
|
|
241
|
+
cy.url().should('include', '/dashboard/pages')
|
|
242
|
+
cy.get(this.listSelectors.page, { timeout: 15000 }).should('exist')
|
|
243
|
+
return this
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
static waitForEditorLoad() {
|
|
247
|
+
cy.get(this.editorSelectors.editorPage, { timeout: 15000 }).should('be.visible')
|
|
248
|
+
return this
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
static waitForBlockPickerLoad() {
|
|
252
|
+
cy.get(this.editorSelectors.blockPicker, { timeout: 10000 }).should('be.visible')
|
|
253
|
+
return this
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
static waitForSettingsPanelLoad() {
|
|
257
|
+
cy.get(this.editorSelectors.settingsPanel, { timeout: 10000 }).should('be.visible')
|
|
258
|
+
return this
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// ============================================
|
|
262
|
+
// LIST PAGE INTERACTIONS
|
|
263
|
+
// ============================================
|
|
264
|
+
|
|
265
|
+
static clickCreatePage() {
|
|
266
|
+
cy.get(this.listSelectors.createBtn).click()
|
|
267
|
+
return this
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
static searchPages(term: string) {
|
|
271
|
+
cy.get(this.listSelectors.searchInput).clear().type(term)
|
|
272
|
+
return this
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
static clearSearch() {
|
|
276
|
+
cy.get(this.listSelectors.searchInput).clear()
|
|
277
|
+
return this
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
static filterByStatus(status: 'all' | 'published' | 'draft') {
|
|
281
|
+
cy.get(this.listSelectors.filterStatus).click()
|
|
282
|
+
cy.contains('[role="option"]', status).click()
|
|
283
|
+
return this
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
static openRowMenu(id: string) {
|
|
287
|
+
cy.get(this.listSelectors.menuTrigger(id)).click()
|
|
288
|
+
return this
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
static clickMenuEdit(id: string) {
|
|
292
|
+
cy.get(this.listSelectors.menuEdit(id)).click()
|
|
293
|
+
return this
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
static clickMenuDelete(id: string) {
|
|
297
|
+
cy.get(this.listSelectors.menuDelete(id)).click()
|
|
298
|
+
return this
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
static clickMenuView(id: string) {
|
|
302
|
+
cy.get(this.listSelectors.menuView(id)).click()
|
|
303
|
+
return this
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
static confirmDelete() {
|
|
307
|
+
cy.get(this.listSelectors.confirmDeleteBtn).click()
|
|
308
|
+
return this
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
static cancelDelete() {
|
|
312
|
+
cy.get(this.listSelectors.cancelDeleteBtn).click()
|
|
313
|
+
return this
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// ============================================
|
|
317
|
+
// BLOCK EDITOR INTERACTIONS
|
|
318
|
+
// ============================================
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* Ensures the block picker sidebar is visible (expanded)
|
|
322
|
+
* If not visible, clicks the toggle to expand it
|
|
323
|
+
*/
|
|
324
|
+
static ensureBlockPickerVisible() {
|
|
325
|
+
// Use invoke to get a primitive boolean, avoiding allure-cypress serialization issues
|
|
326
|
+
cy.get(this.editorSelectors.blockPicker, { timeout: 1000 })
|
|
327
|
+
.should('exist')
|
|
328
|
+
.invoke('is', ':visible')
|
|
329
|
+
.then((isVisible: boolean) => {
|
|
330
|
+
if (!isVisible) {
|
|
331
|
+
cy.get(this.editorSelectors.leftSidebarToggle).click()
|
|
332
|
+
cy.get(this.editorSelectors.blockPicker, { timeout: 5000 }).should('be.visible')
|
|
333
|
+
}
|
|
334
|
+
})
|
|
335
|
+
return this
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
static switchToLayoutMode() {
|
|
339
|
+
cy.get(this.editorSelectors.modeLayout).click()
|
|
340
|
+
// Ensure block picker is visible after switching to layout mode
|
|
341
|
+
this.ensureBlockPickerVisible()
|
|
342
|
+
return this
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
static switchToPreviewMode() {
|
|
346
|
+
cy.get(this.editorSelectors.modePreview).click()
|
|
347
|
+
return this
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
static searchBlocks(term: string) {
|
|
351
|
+
this.ensureBlockPickerVisible()
|
|
352
|
+
cy.get(this.editorSelectors.blockSearchInput).clear().type(term)
|
|
353
|
+
return this
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
static selectBlockCategory(category: string) {
|
|
357
|
+
this.ensureBlockPickerVisible()
|
|
358
|
+
cy.get(this.editorSelectors.categoryTab(category)).click()
|
|
359
|
+
return this
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
static addBlock(slug: string) {
|
|
363
|
+
this.ensureBlockPickerVisible()
|
|
364
|
+
// Click on block item (not the hidden add button) to add block
|
|
365
|
+
// The block item div is always visible and has onClick handler
|
|
366
|
+
cy.get(this.editorSelectors.blockItem(slug))
|
|
367
|
+
.scrollIntoView()
|
|
368
|
+
.should('be.visible')
|
|
369
|
+
.click()
|
|
370
|
+
return this
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
static selectBlock(blockId: string) {
|
|
374
|
+
cy.get(this.editorSelectors.sortableBlock(blockId)).click()
|
|
375
|
+
return this
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
static selectPreviewBlock(blockId: string) {
|
|
379
|
+
cy.get(this.editorSelectors.previewBlock(blockId)).click()
|
|
380
|
+
return this
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
static duplicateBlock(blockId: string) {
|
|
384
|
+
cy.get(this.editorSelectors.duplicateBlock(blockId)).click()
|
|
385
|
+
return this
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
static removeBlock(blockId: string) {
|
|
389
|
+
cy.get(this.editorSelectors.removeBlock(blockId)).click()
|
|
390
|
+
return this
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
static moveBlockUp(blockId: string) {
|
|
394
|
+
cy.get(this.editorSelectors.moveUpBtn(blockId)).click()
|
|
395
|
+
return this
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
static moveBlockDown(blockId: string) {
|
|
399
|
+
cy.get(this.editorSelectors.moveDownBtn(blockId)).click()
|
|
400
|
+
return this
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
// ============================================
|
|
404
|
+
// SETTINGS PANEL INTERACTIONS
|
|
405
|
+
// ============================================
|
|
406
|
+
|
|
407
|
+
static selectSettingsTab(tab: 'content' | 'design' | 'advanced') {
|
|
408
|
+
const selector =
|
|
409
|
+
tab === 'content'
|
|
410
|
+
? this.editorSelectors.tabContent
|
|
411
|
+
: tab === 'design'
|
|
412
|
+
? this.editorSelectors.tabDesign
|
|
413
|
+
: this.editorSelectors.tabAdvanced
|
|
414
|
+
cy.get(selector).click()
|
|
415
|
+
return this
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
static fillField(name: string, value: string) {
|
|
419
|
+
cy.get(this.editorSelectors.fieldInput(name)).find('input, textarea').first().clear().type(value)
|
|
420
|
+
return this
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
static fillTextarea(name: string, value: string) {
|
|
424
|
+
cy.get(this.editorSelectors.fieldTextarea(name)).clear().type(value)
|
|
425
|
+
return this
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
static selectOption(name: string, value: string) {
|
|
429
|
+
cy.get(this.editorSelectors.fieldSelect(name)).click()
|
|
430
|
+
cy.contains('[role="option"]', value).click()
|
|
431
|
+
return this
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
static toggleCheckbox(name: string) {
|
|
435
|
+
cy.get(this.editorSelectors.fieldCheckbox(name)).click()
|
|
436
|
+
return this
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
static resetBlockProps() {
|
|
440
|
+
cy.get(this.editorSelectors.resetPropsBtn).click()
|
|
441
|
+
return this
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
static removeBlockFromSettings() {
|
|
445
|
+
cy.get(this.editorSelectors.removeBlockSettings).click()
|
|
446
|
+
return this
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
// ============================================
|
|
450
|
+
// ARRAY FIELD INTERACTIONS
|
|
451
|
+
// ============================================
|
|
452
|
+
|
|
453
|
+
static addArrayItem(fieldName: string) {
|
|
454
|
+
cy.get(this.editorSelectors.arrayAddItem(fieldName)).click()
|
|
455
|
+
return this
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
static removeArrayItem(fieldName: string, index: number) {
|
|
459
|
+
cy.get(this.editorSelectors.arrayItemRemove(fieldName, index)).click()
|
|
460
|
+
return this
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
static moveArrayItemUp(fieldName: string, index: number) {
|
|
464
|
+
cy.get(this.editorSelectors.arrayItemMoveUp(fieldName, index)).click()
|
|
465
|
+
return this
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
static moveArrayItemDown(fieldName: string, index: number) {
|
|
469
|
+
cy.get(this.editorSelectors.arrayItemMoveDown(fieldName, index)).click()
|
|
470
|
+
return this
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
// ============================================
|
|
474
|
+
// CTA GROUP INTERACTIONS
|
|
475
|
+
// ============================================
|
|
476
|
+
|
|
477
|
+
static toggleCtaGroup(name: string) {
|
|
478
|
+
cy.get(this.editorSelectors.ctaGroupTrigger(name)).click()
|
|
479
|
+
return this
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
// ============================================
|
|
483
|
+
// PAGE SETTINGS INTERACTIONS
|
|
484
|
+
// ============================================
|
|
485
|
+
|
|
486
|
+
static setPageTitle(title: string) {
|
|
487
|
+
cy.get(this.pageSettingsSelectors.titleInput).clear().type(title)
|
|
488
|
+
return this
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
static setPageSlug(slug: string) {
|
|
492
|
+
cy.get(this.pageSettingsSelectors.slugInput).clear().type(slug)
|
|
493
|
+
return this
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
static setPageLocale(locale: 'en' | 'es') {
|
|
497
|
+
cy.get(this.pageSettingsSelectors.localeSelect).click()
|
|
498
|
+
cy.contains('[role="option"]', locale).click()
|
|
499
|
+
return this
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
/**
|
|
503
|
+
* Select a status from the dropdown
|
|
504
|
+
*/
|
|
505
|
+
static selectStatus(status: 'draft' | 'published' | 'scheduled' | 'archived') {
|
|
506
|
+
// Status selector may be partially outside viewport, use force click
|
|
507
|
+
cy.get(this.pageSettingsSelectors.statusSelector)
|
|
508
|
+
.should('exist')
|
|
509
|
+
.click({ force: true })
|
|
510
|
+
cy.get(this.pageSettingsSelectors.statusOption(status)).click()
|
|
511
|
+
return this
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
static openSeoSettings() {
|
|
515
|
+
cy.get(this.pageSettingsSelectors.seoTrigger).click()
|
|
516
|
+
return this
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
static setMetaTitle(title: string) {
|
|
520
|
+
cy.get(this.pageSettingsSelectors.metaTitle).clear().type(title)
|
|
521
|
+
return this
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
static setMetaDescription(description: string) {
|
|
525
|
+
cy.get(this.pageSettingsSelectors.metaDescription).clear().type(description)
|
|
526
|
+
return this
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
static savePage() {
|
|
530
|
+
// Wait for any pending state updates after adding blocks
|
|
531
|
+
cy.wait(500)
|
|
532
|
+
// The save button might be partially outside viewport, use force click
|
|
533
|
+
cy.get(this.pageSettingsSelectors.saveBtn)
|
|
534
|
+
.should('exist')
|
|
535
|
+
.click({ force: true })
|
|
536
|
+
return this
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
/**
|
|
540
|
+
* Save page and wait for API response (deterministic)
|
|
541
|
+
*/
|
|
542
|
+
static savePageWithApiWait(): typeof PageBuilderPOM {
|
|
543
|
+
this.savePage()
|
|
544
|
+
this.api.waitForUpdate()
|
|
545
|
+
return this
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
/**
|
|
549
|
+
* Change status to published and save
|
|
550
|
+
*/
|
|
551
|
+
static publishPage() {
|
|
552
|
+
this.selectStatus('published')
|
|
553
|
+
this.savePage()
|
|
554
|
+
return this
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
/**
|
|
558
|
+
* Change status to draft and save (unpublish)
|
|
559
|
+
*/
|
|
560
|
+
static unpublishPage() {
|
|
561
|
+
this.selectStatus('draft')
|
|
562
|
+
this.savePage()
|
|
563
|
+
return this
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
static previewPage() {
|
|
567
|
+
cy.get(this.pageSettingsSelectors.previewBtn).click()
|
|
568
|
+
return this
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
static deletePage() {
|
|
572
|
+
cy.get(this.pageSettingsSelectors.deleteBtn).click()
|
|
573
|
+
return this
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
// ============================================
|
|
577
|
+
// COMPLETE WORKFLOWS
|
|
578
|
+
// ============================================
|
|
579
|
+
|
|
580
|
+
/**
|
|
581
|
+
* Create a new page with specified data and blocks
|
|
582
|
+
*/
|
|
583
|
+
static createPage(data: PageFormData, blocks: BlockData[] = []) {
|
|
584
|
+
this.visitCreate()
|
|
585
|
+
this.waitForEditorLoad()
|
|
586
|
+
|
|
587
|
+
// Set page settings
|
|
588
|
+
this.setPageTitle(data.title)
|
|
589
|
+
this.setPageSlug(data.slug)
|
|
590
|
+
|
|
591
|
+
if (data.locale) {
|
|
592
|
+
this.setPageLocale(data.locale)
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
// Add blocks
|
|
596
|
+
blocks.forEach((block) => {
|
|
597
|
+
this.addBlock(block.slug)
|
|
598
|
+
})
|
|
599
|
+
|
|
600
|
+
// Set status if provided
|
|
601
|
+
if (data.status) {
|
|
602
|
+
this.selectStatus(data.status)
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
// Set SEO if provided
|
|
606
|
+
if (data.metaTitle || data.metaDescription) {
|
|
607
|
+
this.openSeoSettings()
|
|
608
|
+
if (data.metaTitle) this.setMetaTitle(data.metaTitle)
|
|
609
|
+
if (data.metaDescription) this.setMetaDescription(data.metaDescription)
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
this.savePage()
|
|
613
|
+
return this
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
// ============================================
|
|
617
|
+
// ASSERTIONS
|
|
618
|
+
// ============================================
|
|
619
|
+
|
|
620
|
+
static assertListPageVisible() {
|
|
621
|
+
cy.get(this.listSelectors.page).should('exist')
|
|
622
|
+
return this
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
static assertEditorVisible() {
|
|
626
|
+
cy.get(this.editorSelectors.editorPage).should('be.visible')
|
|
627
|
+
return this
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
static assertBlockPickerVisible() {
|
|
631
|
+
cy.get(this.editorSelectors.blockPicker).should('be.visible')
|
|
632
|
+
return this
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
static assertBlockInCanvas(blockSlug: string) {
|
|
636
|
+
cy.get(this.editorSelectors.blockCanvas).should('contain.text', blockSlug)
|
|
637
|
+
return this
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
static assertBlockCount(count: number) {
|
|
641
|
+
cy.get(this.editorSelectors.sortableBlockGeneric).should('have.length', count)
|
|
642
|
+
return this
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
static assertPreviewBlockCount(count: number) {
|
|
646
|
+
cy.get(this.editorSelectors.previewBlockGeneric).should('have.length', count)
|
|
647
|
+
return this
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
static assertCanvasEmpty() {
|
|
651
|
+
cy.get(this.editorSelectors.blockCanvasEmpty).should('be.visible')
|
|
652
|
+
return this
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
static assertSettingsPanelEmpty() {
|
|
656
|
+
cy.get(this.editorSelectors.settingsEmpty).should('be.visible')
|
|
657
|
+
return this
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
static assertSettingsPanelHasContent() {
|
|
661
|
+
cy.get(this.editorSelectors.settingsPanel).should('be.visible')
|
|
662
|
+
cy.get(this.editorSelectors.settingsEmpty).should('not.exist')
|
|
663
|
+
return this
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
static assertBlockInPicker(blockSlug: string) {
|
|
667
|
+
// Scroll into view within the block picker scroll area
|
|
668
|
+
cy.get(this.editorSelectors.blockItem(blockSlug))
|
|
669
|
+
.scrollIntoView()
|
|
670
|
+
.should('be.visible')
|
|
671
|
+
return this
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
static assertPageInList(title: string) {
|
|
675
|
+
cy.contains(this.listSelectors.rowGeneric, title).should('be.visible')
|
|
676
|
+
return this
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
static assertPageNotInList(title: string) {
|
|
680
|
+
cy.contains(this.listSelectors.rowGeneric, title).should('not.exist')
|
|
681
|
+
return this
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
static assertEmptyList() {
|
|
685
|
+
cy.get(this.listSelectors.emptyState).should('be.visible')
|
|
686
|
+
return this
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
static assertSaveSuccess() {
|
|
690
|
+
cy.contains('saved', { matchCase: false }).should('be.visible')
|
|
691
|
+
return this
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
static assertPublishSuccess() {
|
|
695
|
+
cy.contains('saved', { matchCase: false }).should('be.visible')
|
|
696
|
+
return this
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
static assertStatusBadge(status: 'draft' | 'published' | 'scheduled' | 'archived') {
|
|
700
|
+
cy.get(this.pageSettingsSelectors.statusBadge).should('contain.text', status)
|
|
701
|
+
return this
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
static assertStatusSelected(status: string) {
|
|
705
|
+
cy.get(this.pageSettingsSelectors.statusSelector).should('contain.text', status)
|
|
706
|
+
return this
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
export default PageBuilderPOM
|