@cepharum/contextual-gherkin 1.2.6 → 2.0.0
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/lib/api.js +3 -3
- package/lib/context.js +14 -22
- package/package.json +1 -1
- package/steps/global-action.js +20 -34
- package/steps/global-find.js +21 -21
- package/steps/local-action.js +7 -7
- package/steps/local-find.js +23 -17
- package/steps/local-state.js +15 -10
package/lib/api.js
CHANGED
|
@@ -45,7 +45,7 @@ class Api {
|
|
|
45
45
|
*
|
|
46
46
|
* @param {string} typeOfElement names type of element to be looked up
|
|
47
47
|
* @param {SimpleSelector} defaultSelector selector to use as fallback
|
|
48
|
-
* @returns {
|
|
48
|
+
* @returns {Context} node describing performed search, its context and any yielded matches
|
|
49
49
|
* @throws Error if no or multiple selectors have been found for named type and no default has been provided
|
|
50
50
|
*/
|
|
51
51
|
find( typeOfElement, defaultSelector = undefined ) {
|
|
@@ -58,7 +58,7 @@ class Api {
|
|
|
58
58
|
* @param {string} typeOfElement names of type of element to look up
|
|
59
59
|
* @param {string|number} index provided index of match to fetch from type's queue of previous matches
|
|
60
60
|
* @param {Cardinality} cardinality selects expected number of elements in match to find
|
|
61
|
-
* @returns {Context} node describing found previous match of elements of named type
|
|
61
|
+
* @returns {Promise<Context>} promise for node describing found previous match of elements of named type
|
|
62
62
|
*/
|
|
63
63
|
async get( typeOfElement, index, cardinality = null ) {
|
|
64
64
|
const alias = this.getNormalizedAliases( typeOfElement )[0];
|
|
@@ -105,7 +105,7 @@ class Api {
|
|
|
105
105
|
* Conveniently recovers context based on provided description.
|
|
106
106
|
*
|
|
107
107
|
* @param {ContextualWord} context describes context to recover
|
|
108
|
-
* @returns {Promise<Context>}
|
|
108
|
+
* @returns {Promise<Context>} promise for tracked node describing result of a previous search
|
|
109
109
|
*/
|
|
110
110
|
async getContextFor( context ) {
|
|
111
111
|
try {
|
package/lib/context.js
CHANGED
|
@@ -76,7 +76,7 @@ class Context {
|
|
|
76
76
|
*
|
|
77
77
|
* @param {string} typeOfElement names type of elements to search
|
|
78
78
|
* @param {SimpleSelector} defaultSelector selector to use as fallback
|
|
79
|
-
* @returns {
|
|
79
|
+
* @returns {Context} node describing found elements and their processing context
|
|
80
80
|
*/
|
|
81
81
|
find( typeOfElement, defaultSelector = undefined ) {
|
|
82
82
|
const type = this.api.toNormalizedSingularName( typeOfElement );
|
|
@@ -91,7 +91,7 @@ class Context {
|
|
|
91
91
|
matches = Selector( query, dependencies ? { dependencies } : {} );
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
-
return
|
|
94
|
+
return new this.constructor( this.testController, this, this.api, { matches, type, selectors } );
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
/**
|
|
@@ -140,7 +140,7 @@ class Context {
|
|
|
140
140
|
*
|
|
141
141
|
* @param {string} typeOfElement names type of elements to focus on
|
|
142
142
|
* @param {SimpleSelector} defaultSelector selector to use as fallback
|
|
143
|
-
* @returns {
|
|
143
|
+
* @returns {Context} node describing matches of filtering and their processing context
|
|
144
144
|
*/
|
|
145
145
|
filter( typeOfElement, defaultSelector = undefined ) {
|
|
146
146
|
if ( !this.matches ) {
|
|
@@ -151,12 +151,12 @@ class Context {
|
|
|
151
151
|
const { query, dependencies } = this.getSelector( type, defaultSelector );
|
|
152
152
|
const matches = query === "" ? this.matches : Selector( this.matches ).filter( ...dependencies ? [ query, dependencies ] : [query] );
|
|
153
153
|
|
|
154
|
-
return
|
|
154
|
+
return new this.constructor( this.testController, this, this.api, {
|
|
155
155
|
matches,
|
|
156
156
|
type: this.type,
|
|
157
157
|
selectors: this.selectors,
|
|
158
158
|
cardinality: this.cardinality
|
|
159
|
-
} )
|
|
159
|
+
} );
|
|
160
160
|
}
|
|
161
161
|
|
|
162
162
|
/**
|
|
@@ -165,7 +165,7 @@ class Context {
|
|
|
165
165
|
*
|
|
166
166
|
* @param {(node:Element, index:number) => boolean} fn callback invoked in context of browser
|
|
167
167
|
* @param {Object<string,any>} dependencies serializable data exposed in browser for use in callback
|
|
168
|
-
* @returns {
|
|
168
|
+
* @returns {Context} node describing matches of filtering and their processing context
|
|
169
169
|
*/
|
|
170
170
|
filterFn( fn, dependencies = {} ) {
|
|
171
171
|
if ( !this.matches ) {
|
|
@@ -175,12 +175,12 @@ class Context {
|
|
|
175
175
|
const matches = Selector( this.matches, { boundTestRun: this.testController } )
|
|
176
176
|
.filter( fn, dependencies );
|
|
177
177
|
|
|
178
|
-
return
|
|
178
|
+
return new this.constructor( this.testController, this, this.api, {
|
|
179
179
|
matches,
|
|
180
180
|
type: this.type,
|
|
181
181
|
selectors: this.selectors,
|
|
182
182
|
cardinality: this.cardinality,
|
|
183
|
-
} )
|
|
183
|
+
} );
|
|
184
184
|
}
|
|
185
185
|
|
|
186
186
|
/**
|
|
@@ -192,7 +192,7 @@ class Context {
|
|
|
192
192
|
* @param {SimpleSelector} defaultSelector selector to use as fallback on searching sub-elements as candidates
|
|
193
193
|
* @param {(node: Element, index: number) => boolean} fn callback invoked in context of browser
|
|
194
194
|
* @param {Object<string,any>} context serializable data provided as context (via `this`) of invoked callback
|
|
195
|
-
* @returns {
|
|
195
|
+
* @returns {Context} node describing matches of filtering and their processing context
|
|
196
196
|
*/
|
|
197
197
|
filterBySubsWithFn( typeOfSub, defaultSelector, fn, context = {} ) {
|
|
198
198
|
const { query, dependencies } = this.getSelector( typeOfSub, defaultSelector ) || { query: false };
|
|
@@ -232,7 +232,7 @@ class Context {
|
|
|
232
232
|
* @param {SimpleSelector} defaultSelector selector to use as fallback on searching sub-elements as candidates
|
|
233
233
|
* @param {string|RegExp} text text to be contained in either selected sub-element for matching
|
|
234
234
|
* @param {boolean} partially if true, provided text or regular expression does not have to match whole textual content of matching subs
|
|
235
|
-
* @returns {
|
|
235
|
+
* @returns {Context} node describing matches reduced to those having subs with given text
|
|
236
236
|
*/
|
|
237
237
|
filterBySubsWithText( typeOfSub, defaultSelector, text, partially = false ) {
|
|
238
238
|
if ( typeof text === "string" ) {
|
|
@@ -263,13 +263,9 @@ class Context {
|
|
|
263
263
|
*
|
|
264
264
|
* @param {string|RegExp} name name of attribute to look up per matching element
|
|
265
265
|
* @param {string|RegExp|function(any):boolean} value value expected in named attribute of either element, callback for custom test of attribute value
|
|
266
|
-
* @returns {
|
|
266
|
+
* @returns {Context} node listing those matches of current node matching named attribute
|
|
267
267
|
*/
|
|
268
|
-
|
|
269
|
-
if ( ! await this.matches.count ) {
|
|
270
|
-
throw new TypeError( "there are no matches to filter" );
|
|
271
|
-
}
|
|
272
|
-
|
|
268
|
+
withAttribute( name, value ) {
|
|
273
269
|
if ( typeof value !== "function" && !( value instanceof RegExp ) ) {
|
|
274
270
|
value = normalizedString( value );
|
|
275
271
|
}
|
|
@@ -305,13 +301,9 @@ class Context {
|
|
|
305
301
|
*
|
|
306
302
|
* @param {string} name name of DOM property to look up per matching element
|
|
307
303
|
* @param {string|RegExp|function(any):boolean} value value expected in named DOM property of either element, callback for custom test of property value
|
|
308
|
-
* @returns {
|
|
304
|
+
* @returns {Context} node listing those matches of current node matching named property
|
|
309
305
|
*/
|
|
310
|
-
|
|
311
|
-
if ( ! await this.matches.count ) {
|
|
312
|
-
throw new TypeError( "there are no matches to filter" );
|
|
313
|
-
}
|
|
314
|
-
|
|
306
|
+
withProperty( name, value ) {
|
|
315
307
|
if ( value === "string" ) {
|
|
316
308
|
value = normalizedString( value );
|
|
317
309
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cepharum/contextual-gherkin",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "flexible step definitions for Gherkin",
|
|
5
5
|
"author": "cepharum GmbH <thomas.urban@cepharum.de>",
|
|
6
6
|
"homepage": "https://cepharum-foss.gitlab.io/contextual-gherkin/",
|
package/steps/global-action.js
CHANGED
|
@@ -2,11 +2,10 @@ const { When } = require( "@cucumber/cucumber" );
|
|
|
2
2
|
const { Api } = require( "../lib/api" );
|
|
3
3
|
|
|
4
4
|
const actAndTrack = async( testController, cardinal, refined, action, input ) => {
|
|
5
|
-
const target =
|
|
6
|
-
const targetCount = await target.matches.count;
|
|
5
|
+
const target = refined.find( "$" + action, false );
|
|
7
6
|
|
|
8
|
-
await testController.expect(
|
|
9
|
-
await testController.expect(
|
|
7
|
+
await testController.expect( target.matches.count ).gt( 0, `there is no $${action} target for selected ${cardinal.word} to ${input == null ? action : `enter '${input}' into`}` ); // eslint-disable-line max-len
|
|
8
|
+
await testController.expect( target.matches.count ).eql( 1, `there is no single $${action} target for selected ${cardinal.word} to ${input == null ? action : `enter '${input}' into`}` ); // eslint-disable-line max-len
|
|
10
9
|
|
|
11
10
|
await refined.detach();
|
|
12
11
|
|
|
@@ -53,17 +52,14 @@ async function globalActionByAttribute( testController, cardinal, name, value, a
|
|
|
53
52
|
await testController.debug();
|
|
54
53
|
}
|
|
55
54
|
|
|
56
|
-
const matches = await Api.access( testController ).find( cardinal.word );
|
|
57
|
-
|
|
58
55
|
if ( cardinal.cardinality !== "singular" ) {
|
|
59
56
|
await testController.expect( false ).eql( true, `selector is not addressing a single ${cardinal.word} to ${input == null ? action : `enter '${input}' into`}` ); // eslint-disable-line max-len
|
|
60
57
|
}
|
|
61
58
|
|
|
62
|
-
const refined =
|
|
63
|
-
const matchCount = await refined.matches.count;
|
|
59
|
+
const refined = Api.access( testController ).find( cardinal.word ).withAttribute( name, value );
|
|
64
60
|
|
|
65
|
-
await testController.expect(
|
|
66
|
-
await testController.expect(
|
|
61
|
+
await testController.expect( refined.matches.count ).gt( 0, `there is no matching ${cardinal.word} with attribute ${name} == "${value}" to ${input == null ? action : `enter '${input}' into`}` ); // eslint-disable-line max-len
|
|
62
|
+
await testController.expect( refined.matches.count ).eql( 1, `there is no single matching ${cardinal.word} with attribute ${name} == "${value}" to ${input == null ? action : `enter '${input}' into`}` ); // eslint-disable-line max-len
|
|
67
63
|
|
|
68
64
|
await actAndTrack( testController, cardinal, refined, action, input );
|
|
69
65
|
}
|
|
@@ -94,18 +90,17 @@ async function globalActionByClass( testController, cardinal, className, action,
|
|
|
94
90
|
await testController.debug();
|
|
95
91
|
}
|
|
96
92
|
|
|
97
|
-
const matches = await Api.access( testController ).find( cardinal.word );
|
|
98
|
-
|
|
99
93
|
if ( cardinal.cardinality !== "singular" ) {
|
|
100
94
|
await testController.expect( false ).eql( true, `selector is not addressing a single ${cardinal.word} ${negated ? "not " : ""}marked as ${className} to ${input == null ? action : `enter '${input}' into`}` );
|
|
101
95
|
}
|
|
102
96
|
|
|
97
|
+
const matches = Api.access( testController ).find( cardinal.word );
|
|
98
|
+
|
|
103
99
|
const { query: property } = matches.getSelector( "#classList", "classList" );
|
|
104
|
-
const refined =
|
|
105
|
-
const matchCount = await refined.matches.count;
|
|
100
|
+
const refined = matches.filterBySubsWithFn( "$classList", false, node => node?.[property]?.contains( className ) ^ negated, { property, className, negated } );
|
|
106
101
|
|
|
107
|
-
await testController.expect(
|
|
108
|
-
await testController.expect(
|
|
102
|
+
await testController.expect( refined.matches.count ).gt( 0, `there is no matching ${cardinal.word} ${negated ? "not " : ""}marked as ${className} to ${input == null ? action : `enter '${input}' into`}` );
|
|
103
|
+
await testController.expect( refined.matches.count ).eql( 1, `there is no single matching ${cardinal.word} ${negated ? "not " : ""}marked as ${className} to ${input == null ? action : `enter '${input}' into`}` );
|
|
109
104
|
|
|
110
105
|
await actAndTrack( testController, cardinal, refined, action, input );
|
|
111
106
|
}
|
|
@@ -133,17 +128,14 @@ async function globalActionByProperty( testController, cardinal, name, value, ac
|
|
|
133
128
|
await testController.debug();
|
|
134
129
|
}
|
|
135
130
|
|
|
136
|
-
const matches = await Api.access( testController ).find( cardinal.word );
|
|
137
|
-
|
|
138
131
|
if ( cardinal.cardinality !== "singular" ) {
|
|
139
132
|
await testController.expect( false ).eql( true, `selector is not addressing a single ${cardinal.word} with property ${name} == "${value}" to ${input == null ? action : `enter '${input}' into`}` ); // eslint-disable-line max-len
|
|
140
133
|
}
|
|
141
134
|
|
|
142
|
-
const refined =
|
|
143
|
-
const matchCount = await refined.matches.count;
|
|
135
|
+
const refined = Api.access( testController ).find( cardinal.word ).withProperty( name, value );
|
|
144
136
|
|
|
145
|
-
await testController.expect(
|
|
146
|
-
await testController.expect(
|
|
137
|
+
await testController.expect( refined.matches.count ).gt( 0, `there is no matching ${cardinal.word} with property ${name} == "${value}" to ${input == null ? action : `enter '${input}' into`}` ); // eslint-disable-line max-len
|
|
138
|
+
await testController.expect( refined.matches.count ).eql( 1, `there is no single matching ${cardinal.word} with property ${name} == "${value}" to ${input == null ? action : `enter '${input}' into`}` ); // eslint-disable-line max-len
|
|
147
139
|
|
|
148
140
|
await actAndTrack( testController, cardinal, refined, action, input );
|
|
149
141
|
}
|
|
@@ -180,17 +172,14 @@ async function globalActionByLabel( testController, cardinal, label, partially,
|
|
|
180
172
|
await testController.debug();
|
|
181
173
|
}
|
|
182
174
|
|
|
183
|
-
const matches = await Api.access( testController ).find( cardinal.word );
|
|
184
|
-
|
|
185
175
|
if ( cardinal.cardinality !== "singular" ) {
|
|
186
176
|
await testController.expect( false ).eql( true, `selector is not addressing a single ${cardinal.word} with ${partially ? "partial " : ""}label "${label}" to ${input == null ? action : `enter '${input}' into`}` );
|
|
187
177
|
}
|
|
188
178
|
|
|
189
|
-
const refined =
|
|
190
|
-
const matchCount = await refined.matches.count;
|
|
179
|
+
const refined = Api.access( testController ).find( cardinal.word ).filterBySubsWithText( "$label", "label", label, partially );
|
|
191
180
|
|
|
192
|
-
await testController.expect(
|
|
193
|
-
await testController.expect(
|
|
181
|
+
await testController.expect( refined.matches.count ).gt( 0, `there is no matching ${cardinal.word} with ${partially ? "partial " : ""}label "${label}" to ${input == null ? action : `enter '${input}' into`}` );
|
|
182
|
+
await testController.expect( refined.matches.count ).eql( 1, `there is no single matching ${cardinal.word} with ${partially ? "partial " : ""}label "${label}" to ${input == null ? action : `enter '${input}' into`}` );
|
|
194
183
|
|
|
195
184
|
await actAndTrack( testController, cardinal, refined, action, input );
|
|
196
185
|
}
|
|
@@ -227,17 +216,14 @@ async function globalActionByTextContent( testController, cardinal, text, partia
|
|
|
227
216
|
await testController.debug();
|
|
228
217
|
}
|
|
229
218
|
|
|
230
|
-
const matches = await Api.access( testController ).find( cardinal.word );
|
|
231
|
-
|
|
232
219
|
if ( cardinal.cardinality !== "singular" ) {
|
|
233
220
|
await testController.expect( false ).eql( true, `selector is not addressing a single ${cardinal.word} ${partially ? "partially " : ""}reading "${text}" to ${input == null ? action : `enter '${input}' into`}` );
|
|
234
221
|
}
|
|
235
222
|
|
|
236
|
-
const refined =
|
|
237
|
-
const matchCount = await refined.matches.count;
|
|
223
|
+
const refined = Api.access( testController ).find( cardinal.word ).filterBySubsWithText( "$text", false, text, partially );
|
|
238
224
|
|
|
239
|
-
await testController.expect(
|
|
240
|
-
await testController.expect(
|
|
225
|
+
await testController.expect( refined.matches.count ).gt( 0, `there is no matching ${cardinal.word} ${partially ? "partially " : ""}reading "${text}" to ${input == null ? action : `enter '${input}' into`}` );
|
|
226
|
+
await testController.expect( refined.matches.count ).eql( 1, `there is no single matching ${cardinal.word} ${partially ? "partially " : ""}reading "${text}" to ${input == null ? action : `enter '${input}' into`}` );
|
|
241
227
|
|
|
242
228
|
await actAndTrack( testController, cardinal, refined, action, input );
|
|
243
229
|
}
|
package/steps/global-find.js
CHANGED
|
@@ -16,9 +16,9 @@ async function globalFind( testController, cardinal ) {
|
|
|
16
16
|
await testController.debug();
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
await Api.access( testController )
|
|
20
|
+
.find( cardinal.word )
|
|
21
|
+
.checkCardinalWord( cardinal );
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
Given( "there is/are {cardinal-word} with ID/id {text-or-regexp}", ( t, [ cardinal, id ] ) => globalFindByAttribute( t, cardinal, "id", id ) );
|
|
@@ -42,10 +42,10 @@ async function globalFindByAttribute( testController, cardinal, name, value ) {
|
|
|
42
42
|
await testController.debug();
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
45
|
+
await Api.access( testController )
|
|
46
|
+
.find( cardinal.word )
|
|
47
|
+
.withAttribute( name, value )
|
|
48
|
+
.checkCardinalWord( cardinal, true, `with ${name} ${value instanceof RegExp ? "matching" : "equals"} ${value}` );
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
Given( "there is/are {cardinal-word} with value {text-or-regexp}", ( t, [ cardinal, value ] ) => globalFindByProperty( t, cardinal, "value", value ) );
|
|
@@ -69,10 +69,10 @@ async function globalFindByProperty( testController, cardinal, name, value ) {
|
|
|
69
69
|
await testController.debug();
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
72
|
+
await Api.access( testController )
|
|
73
|
+
.find( cardinal.word )
|
|
74
|
+
.withProperty( name, value )
|
|
75
|
+
.checkCardinalWord( cardinal, true, typeof value === "function" ? `${value() ? "not " : ""}${name}` : `with ${name} ${value instanceof RegExp ? "matching" : "equals"} ${value}` );
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
Given( "there is/are {cardinal-word} marked/tagged as {word}", ( t, [ cardinal, mark ] ) => globalFindByClass( t, cardinal, mark, false ) );
|
|
@@ -92,9 +92,9 @@ async function globalFindByClass( testController, cardinal, className, negated )
|
|
|
92
92
|
await testController.debug();
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
-
const matches =
|
|
95
|
+
const matches = Api.access( testController ).find( cardinal.word );
|
|
96
96
|
const { query: property } = matches.getSelector( "#classList", "classList" );
|
|
97
|
-
const refined =
|
|
97
|
+
const refined = matches.filterBySubsWithFn( "$classList", false, node => node?.[property]?.contains( className ) ^ negated, { property, className, negated } );
|
|
98
98
|
|
|
99
99
|
await refined.checkCardinalWord( cardinal, true, `${negated ? "not " : ""}marked as "${className}"` );
|
|
100
100
|
}
|
|
@@ -118,10 +118,10 @@ async function globalFindByLabel( testController, cardinal, label, partially ) {
|
|
|
118
118
|
await testController.debug();
|
|
119
119
|
}
|
|
120
120
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
121
|
+
await Api.access( testController )
|
|
122
|
+
.find( cardinal.word )
|
|
123
|
+
.filterBySubsWithText( "$label", "label", label, partially )
|
|
124
|
+
.checkCardinalWord( cardinal, true, `${partially ? "partially " : ""}labelled with "${label}"` );
|
|
125
125
|
}
|
|
126
126
|
|
|
127
127
|
Given( "there is/are {cardinal-word} reading {text-or-regexp}", ( t, [ cardinal, text ] ) => globalFindByTextContent( t, cardinal, text, false ) );
|
|
@@ -143,10 +143,10 @@ async function globalFindByTextContent( testController, cardinal, text, partiall
|
|
|
143
143
|
await testController.debug();
|
|
144
144
|
}
|
|
145
145
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
146
|
+
await Api.access( testController )
|
|
147
|
+
.find( cardinal.word )
|
|
148
|
+
.filterBySubsWithText( "$text", false, text, partially )
|
|
149
|
+
.checkCardinalWord( cardinal, true, `${partially ? "partially " : ""}reading "${text}"` );
|
|
150
150
|
}
|
|
151
151
|
|
|
152
152
|
module.exports = {
|
package/steps/local-action.js
CHANGED
|
@@ -23,16 +23,16 @@ async function localAction( testController, phrase, action, input ) {
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
const context = await Api.access( testController ).getContextFor( phrase );
|
|
26
|
-
const matchCount = await context.matches.count;
|
|
27
26
|
|
|
28
|
-
await testController.expect(
|
|
29
|
-
await testController.expect(
|
|
27
|
+
await testController.expect( context.matches.count ).gt( 0, `there is no ${phrase.word} to ${input == null ? action : `enter '${input}' into`}` );
|
|
28
|
+
await testController.expect( context.matches.count ).eql( 1, `there is no single ${phrase.word} to ${input == null ? action : `enter '${input}' into`}` );
|
|
29
|
+
|
|
30
|
+
const matchCount = await context.matches.count;
|
|
30
31
|
|
|
31
|
-
const target =
|
|
32
|
-
const targetCount = await target.matches.count;
|
|
32
|
+
const target = context.find( "$" + action, false );
|
|
33
33
|
|
|
34
|
-
await testController.expect(
|
|
35
|
-
await testController.expect(
|
|
34
|
+
await testController.expect( target.matches.count ).gt( 0, `there is no $${action} target for selected ${phrase.word} to ${input == null ? action : `enter '${input}' into`}` ); // eslint-disable-line max-len
|
|
35
|
+
await testController.expect( target.matches.count ).eql( 1, `there is no single $${action} target for selected ${phrase.word} to ${input == null ? action : `enter '${input}' into`}` ); // eslint-disable-line max-len
|
|
36
36
|
|
|
37
37
|
await context.detach();
|
|
38
38
|
|
package/steps/local-find.js
CHANGED
|
@@ -18,9 +18,10 @@ async function localFind( testController, phrase, cardinal ) {
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
const context = await Api.access( testController ).getContextFor( phrase );
|
|
21
|
-
const matches = await context.find( cardinal.word );
|
|
22
21
|
|
|
23
|
-
await
|
|
22
|
+
await context
|
|
23
|
+
.find( cardinal.word )
|
|
24
|
+
.checkCardinalWord( cardinal );
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
Given( "{contextual-word} has/have {cardinal-word} with ID/id {text-or-regexp}", ( t, [ context, cardinal, id ] ) => localFindByAttribute( t, context, cardinal, "id", id ) );
|
|
@@ -44,10 +45,11 @@ async function localFindByAttribute( testController, phrase, cardinal, name, val
|
|
|
44
45
|
}
|
|
45
46
|
|
|
46
47
|
const context = await Api.access( testController ).getContextFor( phrase );
|
|
47
|
-
const matches = await context.find( cardinal.word );
|
|
48
|
-
const refined = await matches.withAttribute( name, value );
|
|
49
48
|
|
|
50
|
-
await
|
|
49
|
+
await context
|
|
50
|
+
.find( cardinal.word )
|
|
51
|
+
.withAttribute( name, value )
|
|
52
|
+
.checkCardinalWord( cardinal, true, `with ${name} ${value instanceof RegExp ? "matching" : "equals"} ${value}` );
|
|
51
53
|
}
|
|
52
54
|
|
|
53
55
|
Given( "{contextual-word} has/have {cardinal-word} with value {text-or-regexp}", ( t, [ context, cardinal, value ] ) => localFindByProperty( t, context, cardinal, "value", value ) );
|
|
@@ -74,10 +76,11 @@ async function localFindByProperty( testController, phrase, cardinal, name, valu
|
|
|
74
76
|
}
|
|
75
77
|
|
|
76
78
|
const context = await Api.access( testController ).getContextFor( phrase );
|
|
77
|
-
const matches = await context.find( cardinal.word );
|
|
78
|
-
const refined = await matches.withProperty( name, value );
|
|
79
79
|
|
|
80
|
-
await
|
|
80
|
+
await context
|
|
81
|
+
.find( cardinal.word )
|
|
82
|
+
.withProperty( name, value )
|
|
83
|
+
.checkCardinalWord( cardinal, true, typeof value === "function" ? `${value() ? "not " : ""}${name}` : `with ${name} ${value instanceof RegExp ? "matching" : "equals"} ${value}` );
|
|
81
84
|
}
|
|
82
85
|
|
|
83
86
|
Given( "{contextual-word} has/have {cardinal-word} marked/tagged as {word}", ( t, [ context, cardinal, className ] ) => localFindByClass( t, context, cardinal, className, false ) );
|
|
@@ -99,11 +102,12 @@ async function localFindByClass( testController, phrase, cardinal, className, ne
|
|
|
99
102
|
}
|
|
100
103
|
|
|
101
104
|
const context = await Api.access( testController ).getContextFor( phrase );
|
|
102
|
-
const matches =
|
|
105
|
+
const matches = context.find( cardinal.word );
|
|
103
106
|
const { query: property } = matches.getSelector( "#classList", "classList" );
|
|
104
|
-
const refined = await matches.filterBySubsWithFn( "$classList", false, node => node?.[property]?.contains( className ) ^ negated, { property, className, negated } );
|
|
105
107
|
|
|
106
|
-
await
|
|
108
|
+
await matches
|
|
109
|
+
.filterBySubsWithFn( "$classList", false, node => node?.[property]?.contains( className ) ^ negated, { property, className, negated } )
|
|
110
|
+
.checkCardinalWord( cardinal, true, `${negated ? "not " : ""}marked as "${className}"` );
|
|
107
111
|
}
|
|
108
112
|
|
|
109
113
|
Given( "{contextual-word} has/have {cardinal-word} with label {text-or-regexp}", ( t, [ context, cardinal, label ] ) => localFindByLabel( t, context, cardinal, label, false ) );
|
|
@@ -127,10 +131,11 @@ async function localFindByLabel( testController, phrase, cardinal, label, partia
|
|
|
127
131
|
}
|
|
128
132
|
|
|
129
133
|
const context = await Api.access( testController ).getContextFor( phrase );
|
|
130
|
-
const matches = await context.find( cardinal.word );
|
|
131
|
-
const refined = await matches.filterBySubsWithText( "$label", "label", label, partially );
|
|
132
134
|
|
|
133
|
-
await
|
|
135
|
+
await context
|
|
136
|
+
.find( cardinal.word )
|
|
137
|
+
.filterBySubsWithText( "$label", "label", label, partially )
|
|
138
|
+
.checkCardinalWord( cardinal, true, `${partially ? "partially " : ""}labelled with "${label}"` );
|
|
134
139
|
}
|
|
135
140
|
|
|
136
141
|
Given( "{contextual-word} has/have {cardinal-word} reading {text-or-regexp}", ( t, [ context, cardinal, text ] ) => localFindByTextContent( t, context, cardinal, text, false ) );
|
|
@@ -154,10 +159,11 @@ async function localFindByTextContent( testController, phrase, cardinal, text, p
|
|
|
154
159
|
}
|
|
155
160
|
|
|
156
161
|
const context = await Api.access( testController ).getContextFor( phrase );
|
|
157
|
-
const matches = await context.find( cardinal.word );
|
|
158
|
-
const refined = await matches.filterBySubsWithText( "$text", false, text, partially );
|
|
159
162
|
|
|
160
|
-
await
|
|
163
|
+
await context
|
|
164
|
+
.find( cardinal.word )
|
|
165
|
+
.filterBySubsWithText( "$text", false, text, partially )
|
|
166
|
+
.checkCardinalWord( cardinal, true, `${partially ? "partially " : ""}reading "${text}"` );
|
|
161
167
|
}
|
|
162
168
|
|
|
163
169
|
module.exports = {
|
package/steps/local-state.js
CHANGED
|
@@ -25,7 +25,7 @@ async function localStateByAttribute( testController, phrase, all, name, value )
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
const context = await Api.access( testController ).getContextFor( phrase );
|
|
28
|
-
const filtered =
|
|
28
|
+
const filtered = context.withAttribute( name, value );
|
|
29
29
|
|
|
30
30
|
await context.checkFilteredInContext( filtered, phrase, all );
|
|
31
31
|
}
|
|
@@ -54,7 +54,7 @@ async function localStateByProperty( testController, phrase, all, name, value )
|
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
const context = await Api.access( testController ).getContextFor( phrase );
|
|
57
|
-
const filtered =
|
|
57
|
+
const filtered = context.withProperty( name, value );
|
|
58
58
|
|
|
59
59
|
await context.checkFilteredInContext( filtered, phrase, all );
|
|
60
60
|
}
|
|
@@ -79,7 +79,7 @@ async function localStateByClass( testController, phrase, all, className, negate
|
|
|
79
79
|
|
|
80
80
|
const context = await Api.access( testController ).getContextFor( phrase );
|
|
81
81
|
const { query: property } = context.getSelector( "#classList", "classList" );
|
|
82
|
-
const filtered =
|
|
82
|
+
const filtered = context.filterBySubsWithFn( "$classList", false, node => node?.[property]?.contains( className ) ^ negated, { property, className, negated } );
|
|
83
83
|
|
|
84
84
|
await context.checkFilteredInContext( filtered, phrase, all );
|
|
85
85
|
}
|
|
@@ -105,9 +105,11 @@ async function localStateByLabel( testController, phrase, text, partially ) {
|
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
const context = await Api.access( testController ).getContextFor( phrase );
|
|
108
|
-
const
|
|
108
|
+
const cardinal = phrase.asCardinalWord( await context.matches.count );
|
|
109
109
|
|
|
110
|
-
await
|
|
110
|
+
await context
|
|
111
|
+
.filterBySubsWithText( "$label", "label", text, partially )
|
|
112
|
+
.checkCardinalWord( cardinal, phrase.isRefining, `labelled with "${text}"` );
|
|
111
113
|
}
|
|
112
114
|
|
|
113
115
|
Then( "{contextual-word} read/reads {text-or-regexp}", ( t, [ context, text ] ) => localStateByTextContent( t, context, text, false ) );
|
|
@@ -133,9 +135,11 @@ async function localStateByTextContent( testController, phrase, text, partially
|
|
|
133
135
|
}
|
|
134
136
|
|
|
135
137
|
const context = await Api.access( testController ).getContextFor( phrase );
|
|
136
|
-
const
|
|
138
|
+
const cardinal = phrase.asCardinalWord( await context.matches.count );
|
|
137
139
|
|
|
138
|
-
await
|
|
140
|
+
await context
|
|
141
|
+
.filterBySubsWithText( "$text", false, text, partially )
|
|
142
|
+
.checkCardinalWord( cardinal, phrase.isRefining, `${partially ? "partially " : ""}reading "${text}"` );
|
|
139
143
|
}
|
|
140
144
|
|
|
141
145
|
Then( "{contextual-word} (still )exists/exist", ( t, [context] ) => localStateExists( t, context, true ) );
|
|
@@ -157,15 +161,16 @@ async function localStateExists( testController, phrase, exists ) {
|
|
|
157
161
|
}
|
|
158
162
|
|
|
159
163
|
const context = await Api.access( testController ).getContextFor( phrase );
|
|
160
|
-
const matchCount = await context.matches.count;
|
|
161
164
|
|
|
162
165
|
if ( exists ) {
|
|
163
166
|
// FIXME might pass unintentionally if just one of several elements to be tested exists
|
|
164
|
-
await testController.expect(
|
|
167
|
+
await testController.expect( context.matches.count ).gt( 0 );
|
|
165
168
|
} else {
|
|
166
|
-
await testController.expect(
|
|
169
|
+
await testController.expect( context.matches.count ).eql( 0 );
|
|
167
170
|
}
|
|
168
171
|
|
|
172
|
+
const matchCount = await context.matches.count;
|
|
173
|
+
|
|
169
174
|
if ( phrase.isRefining && matchCount > 0 ) {
|
|
170
175
|
await context.track( phrase.word, phrase.targetCardinality );
|
|
171
176
|
}
|