@nextsparkjs/theme-default 0.1.0-beta.20 → 0.1.0-beta.22
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/support/e2e.ts +89 -0
- package/tests/cypress.config.ts +165 -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,172 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CustomersPOM - Page Object Model for Customers entity
|
|
3
|
+
*
|
|
4
|
+
* Extends DashboardEntityPOM with customer-specific form handling and workflows.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* // Instance usage with chaining
|
|
8
|
+
* CustomersPOM.create()
|
|
9
|
+
* .visitList()
|
|
10
|
+
* .waitForList()
|
|
11
|
+
* .clickAdd()
|
|
12
|
+
* .fillCustomerForm({ name: 'Acme Inc', account: 'ACC001', office: 'HQ' })
|
|
13
|
+
* .submitForm()
|
|
14
|
+
*
|
|
15
|
+
* // API-aware workflow
|
|
16
|
+
* const customers = new CustomersPOM()
|
|
17
|
+
* customers.createCustomerWithApiWait({
|
|
18
|
+
* name: 'Acme Inc',
|
|
19
|
+
* account: 'ACC001',
|
|
20
|
+
* office: 'Main Office'
|
|
21
|
+
* })
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
import { DashboardEntityPOM } from '../core/DashboardEntityPOM'
|
|
25
|
+
import entitiesConfig from '../../fixtures/entities.json'
|
|
26
|
+
|
|
27
|
+
export interface CustomerFormData {
|
|
28
|
+
name: string
|
|
29
|
+
account: string
|
|
30
|
+
office: string
|
|
31
|
+
phone?: string
|
|
32
|
+
salesRep?: string
|
|
33
|
+
visitDays?: string[]
|
|
34
|
+
contactDays?: string[]
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export class CustomersPOM extends DashboardEntityPOM {
|
|
38
|
+
constructor() {
|
|
39
|
+
super(entitiesConfig.entities.customers.slug)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// ============================================
|
|
43
|
+
// FACTORY METHOD
|
|
44
|
+
// ============================================
|
|
45
|
+
|
|
46
|
+
static create(): CustomersPOM {
|
|
47
|
+
return new CustomersPOM()
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// ============================================
|
|
51
|
+
// ENTITY-SPECIFIC FORM METHODS
|
|
52
|
+
// ============================================
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Fill customer form with provided data
|
|
56
|
+
* Only fills fields that are provided in the data object
|
|
57
|
+
*/
|
|
58
|
+
fillCustomerForm(data: CustomerFormData) {
|
|
59
|
+
if (data.name) {
|
|
60
|
+
this.fillTextField('name', data.name)
|
|
61
|
+
}
|
|
62
|
+
if (data.account) {
|
|
63
|
+
this.fillTextField('account', data.account)
|
|
64
|
+
}
|
|
65
|
+
if (data.office) {
|
|
66
|
+
this.fillTextField('office', data.office)
|
|
67
|
+
}
|
|
68
|
+
if (data.phone) {
|
|
69
|
+
this.fillTextField('phone', data.phone)
|
|
70
|
+
}
|
|
71
|
+
if (data.salesRep) {
|
|
72
|
+
this.fillTextField('salesRep', data.salesRep)
|
|
73
|
+
}
|
|
74
|
+
return this
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// ============================================
|
|
78
|
+
// WORKFLOW METHODS
|
|
79
|
+
// ============================================
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Complete create flow without API waits
|
|
83
|
+
*/
|
|
84
|
+
createCustomer(data: CustomerFormData) {
|
|
85
|
+
this.visitCreate()
|
|
86
|
+
this.waitForForm()
|
|
87
|
+
this.fillCustomerForm(data)
|
|
88
|
+
this.submitForm()
|
|
89
|
+
return this
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Create customer with API intercepts and waits
|
|
94
|
+
* Deterministic: waits for actual API responses
|
|
95
|
+
*/
|
|
96
|
+
createCustomerWithApiWait(data: CustomerFormData) {
|
|
97
|
+
this.setupApiIntercepts()
|
|
98
|
+
this.clickAdd()
|
|
99
|
+
this.waitForForm()
|
|
100
|
+
this.fillCustomerForm(data)
|
|
101
|
+
this.submitForm()
|
|
102
|
+
this.api.waitForCreate()
|
|
103
|
+
return this
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Create customer from list page and wait for refresh
|
|
108
|
+
*/
|
|
109
|
+
createCustomerFromListWithApiWait(data: CustomerFormData) {
|
|
110
|
+
this.setupApiIntercepts()
|
|
111
|
+
this.clickAdd()
|
|
112
|
+
this.waitForForm()
|
|
113
|
+
this.fillCustomerForm(data)
|
|
114
|
+
this.submitForm()
|
|
115
|
+
this.api.waitForCreateAndRefresh()
|
|
116
|
+
return this
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Update customer with API waits
|
|
121
|
+
*/
|
|
122
|
+
updateCustomerWithApiWait(data: Partial<CustomerFormData>) {
|
|
123
|
+
this.fillCustomerForm(data as CustomerFormData)
|
|
124
|
+
this.submitForm()
|
|
125
|
+
this.api.waitForUpdate()
|
|
126
|
+
return this
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Delete customer with API waits
|
|
131
|
+
* Flow: Navigate to detail -> Delete -> Confirm
|
|
132
|
+
*/
|
|
133
|
+
deleteCustomerWithApiWait(id: string) {
|
|
134
|
+
this.visitDetailWithApiWait(id)
|
|
135
|
+
this.clickDelete()
|
|
136
|
+
this.confirmDelete()
|
|
137
|
+
this.api.waitForDelete()
|
|
138
|
+
return this
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Delete customer by finding it in the list by name
|
|
143
|
+
*/
|
|
144
|
+
deleteCustomerByNameWithApiWait(name: string) {
|
|
145
|
+
this.clickRowByText(name)
|
|
146
|
+
this.waitForDetail()
|
|
147
|
+
this.clickDelete()
|
|
148
|
+
this.confirmDelete()
|
|
149
|
+
this.api.waitForDelete()
|
|
150
|
+
return this
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// ============================================
|
|
154
|
+
// ENTITY-SPECIFIC ASSERTIONS
|
|
155
|
+
// ============================================
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Assert customer appears in list
|
|
159
|
+
*/
|
|
160
|
+
assertCustomerInList(name: string) {
|
|
161
|
+
return this.assertInList(name)
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Assert customer does not appear in list
|
|
166
|
+
*/
|
|
167
|
+
assertCustomerNotInList(name: string) {
|
|
168
|
+
return this.assertNotInList(name)
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
export default CustomersPOM
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PagesPOM - Page Object Model for Pages entity (List operations)
|
|
3
|
+
*
|
|
4
|
+
* Extends DashboardEntityPOM for list page operations.
|
|
5
|
+
* For editing pages with the block editor, use PageBuilderPOM from features/.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* // List operations
|
|
9
|
+
* PagesPOM.create()
|
|
10
|
+
* .visitList()
|
|
11
|
+
* .waitForList()
|
|
12
|
+
* .search('About Us')
|
|
13
|
+
* .selectFilter('status', 'published')
|
|
14
|
+
*
|
|
15
|
+
* // For editing pages, use PageBuilderPOM
|
|
16
|
+
* import { PageBuilderPOM } from '../features/PageBuilderPOM'
|
|
17
|
+
* PageBuilderPOM.create().visitEdit(pageId).setTitle('New Title').save()
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { DashboardEntityPOM } from '../core/DashboardEntityPOM'
|
|
21
|
+
import entitiesConfig from '../../fixtures/entities.json'
|
|
22
|
+
|
|
23
|
+
export interface PageListFilters {
|
|
24
|
+
status?: 'draft' | 'published' | 'archived'
|
|
25
|
+
locale?: 'en' | 'es'
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export class PagesPOM extends DashboardEntityPOM {
|
|
29
|
+
constructor() {
|
|
30
|
+
super(entitiesConfig.entities.pages.slug)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// ============================================
|
|
34
|
+
// FACTORY METHOD
|
|
35
|
+
// ============================================
|
|
36
|
+
|
|
37
|
+
static create(): PagesPOM {
|
|
38
|
+
return new PagesPOM()
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// ============================================
|
|
42
|
+
// PAGE-SPECIFIC LIST METHODS
|
|
43
|
+
// ============================================
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Filter pages by status
|
|
47
|
+
*/
|
|
48
|
+
filterByStatus(status: 'draft' | 'published' | 'archived') {
|
|
49
|
+
return this.selectFilter('status', status)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Apply multiple filters at once
|
|
54
|
+
*/
|
|
55
|
+
applyFilters(filters: PageListFilters) {
|
|
56
|
+
if (filters.status) {
|
|
57
|
+
this.filterByStatus(filters.status)
|
|
58
|
+
}
|
|
59
|
+
if (filters.locale) {
|
|
60
|
+
this.selectFilter('locale', filters.locale)
|
|
61
|
+
}
|
|
62
|
+
return this
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// ============================================
|
|
66
|
+
// WORKFLOW METHODS
|
|
67
|
+
// ============================================
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Navigate to create page
|
|
71
|
+
* Note: Pages use block editor, so this redirects to the editor
|
|
72
|
+
*/
|
|
73
|
+
navigateToCreate() {
|
|
74
|
+
this.clickAdd()
|
|
75
|
+
return this
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Navigate to edit page for a page
|
|
80
|
+
* Note: Pages use block editor, so this redirects to the editor
|
|
81
|
+
*/
|
|
82
|
+
navigateToEdit(id: string) {
|
|
83
|
+
this.clickRowAction('edit', id)
|
|
84
|
+
return this
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Delete page from list with API waits
|
|
89
|
+
*/
|
|
90
|
+
deletePageWithApiWait(id: string) {
|
|
91
|
+
this.visitDetailWithApiWait(id)
|
|
92
|
+
this.clickDelete()
|
|
93
|
+
this.confirmDelete()
|
|
94
|
+
this.api.waitForDelete()
|
|
95
|
+
return this
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Delete page by finding it in the list by title
|
|
100
|
+
*/
|
|
101
|
+
deletePageByTitleWithApiWait(title: string) {
|
|
102
|
+
this.clickRowByText(title)
|
|
103
|
+
this.waitForDetail()
|
|
104
|
+
this.clickDelete()
|
|
105
|
+
this.confirmDelete()
|
|
106
|
+
this.api.waitForDelete()
|
|
107
|
+
return this
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// ============================================
|
|
111
|
+
// ENTITY-SPECIFIC ASSERTIONS
|
|
112
|
+
// ============================================
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Assert page appears in list
|
|
116
|
+
*/
|
|
117
|
+
assertPageInList(title: string) {
|
|
118
|
+
return this.assertInList(title)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Assert page does not appear in list
|
|
123
|
+
*/
|
|
124
|
+
assertPageNotInList(title: string) {
|
|
125
|
+
return this.assertNotInList(title)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Assert page has specific status badge
|
|
130
|
+
*/
|
|
131
|
+
assertPageStatus(id: string, status: string) {
|
|
132
|
+
cy.get(this.selectors.row(id)).should('contain.text', status)
|
|
133
|
+
return this
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export default PagesPOM
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PostsPOM - Page Object Model for Posts entity (List operations)
|
|
3
|
+
*
|
|
4
|
+
* Extends DashboardEntityPOM for list page operations.
|
|
5
|
+
* For editing posts with the block editor, use PostEditorPOM from features/.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* // List operations
|
|
9
|
+
* PostsPOM.create()
|
|
10
|
+
* .visitList()
|
|
11
|
+
* .waitForList()
|
|
12
|
+
* .search('My Post')
|
|
13
|
+
* .selectFilter('status', 'published')
|
|
14
|
+
*
|
|
15
|
+
* // For editing posts, use PostEditorPOM
|
|
16
|
+
* import { PostEditorPOM } from '../features/PostEditorPOM'
|
|
17
|
+
* PostEditorPOM.create().visitEdit(postId).setTitle('New Title').save()
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { DashboardEntityPOM } from '../core/DashboardEntityPOM'
|
|
21
|
+
import entitiesConfig from '../../fixtures/entities.json'
|
|
22
|
+
|
|
23
|
+
export interface PostListFilters {
|
|
24
|
+
status?: 'draft' | 'published' | 'archived'
|
|
25
|
+
categoryId?: string
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export class PostsPOM extends DashboardEntityPOM {
|
|
29
|
+
constructor() {
|
|
30
|
+
super(entitiesConfig.entities.posts.slug)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// ============================================
|
|
34
|
+
// FACTORY METHOD
|
|
35
|
+
// ============================================
|
|
36
|
+
|
|
37
|
+
static create(): PostsPOM {
|
|
38
|
+
return new PostsPOM()
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// ============================================
|
|
42
|
+
// POST-SPECIFIC LIST METHODS
|
|
43
|
+
// ============================================
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Filter posts by status
|
|
47
|
+
*/
|
|
48
|
+
filterByStatus(status: 'draft' | 'published' | 'archived') {
|
|
49
|
+
return this.selectFilter('status', status)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Apply multiple filters at once
|
|
54
|
+
*/
|
|
55
|
+
applyFilters(filters: PostListFilters) {
|
|
56
|
+
if (filters.status) {
|
|
57
|
+
this.filterByStatus(filters.status)
|
|
58
|
+
}
|
|
59
|
+
if (filters.categoryId) {
|
|
60
|
+
this.selectFilter('categoryId', filters.categoryId)
|
|
61
|
+
}
|
|
62
|
+
return this
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// ============================================
|
|
66
|
+
// WORKFLOW METHODS
|
|
67
|
+
// ============================================
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Navigate to create page
|
|
71
|
+
* Note: Posts use block editor, so this redirects to the editor
|
|
72
|
+
*/
|
|
73
|
+
navigateToCreate() {
|
|
74
|
+
this.clickAdd()
|
|
75
|
+
return this
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Navigate to edit page for a post
|
|
80
|
+
* Note: Posts use block editor, so this redirects to the editor
|
|
81
|
+
*/
|
|
82
|
+
navigateToEdit(id: string) {
|
|
83
|
+
this.clickRowAction('edit', id)
|
|
84
|
+
return this
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Delete post from list with API waits
|
|
89
|
+
*/
|
|
90
|
+
deletePostWithApiWait(id: string) {
|
|
91
|
+
this.visitDetailWithApiWait(id)
|
|
92
|
+
this.clickDelete()
|
|
93
|
+
this.confirmDelete()
|
|
94
|
+
this.api.waitForDelete()
|
|
95
|
+
return this
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Delete post by finding it in the list by title
|
|
100
|
+
*/
|
|
101
|
+
deletePostByTitleWithApiWait(title: string) {
|
|
102
|
+
this.clickRowByText(title)
|
|
103
|
+
this.waitForDetail()
|
|
104
|
+
this.clickDelete()
|
|
105
|
+
this.confirmDelete()
|
|
106
|
+
this.api.waitForDelete()
|
|
107
|
+
return this
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// ============================================
|
|
111
|
+
// ENTITY-SPECIFIC ASSERTIONS
|
|
112
|
+
// ============================================
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Assert post appears in list
|
|
116
|
+
*/
|
|
117
|
+
assertPostInList(title: string) {
|
|
118
|
+
return this.assertInList(title)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Assert post does not appear in list
|
|
123
|
+
*/
|
|
124
|
+
assertPostNotInList(title: string) {
|
|
125
|
+
return this.assertNotInList(title)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Assert post has specific status badge
|
|
130
|
+
*/
|
|
131
|
+
assertPostStatus(id: string, status: string) {
|
|
132
|
+
cy.get(this.selectors.row(id)).should('contain.text', status)
|
|
133
|
+
return this
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export default PostsPOM
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TasksPOM - Page Object Model for Tasks entity
|
|
3
|
+
*
|
|
4
|
+
* Extends DashboardEntityPOM with task-specific form handling and workflows.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* // Instance usage with chaining
|
|
8
|
+
* TasksPOM.create()
|
|
9
|
+
* .visitList()
|
|
10
|
+
* .waitForList()
|
|
11
|
+
* .clickAdd()
|
|
12
|
+
* .fillTaskForm({ title: 'New Task', priority: 'high' })
|
|
13
|
+
* .submitForm()
|
|
14
|
+
*
|
|
15
|
+
* // API-aware workflow
|
|
16
|
+
* const tasks = new TasksPOM()
|
|
17
|
+
* tasks.createTaskWithApiWait({
|
|
18
|
+
* title: 'New Task',
|
|
19
|
+
* description: 'Task description',
|
|
20
|
+
* status: 'todo',
|
|
21
|
+
* priority: 'high'
|
|
22
|
+
* })
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import { DashboardEntityPOM } from '../core/DashboardEntityPOM'
|
|
26
|
+
import entitiesConfig from '../../fixtures/entities.json'
|
|
27
|
+
|
|
28
|
+
export interface TaskFormData {
|
|
29
|
+
title: string
|
|
30
|
+
description?: string
|
|
31
|
+
status?: 'todo' | 'in-progress' | 'review' | 'done' | 'blocked'
|
|
32
|
+
priority?: 'low' | 'medium' | 'high' | 'urgent'
|
|
33
|
+
dueDate?: string
|
|
34
|
+
estimatedHours?: string
|
|
35
|
+
completed?: boolean
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export class TasksPOM extends DashboardEntityPOM {
|
|
39
|
+
constructor() {
|
|
40
|
+
super(entitiesConfig.entities.tasks.slug)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// ============================================
|
|
44
|
+
// FACTORY METHOD
|
|
45
|
+
// ============================================
|
|
46
|
+
|
|
47
|
+
static create(): TasksPOM {
|
|
48
|
+
return new TasksPOM()
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// ============================================
|
|
52
|
+
// ENTITY-SPECIFIC FORM METHODS
|
|
53
|
+
// ============================================
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Fill task form with provided data
|
|
57
|
+
* Only fills fields that are provided in the data object
|
|
58
|
+
*/
|
|
59
|
+
fillTaskForm(data: TaskFormData) {
|
|
60
|
+
if (data.title) {
|
|
61
|
+
this.fillTextField('title', data.title)
|
|
62
|
+
}
|
|
63
|
+
if (data.description) {
|
|
64
|
+
this.fillTextarea('description', data.description)
|
|
65
|
+
}
|
|
66
|
+
if (data.status) {
|
|
67
|
+
this.selectOption('status', data.status)
|
|
68
|
+
}
|
|
69
|
+
if (data.priority) {
|
|
70
|
+
this.selectOption('priority', data.priority)
|
|
71
|
+
}
|
|
72
|
+
if (data.dueDate) {
|
|
73
|
+
this.fillTextField('dueDate', data.dueDate)
|
|
74
|
+
}
|
|
75
|
+
if (data.estimatedHours) {
|
|
76
|
+
this.fillTextField('estimatedHours', data.estimatedHours)
|
|
77
|
+
}
|
|
78
|
+
return this
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// ============================================
|
|
82
|
+
// WORKFLOW METHODS
|
|
83
|
+
// ============================================
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Complete create flow without API waits
|
|
87
|
+
*/
|
|
88
|
+
createTask(data: TaskFormData) {
|
|
89
|
+
this.visitCreate()
|
|
90
|
+
this.waitForForm()
|
|
91
|
+
this.fillTaskForm(data)
|
|
92
|
+
this.submitForm()
|
|
93
|
+
return this
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Create task with API intercepts and waits
|
|
98
|
+
* Deterministic: waits for actual API responses
|
|
99
|
+
*/
|
|
100
|
+
createTaskWithApiWait(data: TaskFormData) {
|
|
101
|
+
this.setupApiIntercepts()
|
|
102
|
+
this.clickAdd()
|
|
103
|
+
this.waitForForm()
|
|
104
|
+
this.fillTaskForm(data)
|
|
105
|
+
this.submitForm()
|
|
106
|
+
this.api.waitForCreate()
|
|
107
|
+
return this
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Create task from list page and wait for refresh
|
|
112
|
+
*/
|
|
113
|
+
createTaskFromListWithApiWait(data: TaskFormData) {
|
|
114
|
+
this.setupApiIntercepts()
|
|
115
|
+
this.clickAdd()
|
|
116
|
+
this.waitForForm()
|
|
117
|
+
this.fillTaskForm(data)
|
|
118
|
+
this.submitForm()
|
|
119
|
+
this.api.waitForCreateAndRefresh()
|
|
120
|
+
return this
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Update task with API waits
|
|
125
|
+
*/
|
|
126
|
+
updateTaskWithApiWait(data: Partial<TaskFormData>) {
|
|
127
|
+
this.fillTaskForm(data as TaskFormData)
|
|
128
|
+
this.submitForm()
|
|
129
|
+
this.api.waitForUpdate()
|
|
130
|
+
return this
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Delete task with API waits
|
|
135
|
+
* Flow: Navigate to detail -> Delete -> Confirm
|
|
136
|
+
*/
|
|
137
|
+
deleteTaskWithApiWait(id: string) {
|
|
138
|
+
this.visitDetailWithApiWait(id)
|
|
139
|
+
this.clickDelete()
|
|
140
|
+
this.confirmDelete()
|
|
141
|
+
this.api.waitForDelete()
|
|
142
|
+
return this
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Delete task by finding it in the list by name
|
|
147
|
+
*/
|
|
148
|
+
deleteTaskByNameWithApiWait(name: string) {
|
|
149
|
+
this.clickRowByText(name)
|
|
150
|
+
this.waitForDetail()
|
|
151
|
+
this.clickDelete()
|
|
152
|
+
this.confirmDelete()
|
|
153
|
+
this.api.waitForDelete()
|
|
154
|
+
return this
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// ============================================
|
|
158
|
+
// ENTITY-SPECIFIC ASSERTIONS
|
|
159
|
+
// ============================================
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Assert task appears in list
|
|
163
|
+
*/
|
|
164
|
+
assertTaskInList(title: string) {
|
|
165
|
+
return this.assertInList(title)
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Assert task does not appear in list
|
|
170
|
+
*/
|
|
171
|
+
assertTaskNotInList(title: string) {
|
|
172
|
+
return this.assertNotInList(title)
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
export default TasksPOM
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Entity POM exports
|
|
3
|
+
*
|
|
4
|
+
* Page Object Models for specific entities:
|
|
5
|
+
* - TasksPOM: Tasks CRUD operations
|
|
6
|
+
* - CustomersPOM: Customers CRUD operations
|
|
7
|
+
* - PostsPOM: Posts list operations (use PostEditorPOM for editing)
|
|
8
|
+
* - PagesPOM: Pages list operations (use PageBuilderPOM for editing)
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
export { TasksPOM, type TaskFormData } from './TasksPOM'
|
|
12
|
+
export { CustomersPOM, type CustomerFormData } from './CustomersPOM'
|
|
13
|
+
export { PostsPOM, type PostListFilters } from './PostsPOM'
|
|
14
|
+
export { PagesPOM, type PageListFilters } from './PagesPOM'
|