@nextsparkjs/testing 0.1.0-beta.39
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/LICENSE +21 -0
- package/README.md +99 -0
- package/dist/helpers/index.d.ts +97 -0
- package/dist/helpers/index.js +126 -0
- package/dist/helpers/index.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +1994 -0
- package/dist/index.js.map +1 -0
- package/dist/pom/index.d.ts +473 -0
- package/dist/pom/index.js +817 -0
- package/dist/pom/index.js.map +1 -0
- package/dist/selector-factory-BivSWXbw.d.ts +123 -0
- package/dist/selectors/index.d.ts +1774 -0
- package/dist/selectors/index.js +1000 -0
- package/dist/selectors/index.js.map +1 -0
- package/dist/utils/index.d.ts +224 -0
- package/dist/utils/index.js +183 -0
- package/dist/utils/index.js.map +1 -0
- package/package.json +77 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,1994 @@
|
|
|
1
|
+
// src/selectors/selector-factory.ts
|
|
2
|
+
function getNestedValue(obj, path) {
|
|
3
|
+
return path.split(".").reduce((current, key) => {
|
|
4
|
+
if (current && typeof current === "object" && key in current) {
|
|
5
|
+
return current[key];
|
|
6
|
+
}
|
|
7
|
+
return void 0;
|
|
8
|
+
}, obj);
|
|
9
|
+
}
|
|
10
|
+
function replacePlaceholders(selector, replacements) {
|
|
11
|
+
if (!replacements) return selector;
|
|
12
|
+
return Object.entries(replacements).reduce(
|
|
13
|
+
(result, [key, value]) => result.replace(new RegExp(`\\{${key}\\}`, "g"), String(value)),
|
|
14
|
+
selector
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
var isDevelopment = process.env.NODE_ENV === "development";
|
|
18
|
+
var isTest = process.env.NODE_ENV === "test";
|
|
19
|
+
var enableTestingAttributes = isDevelopment || isTest;
|
|
20
|
+
function createSelectorHelpers(selectors) {
|
|
21
|
+
function sel2(path, replacements) {
|
|
22
|
+
const value = getNestedValue(selectors, path);
|
|
23
|
+
if (value === void 0) {
|
|
24
|
+
if (process.env.NODE_ENV === "development") {
|
|
25
|
+
console.error(`[sel] Invalid selector path: "${path}"`);
|
|
26
|
+
}
|
|
27
|
+
return `INVALID_SELECTOR_${path.replace(/\./g, "_")}`;
|
|
28
|
+
}
|
|
29
|
+
if (typeof value !== "string") {
|
|
30
|
+
if (process.env.NODE_ENV === "development") {
|
|
31
|
+
console.error(
|
|
32
|
+
`[sel] Path "${path}" points to an object, not a string. Did you forget a property?`
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
return `INVALID_SELECTOR_${path.replace(/\./g, "_")}`;
|
|
36
|
+
}
|
|
37
|
+
return replacePlaceholders(value, replacements);
|
|
38
|
+
}
|
|
39
|
+
function cySelector2(path, replacements) {
|
|
40
|
+
return `[data-cy="${sel2(path, replacements)}"]`;
|
|
41
|
+
}
|
|
42
|
+
function selDev2(path, replacements) {
|
|
43
|
+
if (!enableTestingAttributes) return void 0;
|
|
44
|
+
return sel2(path, replacements);
|
|
45
|
+
}
|
|
46
|
+
function entitySelectors2(slug) {
|
|
47
|
+
return {
|
|
48
|
+
// Page
|
|
49
|
+
page: () => sel2("entities.page.container", { slug }),
|
|
50
|
+
title: () => sel2("entities.page.title", { slug }),
|
|
51
|
+
// Table
|
|
52
|
+
table: () => sel2("entities.table.element", { slug }),
|
|
53
|
+
tableContainer: () => sel2("entities.table.container", { slug }),
|
|
54
|
+
search: () => sel2("entities.table.search", { slug }),
|
|
55
|
+
addButton: () => sel2("entities.table.addButton", { slug }),
|
|
56
|
+
row: (id) => sel2("entities.table.row", { slug, id }),
|
|
57
|
+
rowMenu: (id) => sel2("entities.table.rowMenu", { slug, id }),
|
|
58
|
+
rowAction: (action, id) => sel2("entities.table.rowAction", { slug, action, id }),
|
|
59
|
+
cell: (field, id) => sel2("entities.table.cell", { slug, field, id }),
|
|
60
|
+
// Form
|
|
61
|
+
form: () => sel2("entities.form.container", { slug }),
|
|
62
|
+
field: (name) => sel2("entities.form.field", { slug, name }),
|
|
63
|
+
submitButton: () => sel2("entities.form.submitButton", { slug }),
|
|
64
|
+
// Header
|
|
65
|
+
header: (mode) => sel2("entities.header.container", { slug, mode }),
|
|
66
|
+
backButton: () => sel2("entities.header.backButton", { slug }),
|
|
67
|
+
editButton: () => sel2("entities.header.editButton", { slug }),
|
|
68
|
+
deleteButton: () => sel2("entities.header.deleteButton", { slug }),
|
|
69
|
+
// Detail
|
|
70
|
+
detail: () => sel2("entities.detail.container", { slug }),
|
|
71
|
+
// Filter
|
|
72
|
+
filter: (field) => sel2("entities.filter.container", { slug, field }),
|
|
73
|
+
filterTrigger: (field) => sel2("entities.filter.trigger", { slug, field }),
|
|
74
|
+
filterOption: (field, value) => sel2("entities.filter.option", { slug, field, value })
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
return {
|
|
78
|
+
SELECTORS: selectors,
|
|
79
|
+
sel: sel2,
|
|
80
|
+
s: sel2,
|
|
81
|
+
selDev: selDev2,
|
|
82
|
+
cySelector: cySelector2,
|
|
83
|
+
entitySelectors: entitySelectors2
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// src/selectors/core-selectors.ts
|
|
88
|
+
var CORE_SELECTORS = {
|
|
89
|
+
// ===========================================================================
|
|
90
|
+
// AUTH
|
|
91
|
+
// ===========================================================================
|
|
92
|
+
auth: {
|
|
93
|
+
login: {
|
|
94
|
+
// Structure
|
|
95
|
+
card: "login-form-card",
|
|
96
|
+
header: "login-header",
|
|
97
|
+
footer: "login-footer",
|
|
98
|
+
form: "login-form",
|
|
99
|
+
options: "login-options",
|
|
100
|
+
// Inputs
|
|
101
|
+
emailInput: "login-email-input",
|
|
102
|
+
passwordInput: "login-password-input",
|
|
103
|
+
emailError: "login-email-error",
|
|
104
|
+
passwordError: "login-password-error",
|
|
105
|
+
// Buttons
|
|
106
|
+
submit: "login-submit",
|
|
107
|
+
googleSignin: "login-google-signin",
|
|
108
|
+
showEmail: "login-show-email",
|
|
109
|
+
hideEmail: "login-hide-email",
|
|
110
|
+
// Links
|
|
111
|
+
forgotPassword: "login-forgot-password",
|
|
112
|
+
signupLink: "login-signup-link",
|
|
113
|
+
// Misc
|
|
114
|
+
inviteBanner: "login-invite-banner",
|
|
115
|
+
errorAlert: "login-error-alert",
|
|
116
|
+
rememberCheckbox: "login-remember-checkbox"
|
|
117
|
+
},
|
|
118
|
+
signup: {
|
|
119
|
+
form: "signup-form",
|
|
120
|
+
firstName: "signup-first-name",
|
|
121
|
+
lastName: "signup-last-name",
|
|
122
|
+
email: "signup-email",
|
|
123
|
+
password: "signup-password",
|
|
124
|
+
confirmPassword: "signup-confirm-password",
|
|
125
|
+
submitButton: "signup-submit",
|
|
126
|
+
googleButton: "signup-google",
|
|
127
|
+
loginLink: "signup-login-link",
|
|
128
|
+
inviteBanner: "signup-invite-banner",
|
|
129
|
+
error: "signup-error"
|
|
130
|
+
},
|
|
131
|
+
forgotPassword: {
|
|
132
|
+
form: "forgot-password-form",
|
|
133
|
+
email: "forgot-password-email",
|
|
134
|
+
submitButton: "forgot-password-submit",
|
|
135
|
+
backToLogin: "forgot-password-back",
|
|
136
|
+
successMessage: "forgot-password-success",
|
|
137
|
+
successBack: "forgot-password-success-back",
|
|
138
|
+
retryButton: "forgot-password-retry",
|
|
139
|
+
error: "forgot-password-error"
|
|
140
|
+
},
|
|
141
|
+
resetPassword: {
|
|
142
|
+
form: "reset-password-form",
|
|
143
|
+
password: "reset-password-password",
|
|
144
|
+
confirmPassword: "reset-password-confirm",
|
|
145
|
+
submitButton: "reset-password-submit",
|
|
146
|
+
error: "reset-password-error",
|
|
147
|
+
success: "reset-password-success",
|
|
148
|
+
loginLink: "reset-password-login-link",
|
|
149
|
+
backToLogin: "reset-password-back"
|
|
150
|
+
},
|
|
151
|
+
verifyEmail: {
|
|
152
|
+
container: "verify-email-container",
|
|
153
|
+
resendButton: "verify-email-resend",
|
|
154
|
+
successMessage: "verify-email-success",
|
|
155
|
+
error: "verify-email-error"
|
|
156
|
+
},
|
|
157
|
+
devKeyring: {
|
|
158
|
+
container: "devkeyring-container",
|
|
159
|
+
trigger: "devkeyring-trigger",
|
|
160
|
+
content: "devkeyring-content",
|
|
161
|
+
user: "devkeyring-user-{index}"
|
|
162
|
+
}
|
|
163
|
+
},
|
|
164
|
+
// ===========================================================================
|
|
165
|
+
// DASHBOARD - Shell & TopNav
|
|
166
|
+
// ===========================================================================
|
|
167
|
+
dashboard: {
|
|
168
|
+
shell: {
|
|
169
|
+
container: "dashboard-container",
|
|
170
|
+
quickCreateButton: "topnav-quick-create-button",
|
|
171
|
+
quickCreateDropdown: "topnav-quick-create-dropdown",
|
|
172
|
+
quickCreateLink: "quick-create-{slug}-link"
|
|
173
|
+
},
|
|
174
|
+
topnav: {
|
|
175
|
+
sidebarToggle: "topnav-sidebar-toggle",
|
|
176
|
+
header: "topnav-header",
|
|
177
|
+
logo: "topnav-logo",
|
|
178
|
+
searchSection: "topnav-search-section",
|
|
179
|
+
actions: "topnav-actions",
|
|
180
|
+
notifications: "topnav-notifications",
|
|
181
|
+
help: "topnav-help",
|
|
182
|
+
themeToggle: "topnav-theme-toggle",
|
|
183
|
+
superadmin: "topnav-superadmin",
|
|
184
|
+
devtools: "topnav-devtools",
|
|
185
|
+
userMenuTrigger: "topnav-user-menu-trigger",
|
|
186
|
+
userMenu: "topnav-user-menu",
|
|
187
|
+
menuItem: "topnav-menu-{icon}",
|
|
188
|
+
menuAction: "topnav-menu-{action}",
|
|
189
|
+
userLoading: "topnav-user-loading",
|
|
190
|
+
signin: "topnav-signin",
|
|
191
|
+
signup: "topnav-signup",
|
|
192
|
+
// Mobile
|
|
193
|
+
mobileActions: "topnav-mobile-actions",
|
|
194
|
+
mobileMenuToggle: "topnav-mobile-menu-toggle",
|
|
195
|
+
mobileMenu: "topnav-mobile-menu",
|
|
196
|
+
mobileUserInfo: "topnav-mobile-user-info",
|
|
197
|
+
mobileLinkProfile: "topnav-mobile-link-profile",
|
|
198
|
+
mobileLinkSettings: "topnav-mobile-link-settings",
|
|
199
|
+
mobileLinkBilling: "topnav-mobile-link-billing",
|
|
200
|
+
mobileSignout: "topnav-mobile-signout",
|
|
201
|
+
mobileNavSuperadmin: "topnav-mobile-nav-superadmin",
|
|
202
|
+
mobileNavDevtools: "topnav-mobile-nav-devtools"
|
|
203
|
+
},
|
|
204
|
+
sidebar: {
|
|
205
|
+
main: "sidebar-main",
|
|
206
|
+
header: "sidebar-header",
|
|
207
|
+
content: "sidebar-content",
|
|
208
|
+
footer: "sidebar-footer"
|
|
209
|
+
},
|
|
210
|
+
navigation: {
|
|
211
|
+
main: "nav-main",
|
|
212
|
+
dashboardLink: "nav-link-dashboard",
|
|
213
|
+
entityLink: "nav-link-entity-{slug}",
|
|
214
|
+
section: "nav-section-{id}",
|
|
215
|
+
sectionLabel: "nav-section-label-{id}",
|
|
216
|
+
sectionItem: "nav-section-item-{sectionId}-{itemId}"
|
|
217
|
+
},
|
|
218
|
+
// Mobile components
|
|
219
|
+
mobile: {
|
|
220
|
+
topbar: {
|
|
221
|
+
header: "mobile-topbar-header",
|
|
222
|
+
userProfile: "mobile-topbar-user-profile",
|
|
223
|
+
notifications: "mobile-topbar-notifications",
|
|
224
|
+
themeToggle: "mobile-topbar-theme-toggle"
|
|
225
|
+
},
|
|
226
|
+
bottomNav: {
|
|
227
|
+
nav: "mobile-bottomnav-nav",
|
|
228
|
+
item: "mobile-bottomnav-item-{id}"
|
|
229
|
+
},
|
|
230
|
+
moreSheet: {
|
|
231
|
+
content: "mobile-more-sheet-content",
|
|
232
|
+
item: "mobile-more-sheet-item-{id}",
|
|
233
|
+
superadminLink: "mobile-more-sheet-superadmin-link",
|
|
234
|
+
teamSwitcher: "mobile-more-sheet-team-switcher",
|
|
235
|
+
signoutButton: "mobile-more-sheet-signout-button"
|
|
236
|
+
},
|
|
237
|
+
quickCreateSheet: {
|
|
238
|
+
content: "mobile-quick-create-sheet-content",
|
|
239
|
+
item: "mobile-quick-create-sheet-item-{slug}"
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
},
|
|
243
|
+
// ===========================================================================
|
|
244
|
+
// DASHBOARD - Entities (Dynamic with {slug})
|
|
245
|
+
// ===========================================================================
|
|
246
|
+
entities: {
|
|
247
|
+
page: {
|
|
248
|
+
container: "{slug}-page",
|
|
249
|
+
title: "{slug}-title"
|
|
250
|
+
},
|
|
251
|
+
list: {
|
|
252
|
+
container: "{slug}-list"
|
|
253
|
+
},
|
|
254
|
+
table: {
|
|
255
|
+
container: "{slug}-table-container",
|
|
256
|
+
element: "{slug}-table",
|
|
257
|
+
search: "{slug}-search",
|
|
258
|
+
addButton: "{slug}-add",
|
|
259
|
+
selectionCount: "{slug}-selection-count",
|
|
260
|
+
selectAll: "{slug}-select-all",
|
|
261
|
+
row: "{slug}-row-{id}",
|
|
262
|
+
rowSelect: "{slug}-select-{id}",
|
|
263
|
+
cell: "{slug}-cell-{field}-{id}",
|
|
264
|
+
rowMenu: "{slug}-menu-{id}",
|
|
265
|
+
rowActionsMenu: "{slug}-actions-{id}",
|
|
266
|
+
rowAction: "{slug}-menu-{action}-{id}",
|
|
267
|
+
quickAction: "{slug}-quick-{action}-{id}"
|
|
268
|
+
},
|
|
269
|
+
pagination: {
|
|
270
|
+
container: "{slug}-pagination",
|
|
271
|
+
pageSize: "{slug}-page-size",
|
|
272
|
+
pageSizeOption: "{slug}-page-size-{size}",
|
|
273
|
+
pageInfo: "{slug}-page-info",
|
|
274
|
+
first: "{slug}-page-first",
|
|
275
|
+
prev: "{slug}-page-prev",
|
|
276
|
+
next: "{slug}-page-next",
|
|
277
|
+
last: "{slug}-page-last"
|
|
278
|
+
},
|
|
279
|
+
bulk: {
|
|
280
|
+
bar: "{slug}-bulk-bar",
|
|
281
|
+
count: "{slug}-bulk-count",
|
|
282
|
+
selectAll: "{slug}-bulk-select-all",
|
|
283
|
+
statusButton: "{slug}-bulk-status",
|
|
284
|
+
deleteButton: "{slug}-bulk-delete",
|
|
285
|
+
clearButton: "{slug}-bulk-clear",
|
|
286
|
+
statusDialog: "{slug}-bulk-status-dialog",
|
|
287
|
+
statusSelect: "{slug}-bulk-status-select",
|
|
288
|
+
statusOption: "{slug}-bulk-status-option-{value}",
|
|
289
|
+
statusCancel: "{slug}-bulk-status-cancel",
|
|
290
|
+
statusConfirm: "{slug}-bulk-status-confirm",
|
|
291
|
+
deleteDialog: "{slug}-bulk-delete-dialog",
|
|
292
|
+
deleteCancel: "{slug}-bulk-delete-cancel",
|
|
293
|
+
deleteConfirm: "{slug}-bulk-delete-confirm"
|
|
294
|
+
},
|
|
295
|
+
header: {
|
|
296
|
+
container: "{slug}-{mode}-header",
|
|
297
|
+
backButton: "{slug}-back-btn",
|
|
298
|
+
title: "{slug}-title",
|
|
299
|
+
copyId: "{slug}-copy-id",
|
|
300
|
+
editButton: "{slug}-edit-btn",
|
|
301
|
+
deleteButton: "{slug}-delete-btn",
|
|
302
|
+
deleteDialog: "{slug}-delete-dialog",
|
|
303
|
+
deleteCancel: "{slug}-delete-cancel",
|
|
304
|
+
deleteConfirm: "{slug}-delete-confirm"
|
|
305
|
+
},
|
|
306
|
+
detail: {
|
|
307
|
+
container: "{slug}-detail"
|
|
308
|
+
},
|
|
309
|
+
form: {
|
|
310
|
+
container: "{slug}-form",
|
|
311
|
+
field: "{slug}-field-{name}",
|
|
312
|
+
submitButton: "{slug}-form-submit",
|
|
313
|
+
cancelButton: "{slug}-form-cancel"
|
|
314
|
+
},
|
|
315
|
+
filter: {
|
|
316
|
+
container: "{slug}-filter-{field}",
|
|
317
|
+
trigger: "{slug}-filter-{field}-trigger",
|
|
318
|
+
content: "{slug}-filter-{field}-content",
|
|
319
|
+
option: "{slug}-filter-{field}-option-{value}",
|
|
320
|
+
badge: "{slug}-filter-{field}-badge-{value}",
|
|
321
|
+
removeBadge: "{slug}-filter-{field}-remove-{value}",
|
|
322
|
+
clearAll: "{slug}-filter-{field}-clear-all"
|
|
323
|
+
},
|
|
324
|
+
search: {
|
|
325
|
+
container: "{slug}-search",
|
|
326
|
+
icon: "{slug}-search-icon",
|
|
327
|
+
input: "{slug}-search-input",
|
|
328
|
+
clear: "{slug}-search-clear"
|
|
329
|
+
},
|
|
330
|
+
confirm: {
|
|
331
|
+
dialog: "{slug}-confirm-dialog",
|
|
332
|
+
cancel: "{slug}-confirm-cancel",
|
|
333
|
+
action: "{slug}-confirm-action"
|
|
334
|
+
},
|
|
335
|
+
childEntity: {
|
|
336
|
+
container: "{parentSlug}-{childName}-container",
|
|
337
|
+
addButton: "{parentSlug}-{childName}-add-button"
|
|
338
|
+
}
|
|
339
|
+
},
|
|
340
|
+
// ===========================================================================
|
|
341
|
+
// DASHBOARD - Global Search
|
|
342
|
+
// ===========================================================================
|
|
343
|
+
globalSearch: {
|
|
344
|
+
modal: "search-modal",
|
|
345
|
+
trigger: "search-trigger",
|
|
346
|
+
input: "search-input",
|
|
347
|
+
results: "search-results",
|
|
348
|
+
result: "search-result"
|
|
349
|
+
},
|
|
350
|
+
// ===========================================================================
|
|
351
|
+
// DASHBOARD - Taxonomies (Categories, Tags, etc.)
|
|
352
|
+
// ===========================================================================
|
|
353
|
+
taxonomies: {
|
|
354
|
+
list: {
|
|
355
|
+
container: "taxonomies-list-table",
|
|
356
|
+
createButton: "taxonomies-create-button",
|
|
357
|
+
row: "taxonomy-row-{id}",
|
|
358
|
+
editButton: "taxonomies-edit-{id}",
|
|
359
|
+
deleteButton: "taxonomies-delete-{id}"
|
|
360
|
+
},
|
|
361
|
+
form: {
|
|
362
|
+
dialog: "taxonomy-form-dialog",
|
|
363
|
+
nameInput: "taxonomy-name-input",
|
|
364
|
+
slugInput: "taxonomy-slug-input",
|
|
365
|
+
descriptionInput: "taxonomy-description-input",
|
|
366
|
+
iconInput: "taxonomy-icon-input",
|
|
367
|
+
colorInput: "taxonomy-color-input",
|
|
368
|
+
parentSelect: "taxonomy-parent-select",
|
|
369
|
+
orderInput: "taxonomy-order-input",
|
|
370
|
+
saveButton: "taxonomy-save-button",
|
|
371
|
+
cancelButton: "taxonomy-cancel-button"
|
|
372
|
+
},
|
|
373
|
+
confirmDelete: {
|
|
374
|
+
dialog: "taxonomy-delete-dialog",
|
|
375
|
+
confirmButton: "taxonomy-delete-confirm",
|
|
376
|
+
cancelButton: "taxonomy-delete-cancel"
|
|
377
|
+
}
|
|
378
|
+
},
|
|
379
|
+
// ===========================================================================
|
|
380
|
+
// DASHBOARD - Teams
|
|
381
|
+
// ===========================================================================
|
|
382
|
+
teams: {
|
|
383
|
+
switcher: {
|
|
384
|
+
compact: "team-switcher-compact",
|
|
385
|
+
full: "team-switcher",
|
|
386
|
+
dropdown: "team-switcher-dropdown",
|
|
387
|
+
option: "team-option-{slug}",
|
|
388
|
+
manageLink: "manage-teams-link",
|
|
389
|
+
createButton: "create-team-button"
|
|
390
|
+
},
|
|
391
|
+
switchModal: {
|
|
392
|
+
container: "team-switch-modal"
|
|
393
|
+
},
|
|
394
|
+
create: {
|
|
395
|
+
dialog: "create-team-dialog",
|
|
396
|
+
button: "create-team-button",
|
|
397
|
+
nameInput: "team-name-input",
|
|
398
|
+
slugInput: "team-slug-input",
|
|
399
|
+
descriptionInput: "team-description-input",
|
|
400
|
+
cancel: "cancel-create-team",
|
|
401
|
+
submit: "submit-create-team"
|
|
402
|
+
},
|
|
403
|
+
members: {
|
|
404
|
+
section: "team-members-section",
|
|
405
|
+
row: "member-row-{id}",
|
|
406
|
+
actions: "member-actions-{id}",
|
|
407
|
+
makeRole: "make-{role}-action",
|
|
408
|
+
remove: "remove-member-action"
|
|
409
|
+
},
|
|
410
|
+
invite: {
|
|
411
|
+
button: "invite-member-button",
|
|
412
|
+
buttonDisabled: "invite-member-button-disabled",
|
|
413
|
+
dialog: "invite-member-dialog",
|
|
414
|
+
emailInput: "member-email-input",
|
|
415
|
+
roleSelect: "member-role-select",
|
|
416
|
+
roleOption: "role-option-{role}",
|
|
417
|
+
cancel: "cancel-invite-member",
|
|
418
|
+
submit: "submit-invite-member"
|
|
419
|
+
},
|
|
420
|
+
invitations: {
|
|
421
|
+
row: "invitation-row-{id}",
|
|
422
|
+
cancel: "cancel-invitation-{id}"
|
|
423
|
+
}
|
|
424
|
+
},
|
|
425
|
+
// ===========================================================================
|
|
426
|
+
// DASHBOARD - Block Editor (Pages & Posts)
|
|
427
|
+
// ===========================================================================
|
|
428
|
+
blockEditor: {
|
|
429
|
+
container: "builder-editor",
|
|
430
|
+
titleInput: "editor-title-input",
|
|
431
|
+
slugInput: "editor-slug-input",
|
|
432
|
+
saveButton: "save-btn",
|
|
433
|
+
statusBadge: "status-badge",
|
|
434
|
+
leftSidebarToggle: "left-sidebar-toggle",
|
|
435
|
+
viewModeToggle: "view-mode-toggle",
|
|
436
|
+
blockPicker: {
|
|
437
|
+
container: "block-picker",
|
|
438
|
+
searchInput: "block-search-input",
|
|
439
|
+
categoryAll: "category-all",
|
|
440
|
+
category: "category-{category}",
|
|
441
|
+
blockItem: "block-item-{slug}",
|
|
442
|
+
addBlock: "add-block-{slug}"
|
|
443
|
+
},
|
|
444
|
+
blockCanvas: {
|
|
445
|
+
container: "block-preview-canvas",
|
|
446
|
+
empty: "block-preview-canvas-empty"
|
|
447
|
+
},
|
|
448
|
+
previewCanvas: {
|
|
449
|
+
container: "block-preview-canvas",
|
|
450
|
+
empty: "block-preview-canvas-empty",
|
|
451
|
+
block: "preview-block-{id}",
|
|
452
|
+
moveUp: "preview-block-{id}-move-up",
|
|
453
|
+
moveDown: "preview-block-{id}-move-down"
|
|
454
|
+
},
|
|
455
|
+
sortableBlock: {
|
|
456
|
+
container: "sortable-block-{id}",
|
|
457
|
+
dragHandle: "drag-handle-{id}",
|
|
458
|
+
duplicate: "duplicate-block-{id}",
|
|
459
|
+
remove: "remove-block-{id}",
|
|
460
|
+
error: "block-error-{id}"
|
|
461
|
+
},
|
|
462
|
+
settingsPanel: {
|
|
463
|
+
container: "block-settings-panel",
|
|
464
|
+
empty: "settings-panel-empty",
|
|
465
|
+
error: "settings-panel-error",
|
|
466
|
+
resetProps: "reset-block-props",
|
|
467
|
+
removeBlock: "remove-block-settings",
|
|
468
|
+
tabContent: "tab-content",
|
|
469
|
+
tabDesign: "tab-design",
|
|
470
|
+
tabAdvanced: "tab-advanced"
|
|
471
|
+
},
|
|
472
|
+
pageSettings: {
|
|
473
|
+
container: "page-settings-panel",
|
|
474
|
+
seoTrigger: "seo-settings-trigger",
|
|
475
|
+
metaTitle: "seo-meta-title",
|
|
476
|
+
metaDescription: "seo-meta-description",
|
|
477
|
+
metaKeywords: "seo-meta-keywords",
|
|
478
|
+
ogImage: "seo-og-image",
|
|
479
|
+
customFieldsTrigger: "custom-fields-trigger",
|
|
480
|
+
customFieldKey: "custom-field-key-{index}",
|
|
481
|
+
customFieldValue: "custom-field-value-{index}",
|
|
482
|
+
customFieldRemove: "custom-field-remove-{index}",
|
|
483
|
+
addCustomField: "add-custom-field"
|
|
484
|
+
},
|
|
485
|
+
statusSelector: {
|
|
486
|
+
trigger: "status-selector",
|
|
487
|
+
option: "status-option-{value}"
|
|
488
|
+
},
|
|
489
|
+
dynamicForm: {
|
|
490
|
+
container: "dynamic-form",
|
|
491
|
+
field: "field-{name}",
|
|
492
|
+
fieldGroup: "field-group-{id}",
|
|
493
|
+
arrayGroup: "array-group-{name}"
|
|
494
|
+
},
|
|
495
|
+
arrayField: {
|
|
496
|
+
container: "array-field-{name}",
|
|
497
|
+
item: "array-field-{name}-{index}-{field}",
|
|
498
|
+
moveUp: "array-field-{name}-{index}-move-up",
|
|
499
|
+
moveDown: "array-field-{name}-{index}-move-down",
|
|
500
|
+
remove: "array-field-{name}-{index}-remove",
|
|
501
|
+
add: "array-field-{name}-add"
|
|
502
|
+
},
|
|
503
|
+
entityFieldsSidebar: {
|
|
504
|
+
container: "entity-fields-sidebar",
|
|
505
|
+
field: "field-{name}",
|
|
506
|
+
category: "category-{slug}"
|
|
507
|
+
},
|
|
508
|
+
// Post-specific fields
|
|
509
|
+
postFields: {
|
|
510
|
+
excerpt: "field-excerpt",
|
|
511
|
+
featuredImage: "field-featuredImage",
|
|
512
|
+
featuredImageUpload: "field-featuredImage-upload",
|
|
513
|
+
categories: "field-categories",
|
|
514
|
+
categoryOption: "category-option-{id}",
|
|
515
|
+
categoryBadge: "category-badge-{id}",
|
|
516
|
+
categoryRemove: "category-remove-{id}"
|
|
517
|
+
},
|
|
518
|
+
// Page/Post locale field
|
|
519
|
+
localeField: {
|
|
520
|
+
select: "field-locale",
|
|
521
|
+
option: "locale-option-{locale}"
|
|
522
|
+
}
|
|
523
|
+
},
|
|
524
|
+
// ===========================================================================
|
|
525
|
+
// SETTINGS
|
|
526
|
+
// ===========================================================================
|
|
527
|
+
settings: {
|
|
528
|
+
layout: {
|
|
529
|
+
main: "settings-layout-main",
|
|
530
|
+
nav: "settings-layout-nav",
|
|
531
|
+
backToDashboard: "settings-layout-back-to-dashboard",
|
|
532
|
+
header: "settings-layout-header",
|
|
533
|
+
contentArea: "settings-layout-content-area",
|
|
534
|
+
sidebar: "settings-layout-sidebar",
|
|
535
|
+
pageContent: "settings-layout-page-content"
|
|
536
|
+
},
|
|
537
|
+
sidebar: {
|
|
538
|
+
main: "settings-sidebar-main",
|
|
539
|
+
header: "settings-sidebar-header",
|
|
540
|
+
navItems: "settings-sidebar-nav-items",
|
|
541
|
+
navItem: "settings-sidebar-nav-{section}"
|
|
542
|
+
},
|
|
543
|
+
overview: {
|
|
544
|
+
container: "settings-overview",
|
|
545
|
+
item: "settings-overview-{key}"
|
|
546
|
+
},
|
|
547
|
+
profile: {
|
|
548
|
+
container: "settings-profile",
|
|
549
|
+
form: "profile-form",
|
|
550
|
+
avatar: "profile-avatar",
|
|
551
|
+
avatarUpload: "profile-avatar-upload",
|
|
552
|
+
firstName: "profile-first-name",
|
|
553
|
+
lastName: "profile-last-name",
|
|
554
|
+
email: "profile-email",
|
|
555
|
+
submitButton: "profile-submit",
|
|
556
|
+
successMessage: "profile-success"
|
|
557
|
+
},
|
|
558
|
+
password: {
|
|
559
|
+
container: "settings-password",
|
|
560
|
+
form: "password-form",
|
|
561
|
+
currentPassword: "password-current",
|
|
562
|
+
newPassword: "password-new",
|
|
563
|
+
confirmPassword: "password-confirm",
|
|
564
|
+
submitButton: "password-submit",
|
|
565
|
+
successMessage: "password-success"
|
|
566
|
+
},
|
|
567
|
+
team: {
|
|
568
|
+
container: "settings-team",
|
|
569
|
+
name: "team-name",
|
|
570
|
+
slug: "team-slug",
|
|
571
|
+
description: "team-description",
|
|
572
|
+
avatar: "team-avatar",
|
|
573
|
+
avatarUpload: "team-avatar-upload",
|
|
574
|
+
submitButton: "team-submit",
|
|
575
|
+
deleteButton: "team-delete",
|
|
576
|
+
deleteDialog: "team-delete-dialog",
|
|
577
|
+
deleteConfirm: "team-delete-confirm"
|
|
578
|
+
},
|
|
579
|
+
members: {
|
|
580
|
+
container: "settings-members",
|
|
581
|
+
inviteButton: "members-invite",
|
|
582
|
+
inviteDialog: "members-invite-dialog",
|
|
583
|
+
inviteEmail: "members-invite-email",
|
|
584
|
+
inviteRole: "members-invite-role",
|
|
585
|
+
inviteSubmit: "members-invite-submit",
|
|
586
|
+
memberRow: "member-row-{id}",
|
|
587
|
+
memberRole: "member-role-{id}",
|
|
588
|
+
memberRemove: "member-remove-{id}",
|
|
589
|
+
pendingInvites: "members-pending-invites",
|
|
590
|
+
pendingInvite: "pending-invite-{id}",
|
|
591
|
+
cancelInvite: "cancel-invite-{id}"
|
|
592
|
+
},
|
|
593
|
+
billing: {
|
|
594
|
+
container: "settings-billing",
|
|
595
|
+
main: "billing-main",
|
|
596
|
+
header: "billing-header",
|
|
597
|
+
currentPlan: "billing-current-plan",
|
|
598
|
+
upgradeButton: "billing-upgrade",
|
|
599
|
+
upgradePlan: "billing-upgrade-plan",
|
|
600
|
+
cancelButton: "billing-cancel",
|
|
601
|
+
addPayment: "billing-add-payment",
|
|
602
|
+
invoicesTable: "billing-invoices",
|
|
603
|
+
invoicesTableAlt: "invoices-table",
|
|
604
|
+
invoiceRow: "invoice-row-{id}",
|
|
605
|
+
invoicesRow: "invoices-row",
|
|
606
|
+
invoiceDownload: "invoice-download-{id}",
|
|
607
|
+
invoicesLoadMore: "invoices-load-more",
|
|
608
|
+
invoiceStatusBadge: "invoice-status-badge",
|
|
609
|
+
paymentMethod: "billing-payment-method",
|
|
610
|
+
paymentMethodAlt: "payment-method",
|
|
611
|
+
updatePayment: "billing-update-payment",
|
|
612
|
+
usage: "billing-usage",
|
|
613
|
+
usageDashboard: "usage-dashboard"
|
|
614
|
+
},
|
|
615
|
+
pricing: {
|
|
616
|
+
table: "pricing-table",
|
|
617
|
+
settingsTable: "pricing-settings-table"
|
|
618
|
+
},
|
|
619
|
+
features: {
|
|
620
|
+
placeholder: "feature-placeholder-{feature}",
|
|
621
|
+
content: "{feature}-content",
|
|
622
|
+
placeholderUpgradeBtn: "placeholder-upgrade-btn"
|
|
623
|
+
},
|
|
624
|
+
apiKeys: {
|
|
625
|
+
page: "api-keys-page",
|
|
626
|
+
title: "api-keys-title",
|
|
627
|
+
container: "settings-api-keys",
|
|
628
|
+
createButton: "api-keys-create-button",
|
|
629
|
+
createDialog: "api-keys-create-dialog",
|
|
630
|
+
list: "api-keys-list",
|
|
631
|
+
skeleton: "api-keys-skeleton",
|
|
632
|
+
empty: "api-keys-empty",
|
|
633
|
+
emptyCreateButton: "api-keys-empty-create-button",
|
|
634
|
+
keyName: "api-key-name",
|
|
635
|
+
keyScopes: "api-key-scopes",
|
|
636
|
+
scopeOption: "api-key-scope-{scope}",
|
|
637
|
+
createSubmit: "api-key-create-submit",
|
|
638
|
+
keyRow: "api-key-row-{id}",
|
|
639
|
+
keyName_: "api-keys-name-{id}",
|
|
640
|
+
keyPrefix: "api-keys-prefix-{id}",
|
|
641
|
+
copyPrefix: "api-keys-copy-prefix-{id}",
|
|
642
|
+
keyStatus: "api-keys-status-{id}",
|
|
643
|
+
statusBadge: "api-keys-status-badge-{id}",
|
|
644
|
+
menuTrigger: "api-keys-menu-trigger-{id}",
|
|
645
|
+
menu: "api-keys-menu-{id}",
|
|
646
|
+
viewDetails: "api-keys-view-details-{id}",
|
|
647
|
+
toggle: "api-keys-toggle-{id}",
|
|
648
|
+
revoke: "api-keys-revoke-{id}",
|
|
649
|
+
scopes: "api-keys-scopes-{id}",
|
|
650
|
+
scope: "api-keys-scope-{id}-{scope}",
|
|
651
|
+
stats: "api-keys-stats-{id}",
|
|
652
|
+
totalRequests: "api-keys-total-requests-{id}",
|
|
653
|
+
last24h: "api-keys-last-24h-{id}",
|
|
654
|
+
avgTime: "api-keys-avg-time-{id}",
|
|
655
|
+
metadata: "api-keys-metadata-{id}",
|
|
656
|
+
createdAt: "api-keys-created-at-{id}",
|
|
657
|
+
lastUsed: "api-keys-last-used-{id}",
|
|
658
|
+
expiresAt: "api-keys-expires-at-{id}",
|
|
659
|
+
detailsDialog: "api-keys-details-dialog",
|
|
660
|
+
detailsTitle: "api-keys-details-title",
|
|
661
|
+
detailsLoading: "api-keys-details-loading",
|
|
662
|
+
detailsContent: "api-keys-details-content",
|
|
663
|
+
detailsBasicInfo: "api-keys-details-basic-info",
|
|
664
|
+
detailsName: "api-keys-details-name",
|
|
665
|
+
detailsStatus: "api-keys-details-status",
|
|
666
|
+
detailsStats: "api-keys-details-stats",
|
|
667
|
+
detailsTotalRequests: "api-keys-details-total-requests",
|
|
668
|
+
detailsLast24h: "api-keys-details-last-24h",
|
|
669
|
+
detailsLast7d: "api-keys-details-last-7d",
|
|
670
|
+
detailsLast30d: "api-keys-details-last-30d",
|
|
671
|
+
detailsAvgTime: "api-keys-details-avg-time",
|
|
672
|
+
detailsSuccessRate: "api-keys-details-success-rate",
|
|
673
|
+
keyReveal: "api-key-reveal-{id}",
|
|
674
|
+
keyRevoke: "api-key-revoke-{id}",
|
|
675
|
+
revokeDialog: "api-key-revoke-dialog",
|
|
676
|
+
revokeConfirm: "api-key-revoke-confirm",
|
|
677
|
+
newKeyDisplay: "api-key-new-display",
|
|
678
|
+
copyKey: "api-key-copy",
|
|
679
|
+
dialogFooter: "api-keys-dialog-footer"
|
|
680
|
+
},
|
|
681
|
+
notifications: {
|
|
682
|
+
container: "settings-notifications",
|
|
683
|
+
emailToggle: "notifications-email",
|
|
684
|
+
pushToggle: "notifications-push",
|
|
685
|
+
category: "notifications-{category}",
|
|
686
|
+
submitButton: "notifications-submit"
|
|
687
|
+
},
|
|
688
|
+
teams: {
|
|
689
|
+
main: "teams-settings-main",
|
|
690
|
+
header: "teams-settings-header",
|
|
691
|
+
loading: "teams-settings-loading",
|
|
692
|
+
singleUser: "teams-settings-single-user",
|
|
693
|
+
teamsList: "teams-settings-teams-list",
|
|
694
|
+
teamDetails: "teams-settings-team-details"
|
|
695
|
+
},
|
|
696
|
+
plans: {
|
|
697
|
+
main: "plans-settings-main",
|
|
698
|
+
header: "plans-settings-header",
|
|
699
|
+
table: "plans-settings-table"
|
|
700
|
+
}
|
|
701
|
+
},
|
|
702
|
+
// ===========================================================================
|
|
703
|
+
// SUPERADMIN (Super Admin Panel)
|
|
704
|
+
// ===========================================================================
|
|
705
|
+
superadmin: {
|
|
706
|
+
container: "superadmin-container",
|
|
707
|
+
navigation: {
|
|
708
|
+
dashboard: "superadmin-nav-dashboard",
|
|
709
|
+
users: "superadmin-nav-users",
|
|
710
|
+
teams: "superadmin-nav-teams",
|
|
711
|
+
teamRoles: "superadmin-nav-team-roles",
|
|
712
|
+
docs: "superadmin-nav-docs",
|
|
713
|
+
subscriptions: "superadmin-nav-subscriptions",
|
|
714
|
+
analytics: "superadmin-nav-analytics",
|
|
715
|
+
config: "superadmin-nav-config",
|
|
716
|
+
exitToDashboard: "superadmin-sidebar-exit-to-dashboard"
|
|
717
|
+
},
|
|
718
|
+
dashboard: {
|
|
719
|
+
container: "superadmin-dashboard"
|
|
720
|
+
},
|
|
721
|
+
users: {
|
|
722
|
+
container: "superadmin-users-container",
|
|
723
|
+
table: "superadmin-users-table",
|
|
724
|
+
search: "superadmin-users-search",
|
|
725
|
+
row: "superadmin-user-row-{id}",
|
|
726
|
+
viewButton: "superadmin-user-view-{id}",
|
|
727
|
+
editButton: "superadmin-user-edit-{id}",
|
|
728
|
+
banButton: "superadmin-user-ban-{id}",
|
|
729
|
+
deleteButton: "superadmin-user-delete-{id}",
|
|
730
|
+
impersonateButton: "superadmin-user-impersonate-{id}"
|
|
731
|
+
},
|
|
732
|
+
userDetail: {
|
|
733
|
+
container: "superadmin-user-detail",
|
|
734
|
+
email: "superadmin-user-email",
|
|
735
|
+
role: "superadmin-user-role",
|
|
736
|
+
status: "superadmin-user-status",
|
|
737
|
+
teams: "superadmin-user-teams",
|
|
738
|
+
activity: "superadmin-user-activity",
|
|
739
|
+
actions: "superadmin-user-actions",
|
|
740
|
+
// User Metadata
|
|
741
|
+
metas: "superadmin-user-metas",
|
|
742
|
+
metasTitle: "superadmin-user-metas-title",
|
|
743
|
+
metasTable: "superadmin-user-metas-table",
|
|
744
|
+
metasEmpty: "superadmin-user-metas-empty",
|
|
745
|
+
metaRow: "superadmin-user-meta-row-{key}",
|
|
746
|
+
metaKey: "superadmin-user-meta-key-{key}",
|
|
747
|
+
metaValue: "superadmin-user-meta-value-{key}",
|
|
748
|
+
metaType: "superadmin-user-meta-type-{key}",
|
|
749
|
+
metaPublic: "superadmin-user-meta-public-{key}",
|
|
750
|
+
metaSearchable: "superadmin-user-meta-searchable-{key}"
|
|
751
|
+
},
|
|
752
|
+
teams: {
|
|
753
|
+
container: "superadmin-teams-container",
|
|
754
|
+
table: "superadmin-teams-table",
|
|
755
|
+
search: "superadmin-teams-search",
|
|
756
|
+
row: "superadmin-team-row-{id}",
|
|
757
|
+
actionsButton: "superadmin-team-actions-{id}",
|
|
758
|
+
viewButton: "superadmin-team-view-{id}",
|
|
759
|
+
editButton: "superadmin-team-edit-{id}",
|
|
760
|
+
deleteButton: "superadmin-team-delete-{id}"
|
|
761
|
+
},
|
|
762
|
+
teamDetail: {
|
|
763
|
+
container: "superadmin-team-detail",
|
|
764
|
+
name: "superadmin-team-name",
|
|
765
|
+
owner: "superadmin-team-owner",
|
|
766
|
+
members: "superadmin-team-members",
|
|
767
|
+
plan: "superadmin-team-plan",
|
|
768
|
+
usage: "superadmin-team-usage"
|
|
769
|
+
},
|
|
770
|
+
subscriptions: {
|
|
771
|
+
container: "superadmin-subscriptions-container",
|
|
772
|
+
mrr: "superadmin-subscriptions-mrr",
|
|
773
|
+
planDistribution: "superadmin-subscriptions-plan-distribution",
|
|
774
|
+
planCount: "superadmin-subscriptions-plan-count-{plan}",
|
|
775
|
+
activeCount: "superadmin-subscriptions-active-count"
|
|
776
|
+
},
|
|
777
|
+
pagination: {
|
|
778
|
+
pageSize: "superadmin-page-size-select",
|
|
779
|
+
first: "superadmin-pagination-first",
|
|
780
|
+
prev: "superadmin-pagination-prev",
|
|
781
|
+
next: "superadmin-pagination-next",
|
|
782
|
+
last: "superadmin-pagination-last"
|
|
783
|
+
},
|
|
784
|
+
filters: {
|
|
785
|
+
search: "superadmin-search-{context}",
|
|
786
|
+
dropdown: "superadmin-filter-{context}"
|
|
787
|
+
},
|
|
788
|
+
permissions: {
|
|
789
|
+
row: "superadmin-permission-row-{permission}"
|
|
790
|
+
},
|
|
791
|
+
teamRoles: {
|
|
792
|
+
backButton: "back-to-superadmin",
|
|
793
|
+
roleCard: "role-card-{role}",
|
|
794
|
+
permissionRow: "permission-row-{permission}"
|
|
795
|
+
},
|
|
796
|
+
planFeatures: {
|
|
797
|
+
featureRow: "superadmin-feature-row-{slug}",
|
|
798
|
+
limitRow: "superadmin-limit-row-{slug}"
|
|
799
|
+
}
|
|
800
|
+
},
|
|
801
|
+
// ===========================================================================
|
|
802
|
+
// DEVTOOLS
|
|
803
|
+
// ===========================================================================
|
|
804
|
+
devtools: {
|
|
805
|
+
navigation: {
|
|
806
|
+
sidebar: "devtools-sidebar",
|
|
807
|
+
collapseToggle: "devtools-sidebar-collapse-toggle",
|
|
808
|
+
navItem: "devtools-nav-{section}",
|
|
809
|
+
exitToDashboard: "devtools-sidebar-exit-to-dashboard",
|
|
810
|
+
goToSuperadmin: "devtools-sidebar-go-to-superadmin",
|
|
811
|
+
mobileHeader: "devtools-mobile-header"
|
|
812
|
+
},
|
|
813
|
+
home: {
|
|
814
|
+
page: "devtools-home-page",
|
|
815
|
+
styleLink: "devtools-home-style-link",
|
|
816
|
+
testsLink: "devtools-home-tests-link",
|
|
817
|
+
configLink: "devtools-home-config-link"
|
|
818
|
+
},
|
|
819
|
+
style: {
|
|
820
|
+
page: "devtools-style-page",
|
|
821
|
+
tabComponents: "devtools-style-tab-components",
|
|
822
|
+
tabFieldTypes: "devtools-style-tab-field-types",
|
|
823
|
+
tabTheme: "devtools-style-tab-theme",
|
|
824
|
+
tabGuidelines: "devtools-style-tab-guidelines",
|
|
825
|
+
componentGallery: "devtools-style-component-gallery",
|
|
826
|
+
fieldTypes: "devtools-style-field-types",
|
|
827
|
+
themePreview: "devtools-style-theme-preview"
|
|
828
|
+
},
|
|
829
|
+
config: {
|
|
830
|
+
page: "devtools-config-page",
|
|
831
|
+
viewer: "devtools-config-viewer",
|
|
832
|
+
tabTheme: "devtools-config-tab-theme",
|
|
833
|
+
tabEntities: "devtools-config-tab-entities",
|
|
834
|
+
themeContent: "devtools-config-theme-content",
|
|
835
|
+
entitiesContent: "devtools-config-entities-content",
|
|
836
|
+
copyTheme: "devtools-config-copy-theme",
|
|
837
|
+
copyEntities: "devtools-config-copy-entities"
|
|
838
|
+
},
|
|
839
|
+
tests: {
|
|
840
|
+
page: "devtools-tests-page",
|
|
841
|
+
viewer: "devtools-tests-viewer",
|
|
842
|
+
loading: "devtools-tests-loading",
|
|
843
|
+
tree: "devtools-tests-tree",
|
|
844
|
+
folder: "devtools-tests-folder-{name}",
|
|
845
|
+
file: "devtools-tests-file-{name}",
|
|
846
|
+
content: "devtools-tests-content",
|
|
847
|
+
markdownContent: "devtools-tests-markdown-content",
|
|
848
|
+
notFound: "devtools-tests-not-found",
|
|
849
|
+
backToList: "devtools-tests-back-to-list",
|
|
850
|
+
emptyState: "devtools-tests-empty-state",
|
|
851
|
+
fileLoading: "devtools-tests-file-loading",
|
|
852
|
+
error: "devtools-tests-error",
|
|
853
|
+
// Dashboard
|
|
854
|
+
dashboard: "devtools-tests-dashboard",
|
|
855
|
+
dashboardButton: "devtools-tests-dashboard-button",
|
|
856
|
+
dashboardStats: "devtools-tests-dashboard-stats",
|
|
857
|
+
dashboardStatFeatures: "devtools-tests-dashboard-stat-features",
|
|
858
|
+
dashboardStatFlows: "devtools-tests-dashboard-stat-flows",
|
|
859
|
+
dashboardStatFiles: "devtools-tests-dashboard-stat-files",
|
|
860
|
+
dashboardStatTags: "devtools-tests-dashboard-stat-tags",
|
|
861
|
+
dashboardGaps: "devtools-tests-dashboard-gaps",
|
|
862
|
+
dashboardGapItem: "devtools-tests-dashboard-gap-{slug}"
|
|
863
|
+
},
|
|
864
|
+
features: {
|
|
865
|
+
page: "devtools-features-page",
|
|
866
|
+
viewer: "devtools-features-viewer",
|
|
867
|
+
search: "devtools-features-search",
|
|
868
|
+
filterAll: "devtools-features-filter-all",
|
|
869
|
+
filterCategory: "devtools-features-filter-{category}",
|
|
870
|
+
coverageAll: "devtools-features-coverage-all",
|
|
871
|
+
coverageCovered: "devtools-features-coverage-covered",
|
|
872
|
+
coverageUncovered: "devtools-features-coverage-uncovered",
|
|
873
|
+
card: "devtools-features-card-{slug}",
|
|
874
|
+
copyTag: "devtools-features-copy-{slug}"
|
|
875
|
+
},
|
|
876
|
+
flows: {
|
|
877
|
+
page: "devtools-flows-page",
|
|
878
|
+
viewer: "devtools-flows-viewer",
|
|
879
|
+
search: "devtools-flows-search",
|
|
880
|
+
filterAll: "devtools-flows-filter-all",
|
|
881
|
+
filterCategory: "devtools-flows-filter-{category}",
|
|
882
|
+
coverageAll: "devtools-flows-coverage-all",
|
|
883
|
+
coverageCovered: "devtools-flows-coverage-covered",
|
|
884
|
+
coverageUncovered: "devtools-flows-coverage-uncovered",
|
|
885
|
+
card: "devtools-flows-card-{slug}",
|
|
886
|
+
copyTag: "devtools-flows-copy-{slug}"
|
|
887
|
+
},
|
|
888
|
+
blocks: {
|
|
889
|
+
page: "devtools-blocks-page",
|
|
890
|
+
viewer: "devtools-blocks-viewer",
|
|
891
|
+
search: "devtools-blocks-search",
|
|
892
|
+
filterAll: "devtools-blocks-filter-all",
|
|
893
|
+
filterCategory: "devtools-blocks-filter-{category}",
|
|
894
|
+
coverageAll: "devtools-blocks-coverage-all",
|
|
895
|
+
coverageCovered: "devtools-blocks-coverage-covered",
|
|
896
|
+
coverageUncovered: "devtools-blocks-coverage-uncovered",
|
|
897
|
+
card: "devtools-blocks-card-{slug}",
|
|
898
|
+
copyTag: "devtools-blocks-copy-{slug}",
|
|
899
|
+
viewDetails: "devtools-blocks-view-{slug}",
|
|
900
|
+
detail: {
|
|
901
|
+
page: "devtools-block-detail-{slug}",
|
|
902
|
+
back: "devtools-block-detail-back",
|
|
903
|
+
tabPreview: "devtools-block-detail-tab-preview",
|
|
904
|
+
tabFields: "devtools-block-detail-tab-fields",
|
|
905
|
+
tabOverview: "devtools-block-detail-tab-overview",
|
|
906
|
+
preview: "devtools-block-detail-preview-{slug}",
|
|
907
|
+
exampleSelector: "devtools-block-example-selector",
|
|
908
|
+
exampleBtn: "devtools-block-example-btn-{index}",
|
|
909
|
+
exampleName: "devtools-block-example-name",
|
|
910
|
+
exampleDescription: "devtools-block-example-description"
|
|
911
|
+
}
|
|
912
|
+
},
|
|
913
|
+
tags: {
|
|
914
|
+
page: "devtools-tags-page",
|
|
915
|
+
viewer: "devtools-tags-viewer",
|
|
916
|
+
search: "devtools-tags-search",
|
|
917
|
+
category: "devtools-tags-category-{category}",
|
|
918
|
+
tag: "devtools-tags-tag-{tag}",
|
|
919
|
+
tagLink: "devtools-tags-link-{tag}",
|
|
920
|
+
filesPanel: "devtools-tags-files-panel-{tag}"
|
|
921
|
+
},
|
|
922
|
+
scheduledActions: {
|
|
923
|
+
page: "devtools-scheduled-actions-page",
|
|
924
|
+
filterStatus: "scheduled-actions-filter-status",
|
|
925
|
+
filterType: "scheduled-actions-filter-type",
|
|
926
|
+
filterApply: "scheduled-actions-filter-apply",
|
|
927
|
+
filterReset: "scheduled-actions-filter-reset",
|
|
928
|
+
table: "scheduled-actions-table",
|
|
929
|
+
row: "scheduled-actions-row-{id}",
|
|
930
|
+
cellType: "scheduled-actions-cell-type",
|
|
931
|
+
cellStatus: "scheduled-actions-cell-status",
|
|
932
|
+
cellScheduledAt: "scheduled-actions-cell-scheduled-at",
|
|
933
|
+
cellTeam: "scheduled-actions-cell-team",
|
|
934
|
+
cellPayload: "scheduled-actions-cell-payload",
|
|
935
|
+
cellError: "scheduled-actions-cell-error",
|
|
936
|
+
statusPending: "scheduled-actions-status-pending",
|
|
937
|
+
statusRunning: "scheduled-actions-status-running",
|
|
938
|
+
statusCompleted: "scheduled-actions-status-completed",
|
|
939
|
+
statusFailed: "scheduled-actions-status-failed",
|
|
940
|
+
pagination: "scheduled-actions-pagination",
|
|
941
|
+
paginationPrev: "scheduled-actions-pagination-prev",
|
|
942
|
+
paginationNext: "scheduled-actions-pagination-next",
|
|
943
|
+
emptyState: "scheduled-actions-empty-state"
|
|
944
|
+
}
|
|
945
|
+
},
|
|
946
|
+
// ===========================================================================
|
|
947
|
+
// PUBLIC PAGES
|
|
948
|
+
// ===========================================================================
|
|
949
|
+
public: {
|
|
950
|
+
navbar: {
|
|
951
|
+
container: "public-navbar",
|
|
952
|
+
logo: "navbar-logo",
|
|
953
|
+
loginButton: "navbar-login",
|
|
954
|
+
signupButton: "navbar-signup"
|
|
955
|
+
},
|
|
956
|
+
footer: {
|
|
957
|
+
container: "public-footer",
|
|
958
|
+
logo: "footer-logo"
|
|
959
|
+
},
|
|
960
|
+
page: {
|
|
961
|
+
container: "public-page-{slug}",
|
|
962
|
+
title: "page-title",
|
|
963
|
+
content: "page-content"
|
|
964
|
+
},
|
|
965
|
+
blog: {
|
|
966
|
+
listContainer: "blog-list",
|
|
967
|
+
postCard: "blog-post-{slug}"
|
|
968
|
+
}
|
|
969
|
+
},
|
|
970
|
+
// ===========================================================================
|
|
971
|
+
// COMMON / SHARED
|
|
972
|
+
// ===========================================================================
|
|
973
|
+
common: {
|
|
974
|
+
permissionDenied: "permission-denied",
|
|
975
|
+
loading: "loading-spinner",
|
|
976
|
+
error: "error-message",
|
|
977
|
+
toast: "toast-{type}",
|
|
978
|
+
modal: {
|
|
979
|
+
overlay: "modal-overlay",
|
|
980
|
+
container: "modal-container",
|
|
981
|
+
title: "modal-title",
|
|
982
|
+
close: "modal-close",
|
|
983
|
+
content: "modal-content",
|
|
984
|
+
footer: "modal-footer"
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
};
|
|
988
|
+
|
|
989
|
+
// src/selectors/selectors.ts
|
|
990
|
+
var helpers = createSelectorHelpers(CORE_SELECTORS);
|
|
991
|
+
var SELECTORS = helpers.SELECTORS;
|
|
992
|
+
var sel = helpers.sel;
|
|
993
|
+
var s = helpers.s;
|
|
994
|
+
var selDev = helpers.selDev;
|
|
995
|
+
var cySelector = helpers.cySelector;
|
|
996
|
+
var entitySelectors = helpers.entitySelectors;
|
|
997
|
+
|
|
998
|
+
// src/utils/utils.ts
|
|
999
|
+
var isDevelopment2 = process.env.NODE_ENV === "development";
|
|
1000
|
+
var isTest2 = process.env.NODE_ENV === "test";
|
|
1001
|
+
var enableTestingAttributes2 = isDevelopment2 || isTest2;
|
|
1002
|
+
function createTestId(component, element, action) {
|
|
1003
|
+
if (!enableTestingAttributes2) return void 0;
|
|
1004
|
+
const parts = [component, element, action].filter(Boolean);
|
|
1005
|
+
return parts.join("-");
|
|
1006
|
+
}
|
|
1007
|
+
function createCyId(domain, element) {
|
|
1008
|
+
if (!enableTestingAttributes2) return void 0;
|
|
1009
|
+
return `${domain}-${element}`;
|
|
1010
|
+
}
|
|
1011
|
+
function createStateAttr(state) {
|
|
1012
|
+
return state;
|
|
1013
|
+
}
|
|
1014
|
+
function createPriorityAttr(priority) {
|
|
1015
|
+
return priority;
|
|
1016
|
+
}
|
|
1017
|
+
function createTestingProps(config) {
|
|
1018
|
+
const props = {};
|
|
1019
|
+
if (config.testId) {
|
|
1020
|
+
props["data-testid"] = enableTestingAttributes2 ? config.testId : void 0;
|
|
1021
|
+
}
|
|
1022
|
+
if (config.cyId) {
|
|
1023
|
+
props["data-cy"] = enableTestingAttributes2 ? config.cyId : void 0;
|
|
1024
|
+
}
|
|
1025
|
+
if (config.state) {
|
|
1026
|
+
props["data-state"] = config.state;
|
|
1027
|
+
}
|
|
1028
|
+
if (config.priority) {
|
|
1029
|
+
props["data-priority"] = config.priority;
|
|
1030
|
+
}
|
|
1031
|
+
if (config.taskId) {
|
|
1032
|
+
props["data-task-id"] = config.taskId;
|
|
1033
|
+
}
|
|
1034
|
+
if (config.userId) {
|
|
1035
|
+
props["data-user-id"] = config.userId;
|
|
1036
|
+
}
|
|
1037
|
+
return Object.fromEntries(
|
|
1038
|
+
Object.entries(props).filter((entry) => entry[1] !== void 0)
|
|
1039
|
+
);
|
|
1040
|
+
}
|
|
1041
|
+
function createAriaLabel(template, values) {
|
|
1042
|
+
return template.replace(/\{(\w+)\}/g, (match, key) => {
|
|
1043
|
+
return String(values[key] ?? match);
|
|
1044
|
+
});
|
|
1045
|
+
}
|
|
1046
|
+
var testingPatterns = {
|
|
1047
|
+
// Task/Todo components
|
|
1048
|
+
task: {
|
|
1049
|
+
card: (taskId) => createTestingProps({
|
|
1050
|
+
testId: createTestId("task", "card"),
|
|
1051
|
+
cyId: createCyId("task", "item"),
|
|
1052
|
+
taskId
|
|
1053
|
+
}),
|
|
1054
|
+
checkbox: () => createTestingProps({
|
|
1055
|
+
testId: createTestId("task", "checkbox"),
|
|
1056
|
+
cyId: createCyId("task", "toggle")
|
|
1057
|
+
}),
|
|
1058
|
+
title: () => createTestingProps({
|
|
1059
|
+
testId: createTestId("task", "title"),
|
|
1060
|
+
cyId: createCyId("task", "title")
|
|
1061
|
+
}),
|
|
1062
|
+
deleteButton: () => createTestingProps({
|
|
1063
|
+
testId: createTestId("task", "delete", "button"),
|
|
1064
|
+
cyId: createCyId("task", "delete")
|
|
1065
|
+
})
|
|
1066
|
+
},
|
|
1067
|
+
// Navigation components
|
|
1068
|
+
nav: {
|
|
1069
|
+
searchDropdown: () => createTestingProps({
|
|
1070
|
+
testId: createTestId("nav", "search", "dropdown"),
|
|
1071
|
+
cyId: createCyId("nav", "search")
|
|
1072
|
+
}),
|
|
1073
|
+
notifications: () => createTestingProps({
|
|
1074
|
+
testId: createTestId("nav", "notifications", "button"),
|
|
1075
|
+
cyId: createCyId("nav", "notifications")
|
|
1076
|
+
}),
|
|
1077
|
+
userMenu: () => createTestingProps({
|
|
1078
|
+
testId: createTestId("nav", "user", "menu"),
|
|
1079
|
+
cyId: createCyId("nav", "user-menu")
|
|
1080
|
+
})
|
|
1081
|
+
},
|
|
1082
|
+
// Form components
|
|
1083
|
+
form: {
|
|
1084
|
+
input: (fieldName) => createTestingProps({
|
|
1085
|
+
testId: createTestId("form", fieldName, "input"),
|
|
1086
|
+
cyId: createCyId("form", fieldName)
|
|
1087
|
+
}),
|
|
1088
|
+
submitButton: () => createTestingProps({
|
|
1089
|
+
testId: createTestId("form", "submit", "button"),
|
|
1090
|
+
cyId: createCyId("form", "submit")
|
|
1091
|
+
})
|
|
1092
|
+
}
|
|
1093
|
+
};
|
|
1094
|
+
var keyboardHelpers = {
|
|
1095
|
+
/**
|
|
1096
|
+
* Handle Enter and Space key activation
|
|
1097
|
+
*/
|
|
1098
|
+
createActivationHandler: (onActivate) => {
|
|
1099
|
+
return (e) => {
|
|
1100
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
1101
|
+
e.preventDefault();
|
|
1102
|
+
onActivate();
|
|
1103
|
+
}
|
|
1104
|
+
};
|
|
1105
|
+
},
|
|
1106
|
+
/**
|
|
1107
|
+
* Handle Escape key for closing
|
|
1108
|
+
*/
|
|
1109
|
+
createEscapeHandler: (onClose) => {
|
|
1110
|
+
return (e) => {
|
|
1111
|
+
if (e.key === "Escape") {
|
|
1112
|
+
e.preventDefault();
|
|
1113
|
+
onClose();
|
|
1114
|
+
}
|
|
1115
|
+
};
|
|
1116
|
+
},
|
|
1117
|
+
/**
|
|
1118
|
+
* Handle arrow navigation in lists
|
|
1119
|
+
*/
|
|
1120
|
+
createArrowNavigationHandler: (currentIndex, maxIndex, onIndexChange) => {
|
|
1121
|
+
return (e) => {
|
|
1122
|
+
switch (e.key) {
|
|
1123
|
+
case "ArrowDown":
|
|
1124
|
+
e.preventDefault();
|
|
1125
|
+
onIndexChange(currentIndex < maxIndex ? currentIndex + 1 : 0);
|
|
1126
|
+
break;
|
|
1127
|
+
case "ArrowUp":
|
|
1128
|
+
e.preventDefault();
|
|
1129
|
+
onIndexChange(currentIndex > 0 ? currentIndex - 1 : maxIndex);
|
|
1130
|
+
break;
|
|
1131
|
+
}
|
|
1132
|
+
};
|
|
1133
|
+
}
|
|
1134
|
+
};
|
|
1135
|
+
function createEntityCyId(entitySlug, component, detail) {
|
|
1136
|
+
if (!enableTestingAttributes2) return void 0;
|
|
1137
|
+
const parts = [entitySlug, component, detail].filter(Boolean);
|
|
1138
|
+
return parts.join("-");
|
|
1139
|
+
}
|
|
1140
|
+
function createEntityTestingHelper(entitySlug) {
|
|
1141
|
+
return {
|
|
1142
|
+
// Generic (framework-agnostic)
|
|
1143
|
+
get: (component, detail) => createEntityCyId(entitySlug, component, detail),
|
|
1144
|
+
// Page
|
|
1145
|
+
page: () => createEntityCyId(entitySlug, "page"),
|
|
1146
|
+
formPage: () => createEntityCyId(entitySlug, "form-page"),
|
|
1147
|
+
// Form
|
|
1148
|
+
form: () => createEntityCyId(entitySlug, "form"),
|
|
1149
|
+
formSubmit: () => createEntityCyId(entitySlug, "form-submit"),
|
|
1150
|
+
formCancel: () => createEntityCyId(entitySlug, "form-cancel"),
|
|
1151
|
+
// Fields
|
|
1152
|
+
field: (name) => createEntityCyId(entitySlug, "field", name),
|
|
1153
|
+
fieldOption: (name, value) => createEntityCyId(entitySlug, `field-${name}-option`, value),
|
|
1154
|
+
fieldError: (name) => createEntityCyId(entitySlug, `field-${name}`, "error"),
|
|
1155
|
+
// Sections
|
|
1156
|
+
section: (name) => createEntityCyId(entitySlug, "section", name),
|
|
1157
|
+
// Card
|
|
1158
|
+
card: (id) => createEntityCyId(entitySlug, "card", id),
|
|
1159
|
+
// List/Table
|
|
1160
|
+
table: () => createEntityCyId(entitySlug, "table"),
|
|
1161
|
+
row: (id) => createEntityCyId(entitySlug, "row", id),
|
|
1162
|
+
createBtn: () => createEntityCyId(entitySlug, "create-btn"),
|
|
1163
|
+
searchInput: () => createEntityCyId(entitySlug, "search-input"),
|
|
1164
|
+
// Filters
|
|
1165
|
+
filter: (field) => createEntityCyId(entitySlug, "filter", field),
|
|
1166
|
+
filterTrigger: (field) => createEntityCyId(entitySlug, `filter-${field}`, "trigger"),
|
|
1167
|
+
filterOption: (field, value) => createEntityCyId(entitySlug, `filter-${field}-option`, value),
|
|
1168
|
+
// Actions
|
|
1169
|
+
action: (action, id) => createEntityCyId(entitySlug, `action-${action}`, id),
|
|
1170
|
+
actionsTrigger: (id) => createEntityCyId(entitySlug, "actions-trigger", id),
|
|
1171
|
+
// Dialogs
|
|
1172
|
+
confirmDelete: () => createEntityCyId(entitySlug, "confirm-delete"),
|
|
1173
|
+
confirmDeleteBtn: () => createEntityCyId(entitySlug, "confirm-delete-btn"),
|
|
1174
|
+
cancelDeleteBtn: () => createEntityCyId(entitySlug, "cancel-delete-btn")
|
|
1175
|
+
};
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
// src/pom/BasePOMCore.ts
|
|
1179
|
+
var BasePOMCore = class {
|
|
1180
|
+
/**
|
|
1181
|
+
* Get a Cypress selector using the centralized selectors
|
|
1182
|
+
* Wrapper for cySelector with a shorter name
|
|
1183
|
+
*
|
|
1184
|
+
* @example
|
|
1185
|
+
* this.cy('auth.login.form')
|
|
1186
|
+
* // Returns: '[data-cy="login-form"]'
|
|
1187
|
+
*
|
|
1188
|
+
* this.cy('entities.table.row', { slug: 'tasks', id: '123' })
|
|
1189
|
+
* // Returns: '[data-cy="tasks-row-123"]'
|
|
1190
|
+
*/
|
|
1191
|
+
cy(path, replacements) {
|
|
1192
|
+
return this.cySelector(path, replacements);
|
|
1193
|
+
}
|
|
1194
|
+
/**
|
|
1195
|
+
* Replaces placeholders in a selector pattern and wraps with data-cy attribute
|
|
1196
|
+
*
|
|
1197
|
+
* @param pattern - Selector pattern with {placeholder} syntax
|
|
1198
|
+
* @param replacements - Object with placeholder values
|
|
1199
|
+
* @returns Formatted data-cy selector string
|
|
1200
|
+
*
|
|
1201
|
+
* @example
|
|
1202
|
+
* selector('{slug}-row-{id}', { slug: 'tasks', id: '123' })
|
|
1203
|
+
* // Returns: '[data-cy="tasks-row-123"]'
|
|
1204
|
+
*/
|
|
1205
|
+
selector(pattern, replacements = {}) {
|
|
1206
|
+
let result = pattern;
|
|
1207
|
+
for (const [key, value] of Object.entries(replacements)) {
|
|
1208
|
+
result = result.replaceAll(`{${key}}`, String(value));
|
|
1209
|
+
}
|
|
1210
|
+
return `[data-cy="${result}"]`;
|
|
1211
|
+
}
|
|
1212
|
+
/**
|
|
1213
|
+
* Wrapper for cy.get with selector pattern support
|
|
1214
|
+
* @param pattern - Selector pattern or direct selector
|
|
1215
|
+
* @param replacements - Optional placeholder replacements
|
|
1216
|
+
*/
|
|
1217
|
+
get(pattern, replacements = {}) {
|
|
1218
|
+
return cy.get(this.selector(pattern, replacements));
|
|
1219
|
+
}
|
|
1220
|
+
/**
|
|
1221
|
+
* Generic wait with configurable timeout
|
|
1222
|
+
* @param selector - CSS selector to wait for
|
|
1223
|
+
* @param timeout - Max wait time in ms (default: 15000)
|
|
1224
|
+
*/
|
|
1225
|
+
waitFor(selector, timeout = 15e3) {
|
|
1226
|
+
cy.get(selector, { timeout }).should("be.visible");
|
|
1227
|
+
return this;
|
|
1228
|
+
}
|
|
1229
|
+
/**
|
|
1230
|
+
* Wait for URL to contain a specific path
|
|
1231
|
+
* @param path - Path segment to check for
|
|
1232
|
+
*/
|
|
1233
|
+
waitForUrl(path) {
|
|
1234
|
+
cy.url().should("include", path);
|
|
1235
|
+
return this;
|
|
1236
|
+
}
|
|
1237
|
+
/**
|
|
1238
|
+
* Wait for URL to match a regex pattern
|
|
1239
|
+
* @param pattern - RegExp to match against URL
|
|
1240
|
+
*/
|
|
1241
|
+
waitForUrlMatch(pattern) {
|
|
1242
|
+
cy.url().should("match", pattern);
|
|
1243
|
+
return this;
|
|
1244
|
+
}
|
|
1245
|
+
/**
|
|
1246
|
+
* Visit a URL and return self for chaining
|
|
1247
|
+
* @param url - URL to visit
|
|
1248
|
+
*/
|
|
1249
|
+
visit(url) {
|
|
1250
|
+
cy.visit(url);
|
|
1251
|
+
return this;
|
|
1252
|
+
}
|
|
1253
|
+
/**
|
|
1254
|
+
* Wait for page to load (checks for body visible)
|
|
1255
|
+
*/
|
|
1256
|
+
waitForPageLoad() {
|
|
1257
|
+
cy.get("body").should("be.visible");
|
|
1258
|
+
return this;
|
|
1259
|
+
}
|
|
1260
|
+
/**
|
|
1261
|
+
* Get an element by selector
|
|
1262
|
+
* @param selector - CSS selector
|
|
1263
|
+
*/
|
|
1264
|
+
getElement(selector) {
|
|
1265
|
+
return cy.get(selector);
|
|
1266
|
+
}
|
|
1267
|
+
/**
|
|
1268
|
+
* Click on an element
|
|
1269
|
+
* @param selector - CSS selector
|
|
1270
|
+
*/
|
|
1271
|
+
click(selector) {
|
|
1272
|
+
cy.get(selector).click();
|
|
1273
|
+
return this;
|
|
1274
|
+
}
|
|
1275
|
+
/**
|
|
1276
|
+
* Type text into an input
|
|
1277
|
+
* @param selector - CSS selector
|
|
1278
|
+
* @param text - Text to type
|
|
1279
|
+
*/
|
|
1280
|
+
type(selector, text) {
|
|
1281
|
+
cy.get(selector).clear().type(text);
|
|
1282
|
+
return this;
|
|
1283
|
+
}
|
|
1284
|
+
/**
|
|
1285
|
+
* Check if element exists
|
|
1286
|
+
* @param selector - CSS selector
|
|
1287
|
+
*/
|
|
1288
|
+
exists(selector) {
|
|
1289
|
+
return cy.get(selector).should("exist");
|
|
1290
|
+
}
|
|
1291
|
+
/**
|
|
1292
|
+
* Check if element is visible
|
|
1293
|
+
* @param selector - CSS selector
|
|
1294
|
+
*/
|
|
1295
|
+
isVisible(selector) {
|
|
1296
|
+
return cy.get(selector).should("be.visible");
|
|
1297
|
+
}
|
|
1298
|
+
/**
|
|
1299
|
+
* Check if element does not exist
|
|
1300
|
+
* @param selector - CSS selector
|
|
1301
|
+
*/
|
|
1302
|
+
notExists(selector) {
|
|
1303
|
+
return cy.get(selector).should("not.exist");
|
|
1304
|
+
}
|
|
1305
|
+
};
|
|
1306
|
+
|
|
1307
|
+
// src/helpers/ApiInterceptor.ts
|
|
1308
|
+
var ApiInterceptor = class {
|
|
1309
|
+
constructor(slugOrConfig) {
|
|
1310
|
+
if (typeof slugOrConfig === "string") {
|
|
1311
|
+
this.slug = slugOrConfig;
|
|
1312
|
+
this.endpoint = `/api/v1/${slugOrConfig}`;
|
|
1313
|
+
} else {
|
|
1314
|
+
this.slug = slugOrConfig.slug;
|
|
1315
|
+
this.endpoint = slugOrConfig.customPath || `/api/v1/${slugOrConfig.slug}`;
|
|
1316
|
+
}
|
|
1317
|
+
}
|
|
1318
|
+
// ============================================
|
|
1319
|
+
// ACCESSORS
|
|
1320
|
+
// ============================================
|
|
1321
|
+
/** Get the API endpoint path */
|
|
1322
|
+
get path() {
|
|
1323
|
+
return this.endpoint;
|
|
1324
|
+
}
|
|
1325
|
+
/** Get the entity slug */
|
|
1326
|
+
get entitySlug() {
|
|
1327
|
+
return this.slug;
|
|
1328
|
+
}
|
|
1329
|
+
/** Get alias names for all operations */
|
|
1330
|
+
get aliases() {
|
|
1331
|
+
return {
|
|
1332
|
+
list: `${this.slug}List`,
|
|
1333
|
+
create: `${this.slug}Create`,
|
|
1334
|
+
update: `${this.slug}Update`,
|
|
1335
|
+
delete: `${this.slug}Delete`
|
|
1336
|
+
};
|
|
1337
|
+
}
|
|
1338
|
+
// ============================================
|
|
1339
|
+
// INTERCEPT SETUP
|
|
1340
|
+
// ============================================
|
|
1341
|
+
/**
|
|
1342
|
+
* Setup intercepts for all CRUD operations
|
|
1343
|
+
* Call this BEFORE navigation in beforeEach or at test start
|
|
1344
|
+
*
|
|
1345
|
+
* Note: We intercept both PUT and PATCH for updates since different
|
|
1346
|
+
* APIs may use different HTTP methods for updates.
|
|
1347
|
+
*/
|
|
1348
|
+
setupCrudIntercepts() {
|
|
1349
|
+
cy.intercept("GET", `${this.endpoint}*`).as(this.aliases.list);
|
|
1350
|
+
cy.intercept("POST", this.endpoint).as(this.aliases.create);
|
|
1351
|
+
cy.intercept("PUT", `${this.endpoint}/*`).as(this.aliases.update);
|
|
1352
|
+
cy.intercept("PATCH", `${this.endpoint}/*`).as(`${this.aliases.update}Patch`);
|
|
1353
|
+
cy.intercept("DELETE", `${this.endpoint}/*`).as(this.aliases.delete);
|
|
1354
|
+
return this;
|
|
1355
|
+
}
|
|
1356
|
+
/**
|
|
1357
|
+
* Setup only list + create intercepts
|
|
1358
|
+
* Useful for list pages with inline create
|
|
1359
|
+
*/
|
|
1360
|
+
setupListIntercepts() {
|
|
1361
|
+
cy.intercept("GET", `${this.endpoint}*`).as(this.aliases.list);
|
|
1362
|
+
cy.intercept("POST", this.endpoint).as(this.aliases.create);
|
|
1363
|
+
return this;
|
|
1364
|
+
}
|
|
1365
|
+
// ============================================
|
|
1366
|
+
// WAIT METHODS
|
|
1367
|
+
// ============================================
|
|
1368
|
+
/**
|
|
1369
|
+
* Wait for list response (GET)
|
|
1370
|
+
* Use after navigation or after mutations to wait for refresh
|
|
1371
|
+
*/
|
|
1372
|
+
waitForList(timeout = 1e4) {
|
|
1373
|
+
return cy.wait(`@${this.aliases.list}`, { timeout });
|
|
1374
|
+
}
|
|
1375
|
+
/**
|
|
1376
|
+
* Wait for create response (POST) and validate success status
|
|
1377
|
+
*/
|
|
1378
|
+
waitForCreate(timeout = 1e4) {
|
|
1379
|
+
return cy.wait(`@${this.aliases.create}`, { timeout }).its("response.statusCode").should("be.oneOf", [200, 201]);
|
|
1380
|
+
}
|
|
1381
|
+
/**
|
|
1382
|
+
* Wait for update response (PATCH or PUT) and validate success status
|
|
1383
|
+
* Waits for PATCH first (more common), falls back to PUT
|
|
1384
|
+
*/
|
|
1385
|
+
waitForUpdate(timeout = 1e4) {
|
|
1386
|
+
return cy.wait(`@${this.aliases.update}Patch`, { timeout }).its("response.statusCode").should("be.oneOf", [200, 201]);
|
|
1387
|
+
}
|
|
1388
|
+
/**
|
|
1389
|
+
* Wait for delete response (DELETE) and validate success status
|
|
1390
|
+
*/
|
|
1391
|
+
waitForDelete(timeout = 1e4) {
|
|
1392
|
+
return cy.wait(`@${this.aliases.delete}`, { timeout }).its("response.statusCode").should("be.oneOf", [200, 204]);
|
|
1393
|
+
}
|
|
1394
|
+
// ============================================
|
|
1395
|
+
// CONVENIENCE METHODS
|
|
1396
|
+
// ============================================
|
|
1397
|
+
/**
|
|
1398
|
+
* Wait for list refresh (alias for waitForList)
|
|
1399
|
+
* Semantic name for use after create/update/delete
|
|
1400
|
+
*/
|
|
1401
|
+
waitForRefresh(timeout = 1e4) {
|
|
1402
|
+
return this.waitForList(timeout);
|
|
1403
|
+
}
|
|
1404
|
+
/**
|
|
1405
|
+
* Wait for create + list refresh
|
|
1406
|
+
* Common pattern: create entity, wait for success, wait for list to refresh
|
|
1407
|
+
*/
|
|
1408
|
+
waitForCreateAndRefresh(timeout = 1e4) {
|
|
1409
|
+
this.waitForCreate(timeout);
|
|
1410
|
+
return this.waitForList(timeout);
|
|
1411
|
+
}
|
|
1412
|
+
/**
|
|
1413
|
+
* Wait for update + list refresh
|
|
1414
|
+
* Common pattern: update entity, wait for success, wait for list to refresh
|
|
1415
|
+
*/
|
|
1416
|
+
waitForUpdateAndRefresh(timeout = 1e4) {
|
|
1417
|
+
this.waitForUpdate(timeout);
|
|
1418
|
+
return this.waitForList(timeout);
|
|
1419
|
+
}
|
|
1420
|
+
/**
|
|
1421
|
+
* Wait for delete + list refresh
|
|
1422
|
+
* Common pattern: delete entity, wait for success, wait for list to refresh
|
|
1423
|
+
*/
|
|
1424
|
+
waitForDeleteAndRefresh(timeout = 1e4) {
|
|
1425
|
+
this.waitForDelete(timeout);
|
|
1426
|
+
return this.waitForList(timeout);
|
|
1427
|
+
}
|
|
1428
|
+
};
|
|
1429
|
+
|
|
1430
|
+
// src/pom/DashboardEntityPOMCore.ts
|
|
1431
|
+
var DashboardEntityPOMCore = class extends BasePOMCore {
|
|
1432
|
+
constructor(entitySlugOrConfig) {
|
|
1433
|
+
super();
|
|
1434
|
+
this._api = null;
|
|
1435
|
+
if (typeof entitySlugOrConfig === "string") {
|
|
1436
|
+
this.slug = entitySlugOrConfig;
|
|
1437
|
+
this.entityConfig = { slug: entitySlugOrConfig };
|
|
1438
|
+
} else {
|
|
1439
|
+
this.slug = entitySlugOrConfig.slug;
|
|
1440
|
+
this.entityConfig = entitySlugOrConfig;
|
|
1441
|
+
}
|
|
1442
|
+
}
|
|
1443
|
+
/**
|
|
1444
|
+
* Get the entity slug (public accessor)
|
|
1445
|
+
* Useful for building dynamic selectors and URLs in tests
|
|
1446
|
+
*/
|
|
1447
|
+
get entitySlug() {
|
|
1448
|
+
return this.slug;
|
|
1449
|
+
}
|
|
1450
|
+
// ============================================
|
|
1451
|
+
// API INTERCEPTOR
|
|
1452
|
+
// ============================================
|
|
1453
|
+
/**
|
|
1454
|
+
* Get or create ApiInterceptor instance for this entity
|
|
1455
|
+
*/
|
|
1456
|
+
get api() {
|
|
1457
|
+
if (!this._api) {
|
|
1458
|
+
this._api = new ApiInterceptor(this.slug);
|
|
1459
|
+
}
|
|
1460
|
+
return this._api;
|
|
1461
|
+
}
|
|
1462
|
+
/**
|
|
1463
|
+
* Setup API intercepts for all CRUD operations
|
|
1464
|
+
* Call this BEFORE navigation
|
|
1465
|
+
*/
|
|
1466
|
+
setupApiIntercepts() {
|
|
1467
|
+
this.api.setupCrudIntercepts();
|
|
1468
|
+
return this;
|
|
1469
|
+
}
|
|
1470
|
+
// ============================================
|
|
1471
|
+
// SELECTORS (uses cySelector from theme)
|
|
1472
|
+
// ============================================
|
|
1473
|
+
/**
|
|
1474
|
+
* Get all selectors for this entity, with placeholders replaced
|
|
1475
|
+
* Uses the abstract cySelector method which themes implement
|
|
1476
|
+
*/
|
|
1477
|
+
get selectors() {
|
|
1478
|
+
const slug = this.slug;
|
|
1479
|
+
return {
|
|
1480
|
+
// Page
|
|
1481
|
+
page: this.cySelector("entities.page.container", { slug }),
|
|
1482
|
+
pageTitle: this.cySelector("entities.page.title", { slug }),
|
|
1483
|
+
// Table
|
|
1484
|
+
tableContainer: this.cySelector("entities.table.container", { slug }),
|
|
1485
|
+
table: this.cySelector("entities.table.element", { slug }),
|
|
1486
|
+
addButton: this.cySelector("entities.table.addButton", { slug }),
|
|
1487
|
+
search: this.cySelector("entities.table.search", { slug }),
|
|
1488
|
+
searchContainer: this.cySelector("entities.table.search", { slug }),
|
|
1489
|
+
searchClear: this.cySelector("entities.search.clear", { slug }),
|
|
1490
|
+
selectAll: this.cySelector("entities.table.selectAll", { slug }),
|
|
1491
|
+
selectionCount: this.cySelector("entities.table.selectionCount", { slug }),
|
|
1492
|
+
row: (id) => this.cySelector("entities.table.row", { slug, id }),
|
|
1493
|
+
rowSelect: (id) => this.cySelector("entities.table.rowSelect", { slug, id }),
|
|
1494
|
+
rowMenu: (id) => this.cySelector("entities.table.rowMenu", { slug, id }),
|
|
1495
|
+
rowAction: (action, id) => this.cySelector("entities.table.rowAction", { slug, action, id }),
|
|
1496
|
+
cell: (field, id) => this.cySelector("entities.table.cell", { slug, field, id }),
|
|
1497
|
+
rowGeneric: `[data-cy^="${slug}-row-"]`,
|
|
1498
|
+
// Pagination
|
|
1499
|
+
pagination: this.cySelector("entities.pagination.container", { slug }),
|
|
1500
|
+
pageSize: this.cySelector("entities.pagination.pageSize", { slug }),
|
|
1501
|
+
pageSizeOption: (size) => this.cySelector("entities.pagination.pageSizeOption", { slug, size }),
|
|
1502
|
+
pageInfo: this.cySelector("entities.pagination.pageInfo", { slug }),
|
|
1503
|
+
pageFirst: this.cySelector("entities.pagination.first", { slug }),
|
|
1504
|
+
pagePrev: this.cySelector("entities.pagination.prev", { slug }),
|
|
1505
|
+
pageNext: this.cySelector("entities.pagination.next", { slug }),
|
|
1506
|
+
pageLast: this.cySelector("entities.pagination.last", { slug }),
|
|
1507
|
+
// Header (detail pages) - modes: view, edit, create
|
|
1508
|
+
viewHeader: this.cySelector("entities.header.container", { slug, mode: "view" }),
|
|
1509
|
+
editHeader: this.cySelector("entities.header.container", { slug, mode: "edit" }),
|
|
1510
|
+
createHeader: this.cySelector("entities.header.container", { slug, mode: "create" }),
|
|
1511
|
+
backButton: this.cySelector("entities.header.backButton", { slug }),
|
|
1512
|
+
editButton: this.cySelector("entities.header.editButton", { slug }),
|
|
1513
|
+
deleteButton: this.cySelector("entities.header.deleteButton", { slug }),
|
|
1514
|
+
copyId: this.cySelector("entities.header.copyId", { slug }),
|
|
1515
|
+
title: this.cySelector("entities.header.title", { slug }),
|
|
1516
|
+
// Delete confirmation
|
|
1517
|
+
deleteDialog: this.cySelector("entities.header.deleteDialog", { slug }),
|
|
1518
|
+
deleteCancel: this.cySelector("entities.header.deleteCancel", { slug }),
|
|
1519
|
+
deleteConfirm: this.cySelector("entities.header.deleteConfirm", { slug }),
|
|
1520
|
+
// Form
|
|
1521
|
+
form: this.cySelector("entities.form.container", { slug }),
|
|
1522
|
+
field: (name) => this.cySelector("entities.form.field", { slug, name }),
|
|
1523
|
+
submitButton: this.cySelector("entities.form.submitButton", { slug }),
|
|
1524
|
+
// Filters
|
|
1525
|
+
filter: (field) => this.cySelector("entities.filter.container", { slug, field }),
|
|
1526
|
+
filterTrigger: (field) => this.cySelector("entities.filter.trigger", { slug, field }),
|
|
1527
|
+
filterContent: (field) => this.cySelector("entities.filter.content", { slug, field }),
|
|
1528
|
+
filterOption: (field, value) => this.cySelector("entities.filter.option", { slug, field, value }),
|
|
1529
|
+
filterBadge: (field, value) => this.cySelector("entities.filter.badge", { slug, field, value }),
|
|
1530
|
+
filterRemoveBadge: (field, value) => this.cySelector("entities.filter.removeBadge", { slug, field, value }),
|
|
1531
|
+
filterClearAll: (field) => this.cySelector("entities.filter.clearAll", { slug, field }),
|
|
1532
|
+
// Bulk actions
|
|
1533
|
+
bulkBar: this.cySelector("entities.bulk.bar", { slug }),
|
|
1534
|
+
bulkCount: this.cySelector("entities.bulk.count", { slug }),
|
|
1535
|
+
bulkSelectAll: this.cySelector("entities.bulk.selectAll", { slug }),
|
|
1536
|
+
bulkStatus: this.cySelector("entities.bulk.statusButton", { slug }),
|
|
1537
|
+
bulkDelete: this.cySelector("entities.bulk.deleteButton", { slug }),
|
|
1538
|
+
bulkClear: this.cySelector("entities.bulk.clearButton", { slug }),
|
|
1539
|
+
// Bulk status dialog
|
|
1540
|
+
bulkStatusDialog: this.cySelector("entities.bulk.statusDialog", { slug }),
|
|
1541
|
+
bulkStatusSelect: this.cySelector("entities.bulk.statusSelect", { slug }),
|
|
1542
|
+
bulkStatusOption: (value) => this.cySelector("entities.bulk.statusOption", { slug, value }),
|
|
1543
|
+
bulkStatusCancel: this.cySelector("entities.bulk.statusCancel", { slug }),
|
|
1544
|
+
bulkStatusConfirm: this.cySelector("entities.bulk.statusConfirm", { slug }),
|
|
1545
|
+
// Bulk delete dialog
|
|
1546
|
+
bulkDeleteDialog: this.cySelector("entities.bulk.deleteDialog", { slug }),
|
|
1547
|
+
bulkDeleteCancel: this.cySelector("entities.bulk.deleteCancel", { slug }),
|
|
1548
|
+
bulkDeleteConfirm: this.cySelector("entities.bulk.deleteConfirm", { slug }),
|
|
1549
|
+
// Generic confirm dialog
|
|
1550
|
+
confirmDialog: this.cySelector("entities.confirm.dialog", { slug }),
|
|
1551
|
+
confirmCancel: this.cySelector("entities.confirm.cancel", { slug }),
|
|
1552
|
+
confirmAction: this.cySelector("entities.confirm.action", { slug }),
|
|
1553
|
+
// Parent delete confirmation (EntityDetailWrapper - generic, no slug)
|
|
1554
|
+
parentDeleteConfirm: '[data-cy="confirm-delete"]',
|
|
1555
|
+
parentDeleteCancel: '[data-cy="cancel-delete"]',
|
|
1556
|
+
// Row action selectors (generic patterns for checking existence)
|
|
1557
|
+
rowActionEditGeneric: `[data-cy^="${slug}-action-edit-"]`,
|
|
1558
|
+
rowActionDeleteGeneric: `[data-cy^="${slug}-action-delete-"]`,
|
|
1559
|
+
// Detail view
|
|
1560
|
+
detail: this.cySelector("entities.detail.container", { slug })
|
|
1561
|
+
};
|
|
1562
|
+
}
|
|
1563
|
+
// ============================================
|
|
1564
|
+
// NAVIGATION
|
|
1565
|
+
// ============================================
|
|
1566
|
+
/**
|
|
1567
|
+
* Navigate to entity list page
|
|
1568
|
+
*/
|
|
1569
|
+
visitList() {
|
|
1570
|
+
cy.visit(`/dashboard/${this.slug}`);
|
|
1571
|
+
return this;
|
|
1572
|
+
}
|
|
1573
|
+
/**
|
|
1574
|
+
* Navigate to create page
|
|
1575
|
+
*/
|
|
1576
|
+
visitCreate() {
|
|
1577
|
+
cy.visit(`/dashboard/${this.slug}/create`);
|
|
1578
|
+
return this;
|
|
1579
|
+
}
|
|
1580
|
+
/**
|
|
1581
|
+
* Navigate to edit page for specific entity
|
|
1582
|
+
*/
|
|
1583
|
+
visitEdit(id) {
|
|
1584
|
+
cy.visit(`/dashboard/${this.slug}/${id}/edit`);
|
|
1585
|
+
return this;
|
|
1586
|
+
}
|
|
1587
|
+
/**
|
|
1588
|
+
* Navigate to detail/view page for specific entity
|
|
1589
|
+
*/
|
|
1590
|
+
visitDetail(id) {
|
|
1591
|
+
cy.visit(`/dashboard/${this.slug}/${id}`);
|
|
1592
|
+
return this;
|
|
1593
|
+
}
|
|
1594
|
+
// ============================================
|
|
1595
|
+
// API-AWARE NAVIGATION
|
|
1596
|
+
// ============================================
|
|
1597
|
+
/**
|
|
1598
|
+
* Navigate to list and wait for API response
|
|
1599
|
+
*/
|
|
1600
|
+
visitListWithApiWait() {
|
|
1601
|
+
this.setupApiIntercepts();
|
|
1602
|
+
this.visitList();
|
|
1603
|
+
this.api.waitForList();
|
|
1604
|
+
return this;
|
|
1605
|
+
}
|
|
1606
|
+
/**
|
|
1607
|
+
* Navigate to edit page and wait for form to be visible
|
|
1608
|
+
*/
|
|
1609
|
+
visitEditWithApiWait(id) {
|
|
1610
|
+
this.setupApiIntercepts();
|
|
1611
|
+
this.visitEdit(id);
|
|
1612
|
+
this.waitForForm();
|
|
1613
|
+
return this;
|
|
1614
|
+
}
|
|
1615
|
+
/**
|
|
1616
|
+
* Navigate to detail page and wait for content
|
|
1617
|
+
*/
|
|
1618
|
+
visitDetailWithApiWait(id) {
|
|
1619
|
+
this.setupApiIntercepts();
|
|
1620
|
+
this.visitDetail(id);
|
|
1621
|
+
this.waitForDetail();
|
|
1622
|
+
return this;
|
|
1623
|
+
}
|
|
1624
|
+
// ============================================
|
|
1625
|
+
// WAITS
|
|
1626
|
+
// ============================================
|
|
1627
|
+
/**
|
|
1628
|
+
* Wait for list page to be fully loaded
|
|
1629
|
+
*/
|
|
1630
|
+
waitForList() {
|
|
1631
|
+
cy.url().should("include", `/dashboard/${this.slug}`);
|
|
1632
|
+
cy.get(this.selectors.tableContainer, { timeout: 15e3 }).should("be.visible");
|
|
1633
|
+
return this;
|
|
1634
|
+
}
|
|
1635
|
+
/**
|
|
1636
|
+
* Wait for form to be visible
|
|
1637
|
+
*/
|
|
1638
|
+
waitForForm() {
|
|
1639
|
+
cy.get(this.selectors.form, { timeout: 15e3 }).should("be.visible");
|
|
1640
|
+
return this;
|
|
1641
|
+
}
|
|
1642
|
+
/**
|
|
1643
|
+
* Wait for detail page to be loaded
|
|
1644
|
+
*/
|
|
1645
|
+
waitForDetail() {
|
|
1646
|
+
cy.url().should("match", new RegExp(`/dashboard/${this.slug}/[a-z0-9-]+$`));
|
|
1647
|
+
cy.get(this.selectors.editButton, { timeout: 15e3 }).should("be.visible");
|
|
1648
|
+
return this;
|
|
1649
|
+
}
|
|
1650
|
+
// ============================================
|
|
1651
|
+
// TABLE ACTIONS
|
|
1652
|
+
// ============================================
|
|
1653
|
+
/**
|
|
1654
|
+
* Click the Add/Create button
|
|
1655
|
+
*/
|
|
1656
|
+
clickAdd() {
|
|
1657
|
+
cy.get(this.selectors.addButton).click();
|
|
1658
|
+
return this;
|
|
1659
|
+
}
|
|
1660
|
+
/**
|
|
1661
|
+
* Type in the search input
|
|
1662
|
+
*/
|
|
1663
|
+
search(term) {
|
|
1664
|
+
cy.get(this.selectors.search).clear().type(term);
|
|
1665
|
+
return this;
|
|
1666
|
+
}
|
|
1667
|
+
/**
|
|
1668
|
+
* Clear the search input
|
|
1669
|
+
*/
|
|
1670
|
+
clearSearch() {
|
|
1671
|
+
cy.get(this.selectors.searchClear).click();
|
|
1672
|
+
return this;
|
|
1673
|
+
}
|
|
1674
|
+
/**
|
|
1675
|
+
* Click a specific row by ID
|
|
1676
|
+
*/
|
|
1677
|
+
clickRow(id) {
|
|
1678
|
+
cy.get(this.selectors.row(id)).click();
|
|
1679
|
+
return this;
|
|
1680
|
+
}
|
|
1681
|
+
/**
|
|
1682
|
+
* Find and click a row containing specific text
|
|
1683
|
+
*/
|
|
1684
|
+
clickRowByText(text) {
|
|
1685
|
+
cy.contains(this.selectors.rowGeneric, text).click();
|
|
1686
|
+
return this;
|
|
1687
|
+
}
|
|
1688
|
+
/**
|
|
1689
|
+
* Select a row checkbox
|
|
1690
|
+
*/
|
|
1691
|
+
selectRow(id) {
|
|
1692
|
+
cy.get(this.selectors.rowSelect(id)).click();
|
|
1693
|
+
return this;
|
|
1694
|
+
}
|
|
1695
|
+
/**
|
|
1696
|
+
* Open the row menu (three dots)
|
|
1697
|
+
*/
|
|
1698
|
+
openRowMenu(id) {
|
|
1699
|
+
cy.get(this.selectors.rowMenu(id)).click();
|
|
1700
|
+
return this;
|
|
1701
|
+
}
|
|
1702
|
+
/**
|
|
1703
|
+
* Click an action in the row menu
|
|
1704
|
+
*/
|
|
1705
|
+
clickRowAction(action, id) {
|
|
1706
|
+
cy.get(this.selectors.rowAction(action, id)).click();
|
|
1707
|
+
return this;
|
|
1708
|
+
}
|
|
1709
|
+
// ============================================
|
|
1710
|
+
// FILTERS
|
|
1711
|
+
// ============================================
|
|
1712
|
+
/**
|
|
1713
|
+
* Open a filter dropdown
|
|
1714
|
+
*/
|
|
1715
|
+
openFilter(field) {
|
|
1716
|
+
cy.get(this.selectors.filterTrigger(field)).click();
|
|
1717
|
+
return this;
|
|
1718
|
+
}
|
|
1719
|
+
/**
|
|
1720
|
+
* Select a filter option
|
|
1721
|
+
*/
|
|
1722
|
+
selectFilterOption(field, value) {
|
|
1723
|
+
cy.get(this.selectors.filterOption(field, value)).click();
|
|
1724
|
+
return this;
|
|
1725
|
+
}
|
|
1726
|
+
/**
|
|
1727
|
+
* Open filter and select option (convenience method)
|
|
1728
|
+
*/
|
|
1729
|
+
selectFilter(field, value) {
|
|
1730
|
+
this.openFilter(field);
|
|
1731
|
+
this.selectFilterOption(field, value);
|
|
1732
|
+
return this;
|
|
1733
|
+
}
|
|
1734
|
+
/**
|
|
1735
|
+
* Remove a filter badge
|
|
1736
|
+
*/
|
|
1737
|
+
removeFilterBadge(field, value) {
|
|
1738
|
+
cy.get(this.selectors.filterRemoveBadge(field, value)).click();
|
|
1739
|
+
return this;
|
|
1740
|
+
}
|
|
1741
|
+
/**
|
|
1742
|
+
* Clear all values for a filter
|
|
1743
|
+
*/
|
|
1744
|
+
clearFilter(field) {
|
|
1745
|
+
cy.get(this.selectors.filterClearAll(field)).click();
|
|
1746
|
+
return this;
|
|
1747
|
+
}
|
|
1748
|
+
// ============================================
|
|
1749
|
+
// PAGINATION
|
|
1750
|
+
// ============================================
|
|
1751
|
+
/**
|
|
1752
|
+
* Go to next page
|
|
1753
|
+
*/
|
|
1754
|
+
nextPage() {
|
|
1755
|
+
cy.get(this.selectors.pageNext).click();
|
|
1756
|
+
return this;
|
|
1757
|
+
}
|
|
1758
|
+
/**
|
|
1759
|
+
* Go to previous page
|
|
1760
|
+
*/
|
|
1761
|
+
prevPage() {
|
|
1762
|
+
cy.get(this.selectors.pagePrev).click();
|
|
1763
|
+
return this;
|
|
1764
|
+
}
|
|
1765
|
+
/**
|
|
1766
|
+
* Go to first page
|
|
1767
|
+
*/
|
|
1768
|
+
firstPage() {
|
|
1769
|
+
cy.get(this.selectors.pageFirst).click();
|
|
1770
|
+
return this;
|
|
1771
|
+
}
|
|
1772
|
+
/**
|
|
1773
|
+
* Go to last page
|
|
1774
|
+
*/
|
|
1775
|
+
lastPage() {
|
|
1776
|
+
cy.get(this.selectors.pageLast).click();
|
|
1777
|
+
return this;
|
|
1778
|
+
}
|
|
1779
|
+
/**
|
|
1780
|
+
* Change page size
|
|
1781
|
+
*/
|
|
1782
|
+
setPageSize(size) {
|
|
1783
|
+
cy.get(this.selectors.pageSize).click();
|
|
1784
|
+
cy.get(this.selectors.pageSizeOption(size)).click();
|
|
1785
|
+
return this;
|
|
1786
|
+
}
|
|
1787
|
+
// ============================================
|
|
1788
|
+
// FORM ACTIONS
|
|
1789
|
+
// ============================================
|
|
1790
|
+
/**
|
|
1791
|
+
* Fill a text input field
|
|
1792
|
+
*/
|
|
1793
|
+
fillTextField(name, value) {
|
|
1794
|
+
cy.get(this.selectors.field(name)).find("input").clear().type(value);
|
|
1795
|
+
return this;
|
|
1796
|
+
}
|
|
1797
|
+
/**
|
|
1798
|
+
* Fill a textarea field
|
|
1799
|
+
*/
|
|
1800
|
+
fillTextarea(name, value) {
|
|
1801
|
+
cy.get(this.selectors.field(name)).find("textarea").clear().type(value);
|
|
1802
|
+
return this;
|
|
1803
|
+
}
|
|
1804
|
+
/**
|
|
1805
|
+
* Select an option in a combobox/select field
|
|
1806
|
+
*/
|
|
1807
|
+
selectOption(name, value) {
|
|
1808
|
+
cy.get(this.selectors.field(name)).find('[role="combobox"]').click();
|
|
1809
|
+
cy.get(`[data-cy="${this.slug}-field-${name}-option-${value}"]`).click();
|
|
1810
|
+
return this;
|
|
1811
|
+
}
|
|
1812
|
+
/**
|
|
1813
|
+
* Submit the form
|
|
1814
|
+
*/
|
|
1815
|
+
submitForm() {
|
|
1816
|
+
cy.get(this.selectors.submitButton).click();
|
|
1817
|
+
return this;
|
|
1818
|
+
}
|
|
1819
|
+
// ============================================
|
|
1820
|
+
// HEADER/DETAIL ACTIONS
|
|
1821
|
+
// ============================================
|
|
1822
|
+
/**
|
|
1823
|
+
* Click back button
|
|
1824
|
+
*/
|
|
1825
|
+
clickBack() {
|
|
1826
|
+
cy.get(this.selectors.backButton).click();
|
|
1827
|
+
return this;
|
|
1828
|
+
}
|
|
1829
|
+
/**
|
|
1830
|
+
* Click edit button
|
|
1831
|
+
*/
|
|
1832
|
+
clickEdit() {
|
|
1833
|
+
cy.get(this.selectors.editButton).click();
|
|
1834
|
+
return this;
|
|
1835
|
+
}
|
|
1836
|
+
/**
|
|
1837
|
+
* Click delete button
|
|
1838
|
+
*/
|
|
1839
|
+
clickDelete() {
|
|
1840
|
+
cy.get(this.selectors.deleteButton).click();
|
|
1841
|
+
return this;
|
|
1842
|
+
}
|
|
1843
|
+
/**
|
|
1844
|
+
* Confirm delete in dialog
|
|
1845
|
+
*/
|
|
1846
|
+
confirmDelete() {
|
|
1847
|
+
cy.get(this.selectors.deleteConfirm).click();
|
|
1848
|
+
return this;
|
|
1849
|
+
}
|
|
1850
|
+
/**
|
|
1851
|
+
* Cancel delete in dialog
|
|
1852
|
+
*/
|
|
1853
|
+
cancelDelete() {
|
|
1854
|
+
cy.get(this.selectors.deleteCancel).click();
|
|
1855
|
+
return this;
|
|
1856
|
+
}
|
|
1857
|
+
// ============================================
|
|
1858
|
+
// BULK ACTIONS
|
|
1859
|
+
// ============================================
|
|
1860
|
+
/**
|
|
1861
|
+
* Select all items using table header checkbox
|
|
1862
|
+
*/
|
|
1863
|
+
selectAll() {
|
|
1864
|
+
cy.get(this.selectors.selectAll).click();
|
|
1865
|
+
return this;
|
|
1866
|
+
}
|
|
1867
|
+
/**
|
|
1868
|
+
* Click bulk delete button
|
|
1869
|
+
*/
|
|
1870
|
+
bulkDelete() {
|
|
1871
|
+
cy.get(this.selectors.bulkDelete).click();
|
|
1872
|
+
return this;
|
|
1873
|
+
}
|
|
1874
|
+
/**
|
|
1875
|
+
* Confirm bulk delete
|
|
1876
|
+
*/
|
|
1877
|
+
confirmBulkDelete() {
|
|
1878
|
+
cy.get(this.selectors.bulkDeleteConfirm).click();
|
|
1879
|
+
return this;
|
|
1880
|
+
}
|
|
1881
|
+
/**
|
|
1882
|
+
* Cancel bulk delete
|
|
1883
|
+
*/
|
|
1884
|
+
cancelBulkDelete() {
|
|
1885
|
+
cy.get(this.selectors.bulkDeleteCancel).click();
|
|
1886
|
+
return this;
|
|
1887
|
+
}
|
|
1888
|
+
/**
|
|
1889
|
+
* Click bulk status button
|
|
1890
|
+
*/
|
|
1891
|
+
bulkChangeStatus() {
|
|
1892
|
+
cy.get(this.selectors.bulkStatus).click();
|
|
1893
|
+
return this;
|
|
1894
|
+
}
|
|
1895
|
+
/**
|
|
1896
|
+
* Select status in bulk status dialog
|
|
1897
|
+
*/
|
|
1898
|
+
selectBulkStatus(value) {
|
|
1899
|
+
cy.get(this.selectors.bulkStatusSelect).click();
|
|
1900
|
+
cy.get(this.selectors.bulkStatusOption(value)).click();
|
|
1901
|
+
return this;
|
|
1902
|
+
}
|
|
1903
|
+
/**
|
|
1904
|
+
* Confirm bulk status change
|
|
1905
|
+
*/
|
|
1906
|
+
confirmBulkStatus() {
|
|
1907
|
+
cy.get(this.selectors.bulkStatusConfirm).click();
|
|
1908
|
+
return this;
|
|
1909
|
+
}
|
|
1910
|
+
/**
|
|
1911
|
+
* Clear selection
|
|
1912
|
+
*/
|
|
1913
|
+
clearSelection() {
|
|
1914
|
+
cy.get(this.selectors.bulkClear).click();
|
|
1915
|
+
return this;
|
|
1916
|
+
}
|
|
1917
|
+
// ============================================
|
|
1918
|
+
// ASSERTIONS
|
|
1919
|
+
// ============================================
|
|
1920
|
+
/**
|
|
1921
|
+
* Assert text is visible in the list
|
|
1922
|
+
*/
|
|
1923
|
+
assertInList(text) {
|
|
1924
|
+
cy.contains(text).should("be.visible");
|
|
1925
|
+
return this;
|
|
1926
|
+
}
|
|
1927
|
+
/**
|
|
1928
|
+
* Assert text is not in the list
|
|
1929
|
+
*/
|
|
1930
|
+
assertNotInList(text) {
|
|
1931
|
+
cy.contains(text).should("not.exist");
|
|
1932
|
+
return this;
|
|
1933
|
+
}
|
|
1934
|
+
/**
|
|
1935
|
+
* Assert table is visible
|
|
1936
|
+
*/
|
|
1937
|
+
assertTableVisible() {
|
|
1938
|
+
cy.get(this.selectors.table).should("be.visible");
|
|
1939
|
+
return this;
|
|
1940
|
+
}
|
|
1941
|
+
/**
|
|
1942
|
+
* Assert form is visible
|
|
1943
|
+
*/
|
|
1944
|
+
assertFormVisible() {
|
|
1945
|
+
cy.get(this.selectors.form).should("be.visible");
|
|
1946
|
+
return this;
|
|
1947
|
+
}
|
|
1948
|
+
/**
|
|
1949
|
+
* Assert page title contains text
|
|
1950
|
+
*/
|
|
1951
|
+
assertPageTitle(expected) {
|
|
1952
|
+
cy.get(this.selectors.title).should("contain.text", expected);
|
|
1953
|
+
return this;
|
|
1954
|
+
}
|
|
1955
|
+
/**
|
|
1956
|
+
* Assert row exists
|
|
1957
|
+
*/
|
|
1958
|
+
assertRowExists(id) {
|
|
1959
|
+
cy.get(this.selectors.row(id)).should("exist");
|
|
1960
|
+
return this;
|
|
1961
|
+
}
|
|
1962
|
+
/**
|
|
1963
|
+
* Assert row does not exist
|
|
1964
|
+
*/
|
|
1965
|
+
assertRowNotExists(id) {
|
|
1966
|
+
cy.get(this.selectors.row(id)).should("not.exist");
|
|
1967
|
+
return this;
|
|
1968
|
+
}
|
|
1969
|
+
/**
|
|
1970
|
+
* Assert selection count
|
|
1971
|
+
*/
|
|
1972
|
+
assertSelectionCount(count) {
|
|
1973
|
+
cy.get(this.selectors.selectionCount).should("contain.text", count.toString());
|
|
1974
|
+
return this;
|
|
1975
|
+
}
|
|
1976
|
+
/**
|
|
1977
|
+
* Assert bulk bar is visible
|
|
1978
|
+
*/
|
|
1979
|
+
assertBulkBarVisible() {
|
|
1980
|
+
cy.get(this.selectors.bulkBar).should("be.visible");
|
|
1981
|
+
return this;
|
|
1982
|
+
}
|
|
1983
|
+
/**
|
|
1984
|
+
* Assert bulk bar is hidden
|
|
1985
|
+
*/
|
|
1986
|
+
assertBulkBarHidden() {
|
|
1987
|
+
cy.get(this.selectors.bulkBar).should("not.be.visible");
|
|
1988
|
+
return this;
|
|
1989
|
+
}
|
|
1990
|
+
};
|
|
1991
|
+
|
|
1992
|
+
export { ApiInterceptor, BasePOMCore, CORE_SELECTORS, DashboardEntityPOMCore, SELECTORS, createAriaLabel, createCyId, createEntityCyId, createEntityTestingHelper, createPriorityAttr, createSelectorHelpers, createStateAttr, createTestId, createTestingProps, cySelector, entitySelectors, getNestedValue, keyboardHelpers, replacePlaceholders, s, sel, selDev, testingPatterns };
|
|
1993
|
+
//# sourceMappingURL=index.js.map
|
|
1994
|
+
//# sourceMappingURL=index.js.map
|