@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.
@@ -0,0 +1,473 @@
1
+ import { R as Replacements } from '../selector-factory-BivSWXbw.js';
2
+ import { ApiInterceptor } from '../helpers/index.js';
3
+
4
+ /**
5
+ * BasePOMCore - Base class with common utilities for all Page Object Models
6
+ *
7
+ * This is the CORE version that provides generic methods.
8
+ * Themes should extend this class and implement the abstract `cySelector` method
9
+ * to provide theme-specific selector resolution.
10
+ *
11
+ * @example Theme extension:
12
+ * ```ts
13
+ * // theme/tests/cypress/src/core/BasePOM.ts
14
+ * import { BasePOMCore } from '@nextsparkjs/testing/pom'
15
+ * import { cySelector } from '../selectors'
16
+ *
17
+ * export abstract class BasePOM extends BasePOMCore {
18
+ * protected cySelector(path: string, replacements?: Record<string, string>): string {
19
+ * return cySelector(path, replacements)
20
+ * }
21
+ * }
22
+ * ```
23
+ */
24
+
25
+ declare abstract class BasePOMCore {
26
+ /**
27
+ * Abstract method - themes must implement to provide their cySelector
28
+ * This allows themes to use their extended THEME_SELECTORS
29
+ *
30
+ * @param path - Dot-notation path to the selector (e.g., "auth.login.form")
31
+ * @param replacements - Optional placeholder replacements
32
+ * @returns Cypress selector string like [data-cy="selector-value"]
33
+ */
34
+ protected abstract cySelector(path: string, replacements?: Replacements): string;
35
+ /**
36
+ * Get a Cypress selector using the centralized selectors
37
+ * Wrapper for cySelector with a shorter name
38
+ *
39
+ * @example
40
+ * this.cy('auth.login.form')
41
+ * // Returns: '[data-cy="login-form"]'
42
+ *
43
+ * this.cy('entities.table.row', { slug: 'tasks', id: '123' })
44
+ * // Returns: '[data-cy="tasks-row-123"]'
45
+ */
46
+ protected cy(path: string, replacements?: Replacements): string;
47
+ /**
48
+ * Replaces placeholders in a selector pattern and wraps with data-cy attribute
49
+ *
50
+ * @param pattern - Selector pattern with {placeholder} syntax
51
+ * @param replacements - Object with placeholder values
52
+ * @returns Formatted data-cy selector string
53
+ *
54
+ * @example
55
+ * selector('{slug}-row-{id}', { slug: 'tasks', id: '123' })
56
+ * // Returns: '[data-cy="tasks-row-123"]'
57
+ */
58
+ protected selector(pattern: string, replacements?: Replacements): string;
59
+ /**
60
+ * Wrapper for cy.get with selector pattern support
61
+ * @param pattern - Selector pattern or direct selector
62
+ * @param replacements - Optional placeholder replacements
63
+ */
64
+ protected get(pattern: string, replacements?: Replacements): Cypress.Chainable<JQuery<HTMLElement>>;
65
+ /**
66
+ * Generic wait with configurable timeout
67
+ * @param selector - CSS selector to wait for
68
+ * @param timeout - Max wait time in ms (default: 15000)
69
+ */
70
+ protected waitFor(selector: string, timeout?: number): this;
71
+ /**
72
+ * Wait for URL to contain a specific path
73
+ * @param path - Path segment to check for
74
+ */
75
+ protected waitForUrl(path: string): this;
76
+ /**
77
+ * Wait for URL to match a regex pattern
78
+ * @param pattern - RegExp to match against URL
79
+ */
80
+ protected waitForUrlMatch(pattern: RegExp): this;
81
+ /**
82
+ * Visit a URL and return self for chaining
83
+ * @param url - URL to visit
84
+ */
85
+ visit(url: string): this;
86
+ /**
87
+ * Wait for page to load (checks for body visible)
88
+ */
89
+ waitForPageLoad(): this;
90
+ /**
91
+ * Get an element by selector
92
+ * @param selector - CSS selector
93
+ */
94
+ getElement(selector: string): Cypress.Chainable<JQuery<HTMLElement>>;
95
+ /**
96
+ * Click on an element
97
+ * @param selector - CSS selector
98
+ */
99
+ click(selector: string): this;
100
+ /**
101
+ * Type text into an input
102
+ * @param selector - CSS selector
103
+ * @param text - Text to type
104
+ */
105
+ type(selector: string, text: string): this;
106
+ /**
107
+ * Check if element exists
108
+ * @param selector - CSS selector
109
+ */
110
+ exists(selector: string): Cypress.Chainable<JQuery<HTMLElement>>;
111
+ /**
112
+ * Check if element is visible
113
+ * @param selector - CSS selector
114
+ */
115
+ isVisible(selector: string): Cypress.Chainable<JQuery<HTMLElement>>;
116
+ /**
117
+ * Check if element does not exist
118
+ * @param selector - CSS selector
119
+ */
120
+ notExists(selector: string): Cypress.Chainable<JQuery<HTMLElement>>;
121
+ }
122
+
123
+ /**
124
+ * DashboardEntityPOMCore - Base class for all entity Page Object Models
125
+ *
126
+ * Provides standard CRUD operations for dashboard entities:
127
+ * - Navigation (list, create, edit, detail pages)
128
+ * - Table interactions (search, filters, pagination, row actions)
129
+ * - Form operations (fill fields, submit, cancel)
130
+ * - API interceptor integration for deterministic waits
131
+ * - Bulk actions
132
+ * - Delete confirmation dialogs
133
+ *
134
+ * This is the CORE version. Themes should extend this class and implement
135
+ * the abstract `cySelector` method from BasePOMCore.
136
+ *
137
+ * @example Theme extension:
138
+ * ```ts
139
+ * // theme/tests/cypress/src/core/DashboardEntityPOM.ts
140
+ * import { DashboardEntityPOMCore } from '@nextsparkjs/testing/pom'
141
+ * import { cySelector } from '../selectors'
142
+ *
143
+ * export abstract class DashboardEntityPOM extends DashboardEntityPOMCore {
144
+ * protected cySelector(path: string, replacements?: Record<string, string>): string {
145
+ * return cySelector(path, replacements)
146
+ * }
147
+ * }
148
+ * ```
149
+ */
150
+
151
+ interface EntityConfig {
152
+ slug: string;
153
+ singular?: string;
154
+ plural?: string;
155
+ tableName?: string;
156
+ fields?: string[];
157
+ filters?: string[];
158
+ }
159
+ declare abstract class DashboardEntityPOMCore extends BasePOMCore {
160
+ protected slug: string;
161
+ protected entityConfig: EntityConfig;
162
+ protected _api: ApiInterceptor | null;
163
+ /**
164
+ * Get the entity slug (public accessor)
165
+ * Useful for building dynamic selectors and URLs in tests
166
+ */
167
+ get entitySlug(): string;
168
+ constructor(entitySlugOrConfig: string | EntityConfig);
169
+ /**
170
+ * Get or create ApiInterceptor instance for this entity
171
+ */
172
+ get api(): ApiInterceptor;
173
+ /**
174
+ * Setup API intercepts for all CRUD operations
175
+ * Call this BEFORE navigation
176
+ */
177
+ setupApiIntercepts(): this;
178
+ /**
179
+ * Get all selectors for this entity, with placeholders replaced
180
+ * Uses the abstract cySelector method which themes implement
181
+ */
182
+ get selectors(): {
183
+ page: string;
184
+ pageTitle: string;
185
+ tableContainer: string;
186
+ table: string;
187
+ addButton: string;
188
+ search: string;
189
+ searchContainer: string;
190
+ searchClear: string;
191
+ selectAll: string;
192
+ selectionCount: string;
193
+ row: (id: string) => string;
194
+ rowSelect: (id: string) => string;
195
+ rowMenu: (id: string) => string;
196
+ rowAction: (action: string, id: string) => string;
197
+ cell: (field: string, id: string) => string;
198
+ rowGeneric: string;
199
+ pagination: string;
200
+ pageSize: string;
201
+ pageSizeOption: (size: string) => string;
202
+ pageInfo: string;
203
+ pageFirst: string;
204
+ pagePrev: string;
205
+ pageNext: string;
206
+ pageLast: string;
207
+ viewHeader: string;
208
+ editHeader: string;
209
+ createHeader: string;
210
+ backButton: string;
211
+ editButton: string;
212
+ deleteButton: string;
213
+ copyId: string;
214
+ title: string;
215
+ deleteDialog: string;
216
+ deleteCancel: string;
217
+ deleteConfirm: string;
218
+ form: string;
219
+ field: (name: string) => string;
220
+ submitButton: string;
221
+ filter: (field: string) => string;
222
+ filterTrigger: (field: string) => string;
223
+ filterContent: (field: string) => string;
224
+ filterOption: (field: string, value: string) => string;
225
+ filterBadge: (field: string, value: string) => string;
226
+ filterRemoveBadge: (field: string, value: string) => string;
227
+ filterClearAll: (field: string) => string;
228
+ bulkBar: string;
229
+ bulkCount: string;
230
+ bulkSelectAll: string;
231
+ bulkStatus: string;
232
+ bulkDelete: string;
233
+ bulkClear: string;
234
+ bulkStatusDialog: string;
235
+ bulkStatusSelect: string;
236
+ bulkStatusOption: (value: string) => string;
237
+ bulkStatusCancel: string;
238
+ bulkStatusConfirm: string;
239
+ bulkDeleteDialog: string;
240
+ bulkDeleteCancel: string;
241
+ bulkDeleteConfirm: string;
242
+ confirmDialog: string;
243
+ confirmCancel: string;
244
+ confirmAction: string;
245
+ parentDeleteConfirm: string;
246
+ parentDeleteCancel: string;
247
+ rowActionEditGeneric: string;
248
+ rowActionDeleteGeneric: string;
249
+ detail: string;
250
+ };
251
+ /**
252
+ * Navigate to entity list page
253
+ */
254
+ visitList(): this;
255
+ /**
256
+ * Navigate to create page
257
+ */
258
+ visitCreate(): this;
259
+ /**
260
+ * Navigate to edit page for specific entity
261
+ */
262
+ visitEdit(id: string): this;
263
+ /**
264
+ * Navigate to detail/view page for specific entity
265
+ */
266
+ visitDetail(id: string): this;
267
+ /**
268
+ * Navigate to list and wait for API response
269
+ */
270
+ visitListWithApiWait(): this;
271
+ /**
272
+ * Navigate to edit page and wait for form to be visible
273
+ */
274
+ visitEditWithApiWait(id: string): this;
275
+ /**
276
+ * Navigate to detail page and wait for content
277
+ */
278
+ visitDetailWithApiWait(id: string): this;
279
+ /**
280
+ * Wait for list page to be fully loaded
281
+ */
282
+ waitForList(): this;
283
+ /**
284
+ * Wait for form to be visible
285
+ */
286
+ waitForForm(): this;
287
+ /**
288
+ * Wait for detail page to be loaded
289
+ */
290
+ waitForDetail(): this;
291
+ /**
292
+ * Click the Add/Create button
293
+ */
294
+ clickAdd(): this;
295
+ /**
296
+ * Type in the search input
297
+ */
298
+ search(term: string): this;
299
+ /**
300
+ * Clear the search input
301
+ */
302
+ clearSearch(): this;
303
+ /**
304
+ * Click a specific row by ID
305
+ */
306
+ clickRow(id: string): this;
307
+ /**
308
+ * Find and click a row containing specific text
309
+ */
310
+ clickRowByText(text: string): this;
311
+ /**
312
+ * Select a row checkbox
313
+ */
314
+ selectRow(id: string): this;
315
+ /**
316
+ * Open the row menu (three dots)
317
+ */
318
+ openRowMenu(id: string): this;
319
+ /**
320
+ * Click an action in the row menu
321
+ */
322
+ clickRowAction(action: string, id: string): this;
323
+ /**
324
+ * Open a filter dropdown
325
+ */
326
+ openFilter(field: string): this;
327
+ /**
328
+ * Select a filter option
329
+ */
330
+ selectFilterOption(field: string, value: string): this;
331
+ /**
332
+ * Open filter and select option (convenience method)
333
+ */
334
+ selectFilter(field: string, value: string): this;
335
+ /**
336
+ * Remove a filter badge
337
+ */
338
+ removeFilterBadge(field: string, value: string): this;
339
+ /**
340
+ * Clear all values for a filter
341
+ */
342
+ clearFilter(field: string): this;
343
+ /**
344
+ * Go to next page
345
+ */
346
+ nextPage(): this;
347
+ /**
348
+ * Go to previous page
349
+ */
350
+ prevPage(): this;
351
+ /**
352
+ * Go to first page
353
+ */
354
+ firstPage(): this;
355
+ /**
356
+ * Go to last page
357
+ */
358
+ lastPage(): this;
359
+ /**
360
+ * Change page size
361
+ */
362
+ setPageSize(size: string): this;
363
+ /**
364
+ * Fill a text input field
365
+ */
366
+ fillTextField(name: string, value: string): this;
367
+ /**
368
+ * Fill a textarea field
369
+ */
370
+ fillTextarea(name: string, value: string): this;
371
+ /**
372
+ * Select an option in a combobox/select field
373
+ */
374
+ selectOption(name: string, value: string): this;
375
+ /**
376
+ * Submit the form
377
+ */
378
+ submitForm(): this;
379
+ /**
380
+ * Click back button
381
+ */
382
+ clickBack(): this;
383
+ /**
384
+ * Click edit button
385
+ */
386
+ clickEdit(): this;
387
+ /**
388
+ * Click delete button
389
+ */
390
+ clickDelete(): this;
391
+ /**
392
+ * Confirm delete in dialog
393
+ */
394
+ confirmDelete(): this;
395
+ /**
396
+ * Cancel delete in dialog
397
+ */
398
+ cancelDelete(): this;
399
+ /**
400
+ * Select all items using table header checkbox
401
+ */
402
+ selectAll(): this;
403
+ /**
404
+ * Click bulk delete button
405
+ */
406
+ bulkDelete(): this;
407
+ /**
408
+ * Confirm bulk delete
409
+ */
410
+ confirmBulkDelete(): this;
411
+ /**
412
+ * Cancel bulk delete
413
+ */
414
+ cancelBulkDelete(): this;
415
+ /**
416
+ * Click bulk status button
417
+ */
418
+ bulkChangeStatus(): this;
419
+ /**
420
+ * Select status in bulk status dialog
421
+ */
422
+ selectBulkStatus(value: string): this;
423
+ /**
424
+ * Confirm bulk status change
425
+ */
426
+ confirmBulkStatus(): this;
427
+ /**
428
+ * Clear selection
429
+ */
430
+ clearSelection(): this;
431
+ /**
432
+ * Assert text is visible in the list
433
+ */
434
+ assertInList(text: string): this;
435
+ /**
436
+ * Assert text is not in the list
437
+ */
438
+ assertNotInList(text: string): this;
439
+ /**
440
+ * Assert table is visible
441
+ */
442
+ assertTableVisible(): this;
443
+ /**
444
+ * Assert form is visible
445
+ */
446
+ assertFormVisible(): this;
447
+ /**
448
+ * Assert page title contains text
449
+ */
450
+ assertPageTitle(expected: string): this;
451
+ /**
452
+ * Assert row exists
453
+ */
454
+ assertRowExists(id: string): this;
455
+ /**
456
+ * Assert row does not exist
457
+ */
458
+ assertRowNotExists(id: string): this;
459
+ /**
460
+ * Assert selection count
461
+ */
462
+ assertSelectionCount(count: number): this;
463
+ /**
464
+ * Assert bulk bar is visible
465
+ */
466
+ assertBulkBarVisible(): this;
467
+ /**
468
+ * Assert bulk bar is hidden
469
+ */
470
+ assertBulkBarHidden(): this;
471
+ }
472
+
473
+ export { BasePOMCore, DashboardEntityPOMCore, type EntityConfig };