@nextsparkjs/theme-crm 0.1.0-beta.18 → 0.1.0-beta.20

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 (70) hide show
  1. package/package.json +2 -2
  2. package/tests/cypress/e2e/api/activities/activities-crud.cy.ts +686 -0
  3. package/tests/cypress/e2e/api/campaigns/campaigns-crud.cy.ts +592 -0
  4. package/tests/cypress/e2e/api/companies/companies-crud.cy.ts +682 -0
  5. package/tests/cypress/e2e/api/contacts/contacts-crud.cy.ts +668 -0
  6. package/tests/cypress/e2e/api/leads/leads-crud.cy.ts +648 -0
  7. package/tests/cypress/e2e/api/notes/notes-crud.cy.ts +424 -0
  8. package/tests/cypress/e2e/api/opportunities/opportunities-crud.cy.ts +865 -0
  9. package/tests/cypress/e2e/api/pipelines/pipelines-crud.cy.ts +545 -0
  10. package/tests/cypress/e2e/api/products/products-crud.cy.ts +447 -0
  11. package/tests/cypress/e2e/ui/activities/activities-admin.cy.ts +268 -0
  12. package/tests/cypress/e2e/ui/activities/activities-member.cy.ts +257 -0
  13. package/tests/cypress/e2e/ui/activities/activities-owner.cy.ts +268 -0
  14. package/tests/cypress/e2e/ui/companies/companies-admin.cy.ts +188 -0
  15. package/tests/cypress/e2e/ui/companies/companies-member.cy.ts +166 -0
  16. package/tests/cypress/e2e/ui/companies/companies-owner.cy.ts +189 -0
  17. package/tests/cypress/e2e/ui/contacts/contacts-admin.cy.ts +252 -0
  18. package/tests/cypress/e2e/ui/contacts/contacts-member.cy.ts +224 -0
  19. package/tests/cypress/e2e/ui/contacts/contacts-owner.cy.ts +236 -0
  20. package/tests/cypress/e2e/ui/leads/leads-admin.cy.ts +286 -0
  21. package/tests/cypress/e2e/ui/leads/leads-member.cy.ts +193 -0
  22. package/tests/cypress/e2e/ui/leads/leads-owner.cy.ts +210 -0
  23. package/tests/cypress/e2e/ui/opportunities/opportunities-admin.cy.ts +197 -0
  24. package/tests/cypress/e2e/ui/opportunities/opportunities-member.cy.ts +229 -0
  25. package/tests/cypress/e2e/ui/opportunities/opportunities-owner.cy.ts +196 -0
  26. package/tests/cypress/e2e/ui/pipelines/pipelines-admin.cy.ts +320 -0
  27. package/tests/cypress/e2e/ui/pipelines/pipelines-member.cy.ts +262 -0
  28. package/tests/cypress/e2e/ui/pipelines/pipelines-owner.cy.ts +282 -0
  29. package/tests/cypress/fixtures/blocks.json +9 -0
  30. package/tests/cypress/fixtures/entities.json +240 -0
  31. package/tests/cypress/src/components/CRMDataTable.js +223 -0
  32. package/tests/cypress/src/components/CRMMobileNav.js +138 -0
  33. package/tests/cypress/src/components/CRMSidebar.js +145 -0
  34. package/tests/cypress/src/components/CRMTopBar.js +194 -0
  35. package/tests/cypress/src/components/DealCard.js +197 -0
  36. package/tests/cypress/src/components/EntityDetail.ts +290 -0
  37. package/tests/cypress/src/components/EntityForm.ts +357 -0
  38. package/tests/cypress/src/components/EntityList.ts +360 -0
  39. package/tests/cypress/src/components/PipelineKanban.js +204 -0
  40. package/tests/cypress/src/components/StageColumn.js +196 -0
  41. package/tests/cypress/src/components/index.js +13 -0
  42. package/tests/cypress/src/components/index.ts +22 -0
  43. package/tests/cypress/src/controllers/ActivityAPIController.ts +113 -0
  44. package/tests/cypress/src/controllers/BaseAPIController.ts +307 -0
  45. package/tests/cypress/src/controllers/CampaignAPIController.ts +114 -0
  46. package/tests/cypress/src/controllers/CompanyAPIController.ts +112 -0
  47. package/tests/cypress/src/controllers/ContactAPIController.ts +104 -0
  48. package/tests/cypress/src/controllers/LeadAPIController.ts +96 -0
  49. package/tests/cypress/src/controllers/NoteAPIController.ts +130 -0
  50. package/tests/cypress/src/controllers/OpportunityAPIController.ts +134 -0
  51. package/tests/cypress/src/controllers/PipelineAPIController.ts +116 -0
  52. package/tests/cypress/src/controllers/ProductAPIController.ts +113 -0
  53. package/tests/cypress/src/controllers/index.ts +35 -0
  54. package/tests/cypress/src/entities/ActivitiesPOM.ts +130 -0
  55. package/tests/cypress/src/entities/CompaniesPOM.ts +117 -0
  56. package/tests/cypress/src/entities/ContactsPOM.ts +117 -0
  57. package/tests/cypress/src/entities/LeadsPOM.ts +129 -0
  58. package/tests/cypress/src/entities/OpportunitiesPOM.ts +178 -0
  59. package/tests/cypress/src/entities/PipelinesPOM.ts +341 -0
  60. package/tests/cypress/src/entities/index.ts +31 -0
  61. package/tests/cypress/src/forms/OpportunityForm.js +316 -0
  62. package/tests/cypress/src/forms/PipelineForm.js +243 -0
  63. package/tests/cypress/src/forms/index.js +8 -0
  64. package/tests/cypress/src/index.js +22 -0
  65. package/tests/cypress/src/index.ts +68 -0
  66. package/tests/cypress/src/selectors.ts +50 -0
  67. package/tests/cypress/src/session-helpers.ts +94 -0
  68. package/tests/cypress/support/e2e.ts +89 -0
  69. package/tests/cypress.config.ts +165 -0
  70. package/tests/tsconfig.json +15 -0
