@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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 NextSpark
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,99 @@
1
+ # @nextsparkjs/testing
2
+
3
+ Testing utilities for NextSpark applications. Provides selectors, Page Object Models, and Cypress helpers.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @nextsparkjs/testing
9
+ # or
10
+ pnpm add @nextsparkjs/testing
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ ### Basic Selectors
16
+
17
+ ```typescript
18
+ import { sel, cySelector, CORE_SELECTORS } from '@nextsparkjs/testing'
19
+
20
+ // Get selector value
21
+ sel('dashboard.navigation.main') // 'nav-main'
22
+
23
+ // Get Cypress selector
24
+ cySelector('dashboard.navigation.main') // '[data-cy="nav-main"]'
25
+
26
+ // Access raw selectors
27
+ CORE_SELECTORS.dashboard.navigation.main // 'nav-main'
28
+ ```
29
+
30
+ ### Subpath Imports (Recommended)
31
+
32
+ For better tree-shaking:
33
+
34
+ ```typescript
35
+ import { sel, cySelector } from '@nextsparkjs/testing/selectors'
36
+ import { createEntityTestingHelper } from '@nextsparkjs/testing/utils'
37
+ ```
38
+
39
+ ### Theme Extension
40
+
41
+ Themes can extend core selectors:
42
+
43
+ ```typescript
44
+ import { createSelectorHelpers, CORE_SELECTORS } from '@nextsparkjs/testing/selectors'
45
+
46
+ const THEME_SELECTORS = {
47
+ ...CORE_SELECTORS,
48
+ myFeature: {
49
+ button: 'my-feature-btn',
50
+ form: 'my-feature-form',
51
+ },
52
+ }
53
+
54
+ export const { sel, cySelector } = createSelectorHelpers(THEME_SELECTORS)
55
+ ```
56
+
57
+ ### Entity Testing Helper
58
+
59
+ ```typescript
60
+ import { createEntityTestingHelper } from '@nextsparkjs/testing/utils'
61
+
62
+ const testId = createEntityTestingHelper('products')
63
+
64
+ // Usage in components
65
+ <div data-cy={testId.page()}> // products-page
66
+ <form data-cy={testId.form()}> // products-form
67
+ <input data-cy={testId.field('name')} /> // products-field-name
68
+ <button data-cy={testId.formSubmit()}> // products-form-submit
69
+ Submit
70
+ </button>
71
+ </form>
72
+ </div>
73
+ ```
74
+
75
+ ## Exports
76
+
77
+ ### Main Entry (`@nextsparkjs/testing`)
78
+
79
+ - `sel()` - Get selector value by path
80
+ - `cySelector()` - Get Cypress selector string
81
+ - `CORE_SELECTORS` - All core selectors
82
+ - `createSelectorHelpers()` - Factory for custom selectors
83
+ - `createEntityTestingHelper()` - Entity-specific helper factory
84
+
85
+ ### Selectors (`@nextsparkjs/testing/selectors`)
86
+
87
+ - All selector-related exports
88
+
89
+ ### Utils (`@nextsparkjs/testing/utils`)
90
+
91
+ - `createTestId()` - Create test IDs
92
+ - `createCyId()` - Create Cypress IDs
93
+ - `createEntityTestingHelper()` - Entity helper factory
94
+ - `testingPatterns` - Common testing patterns
95
+ - `keyboardHelpers` - Keyboard navigation helpers
96
+
97
+ ## License
98
+
99
+ MIT
@@ -0,0 +1,97 @@
1
+ /**
2
+ * ApiInterceptor - Helper for deterministic waits in Cypress
3
+ *
4
+ * Replaces unreliable cy.wait(ms) with cy.intercept() based waits
5
+ * that wait for actual API responses.
6
+ *
7
+ * @example Basic usage:
8
+ * ```ts
9
+ * const api = new ApiInterceptor('customers')
10
+ * api.setupCrudIntercepts()
11
+ * cy.visit('/dashboard/customers')
12
+ * api.waitForList()
13
+ * ```
14
+ *
15
+ * @example Custom path:
16
+ * ```ts
17
+ * const api = new ApiInterceptor({
18
+ * slug: 'categories',
19
+ * customPath: '/api/v1/post-categories'
20
+ * })
21
+ * ```
22
+ */
23
+ interface ApiInterceptorConfig {
24
+ /** Entity slug - used to generate aliases */
25
+ slug: string;
26
+ /** Custom API path (e.g., '/api/v1/post-categories') */
27
+ customPath?: string;
28
+ }
29
+ declare class ApiInterceptor {
30
+ private slug;
31
+ private endpoint;
32
+ constructor(slugOrConfig: string | ApiInterceptorConfig);
33
+ /** Get the API endpoint path */
34
+ get path(): string;
35
+ /** Get the entity slug */
36
+ get entitySlug(): string;
37
+ /** Get alias names for all operations */
38
+ get aliases(): {
39
+ list: string;
40
+ create: string;
41
+ update: string;
42
+ delete: string;
43
+ };
44
+ /**
45
+ * Setup intercepts for all CRUD operations
46
+ * Call this BEFORE navigation in beforeEach or at test start
47
+ *
48
+ * Note: We intercept both PUT and PATCH for updates since different
49
+ * APIs may use different HTTP methods for updates.
50
+ */
51
+ setupCrudIntercepts(): this;
52
+ /**
53
+ * Setup only list + create intercepts
54
+ * Useful for list pages with inline create
55
+ */
56
+ setupListIntercepts(): this;
57
+ /**
58
+ * Wait for list response (GET)
59
+ * Use after navigation or after mutations to wait for refresh
60
+ */
61
+ waitForList(timeout?: number): Cypress.Chainable;
62
+ /**
63
+ * Wait for create response (POST) and validate success status
64
+ */
65
+ waitForCreate(timeout?: number): Cypress.Chainable;
66
+ /**
67
+ * Wait for update response (PATCH or PUT) and validate success status
68
+ * Waits for PATCH first (more common), falls back to PUT
69
+ */
70
+ waitForUpdate(timeout?: number): Cypress.Chainable;
71
+ /**
72
+ * Wait for delete response (DELETE) and validate success status
73
+ */
74
+ waitForDelete(timeout?: number): Cypress.Chainable;
75
+ /**
76
+ * Wait for list refresh (alias for waitForList)
77
+ * Semantic name for use after create/update/delete
78
+ */
79
+ waitForRefresh(timeout?: number): Cypress.Chainable;
80
+ /**
81
+ * Wait for create + list refresh
82
+ * Common pattern: create entity, wait for success, wait for list to refresh
83
+ */
84
+ waitForCreateAndRefresh(timeout?: number): Cypress.Chainable;
85
+ /**
86
+ * Wait for update + list refresh
87
+ * Common pattern: update entity, wait for success, wait for list to refresh
88
+ */
89
+ waitForUpdateAndRefresh(timeout?: number): Cypress.Chainable;
90
+ /**
91
+ * Wait for delete + list refresh
92
+ * Common pattern: delete entity, wait for success, wait for list to refresh
93
+ */
94
+ waitForDeleteAndRefresh(timeout?: number): Cypress.Chainable;
95
+ }
96
+
97
+ export { ApiInterceptor, type ApiInterceptorConfig };
@@ -0,0 +1,126 @@
1
+ // src/helpers/ApiInterceptor.ts
2
+ var ApiInterceptor = class {
3
+ constructor(slugOrConfig) {
4
+ if (typeof slugOrConfig === "string") {
5
+ this.slug = slugOrConfig;
6
+ this.endpoint = `/api/v1/${slugOrConfig}`;
7
+ } else {
8
+ this.slug = slugOrConfig.slug;
9
+ this.endpoint = slugOrConfig.customPath || `/api/v1/${slugOrConfig.slug}`;
10
+ }
11
+ }
12
+ // ============================================
13
+ // ACCESSORS
14
+ // ============================================
15
+ /** Get the API endpoint path */
16
+ get path() {
17
+ return this.endpoint;
18
+ }
19
+ /** Get the entity slug */
20
+ get entitySlug() {
21
+ return this.slug;
22
+ }
23
+ /** Get alias names for all operations */
24
+ get aliases() {
25
+ return {
26
+ list: `${this.slug}List`,
27
+ create: `${this.slug}Create`,
28
+ update: `${this.slug}Update`,
29
+ delete: `${this.slug}Delete`
30
+ };
31
+ }
32
+ // ============================================
33
+ // INTERCEPT SETUP
34
+ // ============================================
35
+ /**
36
+ * Setup intercepts for all CRUD operations
37
+ * Call this BEFORE navigation in beforeEach or at test start
38
+ *
39
+ * Note: We intercept both PUT and PATCH for updates since different
40
+ * APIs may use different HTTP methods for updates.
41
+ */
42
+ setupCrudIntercepts() {
43
+ cy.intercept("GET", `${this.endpoint}*`).as(this.aliases.list);
44
+ cy.intercept("POST", this.endpoint).as(this.aliases.create);
45
+ cy.intercept("PUT", `${this.endpoint}/*`).as(this.aliases.update);
46
+ cy.intercept("PATCH", `${this.endpoint}/*`).as(`${this.aliases.update}Patch`);
47
+ cy.intercept("DELETE", `${this.endpoint}/*`).as(this.aliases.delete);
48
+ return this;
49
+ }
50
+ /**
51
+ * Setup only list + create intercepts
52
+ * Useful for list pages with inline create
53
+ */
54
+ setupListIntercepts() {
55
+ cy.intercept("GET", `${this.endpoint}*`).as(this.aliases.list);
56
+ cy.intercept("POST", this.endpoint).as(this.aliases.create);
57
+ return this;
58
+ }
59
+ // ============================================
60
+ // WAIT METHODS
61
+ // ============================================
62
+ /**
63
+ * Wait for list response (GET)
64
+ * Use after navigation or after mutations to wait for refresh
65
+ */
66
+ waitForList(timeout = 1e4) {
67
+ return cy.wait(`@${this.aliases.list}`, { timeout });
68
+ }
69
+ /**
70
+ * Wait for create response (POST) and validate success status
71
+ */
72
+ waitForCreate(timeout = 1e4) {
73
+ return cy.wait(`@${this.aliases.create}`, { timeout }).its("response.statusCode").should("be.oneOf", [200, 201]);
74
+ }
75
+ /**
76
+ * Wait for update response (PATCH or PUT) and validate success status
77
+ * Waits for PATCH first (more common), falls back to PUT
78
+ */
79
+ waitForUpdate(timeout = 1e4) {
80
+ return cy.wait(`@${this.aliases.update}Patch`, { timeout }).its("response.statusCode").should("be.oneOf", [200, 201]);
81
+ }
82
+ /**
83
+ * Wait for delete response (DELETE) and validate success status
84
+ */
85
+ waitForDelete(timeout = 1e4) {
86
+ return cy.wait(`@${this.aliases.delete}`, { timeout }).its("response.statusCode").should("be.oneOf", [200, 204]);
87
+ }
88
+ // ============================================
89
+ // CONVENIENCE METHODS
90
+ // ============================================
91
+ /**
92
+ * Wait for list refresh (alias for waitForList)
93
+ * Semantic name for use after create/update/delete
94
+ */
95
+ waitForRefresh(timeout = 1e4) {
96
+ return this.waitForList(timeout);
97
+ }
98
+ /**
99
+ * Wait for create + list refresh
100
+ * Common pattern: create entity, wait for success, wait for list to refresh
101
+ */
102
+ waitForCreateAndRefresh(timeout = 1e4) {
103
+ this.waitForCreate(timeout);
104
+ return this.waitForList(timeout);
105
+ }
106
+ /**
107
+ * Wait for update + list refresh
108
+ * Common pattern: update entity, wait for success, wait for list to refresh
109
+ */
110
+ waitForUpdateAndRefresh(timeout = 1e4) {
111
+ this.waitForUpdate(timeout);
112
+ return this.waitForList(timeout);
113
+ }
114
+ /**
115
+ * Wait for delete + list refresh
116
+ * Common pattern: delete entity, wait for success, wait for list to refresh
117
+ */
118
+ waitForDeleteAndRefresh(timeout = 1e4) {
119
+ this.waitForDelete(timeout);
120
+ return this.waitForList(timeout);
121
+ }
122
+ };
123
+
124
+ export { ApiInterceptor };
125
+ //# sourceMappingURL=index.js.map
126
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/helpers/ApiInterceptor.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * ApiInterceptor - Helper for deterministic waits in Cypress\n *\n * Replaces unreliable cy.wait(ms) with cy.intercept() based waits\n * that wait for actual API responses.\n *\n * @example Basic usage:\n * ```ts\n * const api = new ApiInterceptor('customers')\n * api.setupCrudIntercepts()\n * cy.visit('/dashboard/customers')\n * api.waitForList()\n * ```\n *\n * @example Custom path:\n * ```ts\n * const api = new ApiInterceptor({\n * slug: 'categories',\n * customPath: '/api/v1/post-categories'\n * })\n * ```\n */\n\nexport interface ApiInterceptorConfig {\n /** Entity slug - used to generate aliases */\n slug: string\n /** Custom API path (e.g., '/api/v1/post-categories') */\n customPath?: string\n}\n\nexport class ApiInterceptor {\n private slug: string\n private endpoint: string\n\n constructor(slugOrConfig: string | ApiInterceptorConfig) {\n if (typeof slugOrConfig === 'string') {\n this.slug = slugOrConfig\n this.endpoint = `/api/v1/${slugOrConfig}`\n } else {\n this.slug = slugOrConfig.slug\n this.endpoint = slugOrConfig.customPath || `/api/v1/${slugOrConfig.slug}`\n }\n }\n\n // ============================================\n // ACCESSORS\n // ============================================\n\n /** Get the API endpoint path */\n get path(): string {\n return this.endpoint\n }\n\n /** Get the entity slug */\n get entitySlug(): string {\n return this.slug\n }\n\n /** Get alias names for all operations */\n get aliases() {\n return {\n list: `${this.slug}List`,\n create: `${this.slug}Create`,\n update: `${this.slug}Update`,\n delete: `${this.slug}Delete`,\n }\n }\n\n // ============================================\n // INTERCEPT SETUP\n // ============================================\n\n /**\n * Setup intercepts for all CRUD operations\n * Call this BEFORE navigation in beforeEach or at test start\n *\n * Note: We intercept both PUT and PATCH for updates since different\n * APIs may use different HTTP methods for updates.\n */\n setupCrudIntercepts(): this {\n cy.intercept('GET', `${this.endpoint}*`).as(this.aliases.list)\n cy.intercept('POST', this.endpoint).as(this.aliases.create)\n // Intercept both PUT and PATCH for updates (APIs may use either)\n cy.intercept('PUT', `${this.endpoint}/*`).as(this.aliases.update)\n cy.intercept('PATCH', `${this.endpoint}/*`).as(`${this.aliases.update}Patch`)\n cy.intercept('DELETE', `${this.endpoint}/*`).as(this.aliases.delete)\n return this\n }\n\n /**\n * Setup only list + create intercepts\n * Useful for list pages with inline create\n */\n setupListIntercepts(): this {\n cy.intercept('GET', `${this.endpoint}*`).as(this.aliases.list)\n cy.intercept('POST', this.endpoint).as(this.aliases.create)\n return this\n }\n\n // ============================================\n // WAIT METHODS\n // ============================================\n\n /**\n * Wait for list response (GET)\n * Use after navigation or after mutations to wait for refresh\n */\n waitForList(timeout = 10000): Cypress.Chainable {\n return cy.wait(`@${this.aliases.list}`, { timeout })\n }\n\n /**\n * Wait for create response (POST) and validate success status\n */\n waitForCreate(timeout = 10000): Cypress.Chainable {\n return cy.wait(`@${this.aliases.create}`, { timeout })\n .its('response.statusCode')\n .should('be.oneOf', [200, 201])\n }\n\n /**\n * Wait for update response (PATCH or PUT) and validate success status\n * Waits for PATCH first (more common), falls back to PUT\n */\n waitForUpdate(timeout = 10000): Cypress.Chainable {\n // Try PATCH first (more common in modern APIs), fall back to PUT\n return cy.wait(`@${this.aliases.update}Patch`, { timeout })\n .its('response.statusCode')\n .should('be.oneOf', [200, 201])\n }\n\n /**\n * Wait for delete response (DELETE) and validate success status\n */\n waitForDelete(timeout = 10000): Cypress.Chainable {\n return cy.wait(`@${this.aliases.delete}`, { timeout })\n .its('response.statusCode')\n .should('be.oneOf', [200, 204])\n }\n\n // ============================================\n // CONVENIENCE METHODS\n // ============================================\n\n /**\n * Wait for list refresh (alias for waitForList)\n * Semantic name for use after create/update/delete\n */\n waitForRefresh(timeout = 10000): Cypress.Chainable {\n return this.waitForList(timeout)\n }\n\n /**\n * Wait for create + list refresh\n * Common pattern: create entity, wait for success, wait for list to refresh\n */\n waitForCreateAndRefresh(timeout = 10000): Cypress.Chainable {\n this.waitForCreate(timeout)\n return this.waitForList(timeout)\n }\n\n /**\n * Wait for update + list refresh\n * Common pattern: update entity, wait for success, wait for list to refresh\n */\n waitForUpdateAndRefresh(timeout = 10000): Cypress.Chainable {\n this.waitForUpdate(timeout)\n return this.waitForList(timeout)\n }\n\n /**\n * Wait for delete + list refresh\n * Common pattern: delete entity, wait for success, wait for list to refresh\n */\n waitForDeleteAndRefresh(timeout = 10000): Cypress.Chainable {\n this.waitForDelete(timeout)\n return this.waitForList(timeout)\n }\n}\n\nexport default ApiInterceptor\n"]}
@@ -0,0 +1,5 @@
1
+ export { E as EntitySelectorHelpers, R as Replacements, a as SelectorHelpers, S as SelectorObject, c as createSelectorHelpers, g as getNestedValue, r as replacePlaceholders } from './selector-factory-BivSWXbw.js';
2
+ export { CORE_SELECTORS, CoreSelectorsType, SELECTORS, SelectorPath, SelectorsType, cySelector, entitySelectors, s, sel, selDev } from './selectors/index.js';
3
+ export { CypressIdPattern, EntityTestingHelper, TestIdPattern, createAriaLabel, createCyId, createEntityCyId, createEntityTestingHelper, createPriorityAttr, createStateAttr, createTestId, createTestingProps, keyboardHelpers, testingPatterns } from './utils/index.js';
4
+ export { BasePOMCore, DashboardEntityPOMCore, EntityConfig } from './pom/index.js';
5
+ export { ApiInterceptor, ApiInterceptorConfig } from './helpers/index.js';