@nextsparkjs/theme-crm 0.1.0-beta.19 → 0.1.0-beta.24

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 (74) hide show
  1. package/package.json +3 -3
  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/jest/__mocks__/jose.js +22 -0
  71. package/tests/jest/__mocks__/next-server.js +56 -0
  72. package/tests/jest/jest.config.cjs +127 -0
  73. package/tests/jest/setup.ts +170 -0
  74. package/tests/tsconfig.json +15 -0
@@ -0,0 +1,196 @@
1
+ /// <reference types="cypress" />
2
+
3
+ /**
4
+ * Opportunities CRUD - Owner Role (Full Access)
5
+ *
6
+ * Uses CRM theme-specific POMs with Entity Testing Convention.
7
+ * Selectors follow the pattern: {slug}-{component}-{detail}
8
+ */
9
+
10
+ import { OpportunitiesPOM } from '../../../src/entities/OpportunitiesPOM'
11
+ import { loginAsCrmOwner } from '../../../src/session-helpers'
12
+
13
+ describe('Opportunities CRUD - Owner Role (Full Access)', () => {
14
+ const opportunities = new OpportunitiesPOM()
15
+
16
+ beforeEach(() => {
17
+ loginAsCrmOwner()
18
+ cy.visit('/dashboard/opportunities')
19
+ opportunities.list.validatePageVisible()
20
+ })
21
+
22
+ describe('CREATE - Owner can create opportunities', () => {
23
+ it('OWNER_OPPO_CREATE_001: should create new opportunity with required fields', () => {
24
+ const timestamp = Date.now()
25
+ const opportunityName = `Test Opportunity ${timestamp}`
26
+
27
+ opportunities.list.clickCreate()
28
+ opportunities.form.validateFormVisible()
29
+
30
+ opportunities.fillOpportunityForm({
31
+ name: opportunityName,
32
+ amount: '50000'
33
+ })
34
+
35
+ opportunities.submitForm()
36
+
37
+ cy.url().should('include', '/dashboard/opportunities')
38
+ cy.contains(opportunityName).should('be.visible')
39
+ })
40
+
41
+ it('OWNER_OPPO_CREATE_002: should create opportunity with all fields', () => {
42
+ const timestamp = Date.now()
43
+ const opportunityName = `Complete Opportunity ${timestamp}`
44
+
45
+ opportunities.list.clickCreate()
46
+ opportunities.form.validateFormVisible()
47
+
48
+ opportunities.fillOpportunityForm({
49
+ name: opportunityName,
50
+ amount: '75000',
51
+ probability: '60'
52
+ })
53
+
54
+ opportunities.submitForm()
55
+
56
+ cy.url().should('include', '/dashboard/opportunities')
57
+ cy.contains(opportunityName).should('be.visible')
58
+ })
59
+
60
+ it('OWNER_OPPO_CREATE_003: should validate required fields', () => {
61
+ opportunities.list.clickCreate()
62
+ opportunities.form.validateFormVisible()
63
+
64
+ // Try to submit without filling required fields
65
+ opportunities.submitForm()
66
+
67
+ // Should remain on form page due to validation errors
68
+ opportunities.form.validateFormVisible()
69
+ })
70
+ })
71
+
72
+ describe('READ - Owner can read opportunities', () => {
73
+ it('OWNER_OPPO_READ_001: should view opportunity list', () => {
74
+ opportunities.list.validatePageVisible()
75
+ opportunities.list.validateTableVisible()
76
+ })
77
+
78
+ it('OWNER_OPPO_READ_002: should view opportunity details', () => {
79
+ cy.get(opportunities.list.selectors.rowGeneric).then($rows => {
80
+ if ($rows.length > 0) {
81
+ opportunities.list.clickRowByIndex(0)
82
+ cy.url().should('match', /\/dashboard\/opportunities\/[a-z0-9-]+/)
83
+ }
84
+ })
85
+ })
86
+
87
+ it('OWNER_OPPO_READ_003: should search opportunities', () => {
88
+ opportunities.list.search('test')
89
+ cy.wait(500)
90
+ opportunities.list.clearSearch()
91
+ })
92
+ })
93
+
94
+ describe('UPDATE - Owner can update opportunities', () => {
95
+ it('OWNER_OPPO_UPDATE_001: should edit opportunity name', () => {
96
+ cy.get(opportunities.list.selectors.rowGeneric).then($rows => {
97
+ if ($rows.length > 0) {
98
+ opportunities.list.clickRowByIndex(0)
99
+
100
+ cy.url().then(url => {
101
+ const opportunityId = url.split('/').pop()
102
+ opportunities.form.visitEdit(opportunityId!)
103
+ opportunities.form.validateFormVisible()
104
+
105
+ const updatedName = `Updated Opportunity ${Date.now()}`
106
+ opportunities.form.typeInField('name', updatedName)
107
+
108
+ opportunities.submitForm()
109
+
110
+ cy.url().should('include', '/dashboard/opportunities')
111
+ cy.contains(updatedName).should('be.visible')
112
+ })
113
+ }
114
+ })
115
+ })
116
+
117
+ it('OWNER_OPPO_UPDATE_002: should update opportunity value', () => {
118
+ cy.get(opportunities.list.selectors.rowGeneric).then($rows => {
119
+ if ($rows.length > 0) {
120
+ opportunities.list.clickRowByIndex(0)
121
+
122
+ cy.url().then(url => {
123
+ const opportunityId = url.split('/').pop()
124
+ opportunities.form.visitEdit(opportunityId!)
125
+ opportunities.form.validateFormVisible()
126
+
127
+ opportunities.form.typeInField('amount', '100000')
128
+
129
+ opportunities.submitForm()
130
+ cy.url().should('include', '/dashboard/opportunities')
131
+ })
132
+ }
133
+ })
134
+ })
135
+
136
+ it('OWNER_OPPO_UPDATE_003: should cancel update without saving', () => {
137
+ cy.get(opportunities.list.selectors.rowGeneric).then($rows => {
138
+ if ($rows.length > 0) {
139
+ opportunities.list.clickRowByIndex(0)
140
+
141
+ cy.url().then(url => {
142
+ const opportunityId = url.split('/').pop()
143
+ opportunities.form.visitEdit(opportunityId!)
144
+ opportunities.form.validateFormVisible()
145
+
146
+ opportunities.form.typeInField('name', 'ShouldNotSave')
147
+
148
+ opportunities.form.cancel()
149
+ cy.url().should('not.include', '/edit')
150
+ })
151
+ }
152
+ })
153
+ })
154
+ })
155
+
156
+ describe('DELETE - Owner can delete opportunities', () => {
157
+ it('OWNER_OPPO_DELETE_001: should delete opportunity successfully', () => {
158
+ const timestamp = Date.now()
159
+ const opportunityName = `Delete Test ${timestamp}`
160
+
161
+ opportunities.list.clickCreate()
162
+ opportunities.fillOpportunityForm({
163
+ name: opportunityName,
164
+ amount: '25000'
165
+ })
166
+ opportunities.submitForm()
167
+
168
+ cy.contains(opportunityName).should('be.visible')
169
+
170
+ opportunities.list.search(opportunityName)
171
+
172
+ cy.get(opportunities.list.selectors.rowGeneric).first().within(() => {
173
+ cy.get('[data-cy*="delete"]').click()
174
+ })
175
+
176
+ opportunities.list.confirmDelete()
177
+
178
+ cy.wait(1000)
179
+ opportunities.list.search(opportunityName)
180
+ cy.get(opportunities.list.selectors.emptyState).should('be.visible')
181
+ })
182
+
183
+ it('OWNER_OPPO_DELETE_002: should cancel deletion', () => {
184
+ cy.get(opportunities.list.selectors.rowGeneric).then($rows => {
185
+ if ($rows.length > 0) {
186
+ cy.get(opportunities.list.selectors.rowGeneric).first().within(() => {
187
+ cy.get('[data-cy*="delete"]').click()
188
+ })
189
+
190
+ opportunities.list.cancelDelete()
191
+ opportunities.list.validateTableVisible()
192
+ }
193
+ })
194
+ })
195
+ })
196
+ })
@@ -0,0 +1,320 @@
1
+ /// <reference types="cypress" />
2
+
3
+ /**
4
+ * Pipelines CRUD - Admin Role (Full Access)
5
+ *
6
+ * Uses CRM theme-specific POMs with Entity Testing Convention.
7
+ * Selectors follow the pattern: {slug}-{component}-{detail}
8
+ */
9
+
10
+ import { PipelinesPOM } from '../../../src/entities/PipelinesPOM'
11
+ import { loginAsCrmAdmin } from '../../../src/session-helpers'
12
+
13
+ describe('Pipelines CRUD - Admin Role (Full Access)', () => {
14
+ const pipelines = new PipelinesPOM()
15
+
16
+ beforeEach(() => {
17
+ loginAsCrmAdmin()
18
+ cy.visit('/dashboard/pipelines')
19
+ pipelines.list.validatePageVisible()
20
+ })
21
+
22
+ // ==================== CREATE ====================
23
+ describe('CREATE Pipeline', () => {
24
+ it('ADMIN_PIPE_CREATE_001: Should create new pipeline with required fields', () => {
25
+ // Click create button
26
+ pipelines.list.clickCreate()
27
+ pipelines.validateFormVisible()
28
+
29
+ // Fill required fields using custom form
30
+ pipelines.fillPipelineForm({
31
+ name: 'Admin Sales Pipeline 2025'
32
+ })
33
+
34
+ // Submit form
35
+ pipelines.submitPipelineForm()
36
+
37
+ // Verify success - should navigate to detail or list
38
+ cy.url().should('include', '/pipelines')
39
+ pipelines.list.validatePageVisible()
40
+ })
41
+
42
+ it('ADMIN_PIPE_CREATE_002: Should create pipeline with multiple stages', () => {
43
+ pipelines.list.clickCreate()
44
+ pipelines.validateFormVisible()
45
+
46
+ pipelines.fillPipelineForm({
47
+ name: 'Admin Complex Pipeline'
48
+ })
49
+
50
+ // Validate stages repeater is visible
51
+ pipelines.validateStagesRepeaterVisible()
52
+
53
+ // Fill default stages (they should already exist)
54
+ pipelines.fillStageByIndex(0, { name: 'Prospect', probability: 10 })
55
+ pipelines.fillStageByIndex(1, { name: 'Contact Made', probability: 25 })
56
+
57
+ // Add more stages
58
+ pipelines.addStage()
59
+ pipelines.fillStageByIndex(5, { name: 'Won', probability: 100 })
60
+
61
+ pipelines.submitPipelineForm()
62
+ cy.url().should('include', '/pipelines')
63
+ })
64
+
65
+ it('ADMIN_PIPE_CREATE_003: Should create pipeline with optional fields', () => {
66
+ pipelines.list.clickCreate()
67
+ pipelines.validateFormVisible()
68
+
69
+ pipelines.fillPipelineForm({
70
+ name: 'Admin Default Pipeline',
71
+ description: 'Pipeline created by admin user'
72
+ })
73
+
74
+ pipelines.submitPipelineForm()
75
+ cy.url().should('include', '/pipelines')
76
+ })
77
+
78
+ it('ADMIN_PIPE_CREATE_004: Should show validation error for empty name', () => {
79
+ pipelines.list.clickCreate()
80
+ pipelines.validateFormVisible()
81
+
82
+ // Submit without filling name
83
+ pipelines.submitPipelineForm()
84
+
85
+ // Should show validation error (form shouldn't submit)
86
+ cy.url().should('include', '/create')
87
+ })
88
+
89
+ it('ADMIN_PIPE_CREATE_005: Should cancel pipeline creation', () => {
90
+ pipelines.list.clickCreate()
91
+ pipelines.validateFormVisible()
92
+
93
+ pipelines.fillPipelineForm({
94
+ name: 'Admin Cancel Test Pipeline'
95
+ })
96
+
97
+ // Cancel instead of submit
98
+ pipelines.cancelPipelineForm()
99
+
100
+ // Should return to list
101
+ pipelines.list.validatePageVisible()
102
+ })
103
+ })
104
+
105
+ // ==================== READ ====================
106
+ describe('READ Pipeline', () => {
107
+ it('ADMIN_PIPE_READ_001: Should display pipelines list', () => {
108
+ // List should be visible from beforeEach
109
+ pipelines.list.validatePageVisible()
110
+ pipelines.list.validateTableVisible()
111
+ })
112
+
113
+ it('ADMIN_PIPE_READ_002: Should search and filter pipelines', () => {
114
+ // Search for specific pipeline
115
+ pipelines.list.search('Admin')
116
+
117
+ // Wait for search results
118
+ cy.wait(500)
119
+
120
+ // Clear search
121
+ pipelines.list.clearSearch()
122
+ })
123
+
124
+ it('ADMIN_PIPE_READ_003: Should view pipeline details (Kanban)', () => {
125
+ // Click on first row to view Kanban
126
+ pipelines.list.clickRowByIndex(0)
127
+
128
+ // Should navigate to detail page showing Kanban
129
+ cy.url().should('match', /\/pipelines\/[a-zA-Z0-9-]+$/)
130
+
131
+ // Validate Kanban board is visible
132
+ pipelines.validateKanbanVisible()
133
+ })
134
+
135
+ it('ADMIN_PIPE_READ_004: Should paginate through pipelines', () => {
136
+ pipelines.list.validatePageVisible()
137
+
138
+ // Check if pagination exists
139
+ cy.get(pipelines.list.selectors.pagination).then($pagination => {
140
+ if ($pagination.length > 0) {
141
+ pipelines.list.nextPage()
142
+ }
143
+ })
144
+ })
145
+
146
+ it('ADMIN_PIPE_READ_005: Should view pipelines created by other users', () => {
147
+ // Admin should see all pipelines
148
+ pipelines.list.validateTableVisible()
149
+ })
150
+ })
151
+
152
+ // ==================== UPDATE ====================
153
+ describe('UPDATE Pipeline', () => {
154
+ it('ADMIN_PIPE_UPDATE_001: Should update pipeline name', () => {
155
+ // Navigate to edit page for first pipeline
156
+ pipelines.list.clickRowByIndex(0)
157
+ pipelines.validateKanbanVisible()
158
+
159
+ // Get pipeline ID from URL and navigate to edit
160
+ cy.url().then(url => {
161
+ const pipelineId = url.split('/').pop()
162
+ pipelines.visitEdit(pipelineId!)
163
+ })
164
+
165
+ pipelines.validateFormVisible()
166
+
167
+ // Update name
168
+ cy.get(pipelines.formSelectors.nameInput).clear().type('Admin Sales Pipeline Updated')
169
+
170
+ pipelines.submitPipelineForm()
171
+
172
+ // Verify success
173
+ cy.url().should('include', '/pipelines')
174
+ })
175
+
176
+ it('ADMIN_PIPE_UPDATE_002: Should update pipeline stages', () => {
177
+ // Navigate to first pipeline edit
178
+ pipelines.list.clickRowByIndex(0)
179
+
180
+ cy.url().then(url => {
181
+ const pipelineId = url.split('/').pop()
182
+ pipelines.visitEdit(pipelineId!)
183
+ })
184
+
185
+ pipelines.validateFormVisible()
186
+ pipelines.validateStagesRepeaterVisible()
187
+
188
+ // Add a new stage
189
+ pipelines.addStage()
190
+
191
+ // Fill the new stage
192
+ cy.get(pipelines.stagesSelectors.list)
193
+ .find('[data-cy^="stages-repeater-item-"]')
194
+ .last()
195
+ .within(() => {
196
+ cy.get('input[data-cy^="stages-repeater-name-"]').type('New Admin Stage')
197
+ cy.get('input[data-cy^="stages-repeater-probability-"]').clear().type('50')
198
+ })
199
+
200
+ pipelines.submitPipelineForm()
201
+ cy.url().should('include', '/pipelines')
202
+ })
203
+
204
+ it('ADMIN_PIPE_UPDATE_003: Should cancel update without saving', () => {
205
+ pipelines.list.clickRowByIndex(0)
206
+
207
+ cy.url().then(url => {
208
+ const pipelineId = url.split('/').pop()
209
+ pipelines.visitEdit(pipelineId!)
210
+ })
211
+
212
+ pipelines.validateFormVisible()
213
+
214
+ // Make changes
215
+ cy.get(pipelines.formSelectors.nameInput).clear().type('Admin Should Not Save')
216
+
217
+ // Cancel instead of submit
218
+ pipelines.cancelPipelineForm()
219
+
220
+ // Should return to previous page
221
+ cy.url().should('not.include', '/edit')
222
+ })
223
+ })
224
+
225
+ // ==================== DELETE ====================
226
+ describe('DELETE Pipeline', () => {
227
+ it('ADMIN_PIPE_DELETE_001: Should delete pipeline from list', () => {
228
+ // First create a pipeline to delete
229
+ pipelines.list.clickCreate()
230
+ pipelines.validateFormVisible()
231
+
232
+ pipelines.fillPipelineForm({
233
+ name: 'Admin Pipeline To Delete'
234
+ })
235
+
236
+ pipelines.submitPipelineForm()
237
+ cy.url().should('include', '/pipelines')
238
+
239
+ // Now try to delete from list
240
+ pipelines.list.validatePageVisible()
241
+ pipelines.list.search('Admin Pipeline To Delete')
242
+
243
+ // Click delete action for the row
244
+ cy.get(pipelines.list.selectors.rowGeneric).first().within(() => {
245
+ cy.get('[data-cy*="delete"]').click()
246
+ })
247
+
248
+ // Confirm deletion
249
+ pipelines.list.confirmDelete()
250
+
251
+ // Verify deleted
252
+ pipelines.list.search('Admin Pipeline To Delete')
253
+ cy.get(pipelines.list.selectors.emptyState).should('be.visible')
254
+ })
255
+
256
+ it('ADMIN_PIPE_DELETE_002: Should cancel deletion', () => {
257
+ pipelines.list.search('Admin')
258
+
259
+ // Try to delete first item
260
+ cy.get(pipelines.list.selectors.rowGeneric).first().then($row => {
261
+ cy.wrap($row).within(() => {
262
+ cy.get('[data-cy*="delete"]').click()
263
+ })
264
+ })
265
+
266
+ // Cancel deletion
267
+ pipelines.list.cancelDelete()
268
+
269
+ // Verify still exists
270
+ pipelines.list.validateTableVisible()
271
+ })
272
+
273
+ it('ADMIN_PIPE_DELETE_003: Should handle bulk delete', () => {
274
+ // Select multiple items
275
+ pipelines.list.selectAll()
276
+
277
+ // Validate bulk actions visible
278
+ pipelines.list.validateBulkActionsVisible()
279
+ })
280
+ })
281
+
282
+ // ==================== KANBAN BOARD ====================
283
+ describe('KANBAN Board', () => {
284
+ it('ADMIN_PIPE_KANBAN_001: Should display Kanban board on pipeline detail', () => {
285
+ pipelines.list.clickRowByIndex(0)
286
+
287
+ pipelines.validateKanbanVisible()
288
+ pipelines.validateStatsVisible()
289
+ })
290
+
291
+ it('ADMIN_PIPE_KANBAN_002: Should display pipeline header with name', () => {
292
+ pipelines.list.clickRowByIndex(0)
293
+
294
+ cy.get(pipelines.kanbanSelectors.header).should('be.visible')
295
+ })
296
+
297
+ it('ADMIN_PIPE_KANBAN_003: Should display stats cards', () => {
298
+ pipelines.list.clickRowByIndex(0)
299
+
300
+ pipelines.validateStatsVisible()
301
+ })
302
+
303
+ it('ADMIN_PIPE_KANBAN_004: Should display stage columns', () => {
304
+ pipelines.list.clickRowByIndex(0)
305
+
306
+ cy.get(pipelines.kanbanSelectors.boardContainer).should('be.visible')
307
+ cy.get('[data-cy^="stage-column-"]').should('have.length.at.least', 1)
308
+ })
309
+
310
+ it('ADMIN_PIPE_KANBAN_005: Should click add deal button', () => {
311
+ pipelines.list.clickRowByIndex(0)
312
+ pipelines.validateKanbanVisible()
313
+
314
+ pipelines.clickAddDeal()
315
+
316
+ // Should navigate to opportunity create or open modal
317
+ cy.url().should('include', 'opportunities')
318
+ })
319
+ })
320
+ })