@interactors/core 0.4.0 → 1.0.0-effection.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/dist/cjs/constructor.js +55 -126
- package/dist/cjs/constructor.js.map +1 -1
- package/dist/cjs/converge.js +3 -5
- package/dist/cjs/converge.js.map +1 -1
- package/dist/cjs/format.js +50 -0
- package/dist/cjs/format.js.map +1 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/inspector.js +2 -1
- package/dist/cjs/inspector.js.map +1 -1
- package/dist/cjs/interaction.js +54 -35
- package/dist/cjs/interaction.js.map +1 -1
- package/dist/cjs/match.js +17 -7
- package/dist/cjs/match.js.map +1 -1
- package/dist/cjs/matcher.js +13 -1
- package/dist/cjs/matcher.js.map +1 -1
- package/dist/cjs/matchers/and.js +3 -0
- package/dist/cjs/matchers/and.js.map +1 -1
- package/dist/cjs/matchers/every.js +3 -0
- package/dist/cjs/matchers/every.js.map +1 -1
- package/dist/cjs/matchers/including.js +4 -0
- package/dist/cjs/matchers/including.js.map +1 -1
- package/dist/cjs/matchers/matching.js +4 -0
- package/dist/cjs/matchers/matching.js.map +1 -1
- package/dist/cjs/matchers/not.js +3 -0
- package/dist/cjs/matchers/not.js.map +1 -1
- package/dist/cjs/matchers/or.js +3 -0
- package/dist/cjs/matchers/or.js.map +1 -1
- package/dist/cjs/matchers/some.js +3 -0
- package/dist/cjs/matchers/some.js.map +1 -1
- package/dist/cjs/resolvers.js +98 -0
- package/dist/cjs/resolvers.js.map +1 -0
- package/dist/cjs/serialize.js +48 -0
- package/dist/cjs/serialize.js.map +1 -0
- package/dist/constructor.d.ts +2 -8
- package/dist/constructor.d.ts.map +1 -1
- package/dist/converge.d.ts +2 -1
- package/dist/converge.d.ts.map +1 -1
- package/dist/esm/constructor.js +52 -117
- package/dist/esm/constructor.js.map +1 -1
- package/dist/esm/converge.js +3 -5
- package/dist/esm/converge.js.map +1 -1
- package/dist/esm/{format-table.js → format.js} +19 -1
- package/dist/esm/format.js.map +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/inspector.js +2 -1
- package/dist/esm/inspector.js.map +1 -1
- package/dist/esm/interaction.js +51 -29
- package/dist/esm/interaction.js.map +1 -1
- package/dist/esm/match.js +17 -7
- package/dist/esm/match.js.map +1 -1
- package/dist/esm/matcher.js +11 -0
- package/dist/esm/matcher.js.map +1 -1
- package/dist/esm/matchers/and.js +4 -1
- package/dist/esm/matchers/and.js.map +1 -1
- package/dist/esm/matchers/every.js +4 -1
- package/dist/esm/matchers/every.js.map +1 -1
- package/dist/esm/matchers/including.js +4 -0
- package/dist/esm/matchers/including.js.map +1 -1
- package/dist/esm/matchers/matching.js +4 -0
- package/dist/esm/matchers/matching.js.map +1 -1
- package/dist/esm/matchers/not.js +4 -1
- package/dist/esm/matchers/not.js.map +1 -1
- package/dist/esm/matchers/or.js +4 -1
- package/dist/esm/matchers/or.js.map +1 -1
- package/dist/esm/matchers/some.js +4 -1
- package/dist/esm/matchers/some.js.map +1 -1
- package/dist/esm/resolvers.js +88 -0
- package/dist/esm/resolvers.js.map +1 -0
- package/dist/esm/serialize.js +43 -0
- package/dist/esm/serialize.js.map +1 -0
- package/dist/format.d.ts +10 -0
- package/dist/format.d.ts.map +1 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/inspector.d.ts.map +1 -1
- package/dist/interaction.d.ts +38 -10
- package/dist/interaction.d.ts.map +1 -1
- package/dist/match.d.ts +5 -5
- package/dist/match.d.ts.map +1 -1
- package/dist/matcher.d.ts +2 -0
- package/dist/matcher.d.ts.map +1 -1
- package/dist/matchers/and.d.ts.map +1 -1
- package/dist/matchers/every.d.ts.map +1 -1
- package/dist/matchers/including.d.ts.map +1 -1
- package/dist/matchers/matching.d.ts.map +1 -1
- package/dist/matchers/not.d.ts.map +1 -1
- package/dist/matchers/or.d.ts.map +1 -1
- package/dist/matchers/some.d.ts.map +1 -1
- package/dist/resolvers.d.ts +9 -0
- package/dist/resolvers.d.ts.map +1 -0
- package/dist/serialize.d.ts +13 -0
- package/dist/serialize.d.ts.map +1 -0
- package/dist/specification.d.ts +19 -17
- package/dist/specification.d.ts.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +3 -2
- package/src/constructor.ts +63 -138
- package/src/converge.ts +3 -6
- package/src/format.ts +58 -0
- package/src/index.ts +4 -2
- package/src/inspector.ts +2 -1
- package/src/interaction.ts +96 -36
- package/src/match.ts +23 -15
- package/src/matcher.ts +11 -0
- package/src/matchers/and.ts +4 -1
- package/src/matchers/every.ts +4 -1
- package/src/matchers/including.ts +4 -1
- package/src/matchers/matching.ts +4 -1
- package/src/matchers/not.ts +4 -1
- package/src/matchers/or.ts +4 -1
- package/src/matchers/some.ts +4 -1
- package/src/resolvers.ts +100 -0
- package/src/serialize.ts +54 -0
- package/src/specification.ts +21 -19
- package/CHANGELOG.md +0 -27
- package/dist/cjs/format-table.js +0 -30
- package/dist/cjs/format-table.js.map +0 -1
- package/dist/esm/format-table.js.map +0 -1
- package/dist/format-table.d.ts +0 -6
- package/dist/format-table.d.ts.map +0 -1
- package/src/format-table.ts +0 -34
package/dist/cjs/matcher.js
CHANGED
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.applyMatcher = exports.matcherDescription = exports.isMatcher = void 0;
|
|
6
|
+
exports.matcherCode = exports.applyMatcher = exports.matcherDescription = exports.isMatcher = void 0;
|
|
7
7
|
const lodash_isequal_1 = __importDefault(require("lodash.isequal"));
|
|
8
8
|
function isMatcher(value) {
|
|
9
9
|
return value && typeof value.match === 'function' && typeof value.description === 'function';
|
|
@@ -27,4 +27,16 @@ function applyMatcher(value, actual) {
|
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
29
|
exports.applyMatcher = applyMatcher;
|
|
30
|
+
function matcherCode(value) {
|
|
31
|
+
if (isMatcher(value) && value.code) {
|
|
32
|
+
return value.code();
|
|
33
|
+
}
|
|
34
|
+
else if (value instanceof RegExp) {
|
|
35
|
+
return value.toString();
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
return JSON.stringify(value);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
exports.matcherCode = matcherCode;
|
|
30
42
|
//# sourceMappingURL=matcher.js.map
|
package/dist/cjs/matcher.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"matcher.js","sourceRoot":"","sources":["../../src/matcher.ts"],"names":[],"mappings":";;;;;;AAAA,oEAAqC;
|
|
1
|
+
{"version":3,"file":"matcher.js","sourceRoot":"","sources":["../../src/matcher.ts"],"names":[],"mappings":";;;;;;AAAA,oEAAqC;AAUrC,SAAgB,SAAS,CAAI,KAAsB;IACjD,OAAO,KAAK,IAAI,OAAQ,KAAoB,CAAC,KAAK,KAAK,UAAU,IAAI,OAAQ,KAAoB,CAAC,WAAW,KAAK,UAAU,CAAC;AAC/H,CAAC;AAFD,8BAEC;AAED,SAAgB,kBAAkB,CAAI,KAAsB;IAC1D,IAAG,SAAS,CAAC,KAAK,CAAC,EAAE;QACnB,OAAO,KAAK,CAAC,WAAW,EAAE,CAAC;KAC5B;SAAM;QACL,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;KAC9B;AACH,CAAC;AAND,gDAMC;AAED,SAAgB,YAAY,CAAI,KAAsB,EAAE,MAAS;IAC/D,IAAG,SAAS,CAAC,KAAK,CAAC,EAAE;QACnB,OAAO,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;KAC5B;SAAM;QACL,OAAO,wBAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;KAC/B;AACH,CAAC;AAND,oCAMC;AAED,SAAgB,WAAW,CAAI,KAAsB;IACnD,IAAI,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,EAAE;QAClC,OAAO,KAAK,CAAC,IAAI,EAAE,CAAC;KACrB;SAAM,IAAI,KAAK,YAAY,MAAM,EAAE;QAClC,OAAO,KAAK,CAAC,QAAQ,EAAE,CAAC;KACzB;SAAM;QACL,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;KAC9B;AACH,CAAC;AARD,kCAQC"}
|
package/dist/cjs/matchers/and.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"and.js","sourceRoot":"","sources":["../../../src/matchers/and.ts"],"names":[],"mappings":";;;AAAA,
|
|
1
|
+
{"version":3,"file":"and.js","sourceRoot":"","sources":["../../../src/matchers/and.ts"],"names":[],"mappings":";;;AAAA,wCAAkG;AAElG,SAAgB,GAAG,CAAI,GAAG,IAAuB;IAC/C,OAAO;QACL,KAAK,CAAC,MAAS;YACb,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,sBAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;QAChE,CAAC;QACD,WAAW;YACT,OAAO,IAAI,CAAC,GAAG,CAAC,4BAAkB,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACpD,CAAC;QACD,IAAI;YACF,OAAO,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,qBAAW,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAA;QAC/D,CAAC;KACF,CAAA;AACH,CAAC;AAZD,kBAYC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"every.js","sourceRoot":"","sources":["../../../src/matchers/every.ts"],"names":[],"mappings":";;;AAAA,
|
|
1
|
+
{"version":3,"file":"every.js","sourceRoot":"","sources":["../../../src/matchers/every.ts"],"names":[],"mappings":";;;AAAA,wCAAkG;AAElG,SAAgB,KAAK,CAAI,QAAyB;IAChD,OAAO;QACL,KAAK,CAAC,MAAmB;YACvB,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,sBAAY,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC;QAC5E,CAAC;QACD,WAAW;YACT,OAAO,cAAc,4BAAkB,CAAC,QAAQ,CAAC,EAAE,CAAC;QACtD,CAAC;QACD,IAAI;YACF,OAAO,SAAS,qBAAW,CAAC,QAAQ,CAAC,GAAG,CAAA;QAC1C,CAAC;KACF,CAAA;AACH,CAAC;AAZD,sBAYC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.including = void 0;
|
|
4
|
+
const matcher_1 = require("../matcher");
|
|
4
5
|
function including(subString) {
|
|
5
6
|
return {
|
|
6
7
|
match(actual) {
|
|
@@ -9,6 +10,9 @@ function including(subString) {
|
|
|
9
10
|
description() {
|
|
10
11
|
return `including ${JSON.stringify(subString)}`;
|
|
11
12
|
},
|
|
13
|
+
code() {
|
|
14
|
+
return `including(${matcher_1.matcherCode(subString)})`;
|
|
15
|
+
}
|
|
12
16
|
};
|
|
13
17
|
}
|
|
14
18
|
exports.including = including;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"including.js","sourceRoot":"","sources":["../../../src/matchers/including.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"including.js","sourceRoot":"","sources":["../../../src/matchers/including.ts"],"names":[],"mappings":";;;AAAA,wCAAiD;AAEjD,SAAgB,SAAS,CAAC,SAAiB;IACzC,OAAO;QACL,KAAK,CAAC,MAAc;YAClB,OAAO,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;QACpC,CAAC;QACD,WAAW;YACT,OAAO,aAAa,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,EAAE,CAAC;QAClD,CAAC;QACD,IAAI;YACF,OAAO,aAAa,qBAAW,CAAC,SAAS,CAAC,GAAG,CAAA;QAC/C,CAAC;KACF,CAAA;AACH,CAAC;AAZD,8BAYC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.matching = void 0;
|
|
4
|
+
const matcher_1 = require("../matcher");
|
|
4
5
|
function matching(regexp) {
|
|
5
6
|
return {
|
|
6
7
|
match(actual) {
|
|
@@ -9,6 +10,9 @@ function matching(regexp) {
|
|
|
9
10
|
description() {
|
|
10
11
|
return `matching ${regexp}`;
|
|
11
12
|
},
|
|
13
|
+
code() {
|
|
14
|
+
return `matching(${matcher_1.matcherCode(regexp)})`;
|
|
15
|
+
}
|
|
12
16
|
};
|
|
13
17
|
}
|
|
14
18
|
exports.matching = matching;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"matching.js","sourceRoot":"","sources":["../../../src/matchers/matching.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"matching.js","sourceRoot":"","sources":["../../../src/matchers/matching.ts"],"names":[],"mappings":";;;AAAA,wCAAkD;AAElD,SAAgB,QAAQ,CAAC,MAAc;IACrC,OAAO;QACL,KAAK,CAAC,MAAc;YAClB,OAAO,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC;QACtC,CAAC;QACD,WAAW;YACT,OAAO,YAAY,MAAM,EAAE,CAAC;QAC9B,CAAC;QACD,IAAI;YACF,OAAO,YAAY,qBAAW,CAAC,MAAM,CAAC,GAAG,CAAA;QAC3C,CAAC;KACF,CAAA;AACH,CAAC;AAZD,4BAYC"}
|
package/dist/cjs/matchers/not.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"not.js","sourceRoot":"","sources":["../../../src/matchers/not.ts"],"names":[],"mappings":";;;AAAA,
|
|
1
|
+
{"version":3,"file":"not.js","sourceRoot":"","sources":["../../../src/matchers/not.ts"],"names":[],"mappings":";;;AAAA,wCAAkG;AAElG,SAAgB,GAAG,CAAI,OAAwB;IAC7C,OAAO;QACL,KAAK,CAAC,MAAS;YACb,OAAO,CAAC,sBAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACxC,CAAC;QACD,WAAW;YACT,OAAO,OAAO,4BAAkB,CAAC,OAAO,CAAC,EAAE,CAAC;QAC9C,CAAC;QACD,IAAI;YACF,OAAO,OAAO,qBAAW,CAAC,OAAO,CAAC,GAAG,CAAA;QACvC,CAAC;KACF,CAAA;AACH,CAAC;AAZD,kBAYC"}
|
package/dist/cjs/matchers/or.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"or.js","sourceRoot":"","sources":["../../../src/matchers/or.ts"],"names":[],"mappings":";;;AAAA,
|
|
1
|
+
{"version":3,"file":"or.js","sourceRoot":"","sources":["../../../src/matchers/or.ts"],"names":[],"mappings":";;;AAAA,wCAAkG;AAElG,SAAgB,EAAE,CAAI,GAAG,IAAuB;IAC9C,OAAO;QACL,KAAK,CAAC,MAAS;YACb,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,sBAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;QAC/D,CAAC;QACD,WAAW;YACT,OAAO,IAAI,CAAC,GAAG,CAAC,4BAAkB,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACnD,CAAC;QACD,IAAI;YACF,OAAO,MAAM,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,qBAAW,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAA;QAC9D,CAAC;KACF,CAAA;AACH,CAAC;AAZD,gBAYC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"some.js","sourceRoot":"","sources":["../../../src/matchers/some.ts"],"names":[],"mappings":";;;AAAA,
|
|
1
|
+
{"version":3,"file":"some.js","sourceRoot":"","sources":["../../../src/matchers/some.ts"],"names":[],"mappings":";;;AAAA,wCAAkG;AAElG,SAAgB,IAAI,CAAI,QAAyB;IAC/C,OAAO;QACL,KAAK,CAAC,MAAmB;YACvB,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,sBAAY,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC;QAC3E,CAAC;QACD,WAAW;YACT,OAAO,aAAa,4BAAkB,CAAC,QAAQ,CAAC,EAAE,CAAC;QACrD,CAAC;QACD,IAAI;YACF,OAAO,QAAQ,qBAAW,CAAC,QAAQ,CAAC,GAAG,CAAA;QACzC,CAAC;KACF,CAAA;AACH,CAAC;AAZD,oBAYC"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.unsafeSyncResolveUnique = exports.unsafeSyncResolveParent = exports.resolveEmpty = exports.resolveFirst = exports.resolveUnique = exports.hasMatchMatching = exports.findElements = void 0;
|
|
5
|
+
const globals_1 = require("@interactors/globals");
|
|
6
|
+
const match_1 = require("./match");
|
|
7
|
+
const errors_1 = require("./errors");
|
|
8
|
+
const format_1 = require("./format");
|
|
9
|
+
const defaultSelector = 'div';
|
|
10
|
+
function findElements(parentElement, interactor) {
|
|
11
|
+
if (!interactor.name) {
|
|
12
|
+
throw new Error('One of your interactors was created without a name. Please provide a label for your interactor:\n\tHTML.extend(\'my interactor\') || createInteractor(\'my interactor\')');
|
|
13
|
+
}
|
|
14
|
+
if (typeof interactor.specification.selector === 'function') {
|
|
15
|
+
return interactor.specification.selector(parentElement);
|
|
16
|
+
}
|
|
17
|
+
else if (interactor.specification.selector === ':root') {
|
|
18
|
+
// this is a bit of a hack, because otherwise there isn't a good way of selecting the root element
|
|
19
|
+
return [parentElement.ownerDocument.querySelector(':root')];
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
return Array.from(parentElement.querySelectorAll(interactor.specification.selector || defaultSelector));
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
exports.findElements = findElements;
|
|
26
|
+
function findMatches(parentElement, interactor) {
|
|
27
|
+
return findElements(parentElement, interactor).map((e) => new match_1.Match(e, interactor.filter, interactor.locator));
|
|
28
|
+
}
|
|
29
|
+
function throwNoSuchElementError(matches, interactor) {
|
|
30
|
+
if (matches.length === 0) {
|
|
31
|
+
throw new errors_1.NoSuchElementError(`did not find ${format_1.formatDescription(interactor)}`);
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
throw new errors_1.NoSuchElementError(`did not find ${format_1.formatDescription(interactor)}, did you mean one of:\n\n${format_1.formatMatchesTable(interactor, matches)}`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function findFirstMatch(parentElement, interactor) {
|
|
38
|
+
let matches = [];
|
|
39
|
+
for (let element of findElements(parentElement, interactor)) {
|
|
40
|
+
let match = new match_1.Match(element, interactor.filter, interactor.locator);
|
|
41
|
+
matches.push(match);
|
|
42
|
+
if (match.matches) {
|
|
43
|
+
return match;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
throwNoSuchElementError(matches, interactor);
|
|
47
|
+
}
|
|
48
|
+
function hasMatchMatching(parentElement, interactor) {
|
|
49
|
+
return findElements(parentElement, interactor).some(element => new match_1.Match(element, interactor.filter, interactor.locator).matches);
|
|
50
|
+
}
|
|
51
|
+
exports.hasMatchMatching = hasMatchMatching;
|
|
52
|
+
function findMatchesNonEmpty(parentElement, interactor) {
|
|
53
|
+
let matches = findMatches(parentElement, interactor);
|
|
54
|
+
let matching = matches.filter((m) => m.matches);
|
|
55
|
+
if (matching.length > 0) {
|
|
56
|
+
return matching;
|
|
57
|
+
}
|
|
58
|
+
throwNoSuchElementError(matches, interactor);
|
|
59
|
+
}
|
|
60
|
+
// Given a parent element, and an interactor, find exactly one matching element
|
|
61
|
+
// and return it. If no elements match, raise an error. If more than one
|
|
62
|
+
// element matches, raise an error.
|
|
63
|
+
function resolveUnique(parentElement, interactor) {
|
|
64
|
+
let matching = findMatchesNonEmpty(parentElement, interactor);
|
|
65
|
+
if (matching.length === 1) {
|
|
66
|
+
return matching[0].element;
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
let alternatives = matching.map((m) => '- ' + m.elementDescription());
|
|
70
|
+
throw new errors_1.AmbiguousElementError(`${format_1.formatDescription(interactor)} matches multiple elements:\n\n${alternatives.join('\n')}`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
exports.resolveUnique = resolveUnique;
|
|
74
|
+
// Given a parent element, and an interactor, find the first matching element and
|
|
75
|
+
// return it. If no elements match, raise an error.
|
|
76
|
+
function resolveFirst(parentElement, interactor) {
|
|
77
|
+
return findFirstMatch(parentElement, interactor).element;
|
|
78
|
+
}
|
|
79
|
+
exports.resolveFirst = resolveFirst;
|
|
80
|
+
// Given a parent element, and an interactor, check if there are any matching
|
|
81
|
+
// elements, and throw an error if there are. Otherwise return undefined.
|
|
82
|
+
function resolveEmpty(parentElement, interactor) {
|
|
83
|
+
let matching = findMatches(parentElement, interactor).filter((m) => m.matches);
|
|
84
|
+
if (matching.length !== 0) {
|
|
85
|
+
let alternatives = matching.map((m) => '- ' + m.elementDescription());
|
|
86
|
+
throw new errors_1.NotAbsentError(`${format_1.formatDescription(interactor)} exists but should not:\n\n${alternatives.join('\n')}`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
exports.resolveEmpty = resolveEmpty;
|
|
90
|
+
function unsafeSyncResolveParent(options) {
|
|
91
|
+
return options.ancestors.reduce(resolveUnique, globals_1.globals.document.documentElement);
|
|
92
|
+
}
|
|
93
|
+
exports.unsafeSyncResolveParent = unsafeSyncResolveParent;
|
|
94
|
+
function unsafeSyncResolveUnique(options) {
|
|
95
|
+
return resolveUnique(unsafeSyncResolveParent(options), options);
|
|
96
|
+
}
|
|
97
|
+
exports.unsafeSyncResolveUnique = unsafeSyncResolveUnique;
|
|
98
|
+
//# sourceMappingURL=resolvers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolvers.js","sourceRoot":"","sources":["../../src/resolvers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.serializeInteractionOptions = exports.serializeInteractorOptions = void 0;
|
|
4
|
+
const change_case_1 = require("change-case");
|
|
5
|
+
const matcher_1 = require("./matcher");
|
|
6
|
+
function serializeInteractorOptions(options) {
|
|
7
|
+
var _a;
|
|
8
|
+
let locator = matcher_1.matcherCode((_a = options.locator) === null || _a === void 0 ? void 0 : _a.value);
|
|
9
|
+
return {
|
|
10
|
+
interactor: options.name,
|
|
11
|
+
filter: options.filter.all,
|
|
12
|
+
locator,
|
|
13
|
+
code() {
|
|
14
|
+
let interactorName = change_case_1.pascalCase(options.name);
|
|
15
|
+
let filters = Object.entries(options.filter.all).map(([name, filter]) => `"${name}": ${matcher_1.matcherCode(filter)}`);
|
|
16
|
+
return `${interactorName}(${[locator, filters.length && `{ ${filters.join(", ")} }`]
|
|
17
|
+
.filter(Boolean)
|
|
18
|
+
.join(", ")})`;
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
exports.serializeInteractorOptions = serializeInteractorOptions;
|
|
23
|
+
function serializeInteractionOptions(type, { name, interactor: { options }, args, filters }) {
|
|
24
|
+
let interactor = serializeInteractorOptions(options);
|
|
25
|
+
let ancestors = options.ancestors.map((ancestor) => serializeInteractorOptions(ancestor));
|
|
26
|
+
return {
|
|
27
|
+
...interactor,
|
|
28
|
+
ancestors,
|
|
29
|
+
name,
|
|
30
|
+
type,
|
|
31
|
+
args: filters ? [filters] : args ? args : undefined,
|
|
32
|
+
code() {
|
|
33
|
+
let serializedArgs = "";
|
|
34
|
+
if (filters) {
|
|
35
|
+
let serializedFilters = Object.entries(filters).map(([name, filter]) => `"${name}": ${matcher_1.matcherCode(filter)}`);
|
|
36
|
+
serializedArgs = `{ ${serializedFilters.join(", ")} }`;
|
|
37
|
+
}
|
|
38
|
+
else if (args) {
|
|
39
|
+
serializedArgs = args.map((arg) => JSON.stringify(arg)).join(", ");
|
|
40
|
+
}
|
|
41
|
+
return `${[...ancestors, interactor]
|
|
42
|
+
.map(({ code }, index) => (index == 0 ? code() : `${code()})`))
|
|
43
|
+
.join(".find(")}.${name}(${serializedArgs})`;
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
exports.serializeInteractionOptions = serializeInteractionOptions;
|
|
48
|
+
//# sourceMappingURL=serialize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serialize.js","sourceRoot":"","sources":["../../src/serialize.ts"],"names":[],"mappings":";;;AAEA,6CAAyC;AAEzC,uCAAwC;AAGxC,SAAgB,0BAA0B,CAAC,OAAyC;;IAMlF,IAAI,OAAO,GAAG,qBAAW,CAAC,MAAA,OAAO,CAAC,OAAO,0CAAE,KAAK,CAAC,CAAC;IAClD,OAAO;QACL,UAAU,EAAE,OAAO,CAAC,IAAI;QACxB,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,GAAG;QAC1B,OAAO;QACP,IAAI;YACF,IAAI,cAAc,GAAG,wBAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAC9C,IAAI,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,IAAI,IAAI,MAAM,qBAAW,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YAC9G,OAAO,GAAG,cAAc,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,MAAM,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;iBACjF,MAAM,CAAC,OAAO,CAAC;iBACf,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;QACnB,CAAC;KACF,CAAC;AACJ,CAAC;AAnBD,gEAmBC;AAED,SAAgB,2BAA2B,CACzC,IAAqB,EACrB,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,OAAO,EAA4B;IAE1E,IAAI,UAAU,GAAG,0BAA0B,CAAC,OAAO,CAAC,CAAC;IACrD,IAAI,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,0BAA0B,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC1F,OAAO;QACL,GAAG,UAAU;QACb,SAAS;QACT,IAAI;QACJ,IAAI;QACJ,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;QACnD,IAAI;YACF,IAAI,cAAc,GAAG,EAAE,CAAC;YACxB,IAAI,OAAO,EAAE;gBACX,IAAI,iBAAiB,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,IAAI,IAAI,MAAM,qBAAW,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;gBAC7G,cAAc,GAAG,KAAK,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;aACxD;iBAAM,IAAI,IAAI,EAAE;gBACf,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;aACpE;YACD,OAAO,GAAG,CAAC,GAAG,SAAS,EAAE,UAAU,CAAC;iBACjC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,EAAE,GAAG,CAAC,CAAC;iBAC9D,IAAI,CAAC,QAAQ,CAAC,IAAI,IAAI,IAAI,cAAc,GAAG,CAAC;QACjD,CAAC;KACF,CAAC;AACJ,CAAC;AAzBD,kEAyBC"}
|
package/dist/constructor.d.ts
CHANGED
|
@@ -1,10 +1,4 @@
|
|
|
1
1
|
import { InteractorOptions, ActionMethods, InteractorConstructor, Interactor, Filters, Actions, FilterParams, FilterMethods, InteractorSpecification } from './specification';
|
|
2
|
-
export declare function
|
|
3
|
-
export declare function
|
|
4
|
-
export declare function resolveNonEmpty(parentElement: Element, interactor: InteractorOptions<any, any, any>): Element[];
|
|
5
|
-
export declare function resolveEmpty(parentElement: Element, interactor: InteractorOptions<any, any, any>): void;
|
|
6
|
-
export declare function unsafeSyncResolveParent(options: InteractorOptions<any, any, any>): Element;
|
|
7
|
-
export declare function unsafeSyncResolveUnique<E extends Element>(options: InteractorOptions<E, any, any>): E;
|
|
8
|
-
export declare function instantiateInteractor<E extends Element, F extends Filters<E>, A extends Actions<E>>(options: InteractorOptions<E, F, A>, resolver: (options: InteractorOptions<E, F, A>) => E): Interactor<E, FilterParams<E, F>> & ActionMethods<E, A>;
|
|
9
|
-
export declare function createConstructor<E extends Element, FP extends FilterParams<any, any>, FM extends FilterMethods<any, any>, AM extends ActionMethods<any, any>>(name: string, specification: InteractorSpecification<E, any, any>): InteractorConstructor<E, FP, FM, AM>;
|
|
2
|
+
export declare function instantiateInteractor<E extends Element, F extends Filters<E>, A extends Actions<E, Interactor<E, FilterParams<E, F>>>>(options: InteractorOptions<E, F, A>, resolver: (options: InteractorOptions<E, F, A>) => E): Interactor<E, FilterParams<E, F>> & FilterMethods<E, F> & ActionMethods<E, A, Interactor<E, FilterParams<E, F>>>;
|
|
3
|
+
export declare function createConstructor<E extends Element, FP extends FilterParams<any, any>, FM extends FilterMethods<any, any>, AM extends ActionMethods<any, any, any>>(name: string, specification: InteractorSpecification<E, any, any>): InteractorConstructor<E, FP, FM, AM>;
|
|
10
4
|
//# sourceMappingURL=constructor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constructor.d.ts","sourceRoot":"","sources":["../src/constructor.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"constructor.d.ts","sourceRoot":"","sources":["../src/constructor.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,iBAAiB,EACjB,aAAa,EACb,qBAAqB,EACrB,UAAU,EACV,OAAO,EACP,OAAO,EAEP,YAAY,EACZ,aAAa,EACb,uBAAuB,EAExB,MAAM,iBAAiB,CAAC;AAgCzB,wBAAgB,qBAAqB,CAAC,CAAC,SAAS,OAAO,EAAE,CAAC,SAAS,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,SAAS,OAAO,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EACpI,OAAO,EAAE,iBAAiB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EACnC,QAAQ,EAAE,CAAC,OAAO,EAAE,iBAAiB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,GACnD,UAAU,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,aAAa,CAAC,CAAC,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CA+HlH;AAED,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,OAAO,EAAE,EAAE,SAAS,YAAY,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,EAAE,SAAS,aAAa,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,EAAE,SAAS,aAAa,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EACjK,IAAI,EAAE,MAAM,EACZ,aAAa,EAAE,uBAAuB,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,GAClD,qBAAqB,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CA8BtC"}
|
package/dist/converge.d.ts
CHANGED
package/dist/converge.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"converge.d.ts","sourceRoot":"","sources":["../src/converge.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"converge.d.ts","sourceRoot":"","sources":["../src/converge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAS,MAAM,iBAAiB,CAAC;AAInD,wBAAiB,QAAQ,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CActD"}
|
package/dist/esm/constructor.js
CHANGED
|
@@ -1,95 +1,15 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
-
import { globals } from '@interactors/globals';
|
|
3
2
|
import { converge } from './converge';
|
|
4
3
|
import { FilterSet } from './filter-set';
|
|
5
4
|
import { Locator } from './locator';
|
|
6
5
|
import { MatchFilter, applyFilter } from './match';
|
|
7
|
-
import {
|
|
6
|
+
import { formatDescription } from './format';
|
|
8
7
|
import { FilterNotMatchingError } from './errors';
|
|
9
|
-
import {
|
|
10
|
-
import { Match } from './match';
|
|
11
|
-
import { NoSuchElementError, NotAbsentError, AmbiguousElementError } from './errors';
|
|
8
|
+
import { createInteraction } from './interaction';
|
|
12
9
|
import { isMatcher } from './matcher';
|
|
13
10
|
import { matching } from './matchers/matching';
|
|
11
|
+
import { hasMatchMatching, resolveEmpty, resolveFirst, resolveUnique, unsafeSyncResolveParent, unsafeSyncResolveUnique } from './resolvers';
|
|
14
12
|
const defaultLocator = (element) => element.textContent || "";
|
|
15
|
-
const defaultSelector = 'div';
|
|
16
|
-
export function findElements(parentElement, interactor) {
|
|
17
|
-
if (typeof (interactor.specification.selector) === 'function') {
|
|
18
|
-
return interactor.specification.selector(parentElement);
|
|
19
|
-
}
|
|
20
|
-
else if (interactor.specification.selector === ':root') {
|
|
21
|
-
// this is a bit of a hack, because otherwise there isn't a good way of selecting the root element
|
|
22
|
-
return [parentElement.ownerDocument.querySelector(':root')];
|
|
23
|
-
}
|
|
24
|
-
else {
|
|
25
|
-
return Array.from(parentElement.querySelectorAll(interactor.specification.selector || defaultSelector));
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
function findMatches(parentElement, interactor) {
|
|
29
|
-
if (!interactor.name) {
|
|
30
|
-
throw new Error('One of your interactors was created without a name. Please provide a label for your interactor:\n\tHTML.extend(\'my interactor\') || createInteractor(\'my interactor\')');
|
|
31
|
-
}
|
|
32
|
-
return findElements(parentElement, interactor).map((e) => new Match(e, interactor.filter, interactor.locator));
|
|
33
|
-
}
|
|
34
|
-
function findMatchesMatching(parentElement, interactor) {
|
|
35
|
-
return findMatches(parentElement, interactor).filter((m) => m.matches);
|
|
36
|
-
}
|
|
37
|
-
function findMatchesNonEmpty(parentElement, interactor) {
|
|
38
|
-
let matches = findMatches(parentElement, interactor);
|
|
39
|
-
let matching = matches.filter((m) => m.matches);
|
|
40
|
-
if (matching.length > 0) {
|
|
41
|
-
return matching;
|
|
42
|
-
}
|
|
43
|
-
else if (matches.length === 0) {
|
|
44
|
-
throw new NoSuchElementError(`did not find ${description(interactor)}`);
|
|
45
|
-
}
|
|
46
|
-
else {
|
|
47
|
-
let table = formatTable({
|
|
48
|
-
headers: interactor.locator ? [interactor.name, ...interactor.filter.asTableHeader()] : interactor.filter.asTableHeader(),
|
|
49
|
-
rows: matches.slice().sort((a, b) => b.sortWeight - a.sortWeight).map((m) => m.asTableRow()),
|
|
50
|
-
});
|
|
51
|
-
throw new NoSuchElementError(`did not find ${description(interactor)}, did you mean one of:\n\n${table}`);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
// Given a parent element, and an interactor, find exactly one matching element
|
|
55
|
-
// and return it. If no elements match, raise an error. If more than one
|
|
56
|
-
// element matches, raise an error.
|
|
57
|
-
export function resolveUnique(parentElement, interactor) {
|
|
58
|
-
let matching = findMatchesNonEmpty(parentElement, interactor);
|
|
59
|
-
if (matching.length === 1) {
|
|
60
|
-
return matching[0].element;
|
|
61
|
-
}
|
|
62
|
-
else {
|
|
63
|
-
let alternatives = matching.map((m) => '- ' + m.elementDescription());
|
|
64
|
-
throw new AmbiguousElementError(`${description(interactor)} matches multiple elements:\n\n${alternatives.join('\n')}`);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
// Given a parent element, and an interactor, find all matching elements and
|
|
68
|
-
// return them. If no elements match, raise an error.
|
|
69
|
-
export function resolveNonEmpty(parentElement, interactor) {
|
|
70
|
-
return findMatchesNonEmpty(parentElement, interactor).map(m => m.element);
|
|
71
|
-
}
|
|
72
|
-
// Given a parent element, and an interactor, check if there are any matching
|
|
73
|
-
// elements, and throw an error if there are. Otherwise return undefined.
|
|
74
|
-
export function resolveEmpty(parentElement, interactor) {
|
|
75
|
-
let matching = findMatchesMatching(parentElement, interactor);
|
|
76
|
-
if (matching.length !== 0) {
|
|
77
|
-
let alternatives = matching.map((m) => '- ' + m.elementDescription());
|
|
78
|
-
throw new NotAbsentError(`${description(interactor)} exists but should not:\n\n${alternatives.join('\n')}`);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
function ownDescription(options) {
|
|
82
|
-
if (options.locator) {
|
|
83
|
-
return `${options.name} ${options.locator.description} ${options.filter.description}`.trim();
|
|
84
|
-
}
|
|
85
|
-
else {
|
|
86
|
-
return `${options.name} ${options.filter.description}`.trim();
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
function description(options) {
|
|
90
|
-
let ancestorsAndSelf = options.ancestors.concat(options);
|
|
91
|
-
return ancestorsAndSelf.reverse().map(ownDescription).join(' within ');
|
|
92
|
-
}
|
|
93
13
|
/**
|
|
94
14
|
* Removes any default values for a filter from the lookup if that filter is present in the
|
|
95
15
|
* assertion. Otherwise, it is not possible to make an assertion on a filter that might conflict
|
|
@@ -108,26 +28,26 @@ function getLookupFilterForAssertion(filter, filters) {
|
|
|
108
28
|
}
|
|
109
29
|
return lookupFilter;
|
|
110
30
|
}
|
|
111
|
-
export function unsafeSyncResolveParent(options) {
|
|
112
|
-
return options.ancestors.reduce(resolveUnique, globals.document.documentElement);
|
|
113
|
-
}
|
|
114
|
-
export function unsafeSyncResolveUnique(options) {
|
|
115
|
-
return resolveUnique(unsafeSyncResolveParent(options), options);
|
|
116
|
-
}
|
|
117
31
|
export function instantiateInteractor(options, resolver) {
|
|
118
32
|
let interactor = {
|
|
119
33
|
options,
|
|
120
34
|
get description() {
|
|
121
|
-
return
|
|
35
|
+
return formatDescription(options);
|
|
122
36
|
},
|
|
123
37
|
perform(fn) {
|
|
124
|
-
return
|
|
38
|
+
return createInteraction('action', {
|
|
39
|
+
name: "perform",
|
|
40
|
+
interactor,
|
|
41
|
+
description: `run perform on ${formatDescription(options)}`,
|
|
42
|
+
run: (interactor) => converge(() => fn(resolver(interactor.options))),
|
|
43
|
+
});
|
|
125
44
|
},
|
|
126
45
|
assert(fn) {
|
|
127
|
-
return
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
}
|
|
46
|
+
return createInteraction('assertion', {
|
|
47
|
+
name: "assert",
|
|
48
|
+
interactor,
|
|
49
|
+
description: `${formatDescription(options)} asserts`,
|
|
50
|
+
run: (interactor) => converge(() => { fn(resolver(interactor.options)); }),
|
|
131
51
|
});
|
|
132
52
|
},
|
|
133
53
|
has(filters) {
|
|
@@ -135,14 +55,18 @@ export function instantiateInteractor(options, resolver) {
|
|
|
135
55
|
},
|
|
136
56
|
is(filters) {
|
|
137
57
|
let filter = new FilterSet(options.specification, filters);
|
|
138
|
-
return
|
|
139
|
-
|
|
140
|
-
|
|
58
|
+
return createInteraction('assertion', {
|
|
59
|
+
name: "is",
|
|
60
|
+
interactor,
|
|
61
|
+
filters,
|
|
62
|
+
description: `${formatDescription(options)} matches filters: ${filter.description}`,
|
|
63
|
+
run: (interactor) => converge(() => {
|
|
64
|
+
let element = resolver({ ...interactor.options, filter: getLookupFilterForAssertion(interactor.options.filter, filters) });
|
|
141
65
|
let match = new MatchFilter(element, filter);
|
|
142
66
|
if (!match.matches) {
|
|
143
|
-
throw new FilterNotMatchingError(`${
|
|
67
|
+
throw new FilterNotMatchingError(`${formatDescription(options)} does not match filters:\n\n${match.formatAsExpectations()}`);
|
|
144
68
|
}
|
|
145
|
-
})
|
|
69
|
+
}),
|
|
146
70
|
});
|
|
147
71
|
},
|
|
148
72
|
find(child) {
|
|
@@ -152,22 +76,24 @@ export function instantiateInteractor(options, resolver) {
|
|
|
152
76
|
}, resolver);
|
|
153
77
|
},
|
|
154
78
|
exists() {
|
|
155
|
-
return
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
79
|
+
return createInteraction('assertion', {
|
|
80
|
+
name: 'exists',
|
|
81
|
+
interactor,
|
|
82
|
+
description: `${formatDescription(options)} exists`,
|
|
83
|
+
run: (interactor) => converge(() => {
|
|
84
|
+
resolveFirst(unsafeSyncResolveParent(interactor.options), options);
|
|
85
|
+
}),
|
|
86
|
+
}, (element) => hasMatchMatching(element, options));
|
|
162
87
|
},
|
|
163
88
|
absent() {
|
|
164
|
-
return
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
89
|
+
return createInteraction('assertion', {
|
|
90
|
+
name: 'absent',
|
|
91
|
+
interactor,
|
|
92
|
+
description: `${formatDescription(options)} does not exist`,
|
|
93
|
+
run: (interactor) => converge(() => {
|
|
94
|
+
resolveEmpty(unsafeSyncResolveParent(interactor.options), options);
|
|
95
|
+
}),
|
|
96
|
+
}, (element) => !hasMatchMatching(element, options));
|
|
171
97
|
},
|
|
172
98
|
apply(parentElement) {
|
|
173
99
|
let element = [...options.ancestors, options].reduce(resolveUnique, parentElement);
|
|
@@ -182,7 +108,13 @@ export function instantiateInteractor(options, resolver) {
|
|
|
182
108
|
if (args.length) {
|
|
183
109
|
actionDescription += ` with ` + args.map((a) => JSON.stringify(a)).join(', ');
|
|
184
110
|
}
|
|
185
|
-
return
|
|
111
|
+
return createInteraction('action', {
|
|
112
|
+
name: actionName,
|
|
113
|
+
interactor,
|
|
114
|
+
args,
|
|
115
|
+
description: `${actionDescription} on ${formatDescription(options)}`,
|
|
116
|
+
run: (interactor) => action(interactor, ...args)
|
|
117
|
+
});
|
|
186
118
|
},
|
|
187
119
|
configurable: true,
|
|
188
120
|
writable: true,
|
|
@@ -194,8 +126,11 @@ export function instantiateInteractor(options, resolver) {
|
|
|
194
126
|
if (!interactor.hasOwnProperty(filterName)) {
|
|
195
127
|
Object.defineProperty(interactor, filterName, {
|
|
196
128
|
value: function () {
|
|
197
|
-
return
|
|
198
|
-
|
|
129
|
+
return createInteraction('assertion', {
|
|
130
|
+
name: filterName,
|
|
131
|
+
interactor,
|
|
132
|
+
description: `${filterName} of ${formatDescription(options)}`,
|
|
133
|
+
run: (interactor) => converge(() => applyFilter(filter, resolver(interactor.options))),
|
|
199
134
|
}, (parentElement) => {
|
|
200
135
|
let element = [...options.ancestors, options].reduce(resolveUnique, parentElement);
|
|
201
136
|
return applyFilter(filter, element);
|