@serenity-js/core 3.0.0-rc.23 → 3.0.0-rc.24

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.
Files changed (38) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/lib/screenplay/Answered.d.ts +2 -0
  3. package/lib/screenplay/Answered.js +3 -0
  4. package/lib/screenplay/Answered.js.map +1 -0
  5. package/lib/screenplay/index.d.ts +1 -0
  6. package/lib/screenplay/index.js +1 -0
  7. package/lib/screenplay/index.js.map +1 -1
  8. package/lib/screenplay/interactions/Log.d.ts +1 -1
  9. package/lib/screenplay/interactions/Log.js +7 -7
  10. package/lib/screenplay/interactions/Log.js.map +1 -1
  11. package/lib/screenplay/interactions/debug/Debug.d.ts +95 -0
  12. package/lib/screenplay/interactions/debug/Debug.js +132 -0
  13. package/lib/screenplay/interactions/debug/Debug.js.map +1 -0
  14. package/lib/screenplay/interactions/debug/DebuggingResult.d.ts +5 -0
  15. package/lib/screenplay/interactions/debug/DebuggingResult.js +3 -0
  16. package/lib/screenplay/interactions/debug/DebuggingResult.js.map +1 -0
  17. package/lib/screenplay/interactions/debug/breakpoint.d.ts +1 -0
  18. package/lib/screenplay/interactions/debug/breakpoint.js +9 -0
  19. package/lib/screenplay/interactions/debug/breakpoint.js.map +1 -0
  20. package/lib/screenplay/interactions/debug/index.d.ts +1 -0
  21. package/lib/screenplay/interactions/debug/index.js +18 -0
  22. package/lib/screenplay/interactions/debug/index.js.map +1 -0
  23. package/lib/screenplay/interactions/debug/viewer.d.ts +6 -0
  24. package/lib/screenplay/interactions/debug/viewer.js +19 -0
  25. package/lib/screenplay/interactions/debug/viewer.js.map +1 -0
  26. package/lib/screenplay/interactions/index.d.ts +1 -0
  27. package/lib/screenplay/interactions/index.js +1 -0
  28. package/lib/screenplay/interactions/index.js.map +1 -1
  29. package/package.json +2 -2
  30. package/src/screenplay/Answered.ts +6 -0
  31. package/src/screenplay/index.ts +1 -0
  32. package/src/screenplay/interactions/Log.ts +13 -12
  33. package/src/screenplay/interactions/debug/Debug.ts +155 -0
  34. package/src/screenplay/interactions/debug/DebuggingResult.ts +5 -0
  35. package/src/screenplay/interactions/debug/breakpoint.ts +4 -0
  36. package/src/screenplay/interactions/debug/index.ts +1 -0
  37. package/src/screenplay/interactions/debug/viewer.ts +18 -0
  38. package/src/screenplay/interactions/index.ts +1 -0
