@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,145 @@
1
+ /**
2
+ * CRMSidebar - Page Object Model Class
3
+ *
4
+ * POM for the CRM theme sidebar navigation.
5
+ * Handles desktop sidebar interactions for CRM-specific navigation.
6
+ */
7
+ export class CRMSidebar {
8
+ static selectors = {
9
+ container: '[data-cy="crm-sidebar"]',
10
+ logo: '[data-cy="crm-sidebar-logo"]',
11
+ collapseBtn: '[data-cy="crm-sidebar-collapse-btn"]',
12
+ navDashboard: '[data-cy="crm-sidebar-nav-dashboard"]',
13
+ navLeads: '[data-cy="crm-sidebar-nav-leads"]',
14
+ navContacts: '[data-cy="crm-sidebar-nav-contacts"]',
15
+ navCompanies: '[data-cy="crm-sidebar-nav-companies"]',
16
+ navPipelines: '[data-cy="crm-sidebar-nav-pipelines"]',
17
+ navProducts: '[data-cy="crm-sidebar-nav-products"]',
18
+ navCampaigns: '[data-cy="crm-sidebar-nav-campaigns"]',
19
+ navActivities: '[data-cy="crm-sidebar-nav-activities"]',
20
+ navSettings: '[data-cy="crm-sidebar-nav-settings"]',
21
+ userAvatar: '[data-cy="crm-sidebar-user-avatar"]',
22
+ userName: '[data-cy="crm-sidebar-user-name"]',
23
+ userEmail: '[data-cy="crm-sidebar-user-email"]',
24
+ signoutBtn: '[data-cy="crm-sidebar-signout-btn"]',
25
+ }
26
+
27
+ /**
28
+ * Validate sidebar is visible
29
+ */
30
+ validateVisible() {
31
+ cy.get(CRMSidebar.selectors.container).should('be.visible')
32
+ return this
33
+ }
34
+
35
+ /**
36
+ * Validate sidebar is not visible
37
+ */
38
+ validateNotVisible() {
39
+ cy.get(CRMSidebar.selectors.container).should('not.exist')
40
+ return this
41
+ }
42
+
43
+ /**
44
+ * Navigate to a specific entity
45
+ * @param {string} entity - Entity name (dashboard, leads, contacts, companies, pipelines, products, campaigns, activities, settings)
46
+ */
47
+ navigateTo(entity) {
48
+ const selector = CRMSidebar.selectors[`nav${entity.charAt(0).toUpperCase() + entity.slice(1)}`]
49
+ if (!selector) {
50
+ throw new Error(`Invalid entity: ${entity}. Valid options: dashboard, leads, contacts, companies, pipelines, products, campaigns, activities, settings`)
51
+ }
52
+ cy.get(selector).click()
53
+ return this
54
+ }
55
+
56
+ /**
57
+ * Expand sidebar (if collapsed)
58
+ */
59
+ expand() {
60
+ cy.get(CRMSidebar.selectors.container).then($sidebar => {
61
+ if ($sidebar.attr('data-collapsed') === 'true') {
62
+ cy.get(CRMSidebar.selectors.collapseBtn).click()
63
+ cy.get(CRMSidebar.selectors.container).should('have.attr', 'data-collapsed', 'false')
64
+ }
65
+ })
66
+ return this
67
+ }
68
+
69
+ /**
70
+ * Collapse sidebar (if expanded)
71
+ */
72
+ collapse() {
73
+ cy.get(CRMSidebar.selectors.container).then($sidebar => {
74
+ if ($sidebar.attr('data-collapsed') === 'false') {
75
+ cy.get(CRMSidebar.selectors.collapseBtn).click()
76
+ cy.get(CRMSidebar.selectors.container).should('have.attr', 'data-collapsed', 'true')
77
+ }
78
+ })
79
+ return this
80
+ }
81
+
82
+ /**
83
+ * Check if sidebar is expanded
84
+ */
85
+ isExpanded() {
86
+ return cy.get(CRMSidebar.selectors.container)
87
+ .should('have.attr', 'data-collapsed')
88
+ .then(collapsed => collapsed === 'false')
89
+ }
90
+
91
+ /**
92
+ * Validate logo is visible
93
+ */
94
+ validateLogoVisible() {
95
+ cy.get(CRMSidebar.selectors.logo).should('be.visible')
96
+ return this
97
+ }
98
+
99
+ /**
100
+ * Validate user info is displayed
101
+ * @param {string} name - Expected user name
102
+ * @param {string} email - Expected user email
103
+ */
104
+ validateUserInfo(name, email) {
105
+ cy.get(CRMSidebar.selectors.userName).should('contain', name)
106
+ cy.get(CRMSidebar.selectors.userEmail).should('contain', email)
107
+ return this
108
+ }
109
+
110
+ /**
111
+ * Validate user avatar is visible
112
+ */
113
+ validateUserAvatarVisible() {
114
+ cy.get(CRMSidebar.selectors.userAvatar).should('be.visible')
115
+ return this
116
+ }
117
+
118
+ /**
119
+ * Sign out via sidebar
120
+ */
121
+ signOut() {
122
+ cy.get(CRMSidebar.selectors.signoutBtn).click()
123
+ return this
124
+ }
125
+
126
+ /**
127
+ * Validate navigation item is active
128
+ * @param {string} entity - Entity name
129
+ */
130
+ validateNavActive(entity) {
131
+ const selector = CRMSidebar.selectors[`nav${entity.charAt(0).toUpperCase() + entity.slice(1)}`]
132
+ cy.get(selector).should('have.attr', 'data-active', 'true')
133
+ return this
134
+ }
135
+
136
+ /**
137
+ * Validate navigation item is not active
138
+ * @param {string} entity - Entity name
139
+ */
140
+ validateNavNotActive(entity) {
141
+ const selector = CRMSidebar.selectors[`nav${entity.charAt(0).toUpperCase() + entity.slice(1)}`]
142
+ cy.get(selector).should('have.attr', 'data-active', 'false')
143
+ return this
144
+ }
145
+ }
@@ -0,0 +1,194 @@
1
+ /**
2
+ * CRMTopBar - Page Object Model Class
3
+ *
4
+ * POM for the CRM theme top bar navigation.
5
+ * Handles search, quick create, notifications, and user menu interactions.
6
+ */
7
+ export class CRMTopBar {
8
+ static selectors = {
9
+ container: '[data-cy="crm-topbar"]',
10
+ search: '[data-cy="crm-topbar-search"]',
11
+ searchInput: '[data-cy="crm-topbar-search-input"]',
12
+ searchClear: '[data-cy="crm-topbar-search-clear"]',
13
+ quickCreate: '[data-cy="crm-topbar-quick-create"]',
14
+ quickCreateDropdown: '[data-cy="crm-topbar-quick-create-dropdown"]',
15
+ quickCreateLead: '[data-cy="crm-quick-create-lead"]',
16
+ quickCreateContact: '[data-cy="crm-quick-create-contact"]',
17
+ quickCreateCompany: '[data-cy="crm-quick-create-company"]',
18
+ quickCreateDeal: '[data-cy="crm-quick-create-deal"]',
19
+ quickCreateActivity: '[data-cy="crm-quick-create-activity"]',
20
+ notifications: '[data-cy="crm-topbar-notifications"]',
21
+ notificationsDropdown: '[data-cy="crm-topbar-notifications-dropdown"]',
22
+ notificationsBadge: '[data-cy="crm-topbar-notifications-badge"]',
23
+ help: '[data-cy="crm-topbar-help"]',
24
+ themeToggle: '[data-cy="crm-topbar-theme-toggle"]',
25
+ userMenu: '[data-cy="crm-topbar-user-menu"]',
26
+ userMenuDropdown: '[data-cy="crm-topbar-user-menu-dropdown"]',
27
+ userMenuProfile: '[data-cy="crm-user-menu-profile"]',
28
+ userMenuSettings: '[data-cy="crm-user-menu-settings"]',
29
+ userMenuSignout: '[data-cy="crm-user-menu-signout"]',
30
+ }
31
+
32
+ /**
33
+ * Validate topbar is visible
34
+ */
35
+ validateVisible() {
36
+ cy.get(CRMTopBar.selectors.container).should('be.visible')
37
+ return this
38
+ }
39
+
40
+ /**
41
+ * Validate topbar is not visible
42
+ */
43
+ validateNotVisible() {
44
+ cy.get(CRMTopBar.selectors.container).should('not.exist')
45
+ return this
46
+ }
47
+
48
+ /**
49
+ * Search for a term
50
+ * @param {string} term - Search term
51
+ */
52
+ search(term) {
53
+ cy.get(CRMTopBar.selectors.searchInput).clear().type(term)
54
+ return this
55
+ }
56
+
57
+ /**
58
+ * Clear search input
59
+ */
60
+ clearSearch() {
61
+ cy.get(CRMTopBar.selectors.searchClear).click()
62
+ return this
63
+ }
64
+
65
+ /**
66
+ * Validate search input has value
67
+ * @param {string} value - Expected value
68
+ */
69
+ validateSearchValue(value) {
70
+ cy.get(CRMTopBar.selectors.searchInput).should('have.value', value)
71
+ return this
72
+ }
73
+
74
+ /**
75
+ * Open quick create dropdown
76
+ */
77
+ openQuickCreate() {
78
+ cy.get(CRMTopBar.selectors.quickCreate).click()
79
+ cy.get(CRMTopBar.selectors.quickCreateDropdown).should('be.visible')
80
+ return this
81
+ }
82
+
83
+ /**
84
+ * Quick create an entity
85
+ * @param {string} entity - Entity type (lead, contact, company, deal, activity)
86
+ */
87
+ quickCreate(entity) {
88
+ this.openQuickCreate()
89
+ const selector = CRMTopBar.selectors[`quickCreate${entity.charAt(0).toUpperCase() + entity.slice(1)}`]
90
+ if (!selector) {
91
+ throw new Error(`Invalid entity: ${entity}. Valid options: lead, contact, company, deal, activity`)
92
+ }
93
+ cy.get(selector).click()
94
+ return this
95
+ }
96
+
97
+ /**
98
+ * Open notifications dropdown
99
+ */
100
+ openNotifications() {
101
+ cy.get(CRMTopBar.selectors.notifications).click()
102
+ cy.get(CRMTopBar.selectors.notificationsDropdown).should('be.visible')
103
+ return this
104
+ }
105
+
106
+ /**
107
+ * Validate notifications badge count
108
+ * @param {number} count - Expected notification count
109
+ */
110
+ validateNotificationCount(count) {
111
+ if (count > 0) {
112
+ cy.get(CRMTopBar.selectors.notificationsBadge).should('be.visible').and('contain', count)
113
+ } else {
114
+ cy.get(CRMTopBar.selectors.notificationsBadge).should('not.exist')
115
+ }
116
+ return this
117
+ }
118
+
119
+ /**
120
+ * Click help button
121
+ */
122
+ clickHelp() {
123
+ cy.get(CRMTopBar.selectors.help).click()
124
+ return this
125
+ }
126
+
127
+ /**
128
+ * Toggle theme
129
+ */
130
+ toggleTheme() {
131
+ cy.get(CRMTopBar.selectors.themeToggle).click()
132
+ return this
133
+ }
134
+
135
+ /**
136
+ * Validate theme toggle is visible
137
+ */
138
+ validateThemeToggleVisible() {
139
+ cy.get(CRMTopBar.selectors.themeToggle).should('be.visible')
140
+ return this
141
+ }
142
+
143
+ /**
144
+ * Open user menu dropdown
145
+ */
146
+ openUserMenu() {
147
+ cy.get(CRMTopBar.selectors.userMenu).click()
148
+ cy.get(CRMTopBar.selectors.userMenuDropdown).should('be.visible')
149
+ return this
150
+ }
151
+
152
+ /**
153
+ * Navigate to profile
154
+ */
155
+ goToProfile() {
156
+ this.openUserMenu()
157
+ cy.get(CRMTopBar.selectors.userMenuProfile).click()
158
+ return this
159
+ }
160
+
161
+ /**
162
+ * Navigate to settings
163
+ */
164
+ goToSettings() {
165
+ this.openUserMenu()
166
+ cy.get(CRMTopBar.selectors.userMenuSettings).click()
167
+ return this
168
+ }
169
+
170
+ /**
171
+ * Sign out via user menu
172
+ */
173
+ signOut() {
174
+ this.openUserMenu()
175
+ cy.get(CRMTopBar.selectors.userMenuSignout).click()
176
+ return this
177
+ }
178
+
179
+ /**
180
+ * Validate quick create button is visible
181
+ */
182
+ validateQuickCreateVisible() {
183
+ cy.get(CRMTopBar.selectors.quickCreate).should('be.visible')
184
+ return this
185
+ }
186
+
187
+ /**
188
+ * Validate search is visible
189
+ */
190
+ validateSearchVisible() {
191
+ cy.get(CRMTopBar.selectors.search).should('be.visible')
192
+ return this
193
+ }
194
+ }
@@ -0,0 +1,197 @@
1
+ /**
2
+ * DealCard - Page Object Model Class
3
+ *
4
+ * POM for individual deal cards in the pipeline kanban board.
5
+ * Handles deal card-specific interactions and validations.
6
+ */
7
+ export class DealCard {
8
+ /**
9
+ * Get selectors for a specific deal card
10
+ * @param {string} dealId - Deal ID
11
+ */
12
+ static getDealSelectors(dealId) {
13
+ return {
14
+ card: `[data-cy="deal-card-${dealId}"]`,
15
+ name: `[data-cy="deal-name-${dealId}"]`,
16
+ company: `[data-cy="deal-company-${dealId}"]`,
17
+ amount: `[data-cy="deal-amount-${dealId}"]`,
18
+ probability: `[data-cy="deal-probability-${dealId}"]`,
19
+ owner: `[data-cy="deal-owner-${dealId}"]`,
20
+ dueDate: `[data-cy="deal-due-date-${dealId}"]`,
21
+ rottenBadge: `[data-cy="deal-rotten-${dealId}"]`,
22
+ priorityBadge: `[data-cy="deal-priority-${dealId}"]`,
23
+ }
24
+ }
25
+
26
+ /**
27
+ * @param {string} dealId - The deal ID
28
+ */
29
+ constructor(dealId) {
30
+ this.dealId = dealId
31
+ this.selectors = DealCard.getDealSelectors(dealId)
32
+ }
33
+
34
+ /**
35
+ * Validate deal card is visible
36
+ */
37
+ validateVisible() {
38
+ cy.get(this.selectors.card).should('be.visible')
39
+ return this
40
+ }
41
+
42
+ /**
43
+ * Validate deal card does not exist
44
+ */
45
+ validateNotExists() {
46
+ cy.get(this.selectors.card).should('not.exist')
47
+ return this
48
+ }
49
+
50
+ /**
51
+ * Click the deal card
52
+ */
53
+ click() {
54
+ cy.get(this.selectors.card).click()
55
+ return this
56
+ }
57
+
58
+ /**
59
+ * Validate deal name
60
+ * @param {string} name - Expected name
61
+ */
62
+ validateName(name) {
63
+ cy.get(this.selectors.name).should('contain', name)
64
+ return this
65
+ }
66
+
67
+ /**
68
+ * Validate deal company
69
+ * @param {string} company - Expected company name
70
+ */
71
+ validateCompany(company) {
72
+ cy.get(this.selectors.company).should('contain', company)
73
+ return this
74
+ }
75
+
76
+ /**
77
+ * Get the deal amount
78
+ */
79
+ getAmount() {
80
+ return cy.get(this.selectors.amount).invoke('text')
81
+ }
82
+
83
+ /**
84
+ * Validate deal amount
85
+ * @param {string} amount - Expected amount (e.g., "$25,000")
86
+ */
87
+ validateAmount(amount) {
88
+ cy.get(this.selectors.amount).should('contain', amount)
89
+ return this
90
+ }
91
+
92
+ /**
93
+ * Get the deal probability
94
+ */
95
+ getProbability() {
96
+ return cy.get(this.selectors.probability).invoke('text')
97
+ }
98
+
99
+ /**
100
+ * Validate deal probability
101
+ * @param {string} probability - Expected probability (e.g., "75%")
102
+ */
103
+ validateProbability(probability) {
104
+ cy.get(this.selectors.probability).should('contain', probability)
105
+ return this
106
+ }
107
+
108
+ /**
109
+ * Validate deal owner
110
+ * @param {string} owner - Expected owner name
111
+ */
112
+ validateOwner(owner) {
113
+ cy.get(this.selectors.owner).should('contain', owner)
114
+ return this
115
+ }
116
+
117
+ /**
118
+ * Validate due date
119
+ * @param {string} date - Expected due date
120
+ */
121
+ validateDueDate(date) {
122
+ cy.get(this.selectors.dueDate).should('contain', date)
123
+ return this
124
+ }
125
+
126
+ /**
127
+ * Validate deal is marked as rotten
128
+ */
129
+ isRotten() {
130
+ return cy.get(this.selectors.rottenBadge).should('exist')
131
+ }
132
+
133
+ /**
134
+ * Validate rotten badge is visible
135
+ */
136
+ validateRottenBadge() {
137
+ cy.get(this.selectors.rottenBadge).should('be.visible')
138
+ return this
139
+ }
140
+
141
+ /**
142
+ * Validate deal is not marked as rotten
143
+ */
144
+ validateNotRotten() {
145
+ cy.get(this.selectors.rottenBadge).should('not.exist')
146
+ return this
147
+ }
148
+
149
+ /**
150
+ * Validate priority badge
151
+ * @param {string} priority - Expected priority (e.g., "High", "Medium", "Low")
152
+ */
153
+ validatePriority(priority) {
154
+ cy.get(this.selectors.priorityBadge).should('contain', priority)
155
+ return this
156
+ }
157
+
158
+ /**
159
+ * Validate priority badge is visible
160
+ */
161
+ validatePriorityBadgeVisible() {
162
+ cy.get(this.selectors.priorityBadge).should('be.visible')
163
+ return this
164
+ }
165
+
166
+ /**
167
+ * Validate priority badge is not visible
168
+ */
169
+ validateNoPriorityBadge() {
170
+ cy.get(this.selectors.priorityBadge).should('not.exist')
171
+ return this
172
+ }
173
+
174
+ /**
175
+ * Hover over the deal card
176
+ */
177
+ hover() {
178
+ cy.get(this.selectors.card).trigger('mouseenter')
179
+ return this
180
+ }
181
+
182
+ /**
183
+ * Trigger drag start on the deal card
184
+ */
185
+ dragStart() {
186
+ cy.get(this.selectors.card).trigger('dragstart')
187
+ return this
188
+ }
189
+
190
+ /**
191
+ * Trigger drag end on the deal card
192
+ */
193
+ dragEnd() {
194
+ cy.get(this.selectors.card).trigger('dragend')
195
+ return this
196
+ }
197
+ }