@@ -0,0 +1,316 @@
1
+ /**
2
+ * OpportunityForm - Page Object Model Class
3
+ *
4
+ * POM for the opportunity/deal create/edit form in CRM theme.
5
+ * Handles opportunity form interactions and validations.
6
+ */
7
+ export class OpportunityForm {
8
+ static selectors = {
9
+ form: '[data-cy="opportunity-form"]',
10
+ nameInput: '[data-cy="opportunity-field-name"] input',
11
+ nameField: '[data-cy="opportunity-field-name"]',
12
+ companySelect: '[data-cy="opportunity-field-company"]',
13
+ companyInput: '[data-cy="opportunity-field-company"] select',
14
+ contactSelect: '[data-cy="opportunity-field-contact"]',
15
+ contactInput: '[data-cy="opportunity-field-contact"] select',
16
+ pipelineSelect: '[data-cy="opportunity-field-pipeline"]',
17
+ pipelineInput: '[data-cy="opportunity-field-pipeline"] select',
18
+ stageSelect: '[data-cy="opportunity-field-stage"]',
19
+ stageInput: '[data-cy="opportunity-field-stage"] select',
20
+ amountInput: '[data-cy="opportunity-field-amount"] input',
21
+ amountField: '[data-cy="opportunity-field-amount"]',
22
+ probabilityInput: '[data-cy="opportunity-field-probability"] input',
23
+ probabilityField: '[data-cy="opportunity-field-probability"]',
24
+ expectedCloseDateInput: '[data-cy="opportunity-field-expectedCloseDate"] input',
25
+ expectedCloseDateField: '[data-cy="opportunity-field-expectedCloseDate"]',
26
+ descriptionInput: '[data-cy="opportunity-field-description"] textarea',
27
+ descriptionField: '[data-cy="opportunity-field-description"]',
28
+ ownerSelect: '[data-cy="opportunity-field-owner"]',
29
+ ownerInput: '[data-cy="opportunity-field-owner"] select',
30
+ prioritySelect: '[data-cy="opportunity-field-priority"]',
31
+ priorityInput: '[data-cy="opportunity-field-priority"] select',
32
+ submitBtn: '[data-cy="opportunity-form-submit"]',
33
+ cancelBtn: '[data-cy="opportunity-form-cancel"]',
34
+ error: '[data-cy="opportunity-form-error"]',
35
+ fieldError: '[class*="error"], [data-error="true"]',
36
+ }
37
+
38
+ /**
39
+ * Validate form is visible
40
+ */
41
+ validateVisible() {
42
+ cy.get(OpportunityForm.selectors.form).should('be.visible')
43
+ return this
44
+ }
45
+
46
+ /**
47
+ * Validate form is not visible
48
+ */
49
+ validateNotVisible() {
50
+ cy.get(OpportunityForm.selectors.form).should('not.exist')
51
+ return this
52
+ }
53
+
54
+ /**
55
+ * Fill opportunity name
56
+ * @param {string} name - Opportunity name
57
+ */
58
+ fillName(name) {
59
+ cy.get(OpportunityForm.selectors.nameInput).clear().type(name)
60
+ return this
61
+ }
62
+
63
+ /**
64
+ * Clear opportunity name
65
+ */
66
+ clearName() {
67
+ cy.get(OpportunityForm.selectors.nameInput).clear()
68
+ return this
69
+ }
70
+
71
+ /**
72
+ * Select company
73
+ * @param {string} company - Company name or ID
74
+ */
75
+ selectCompany(company) {
76
+ cy.get(OpportunityForm.selectors.companyInput).select(company)
77
+ return this
78
+ }
79
+
80
+ /**
81
+ * Select contact
82
+ * @param {string} contact - Contact name or ID
83
+ */
84
+ selectContact(contact) {
85
+ cy.get(OpportunityForm.selectors.contactInput).select(contact)
86
+ return this
87
+ }
88
+
89
+ /**
90
+ * Select pipeline
91
+ * @param {string} pipeline - Pipeline name or ID
92
+ */
93
+ selectPipeline(pipeline) {
94
+ cy.get(OpportunityForm.selectors.pipelineInput).select(pipeline)
95
+ return this
96
+ }
97
+
98
+ /**
99
+ * Select stage
100
+ * @param {string} stage - Stage name or ID
101
+ */
102
+ selectStage(stage) {
103
+ cy.get(OpportunityForm.selectors.stageInput).select(stage)
104
+ return this
105
+ }
106
+
107
+ /**
108
+ * Fill opportunity amount
109
+ * @param {string|number} amount - Opportunity amount
110
+ */
111
+ fillAmount(amount) {
112
+ cy.get(OpportunityForm.selectors.amountInput).clear().type(amount.toString())
113
+ return this
114
+ }
115
+
116
+ /**
117
+ * Clear opportunity amount
118
+ */
119
+ clearAmount() {
120
+ cy.get(OpportunityForm.selectors.amountInput).clear()
121
+ return this
122
+ }
123
+
124
+ /**
125
+ * Fill probability percentage
126
+ * @param {string|number} probability - Probability (0-100)
127
+ */
128
+ fillProbability(probability) {
129
+ cy.get(OpportunityForm.selectors.probabilityInput).clear().type(probability.toString())
130
+ return this
131
+ }
132
+
133
+ /**
134
+ * Clear probability
135
+ */
136
+ clearProbability() {
137
+ cy.get(OpportunityForm.selectors.probabilityInput).clear()
138
+ return this
139
+ }
140
+
141
+ /**
142
+ * Fill expected close date
143
+ * @param {string} date - Date in YYYY-MM-DD format
144
+ */
145
+ fillExpectedCloseDate(date) {
146
+ cy.get(OpportunityForm.selectors.expectedCloseDateInput).clear().type(date)
147
+ return this
148
+ }
149
+
150
+ /**
151
+ * Clear expected close date
152
+ */
153
+ clearExpectedCloseDate() {
154
+ cy.get(OpportunityForm.selectors.expectedCloseDateInput).clear()
155
+ return this
156
+ }
157
+
158
+ /**
159
+ * Fill opportunity description
160
+ * @param {string} description - Opportunity description
161
+ */
162
+ fillDescription(description) {
163
+ cy.get(OpportunityForm.selectors.descriptionInput).clear().type(description)
164
+ return this
165
+ }
166
+
167
+ /**
168
+ * Clear description
169
+ */
170
+ clearDescription() {
171
+ cy.get(OpportunityForm.selectors.descriptionInput).clear()
172
+ return this
173
+ }
174
+
175
+ /**
176
+ * Select owner
177
+ * @param {string} owner - Owner name or ID
178
+ */
179
+ selectOwner(owner) {
180
+ cy.get(OpportunityForm.selectors.ownerInput).select(owner)
181
+ return this
182
+ }
183
+
184
+ /**
185
+ * Select priority
186
+ * @param {string} priority - Priority (low, medium, high)
187
+ */
188
+ selectPriority(priority) {
189
+ cy.get(OpportunityForm.selectors.priorityInput).select(priority)
190
+ return this
191
+ }
192
+
193
+ /**
194
+ * Submit the form
195
+ */
196
+ submit() {
197
+ cy.get(OpportunityForm.selectors.submitBtn).click()
198
+ return this
199
+ }
200
+
201
+ /**
202
+ * Cancel the form
203
+ */
204
+ cancel() {
205
+ cy.get(OpportunityForm.selectors.cancelBtn).click()
206
+ return this
207
+ }
208
+
209
+ /**
210
+ * Validate submit button is enabled
211
+ */
212
+ validateSubmitEnabled() {
213
+ cy.get(OpportunityForm.selectors.submitBtn).should('not.be.disabled')
214
+ return this
215
+ }
216
+
217
+ /**
218
+ * Validate submit button is disabled
219
+ */
220
+ validateSubmitDisabled() {
221
+ cy.get(OpportunityForm.selectors.submitBtn).should('be.disabled')
222
+ return this
223
+ }
224
+
225
+ /**
226
+ * Validate form error message
227
+ * @param {string} message - Expected error message
228
+ */
229
+ validateError(message) {
230
+ cy.get(OpportunityForm.selectors.error).should('be.visible').and('contain', message)
231
+ return this
232
+ }
233
+
234
+ /**
235
+ * Validate no form error
236
+ */
237
+ validateNoError() {
238
+ cy.get(OpportunityForm.selectors.error).should('not.exist')
239
+ return this
240
+ }
241
+
242
+ /**
243
+ * Validate field error
244
+ * @param {string} fieldName - Field name
245
+ */
246
+ validateFieldError(fieldName) {
247
+ const fieldSelector = OpportunityForm.selectors[`${fieldName}Field`]
248
+ cy.get(fieldSelector).within(() => {
249
+ cy.get(OpportunityForm.selectors.fieldError).should('exist')
250
+ })
251
+ return this
252
+ }
253
+
254
+ /**
255
+ * Validate no field error
256
+ * @param {string} fieldName - Field name
257
+ */
258
+ validateNoFieldError(fieldName) {
259
+ const fieldSelector = OpportunityForm.selectors[`${fieldName}Field`]
260
+ cy.get(fieldSelector).within(() => {
261
+ cy.get(OpportunityForm.selectors.fieldError).should('not.exist')
262
+ })
263
+ return this
264
+ }
265
+
266
+ /**
267
+ * Validate field value
268
+ * @param {string} fieldName - Field name (name, amount, probability, etc.)
269
+ * @param {string} value - Expected value
270
+ */
271
+ validateFieldValue(fieldName, value) {
272
+ const inputSelector = OpportunityForm.selectors[`${fieldName}Input`]
273
+ cy.get(inputSelector).should('have.value', value)
274
+ return this
275
+ }
276
+
277
+ /**
278
+ * Fill complete opportunity form
279
+ * @param {Object} data - Opportunity data
280
+ * @param {string} data.name - Opportunity name
281
+ * @param {string} data.company - Company ID
282
+ * @param {string} data.contact - Contact ID (optional)
283
+ * @param {string} data.pipeline - Pipeline ID
284
+ * @param {string} data.stage - Stage ID
285
+ * @param {number} data.amount - Amount
286
+ * @param {number} data.probability - Probability (optional)
287
+ * @param {string} data.expectedCloseDate - Expected close date (optional)
288
+ * @param {string} data.description - Description (optional)
289
+ * @param {string} data.owner - Owner ID (optional)
290
+ * @param {string} data.priority - Priority (optional)
291
+ */
292
+ fillForm(data) {
293
+ if (data.name) this.fillName(data.name)
294
+ if (data.company) this.selectCompany(data.company)
295
+ if (data.contact) this.selectContact(data.contact)
296
+ if (data.pipeline) this.selectPipeline(data.pipeline)
297
+ if (data.stage) this.selectStage(data.stage)
298
+ if (data.amount !== undefined) this.fillAmount(data.amount)
299
+ if (data.probability !== undefined) this.fillProbability(data.probability)
300
+ if (data.expectedCloseDate) this.fillExpectedCloseDate(data.expectedCloseDate)
301
+ if (data.description) this.fillDescription(data.description)
302
+ if (data.owner) this.selectOwner(data.owner)
303
+ if (data.priority) this.selectPriority(data.priority)
304
+ return this
305
+ }
306
+
307
+ /**
308
+ * Create an opportunity (fill and submit)
309
+ * @param {Object} data - Opportunity data
310
+ */
311
+ createOpportunity(data) {
312
+ this.fillForm(data)
313
+ this.submit()
314
+ return this
315
+ }
316
+ }
@@ -0,0 +1,243 @@
1
+ /**
2
+ * PipelineForm - Page Object Model Class
3
+ *
4
+ * POM for the pipeline create/edit form in CRM theme.
5
+ * Handles pipeline form interactions and validations.
6
+ */
7
+ export class PipelineForm {
8
+ static selectors = {
9
+ form: '[data-cy="pipeline-form"]',
10
+ nameInput: '[data-cy="pipeline-field-name"] input',
11
+ nameField: '[data-cy="pipeline-field-name"]',
12
+ typeSelect: '[data-cy="pipeline-field-type"]',
13
+ typeInput: '[data-cy="pipeline-field-type"] select',
14
+ descriptionInput: '[data-cy="pipeline-field-description"] textarea',
15
+ descriptionField: '[data-cy="pipeline-field-description"]',
16
+ isActiveCheckbox: '[data-cy="pipeline-field-isActive"] input[type="checkbox"]',
17
+ isActiveField: '[data-cy="pipeline-field-isActive"]',
18
+ submitBtn: '[data-cy="pipeline-form-submit"]',
19
+ cancelBtn: '[data-cy="pipeline-form-cancel"]',
20
+ error: '[data-cy="pipeline-form-error"]',
21
+ fieldError: '[class*="error"], [data-error="true"]',
22
+ }
23
+
24
+ /**
25
+ * Validate form is visible
26
+ */
27
+ validateVisible() {
28
+ cy.get(PipelineForm.selectors.form).should('be.visible')
29
+ return this
30
+ }
31
+
32
+ /**
33
+ * Validate form is not visible
34
+ */
35
+ validateNotVisible() {
36
+ cy.get(PipelineForm.selectors.form).should('not.exist')
37
+ return this
38
+ }
39
+
40
+ /**
41
+ * Fill pipeline name
42
+ * @param {string} name - Pipeline name
43
+ */
44
+ fillName(name) {
45
+ cy.get(PipelineForm.selectors.nameInput).clear().type(name)
46
+ return this
47
+ }
48
+
49
+ /**
50
+ * Clear pipeline name
51
+ */
52
+ clearName() {
53
+ cy.get(PipelineForm.selectors.nameInput).clear()
54
+ return this
55
+ }
56
+
57
+ /**
58
+ * Validate name field value
59
+ * @param {string} name - Expected name
60
+ */
61
+ validateNameValue(name) {
62
+ cy.get(PipelineForm.selectors.nameInput).should('have.value', name)
63
+ return this
64
+ }
65
+
66
+ /**
67
+ * Select pipeline type
68
+ * @param {string} type - Pipeline type (sales, marketing, support, custom)
69
+ */
70
+ selectType(type) {
71
+ cy.get(PipelineForm.selectors.typeInput).select(type)
72
+ return this
73
+ }
74
+
75
+ /**
76
+ * Validate type field value
77
+ * @param {string} type - Expected type
78
+ */
79
+ validateTypeValue(type) {
80
+ cy.get(PipelineForm.selectors.typeInput).should('have.value', type)
81
+ return this
82
+ }
83
+
84
+ /**
85
+ * Fill pipeline description
86
+ * @param {string} description - Pipeline description
87
+ */
88
+ fillDescription(description) {
89
+ cy.get(PipelineForm.selectors.descriptionInput).clear().type(description)
90
+ return this
91
+ }
92
+
93
+ /**
94
+ * Clear pipeline description
95
+ */
96
+ clearDescription() {
97
+ cy.get(PipelineForm.selectors.descriptionInput).clear()
98
+ return this
99
+ }
100
+
101
+ /**
102
+ * Validate description field value
103
+ * @param {string} description - Expected description
104
+ */
105
+ validateDescriptionValue(description) {
106
+ cy.get(PipelineForm.selectors.descriptionInput).should('have.value', description)
107
+ return this
108
+ }
109
+
110
+ /**
111
+ * Toggle isActive checkbox
112
+ */
113
+ toggleIsActive() {
114
+ cy.get(PipelineForm.selectors.isActiveCheckbox).click()
115
+ return this
116
+ }
117
+
118
+ /**
119
+ * Set isActive checkbox
120
+ * @param {boolean} active - True to check, false to uncheck
121
+ */
122
+ setIsActive(active) {
123
+ cy.get(PipelineForm.selectors.isActiveCheckbox).then($checkbox => {
124
+ const isChecked = $checkbox.is(':checked')
125
+ if ((active && !isChecked) || (!active && isChecked)) {
126
+ cy.get(PipelineForm.selectors.isActiveCheckbox).click()
127
+ }
128
+ })
129
+ return this
130
+ }
131
+
132
+ /**
133
+ * Validate isActive checkbox state
134
+ * @param {boolean} checked - Expected checked state
135
+ */
136
+ validateIsActiveChecked(checked) {
137
+ if (checked) {
138
+ cy.get(PipelineForm.selectors.isActiveCheckbox).should('be.checked')
139
+ } else {
140
+ cy.get(PipelineForm.selectors.isActiveCheckbox).should('not.be.checked')
141
+ }
142
+ return this
143
+ }
144
+
145
+ /**
146
+ * Submit the form
147
+ */
148
+ submit() {
149
+ cy.get(PipelineForm.selectors.submitBtn).click()
150
+ return this
151
+ }
152
+
153
+ /**
154
+ * Cancel the form
155
+ */
156
+ cancel() {
157
+ cy.get(PipelineForm.selectors.cancelBtn).click()
158
+ return this
159
+ }
160
+
161
+ /**
162
+ * Validate submit button is enabled
163
+ */
164
+ validateSubmitEnabled() {
165
+ cy.get(PipelineForm.selectors.submitBtn).should('not.be.disabled')
166
+ return this
167
+ }
168
+
169
+ /**
170
+ * Validate submit button is disabled
171
+ */
172
+ validateSubmitDisabled() {
173
+ cy.get(PipelineForm.selectors.submitBtn).should('be.disabled')
174
+ return this
175
+ }
176
+
177
+ /**
178
+ * Validate form error message
179
+ * @param {string} message - Expected error message
180
+ */
181
+ validateError(message) {
182
+ cy.get(PipelineForm.selectors.error).should('be.visible').and('contain', message)
183
+ return this
184
+ }
185
+
186
+ /**
187
+ * Validate no form error
188
+ */
189
+ validateNoError() {
190
+ cy.get(PipelineForm.selectors.error).should('not.exist')
191
+ return this
192
+ }
193
+
194
+ /**
195
+ * Validate field error
196
+ * @param {string} fieldName - Field name (name, type, description)
197
+ */
198
+ validateFieldError(fieldName) {
199
+ const fieldSelector = PipelineForm.selectors[`${fieldName}Field`]
200
+ cy.get(fieldSelector).within(() => {
201
+ cy.get(PipelineForm.selectors.fieldError).should('exist')
202
+ })
203
+ return this
204
+ }
205
+
206
+ /**
207
+ * Validate no field error
208
+ * @param {string} fieldName - Field name (name, type, description)
209
+ */
210
+ validateNoFieldError(fieldName) {
211
+ const fieldSelector = PipelineForm.selectors[`${fieldName}Field`]
212
+ cy.get(fieldSelector).within(() => {
213
+ cy.get(PipelineForm.selectors.fieldError).should('not.exist')
214
+ })
215
+ return this
216
+ }
217
+
218
+ /**
219
+ * Fill complete pipeline form
220
+ * @param {Object} data - Pipeline data
221
+ * @param {string} data.name - Pipeline name
222
+ * @param {string} data.type - Pipeline type
223
+ * @param {string} data.description - Pipeline description (optional)
224
+ * @param {boolean} data.isActive - Is active (optional, defaults to true)
225
+ */
226
+ fillForm(data) {
227
+ if (data.name) this.fillName(data.name)
228
+ if (data.type) this.selectType(data.type)
229
+ if (data.description) this.fillDescription(data.description)
230
+ if (data.isActive !== undefined) this.setIsActive(data.isActive)
231
+ return this
232
+ }
233
+
234
+ /**
235
+ * Create a pipeline (fill and submit)
236
+ * @param {Object} data - Pipeline data
237
+ */
238
+ createPipeline(data) {
239
+ this.fillForm(data)
240
+ this.submit()
241
+ return this
242
+ }
243
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * CRM Theme Forms - Export Index
3
+ *
4
+ * Exports all CRM theme form POM classes.
5
+ */
6
+
7
+ export { PipelineForm } from './PipelineForm.js'
8
+ export { OpportunityForm } from './OpportunityForm.js'
@@ -0,0 +1,22 @@
1
+ /**
2
+ * CRM Theme - Main Export Index
3
+ *
4
+ * Exports all CRM theme POM classes (components and forms).
5
+ */
6
+
7
+ // Components
8
+ export {
9
+ CRMSidebar,
10
+ CRMTopBar,
11
+ CRMMobileNav,
12
+ CRMDataTable,
13
+ PipelineKanban,
14
+ StageColumn,
15
+ DealCard,
16
+ } from './components/index.js'
17
+
18
+ // Forms
19
+ export {
20
+ PipelineForm,
21
+ OpportunityForm,
22
+ } from './forms/index.js'
@@ -0,0 +1,68 @@
1
+ /**
2
+ * CRM Theme - Main Export Index
3
+ *
4
+ * Exports all CRM theme POM classes:
5
+ * - Generic components (EntityList, EntityForm, EntityDetail)
6
+ * - Entity-specific POMs (PipelinesPOM, OpportunitiesPOM, etc.)
7
+ * - API Controllers (TypeScript ES modules)
8
+ *
9
+ * Usage:
10
+ * import { PipelinesPOM, EntityList } from '../classes/themes/crm'
11
+ * import { ActivityAPIController } from '../classes/themes/crm/controllers'
12
+ */
13
+
14
+ // Generic Components (Entity Testing Convention)
15
+ export {
16
+ EntityList,
17
+ EntityForm,
18
+ EntityDetail,
19
+ type EntityConfig,
20
+ type EntityDetailConfig,
21
+ } from './components'
22
+
23
+ // Entity-specific POMs
24
+ export {
25
+ PipelinesPOM,
26
+ OpportunitiesPOM,
27
+ LeadsPOM,
28
+ ContactsPOM,
29
+ CompaniesPOM,
30
+ ActivitiesPOM,
31
+ } from './entities'
32
+
33
+ // Session helpers
34
+ export {
35
+ loginAsCrmOwner,
36
+ loginAsCrmAdmin,
37
+ loginAsCrmMember,
38
+ loginAsCrmLaura,
39
+ CRM_USERS,
40
+ } from './session-helpers'
41
+
42
+ // API Controllers (TypeScript ES modules)
43
+ // Usage: import { ActivityAPIController } from '../classes/themes/crm/controllers'
44
+ //
45
+ // Available controllers:
46
+ // - BaseAPIController (abstract base class)
47
+ // - ActivityAPIController
48
+ // - LeadAPIController
49
+ // - ProductAPIController
50
+ // - PipelineAPIController
51
+ // - ContactAPIController
52
+ // - CampaignAPIController
53
+ // - CompanyAPIController
54
+ // - OpportunityAPIController
55
+ // - NoteAPIController
56
+ //
57
+ // All controllers extend BaseAPIController and provide:
58
+ // - CRUD operations (getAll, getById, create, update, delete)
59
+ // - createTestRecord() with retry support
60
+ // - validateObject() for response validation
61
+ // - Entity-specific methods (complete, pin, closeAsWon, etc.)
62
+
63
+ // Re-export default objects for namespace imports
64
+ import * as Components from './components'
65
+ import * as Entities from './entities'
66
+ import * as Controllers from './controllers'
67
+
68
+ export { Components, Entities, Controllers }
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Theme Selectors for Cypress Tests
3
+ *
4
+ * This file re-exports from the main selectors in lib/.
5
+ * The lib/selectors.ts is the source of truth, placed there so
6
+ * block components can import it (tests/ is excluded from TypeScript).
7
+ *
8
+ * Architecture:
9
+ * - Core selectors: `core/lib/test/core-selectors.ts`
10
+ * - Theme selectors (source): `lib/selectors.ts`
11
+ * - Theme selectors (tests): This file (re-exports)
12
+ *
13
+ * @example POM usage:
14
+ * ```typescript
15
+ * import { cySelector, sel, SELECTORS } from '../selectors'
16
+ *
17
+ * class MyPOM extends BasePOM {
18
+ * get elements() {
19
+ * return {
20
+ * loginForm: cySelector('auth.login.form'),
21
+ * submitButton: cySelector('auth.login.submit'),
22
+ * leadsList: cySelector('entities.leads.list'),
23
+ * }
24
+ * }
25
+ * }
26
+ * ```
27
+ */
28
+
29
+ // Re-export everything from the lib selectors
30
+ export {
31
+ BLOCK_SELECTORS,
32
+ ENTITY_SELECTORS,
33
+ CRM_SELECTORS,
34
+ THEME_SELECTORS,
35
+ SELECTORS,
36
+ sel,
37
+ s,
38
+ selDev,
39
+ cySelector,
40
+ entitySelectors,
41
+ CORE_SELECTORS,
42
+ } from '../../../lib/selectors'
43
+
44
+ export type {
45
+ ThemeSelectorsType,
46
+ BlockSelectorsType,
47
+ EntitySelectorsType,
48
+ CRMSelectorsType,
49
+ Replacements,
50
+ } from '../../../lib/selectors'