package/CHANGELOG.md CHANGED
@@ -3,6 +3,22 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [3.0.0-rc.24](https://github.com/serenity-js/serenity-js/compare/v3.0.0-rc.23...v3.0.0-rc.24) (2022-07-23)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * **core:** improved how the interaction to Log reports names of the logged values ([c4cc60d](https://github.com/serenity-js/serenity-js/commit/c4cc60d0e1d4bdc34218566b1726e74d3ac40909))
12
+
13
+
14
+ ### Features
15
+
16
+ * **core:** new interaction to Debug.values(..) and Debug.setBreakpoint() ([ef54324](https://github.com/serenity-js/serenity-js/commit/ef54324ca1b415d41eee12e7f4667cbffe2c8a01))
17
+
18
+
19
+
20
+
21
+
6
22
  # [3.0.0-rc.23](https://github.com/serenity-js/serenity-js/compare/v2.33.10...v3.0.0-rc.23) (2022-07-19)
7
23
 
8
24
 
@@ -0,0 +1,2 @@
1
+ import { Question } from './Question';
2
+ export declare type Answered<T> = T extends null | undefined ? T : T extends Question<Promise<infer A>> | Question<infer A> | Promise<infer A> ? Awaited<A> : T;
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=Answered.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Answered.js","sourceRoot":"","sources":["../../src/screenplay/Answered.ts"],"names":[],"mappings":""}
@@ -4,6 +4,7 @@ export * from './AbilityType';
4
4
  export * from './Activity';
5
5
  export * from './actor';
6
6
  export * from './Answerable';
7
+ export * from './Answered';
7
8
  export * from './Interaction';
8
9
  export * from './interactions';
9
10
  export * from './notes';
@@ -20,6 +20,7 @@ __exportStar(require("./AbilityType"), exports);
20
20
  __exportStar(require("./Activity"), exports);
21
21
  __exportStar(require("./actor"), exports);
22
22
  __exportStar(require("./Answerable"), exports);
23
+ __exportStar(require("./Answered"), exports);
23
24
  __exportStar(require("./Interaction"), exports);
24
25
  __exportStar(require("./interactions"), exports);
25
26
  __exportStar(require("./notes"), exports);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/screenplay/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,8CAA4B;AAC5B,4CAA0B;AAC1B,gDAA8B;AAC9B,6CAA2B;AAC3B,0CAAwB;AACxB,+CAA6B;AAC7B,gDAA8B;AAC9B,iDAA+B;AAC/B,0CAAwB;AACxB,6CAA2B;AAC3B,6CAA2B;AAC3B,8CAA4B;AAC5B,wDAAsC;AACtC,yCAAuB;AACvB,6DAA2C"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/screenplay/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,8CAA4B;AAC5B,4CAA0B;AAC1B,gDAA8B;AAC9B,6CAA2B;AAC3B,0CAAwB;AACxB,+CAA6B;AAC7B,6CAA2B;AAC3B,gDAA8B;AAC9B,iDAA+B;AAC/B,0CAAwB;AACxB,6CAA2B;AAC3B,6CAA2B;AAC3B,8CAA4B;AAC5B,wDAAsC;AACtC,yCAAuB;AACvB,6DAA2C"}
@@ -29,7 +29,7 @@ export declare class Log extends Interaction {
29
29
  */
30
30
  static the(...items: Array<Answerable<any>>): Interaction;
31
31
  /**
32
- * @param {...items: any[]} items
32
+ * @param {Array<Answerable<any>>} items
33
33
  * The items to be logged
34
34
  */
35
35
  constructor(items: Array<Answerable<any>>);
@@ -4,7 +4,6 @@ exports.Log = void 0;
4
4
  const io_1 = require("../../io");
5
5
  const inspected_1 = require("../../io/inspected");
6
6
  const model_1 = require("../../model");
7
- const artifacts_1 = require("../../model/artifacts");
8
7
  const Interaction_1 = require("../Interaction");
9
8
  /**
10
9
  * @desc
@@ -24,7 +23,7 @@ const Interaction_1 = require("../Interaction");
24
23
  */
25
24
  class Log extends Interaction_1.Interaction {
26
25
  /**
27
- * @param {...items: any[]} items
26
+ * @param {Array<Answerable<any>>} items
28
27
  * The items to be logged
29
28
  */
30
29
  constructor(items) {
@@ -55,10 +54,11 @@ class Log extends Interaction_1.Interaction {
55
54
  * @see {@link AnswersQuestions}
56
55
  * @see {@link CollectsArtifacts}
57
56
  */
58
- performAs(actor) {
59
- return Promise
60
- .all(this.items.map(item => actor.answer(item)))
61
- .then(items => items.forEach((item, i) => actor.collect(artifacts_1.LogEntry.fromJSON({ data: (0, inspected_1.inspected)(item) }), new model_1.Name((0, inspected_1.inspected)(this.items[i])))));
57
+ async performAs(actor) {
58
+ for (const item of this.items) {
59
+ const data = await actor.answer(item);
60
+ actor.collect(model_1.LogEntry.fromJSON({ data: (0, inspected_1.inspected)(data) }), new model_1.Name((0, io_1.d) `${item}`));
61
+ }
62
62
  }
63
63
  /**
64
64
  * @desc
@@ -67,7 +67,7 @@ class Log extends Interaction_1.Interaction {
67
67
  * @returns {string}
68
68
  */
69
69
  toString() {
70
- return `#actor logs: ${this.items.map(item => (0, io_1.formatted) `${item}`).join(', ')}`;
70
+ return `#actor logs: ${this.items.map(item => (0, io_1.d) `${item}`).join(', ')}`;
71
71
  }
72
72
  }
73
73
  exports.Log = Log;
@@ -1 +1 @@
1
- {"version":3,"file":"Log.js","sourceRoot":"","sources":["../../../src/screenplay/interactions/Log.ts"],"names":[],"mappings":";;;AAAA,iCAAqC;AACrC,kDAA+C;AAC/C,uCAAmC;AACnC,qDAAiD;AAGjD,gDAA6C;AAE7C;;;;;;;;;;;;;;;GAeG;AACH,MAAa,GAAI,SAAQ,yBAAW;IAchC;;;OAGG;IACH,YACqB,KAA6B;QAE9C,KAAK,EAAE,CAAC;QAFS,UAAK,GAAL,KAAK,CAAwB;IAGlD,CAAC;IApBD;;;;;;;OAOG;IACH,MAAM,CAAC,GAAG,CAAC,GAAG,KAA6B;QACvC,OAAO,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;IAC1B,CAAC;IAYD;;;;;;;;;;;;OAYG;IACH,SAAS,CAAC,KAA2D;QACjE,OAAO,OAAO;aACT,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;aAC/C,IAAI,CAAC,KAAK,CAAC,EAAE,CACV,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CACtB,KAAK,CAAC,OAAO,CAAC,oBAAQ,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,IAAA,qBAAS,EAAC,IAAI,CAAC,EAAE,CAAC,EAAE,IAAI,YAAI,CAAC,IAAA,qBAAS,EAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAClG,CACJ,CAAC;IACV,CAAC;IAED;;;;;OAKG;IACH,QAAQ;QACJ,OAAO,gBAAiB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAA,cAAS,EAAA,GAAI,IAAK,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAE,EAAE,CAAC;IACvF,CAAC;CACJ;AAxDD,kBAwDC"}
1
+ {"version":3,"file":"Log.js","sourceRoot":"","sources":["../../../src/screenplay/interactions/Log.ts"],"names":[],"mappings":";;;AAAA,iCAA6B;AAC7B,kDAA+C;AAC/C,uCAA6C;AAG7C,gDAA6C;AAE7C;;;;;;;;;;;;;;;GAeG;AACH,MAAa,GAAI,SAAQ,yBAAW;IAchC;;;OAGG;IACH,YACqB,KAA6B;QAE9C,KAAK,EAAE,CAAC;QAFS,UAAK,GAAL,KAAK,CAAwB;IAGlD,CAAC;IApBD;;;;;;;OAOG;IACH,MAAM,CAAC,GAAG,CAAC,GAAG,KAA6B;QACvC,OAAO,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;IAC1B,CAAC;IAYD;;;;;;;;;;;;OAYG;IACH,KAAK,CAAC,SAAS,CAAC,KAA2D;QACvE,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE;YAE3B,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAEtC,KAAK,CAAC,OAAO,CACT,gBAAQ,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,IAAA,qBAAS,EAAC,IAAI,CAAC,EAAE,CAAC,EAC5C,IAAI,YAAI,CAAC,IAAA,MAAC,EAAA,GAAI,IAAK,EAAE,CAAC,CACzB,CAAC;SACL;IACL,CAAC;IAED;;;;;OAKG;IACH,QAAQ;QACJ,OAAO,gBAAiB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAA,MAAC,EAAA,GAAI,IAAK,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAE,EAAE,CAAC;IAC/E,CAAC;CACJ;AA1DD,kBA0DC"}
@@ -0,0 +1,95 @@
1
+ import { AnswersQuestions, CollectsArtifacts, UsesAbilities } from '../../actor';
2
+ import { Answerable } from '../../Answerable';
3
+ import { Answered } from '../../Answered';
4
+ import { Interaction } from '../../Interaction';
5
+ import { DebuggingResult } from './DebuggingResult';
6
+ /**
7
+ * @desc
8
+ * Instructs the {@link Actor} to set a breakpoint and optionally evaluate and log the provided {@link Answerable} values.
9
+ *
10
+ * Since this interaction sets a breakpoint using the [`debugger`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/debugger) statement,
11
+ * the best way to use it is while running the test scenario via a Node.js debugger.
12
+ *
13
+ * @example <caption>Setting a breakpoint to pause the scenario</caption>
14
+ * import { actorCalled, Debug } from '@serenity-js/core';
15
+ * import { Navigate } from '@serenity-js/web';
16
+ *
17
+ * await actorCalled('Debbie').attemptsTo(
18
+ * Navigate.to('http://example.org'),
19
+ * Debug.setBreakpoint(),
20
+ * // ... other activities
21
+ * );
22
+ *
23
+ * @example <caption>Debugging Answerable values</caption>
24
+ * import { actorCalled, Debug } from '@serenity-js/core';
25
+ * import { Navigate, Page } from '@serenity-js/web';
26
+ *
27
+ * // Running the below through the Node.js debugger makes the actor resolve the provided values
28
+ * // and return them to the debugger function, where you can investigate their contents,
29
+ * // or inspect any Errors the evaluation has resulted with.
30
+ * await actorCalled('Debbie').attemptsTo(
31
+ * Navigate.to('http://example.org'),
32
+ * Debug.values(Page.current().title(), Page.current().url()), // accepts multiple values
33
+ * );
34
+ *
35
+ * @extends {Interaction}
36
+ */
37
+ export declare class Debug<Values extends Array<Answerable<unknown>>> extends Interaction {
38
+ private readonly description;
39
+ private readonly debuggerFunction;
40
+ private readonly values;
41
+ /**
42
+ * @desc
43
+ * Invokes a debugger function that sets a breakpoint.
44
+ *
45
+ * To use this interaction, run your test scenario in the Node.js debugger.
46
+ *
47
+ * @returns {Interaction}
48
+ */
49
+ static setBreakpoint(): Interaction;
50
+ /**
51
+ * @desc
52
+ * Instructs the Actor to evaluate the provided `values`,
53
+ * log the results, and then pass them to a debugger function.
54
+ *
55
+ * To use this interaction, run your test scenario in the Node.js debugger.
56
+ *
57
+ * @param {...items: Array<Answerable<any>>} values
58
+ * The values to be debugged
59
+ *
60
+ * @returns {Interaction}
61
+ */
62
+ static values(...values: Array<Answerable<any>>): Interaction;
63
+ /**
64
+ * @param {string} description
65
+ * Description of this interaction
66
+ * @param debuggerFunction
67
+ * Callback function to receive the results of debugging
68
+ * @param {Array<Answerable<any>>} values
69
+ * Values to be evaluated by the actor, and provided to debuggerFunction
70
+ */
71
+ constructor(description: string, debuggerFunction: (args: {
72
+ [Index in keyof Values]: DebuggingResult<Answered<Values[Index]>>;
73
+ }) => void, values: Values);
74
+ /**
75
+ * @desc
76
+ * Makes the provided {@link Actor}
77
+ * perform this {@link Interaction}.
78
+ *
79
+ * @param {UsesAbilities & AnswersQuestions & CollectsArtifacts} actor
80
+ * @returns {Promise<void>}
81
+ *
82
+ * @see {@link Actor}
83
+ * @see {@link UsesAbilities}
84
+ * @see {@link AnswersQuestions}
85
+ * @see {@link CollectsArtifacts}
86
+ */
87
+ performAs(actor: UsesAbilities & AnswersQuestions & CollectsArtifacts): Promise<void>;
88
+ /**
89
+ * @desc
90
+ * Generates a description to be used when reporting this {@link Activity}.
91
+ *
92
+ * @returns {string}
93
+ */
94
+ toString(): string;
95
+ }
@@ -0,0 +1,132 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Debug = void 0;
4
+ const io_1 = require("../../../io");
5
+ const inspected_1 = require("../../../io/inspected");
6
+ const model_1 = require("../../../model");
7
+ const Interaction_1 = require("../../Interaction");
8
+ const breakpoint_1 = require("./breakpoint");
9
+ const viewer_1 = require("./viewer");
10
+ /**
11
+ * @desc
12
+ * Instructs the {@link Actor} to set a breakpoint and optionally evaluate and log the provided {@link Answerable} values.
13
+ *
14
+ * Since this interaction sets a breakpoint using the [`debugger`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/debugger) statement,
15
+ * the best way to use it is while running the test scenario via a Node.js debugger.
16
+ *
17
+ * @example <caption>Setting a breakpoint to pause the scenario</caption>
18
+ * import { actorCalled, Debug } from '@serenity-js/core';
19
+ * import { Navigate } from '@serenity-js/web';
20
+ *
21
+ * await actorCalled('Debbie').attemptsTo(
22
+ * Navigate.to('http://example.org'),
23
+ * Debug.setBreakpoint(),
24
+ * // ... other activities
25
+ * );
26
+ *
27
+ * @example <caption>Debugging Answerable values</caption>
28
+ * import { actorCalled, Debug } from '@serenity-js/core';
29
+ * import { Navigate, Page } from '@serenity-js/web';
30
+ *
31
+ * // Running the below through the Node.js debugger makes the actor resolve the provided values
32
+ * // and return them to the debugger function, where you can investigate their contents,
33
+ * // or inspect any Errors the evaluation has resulted with.
34
+ * await actorCalled('Debbie').attemptsTo(
35
+ * Navigate.to('http://example.org'),
36
+ * Debug.values(Page.current().title(), Page.current().url()), // accepts multiple values
37
+ * );
38
+ *
39
+ * @extends {Interaction}
40
+ */
41
+ class Debug extends Interaction_1.Interaction {
42
+ /**
43
+ * @param {string} description
44
+ * Description of this interaction
45
+ * @param debuggerFunction
46
+ * Callback function to receive the results of debugging
47
+ * @param {Array<Answerable<any>>} values
48
+ * Values to be evaluated by the actor, and provided to debuggerFunction
49
+ */
50
+ constructor(description, debuggerFunction, values) {
51
+ super();
52
+ this.description = description;
53
+ this.debuggerFunction = debuggerFunction;
54
+ this.values = values;
55
+ }
56
+ /**
57
+ * @desc
58
+ * Invokes a debugger function that sets a breakpoint.
59
+ *
60
+ * To use this interaction, run your test scenario in the Node.js debugger.
61
+ *
62
+ * @returns {Interaction}
63
+ */
64
+ static setBreakpoint() {
65
+ /* istanbul ignore next can't test using a debugger in an automated test */
66
+ return new Debug(`#actor sets a breakpoint`, breakpoint_1.breakpoint, []);
67
+ }
68
+ /**
69
+ * @desc
70
+ * Instructs the Actor to evaluate the provided `values`,
71
+ * log the results, and then pass them to a debugger function.
72
+ *
73
+ * To use this interaction, run your test scenario in the Node.js debugger.
74
+ *
75
+ * @param {...items: Array<Answerable<any>>} values
76
+ * The values to be debugged
77
+ *
78
+ * @returns {Interaction}
79
+ */
80
+ static values(...values) {
81
+ /* istanbul ignore next can't test using a debugger in an automated test */
82
+ return new Debug(`#actor debugs ${values.length} values`, viewer_1.viewer, values);
83
+ }
84
+ /**
85
+ * @desc
86
+ * Makes the provided {@link Actor}
87
+ * perform this {@link Interaction}.
88
+ *
89
+ * @param {UsesAbilities & AnswersQuestions & CollectsArtifacts} actor
90
+ * @returns {Promise<void>}
91
+ *
92
+ * @see {@link Actor}
93
+ * @see {@link UsesAbilities}
94
+ * @see {@link AnswersQuestions}
95
+ * @see {@link CollectsArtifacts}
96
+ */
97
+ async performAs(actor) {
98
+ const results = [];
99
+ for (const value of this.values) {
100
+ const result = {
101
+ description: (0, io_1.d) `${value}`,
102
+ value: undefined,
103
+ error: undefined,
104
+ };
105
+ try {
106
+ result.value = await actor.answer(value);
107
+ }
108
+ catch (error) {
109
+ result.error = error;
110
+ }
111
+ actor.collect(model_1.LogEntry.fromJSON({
112
+ data: JSON.stringify({
113
+ value: (0, inspected_1.inspected)(result.value),
114
+ error: result.error ? io_1.ErrorSerialiser.serialise(result.error) : result.error
115
+ }),
116
+ }), new model_1.Name(result.description));
117
+ results.push(result);
118
+ }
119
+ this.debuggerFunction(results);
120
+ }
121
+ /**
122
+ * @desc
123
+ * Generates a description to be used when reporting this {@link Activity}.
124
+ *
125
+ * @returns {string}
126
+ */
127
+ toString() {
128
+ return this.description;
129
+ }
130
+ }
131
+ exports.Debug = Debug;
132
+ //# sourceMappingURL=Debug.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Debug.js","sourceRoot":"","sources":["../../../../src/screenplay/interactions/debug/Debug.ts"],"names":[],"mappings":";;;AAAA,oCAAiD;AACjD,qDAAkD;AAClD,0CAAgD;AAIhD,mDAAgD;AAChD,6CAA0C;AAE1C,qCAAkC;AAElC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAa,KAAiD,SAAQ,yBAAW;IAwC7E;;;;;;;OAOG;IACH,YACqB,WAAmB,EACnB,gBAAyG,EACzG,MAAc;QAE/B,KAAK,EAAE,CAAC;QAJS,gBAAW,GAAX,WAAW,CAAQ;QACnB,qBAAgB,GAAhB,gBAAgB,CAAyF;QACzG,WAAM,GAAN,MAAM,CAAQ;IAGnC,CAAC;IApDD;;;;;;;OAOG;IACH,MAAM,CAAC,aAAa;QAChB,2EAA2E;QAC3E,OAAO,IAAI,KAAK,CACZ,0BAA0B,EAC1B,uBAAU,EACV,EAAE,CACL,CAAC;IACN,CAAC;IAED;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,MAAM,CAAC,GAAG,MAA8B;QAC3C,2EAA2E;QAC3E,OAAO,IAAI,KAAK,CACZ,iBAAkB,MAAM,CAAC,MAAO,SAAS,EACzC,eAAM,EACN,MAAM,CACT,CAAC;IACN,CAAC;IAkBD;;;;;;;;;;;;OAYG;IACH,KAAK,CAAC,SAAS,CAAC,KAA2D;QACvE,MAAM,OAAO,GAAG,EAA6E,CAAC;QAE9F,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE;YAE7B,MAAM,MAAM,GAA6B;gBACrC,WAAW,EAAE,IAAA,MAAC,EAAA,GAAI,KAAM,EAAE;gBAC1B,KAAK,EAAE,SAAS;gBAChB,KAAK,EAAE,SAAS;aACnB,CAAA;YAED,IAAI;gBACA,MAAM,CAAC,KAAK,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;aAC5C;YACD,OAAM,KAAK,EAAE;gBACT,MAAM,CAAC,KAAK,GAAG,KAAK,CAAC;aACxB;YAED,KAAK,CAAC,OAAO,CACT,gBAAQ,CAAC,QAAQ,CAAC;gBACd,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;oBACjB,KAAK,EAAE,IAAA,qBAAS,EAAC,MAAM,CAAC,KAAK,CAAC;oBAC9B,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,oBAAe,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK;iBAC/E,CAAC;aACL,CAAC,EACF,IAAI,YAAI,CAAC,MAAM,CAAC,WAAW,CAAC,CAC/B,CAAC;YAEF,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;SACvB;QAED,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;IACnC,CAAC;IAED;;;;;OAKG;IACH,QAAQ;QACJ,OAAO,IAAI,CAAC,WAAW,CAAC;IAC5B,CAAC;CACJ;AAhHD,sBAgHC"}
@@ -0,0 +1,5 @@
1
+ export interface DebuggingResult<T> {
2
+ description: string;
3
+ value: T | undefined;
4
+ error: Error | undefined;
5
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=DebuggingResult.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DebuggingResult.js","sourceRoot":"","sources":["../../../../src/screenplay/interactions/debug/DebuggingResult.ts"],"names":[],"mappings":""}
@@ -0,0 +1 @@
1
+ export declare function breakpoint(): void;
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.breakpoint = void 0;
4
+ /* istanbul ignore next */
5
+ function breakpoint() {
6
+ debugger; // eslint-disable-line no-debugger
7
+ }
8
+ exports.breakpoint = breakpoint;
9
+ //# sourceMappingURL=breakpoint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"breakpoint.js","sourceRoot":"","sources":["../../../../src/screenplay/interactions/debug/breakpoint.ts"],"names":[],"mappings":";;;AAAA,0BAA0B;AAC1B,SAAgB,UAAU;IACtB,QAAQ,CAAC,CAAG,kCAAkC;AAClD,CAAC;AAFD,gCAEC"}
@@ -0,0 +1 @@
1
+ export * from './Debug';
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./Debug"), exports);
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/screenplay/interactions/debug/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,0CAAwB"}
@@ -0,0 +1,6 @@
1
+ import { Answerable } from '../../Answerable';
2
+ import { Answered } from '../../Answered';
3
+ import { DebuggingResult } from './DebuggingResult';
4
+ export declare function viewer<Values extends Array<Answerable<unknown>>>(results: {
5
+ [Index in keyof Values]: DebuggingResult<Answered<Values[Index]>>;
6
+ }): void;
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.viewer = void 0;
4
+ /* istanbul ignore next */
5
+ function viewer(results) {
6
+ /**
7
+ * Use your debugger to inspect the `results` array.
8
+ * Note that every entry in `results` contains:
9
+ * - description - a string description produced by invoking d`${ value }` on the original value
10
+ * - value - the result of invoking `await actor.answer(value)` on the original value
11
+ * - error - `Error`, if thrown when invoking `await actor.answer(value)` on the original value
12
+ *
13
+ * @see {d}
14
+ * @see {Actor#answer}
15
+ */
16
+ debugger; // eslint-disable-line no-debugger
17
+ }
18
+ exports.viewer = viewer;
19
+ //# sourceMappingURL=viewer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"viewer.js","sourceRoot":"","sources":["../../../../src/screenplay/interactions/debug/viewer.ts"],"names":[],"mappings":";;;AAIA,0BAA0B;AAC1B,SAAgB,MAAM,CAA4C,OAAgF;IAC9I;;;;;;;;;OASG;IACH,QAAQ,CAAC,CAAG,kCAAkC;AAClD,CAAC;AAZD,wBAYC"}
@@ -1,3 +1,4 @@
1
+ export * from './debug';
1
2
  export * from './Log';
2
3
  export * from './Wait';
3
4
  export * from './WaitBuilder';
@@ -14,6 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./debug"), exports);
17
18
  __exportStar(require("./Log"), exports);
18
19
  __exportStar(require("./Wait"), exports);
19
20
  __exportStar(require("./WaitBuilder"), exports);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/screenplay/interactions/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,wCAAsB;AACtB,yCAAuB;AACvB,gDAA8B"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/screenplay/interactions/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,0CAAwB;AACxB,wCAAsB;AACtB,yCAAuB;AACvB,gDAA8B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@serenity-js/core",
3
- "version": "3.0.0-rc.23",
3
+ "version": "3.0.0-rc.24",
4
4
  "description": "Serenity/JS Screenplay, reporting engine and core interfaces.",
5
5
  "author": {
6
6
  "name": "Jan Molak",
@@ -71,5 +71,5 @@
71
71
  "node": "^14 || ^16 || ^18",
72
72
  "npm": "^6 || ^7 || ^8"
73
73
  },
74
- "gitHead": "debd05ecd17b48de66a53afbef8f7aa7f457ba6b"
74
+ "gitHead": "76443ef557e876727b7dae9ef66d4e6612a3034b"
75
75
  }
@@ -0,0 +1,6 @@
1
+ import { Question } from './Question';
2
+
3
+ export type Answered<T> =
4
+ T extends null | undefined ? T : // special case for `null | undefined` when not in `--strictNullChecks` mode
5
+ T extends Question<Promise<infer A>> | Question<infer A> | Promise<infer A> ? Awaited<A> :
6
+ T;
@@ -4,6 +4,7 @@ export * from './AbilityType';
4
4
  export * from './Activity';
5
5
  export * from './actor';
6
6
  export * from './Answerable';
7
+ export * from './Answered';
7
8
  export * from './Interaction';
8
9
  export * from './interactions';
9
10
  export * from './notes';
@@ -1,7 +1,6 @@
1
- import { formatted } from '../../io';
1
+ import { d } from '../../io';
2
2
  import { inspected } from '../../io/inspected';
3
- import { Name } from '../../model';
4
- import { LogEntry } from '../../model/artifacts';
3
+ import { LogEntry, Name } from '../../model';
5
4
  import { AnswersQuestions, CollectsArtifacts, UsesAbilities } from '../actor';
6
5
  import { Answerable } from '../Answerable';
7
6
  import { Interaction } from '../Interaction';
@@ -37,7 +36,7 @@ export class Log extends Interaction {
37
36
  }
38
37
 
39
38
  /**
40
- * @param {...items: any[]} items
39
+ * @param {Array<Answerable<any>>} items
41
40
  * The items to be logged
42
41
  */
43
42
  constructor(
@@ -59,14 +58,16 @@ export class Log extends Interaction {
59
58
  * @see {@link AnswersQuestions}
60
59
  * @see {@link CollectsArtifacts}
61
60
  */
62
- performAs(actor: UsesAbilities & AnswersQuestions & CollectsArtifacts): Promise<void> {
63
- return Promise
64
- .all(this.items.map(item => actor.answer(item)))
65
- .then(items =>
66
- items.forEach((item, i) =>
67
- actor.collect(LogEntry.fromJSON({ data: inspected(item) }), new Name(inspected(this.items[i]))),
68
- ),
61
+ async performAs(actor: UsesAbilities & AnswersQuestions & CollectsArtifacts): Promise<void> {
62
+ for (const item of this.items) {
63
+
64
+ const data = await actor.answer(item);
65
+
66
+ actor.collect(
67
+ LogEntry.fromJSON({ data: inspected(data) }),
68
+ new Name(d`${ item }`)
69
69
  );
70
+ }
70
71
  }
71
72
 
72
73
  /**
@@ -76,6 +77,6 @@ export class Log extends Interaction {
76
77
  * @returns {string}
77
78
  */
78
79
  toString(): string {
79
- return `#actor logs: ${ this.items.map(item => formatted`${ item }`).join(', ') }`;
80
+ return `#actor logs: ${ this.items.map(item => d`${ item }`).join(', ') }`;
80
81
  }
81
82
  }
@@ -0,0 +1,155 @@
1
+ import { d, ErrorSerialiser } from '../../../io';
2
+ import { inspected } from '../../../io/inspected';
3
+ import { LogEntry, Name } from '../../../model';
4
+ import { AnswersQuestions, CollectsArtifacts, UsesAbilities } from '../../actor';
5
+ import { Answerable } from '../../Answerable';
6
+ import { Answered } from '../../Answered';
7
+ import { Interaction } from '../../Interaction';
8
+ import { breakpoint } from './breakpoint';
9
+ import { DebuggingResult } from './DebuggingResult';
10
+ import { viewer } from './viewer';
11
+
12
+ /**
13
+ * @desc
14
+ * Instructs the {@link Actor} to set a breakpoint and optionally evaluate and log the provided {@link Answerable} values.
15
+ *
16
+ * Since this interaction sets a breakpoint using the [`debugger`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/debugger) statement,
17
+ * the best way to use it is while running the test scenario via a Node.js debugger.
18
+ *
19
+ * @example <caption>Setting a breakpoint to pause the scenario</caption>
20
+ * import { actorCalled, Debug } from '@serenity-js/core';
21
+ * import { Navigate } from '@serenity-js/web';
22
+ *
23
+ * await actorCalled('Debbie').attemptsTo(
24
+ * Navigate.to('http://example.org'),
25
+ * Debug.setBreakpoint(),
26
+ * // ... other activities
27
+ * );
28
+ *
29
+ * @example <caption>Debugging Answerable values</caption>
30
+ * import { actorCalled, Debug } from '@serenity-js/core';
31
+ * import { Navigate, Page } from '@serenity-js/web';
32
+ *
33
+ * // Running the below through the Node.js debugger makes the actor resolve the provided values
34
+ * // and return them to the debugger function, where you can investigate their contents,
35
+ * // or inspect any Errors the evaluation has resulted with.
36
+ * await actorCalled('Debbie').attemptsTo(
37
+ * Navigate.to('http://example.org'),
38
+ * Debug.values(Page.current().title(), Page.current().url()), // accepts multiple values
39
+ * );
40
+ *
41
+ * @extends {Interaction}
42
+ */
43
+ export class Debug<Values extends Array<Answerable<unknown>>> extends Interaction {
44
+
45
+ /**
46
+ * @desc
47
+ * Invokes a debugger function that sets a breakpoint.
48
+ *
49
+ * To use this interaction, run your test scenario in the Node.js debugger.
50
+ *
51
+ * @returns {Interaction}
52
+ */
53
+ static setBreakpoint(): Interaction {
54
+ /* istanbul ignore next can't test using a debugger in an automated test */
55
+ return new Debug<Array<Answerable<any>>>(
56
+ `#actor sets a breakpoint`,
57
+ breakpoint,
58
+ []
59
+ );
60
+ }
61
+
62
+ /**
63
+ * @desc
64
+ * Instructs the Actor to evaluate the provided `values`,
65
+ * log the results, and then pass them to a debugger function.
66
+ *
67
+ * To use this interaction, run your test scenario in the Node.js debugger.
68
+ *
69
+ * @param {...items: Array<Answerable<any>>} values
70
+ * The values to be debugged
71
+ *
72
+ * @returns {Interaction}
73
+ */
74
+ static values(...values: Array<Answerable<any>>): Interaction {
75
+ /* istanbul ignore next can't test using a debugger in an automated test */
76
+ return new Debug<Array<Answerable<any>>>(
77
+ `#actor debugs ${ values.length } values`,
78
+ viewer,
79
+ values
80
+ );
81
+ }
82
+
83
+ /**
84
+ * @param {string} description
85
+ * Description of this interaction
86
+ * @param debuggerFunction
87
+ * Callback function to receive the results of debugging
88
+ * @param {Array<Answerable<any>>} values
89
+ * Values to be evaluated by the actor, and provided to debuggerFunction
90
+ */
91
+ constructor(
92
+ private readonly description: string,
93
+ private readonly debuggerFunction: (args: { [ Index in keyof Values ]: DebuggingResult<Answered<Values[Index]>> }) => void,
94
+ private readonly values: Values,
95
+ ) {
96
+ super();
97
+ }
98
+
99
+ /**
100
+ * @desc
101
+ * Makes the provided {@link Actor}
102
+ * perform this {@link Interaction}.
103
+ *
104
+ * @param {UsesAbilities & AnswersQuestions & CollectsArtifacts} actor
105
+ * @returns {Promise<void>}
106
+ *
107
+ * @see {@link Actor}
108
+ * @see {@link UsesAbilities}
109
+ * @see {@link AnswersQuestions}
110
+ * @see {@link CollectsArtifacts}
111
+ */
112
+ async performAs(actor: UsesAbilities & AnswersQuestions & CollectsArtifacts): Promise<void> {
113
+ const results = [] as { [ Index in keyof Values ]: DebuggingResult<Answered<Values[Index]>> };
114
+
115
+ for (const value of this.values) {
116
+
117
+ const result: DebuggingResult<unknown> = {
118
+ description: d`${ value }`,
119
+ value: undefined,
120
+ error: undefined,
121
+ }
122
+
123
+ try {
124
+ result.value = await actor.answer(value);
125
+ }
126
+ catch(error) {
127
+ result.error = error;
128
+ }
129
+
130
+ actor.collect(
131
+ LogEntry.fromJSON({
132
+ data: JSON.stringify({
133
+ value: inspected(result.value),
134
+ error: result.error ? ErrorSerialiser.serialise(result.error) : result.error
135
+ }),
136
+ }),
137
+ new Name(result.description)
138
+ );
139
+
140
+ results.push(result)
141
+ }
142
+
143
+ this.debuggerFunction(results);
144
+ }
145
+
146
+ /**
147
+ * @desc
148
+ * Generates a description to be used when reporting this {@link Activity}.
149
+ *
150
+ * @returns {string}
151
+ */
152
+ toString(): string {
153
+ return this.description;
154
+ }
155
+ }
@@ -0,0 +1,5 @@
1
+ export interface DebuggingResult<T> {
2
+ description: string;
3
+ value: T | undefined;
4
+ error: Error | undefined;
5
+ }
@@ -0,0 +1,4 @@
1
+ /* istanbul ignore next */
2
+ export function breakpoint(): void {
3
+ debugger; // eslint-disable-line no-debugger
4
+ }
@@ -0,0 +1 @@
1
+ export * from './Debug';
@@ -0,0 +1,18 @@
1
+ import { Answerable } from '../../Answerable';
2
+ import { Answered } from '../../Answered';
3
+ import { DebuggingResult } from './DebuggingResult';
4
+
5
+ /* istanbul ignore next */
6
+ export function viewer<Values extends Array<Answerable<unknown>>>(results: { [ Index in keyof Values ]: DebuggingResult<Answered<Values[Index]>> }): void {
7
+ /**
8
+ * Use your debugger to inspect the `results` array.
9
+ * Note that every entry in `results` contains:
10
+ * - description - a string description produced by invoking d`${ value }` on the original value
11
+ * - value - the result of invoking `await actor.answer(value)` on the original value
12
+ * - error - `Error`, if thrown when invoking `await actor.answer(value)` on the original value
13
+ *
14
+ * @see {d}
15
+ * @see {Actor#answer}
16
+ */
17
+ debugger; // eslint-disable-line no-debugger
18
+ }
@@ -1,3 +1,4 @@
1
+ export * from './debug';
1
2
  export * from './Log';
2
3
  export * from './Wait';
3
4
  export * from './WaitBuilder';