@serenity-js/web 3.13.2 → 3.14.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.
Files changed (83) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/lib/screenplay/abilities/BrowseTheWeb.js +1 -0
  3. package/lib/screenplay/abilities/BrowseTheWeb.js.map +1 -1
  4. package/lib/screenplay/interactions/Clear.js +1 -0
  5. package/lib/screenplay/interactions/Clear.js.map +1 -1
  6. package/lib/screenplay/interactions/Click.js +1 -0
  7. package/lib/screenplay/interactions/Click.js.map +1 -1
  8. package/lib/screenplay/interactions/DoubleClick.js +1 -0
  9. package/lib/screenplay/interactions/DoubleClick.js.map +1 -1
  10. package/lib/screenplay/interactions/Enter.js +2 -0
  11. package/lib/screenplay/interactions/Enter.js.map +1 -1
  12. package/lib/screenplay/interactions/ExecuteScript.js +3 -0
  13. package/lib/screenplay/interactions/ExecuteScript.js.map +1 -1
  14. package/lib/screenplay/interactions/Hover.js +1 -0
  15. package/lib/screenplay/interactions/Hover.js.map +1 -1
  16. package/lib/screenplay/interactions/Navigate.js +1 -0
  17. package/lib/screenplay/interactions/Navigate.js.map +1 -1
  18. package/lib/screenplay/interactions/Press.js +5 -0
  19. package/lib/screenplay/interactions/Press.js.map +1 -1
  20. package/lib/screenplay/interactions/RightClick.js +1 -0
  21. package/lib/screenplay/interactions/RightClick.js.map +1 -1
  22. package/lib/screenplay/interactions/Scroll.js +1 -0
  23. package/lib/screenplay/interactions/Scroll.js.map +1 -1
  24. package/lib/screenplay/interactions/Switch.js +3 -0
  25. package/lib/screenplay/interactions/Switch.js.map +1 -1
  26. package/lib/screenplay/interactions/TakeScreenshot.js +1 -0
  27. package/lib/screenplay/interactions/TakeScreenshot.js.map +1 -1
  28. package/lib/screenplay/models/BrowsingSession.js +2 -3
  29. package/lib/screenplay/models/BrowsingSession.js.map +1 -1
  30. package/lib/screenplay/models/Cookie.js +2 -0
  31. package/lib/screenplay/models/Cookie.js.map +1 -1
  32. package/lib/screenplay/models/Key.js +55 -52
  33. package/lib/screenplay/models/Key.js.map +1 -1
  34. package/lib/screenplay/models/Locator.js +6 -6
  35. package/lib/screenplay/models/Locator.js.map +1 -1
  36. package/lib/screenplay/models/Page.js +4 -0
  37. package/lib/screenplay/models/Page.js.map +1 -1
  38. package/lib/screenplay/models/PageElement.js +1 -0
  39. package/lib/screenplay/models/PageElement.js.map +1 -1
  40. package/lib/screenplay/models/PageElementsLocator.js +2 -0
  41. package/lib/screenplay/models/PageElementsLocator.js.map +1 -1
  42. package/lib/screenplay/models/RootLocator.js +1 -5
  43. package/lib/screenplay/models/RootLocator.js.map +1 -1
  44. package/lib/screenplay/models/SelectOption.js +4 -0
  45. package/lib/screenplay/models/SelectOption.js.map +1 -1
  46. package/lib/screenplay/models/dialogs/AcceptedModalDialog.js +1 -0
  47. package/lib/screenplay/models/dialogs/AcceptedModalDialog.js.map +1 -1
  48. package/lib/screenplay/models/dialogs/DismissedModalDialog.js +1 -0
  49. package/lib/screenplay/models/dialogs/DismissedModalDialog.js.map +1 -1
  50. package/lib/screenplay/models/dialogs/ModalDialogHandler.js +1 -0
  51. package/lib/screenplay/models/dialogs/ModalDialogHandler.js.map +1 -1
  52. package/lib/screenplay/models/selectors/ByCss.js +1 -0
  53. package/lib/screenplay/models/selectors/ByCss.js.map +1 -1
  54. package/lib/screenplay/models/selectors/ByCssContainingText.js +2 -0
  55. package/lib/screenplay/models/selectors/ByCssContainingText.js.map +1 -1
  56. package/lib/screenplay/models/selectors/ByDeepCss.js +1 -0
  57. package/lib/screenplay/models/selectors/ByDeepCss.js.map +1 -1
  58. package/lib/screenplay/models/selectors/ById.js +1 -0
  59. package/lib/screenplay/models/selectors/ById.js.map +1 -1
  60. package/lib/screenplay/models/selectors/ByTagName.js +1 -0
  61. package/lib/screenplay/models/selectors/ByTagName.js.map +1 -1
  62. package/lib/screenplay/models/selectors/ByXPath.js +1 -0
  63. package/lib/screenplay/models/selectors/ByXPath.js.map +1 -1
  64. package/lib/screenplay/questions/Attribute.d.ts +9 -9
  65. package/lib/screenplay/questions/Attribute.d.ts.map +1 -1
  66. package/lib/screenplay/questions/Attribute.js +10 -7
  67. package/lib/screenplay/questions/Attribute.js.map +1 -1
  68. package/lib/screenplay/questions/ComputedStyle.d.ts +140 -0
  69. package/lib/screenplay/questions/ComputedStyle.d.ts.map +1 -0
  70. package/lib/screenplay/questions/ComputedStyle.js +176 -0
  71. package/lib/screenplay/questions/ComputedStyle.js.map +1 -0
  72. package/lib/screenplay/questions/index.d.ts +1 -0
  73. package/lib/screenplay/questions/index.d.ts.map +1 -1
  74. package/lib/screenplay/questions/index.js +1 -0
  75. package/lib/screenplay/questions/index.js.map +1 -1
  76. package/lib/stage/crew/photographer/Photographer.js +4 -2
  77. package/lib/stage/crew/photographer/Photographer.js.map +1 -1
  78. package/package.json +6 -6
  79. package/src/screenplay/questions/Attribute.ts +11 -11
  80. package/src/screenplay/questions/ComputedStyle.ts +206 -0
  81. package/src/screenplay/questions/index.ts +1 -0
  82. package/src/stage/crew/photographer/Photographer.ts +2 -2
  83. package/tsconfig.build.json +1 -1
@@ -0,0 +1,176 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ComputedStyle = void 0;
4
+ const core_1 = require("@serenity-js/core");
5
+ const abilities_1 = require("../abilities");
6
+ const models_1 = require("../models");
7
+ /**
8
+ * Uses the {@apilink Actor|actor's} {@apilink Ability|ability} to {@apilink BrowseTheWeb} to retrieve
9
+ * the value of the specified computed style property of a given {@apilink PageElement}.
10
+ *
11
+ * ## Example widget
12
+ *
13
+ * ```html
14
+ * <ul id="shopping-list" style="display: block">
15
+ * <li style="display: block">Coffee<li>
16
+ * <li style="display: none">Honey<li>
17
+ * <li style="display: block">Chocolate<li>
18
+ * </ul>
19
+ * ```
20
+ *
21
+ * ## Retrieve a computed style property of a given {@apilink PageElement}
22
+ *
23
+ * ```ts
24
+ * import { actorCalled } from '@serenity-js/core'
25
+ * import { Ensure, equals } from '@serenity-js/assertions'
26
+ * import { ComputedStyle, By, PageElement } from '@serenity-js/web'
27
+ *
28
+ * const shoppingList = () =>
29
+ * PageElement.located(By.id('shopping-list'))
30
+ * .describedAs('shopping list')
31
+ *
32
+ * await actorCalled('Lisa').attemptsTo(
33
+ * Ensure.that(
34
+ * ComputedStyle.called('display').of(shoppingList()),
35
+ * equals('block')
36
+ * ),
37
+ * )
38
+ * ```
39
+ *
40
+ * ## Using `ComputedStyle` as {@apilink QuestionAdapter}
41
+ *
42
+ * ```ts
43
+ * import { actorCalled } from '@serenity-js/core'
44
+ * import { Ensure, equals } from '@serenity-js/assertions'
45
+ * import { Attribute, By, PageElement } from '@serenity-js/web'
46
+ *
47
+ * const shoppingList = () =>
48
+ * PageElement.located(By.css('#shopping-list'))
49
+ * .describedAs('shopping list')
50
+ *
51
+ * await actorCalled('Lisa').attemptsTo(
52
+ * Ensure.that(
53
+ * ComputedStyle.called('display').of(shoppingList()).toLocaleUpperCase(),
54
+ * equals('BLOCK')
55
+ * ),
56
+ * )
57
+ * ```
58
+ *
59
+ * ## Using as filter in {@apilink PageElements|Page Element Query Language}
60
+ *
61
+ * ```ts
62
+ * import { actorCalled } from '@serenity-js/core'
63
+ * import { Ensure, includes } from '@serenity-js/assertions'
64
+ * import { Attribute, By, PageElements } from '@serenity-js/web'
65
+ *
66
+ * class ShoppingList {
67
+ * static items = () =>
68
+ * PageElements.located(By.css('#shopping-list li'))
69
+ * .describedAs('items')
70
+ *
71
+ * static outstandingItems = () =>
72
+ * ShoppingList.items()
73
+ * .where(
74
+ * ComputedStyle.called('display'),
75
+ * equals('block')
76
+ * )
77
+ * }
78
+ *
79
+ * await actorCalled('Lisa')
80
+ * .whoCan(BrowseTheWebWithWebdriverIO.using(browser))
81
+ * .attemptsTo(
82
+ * Ensure.that(
83
+ * Text.ofAll(ShoppingList.outstandingItems()),
84
+ * equals([ 'Honey', 'Chocolate' ])
85
+ * ),
86
+ * )
87
+ * ```
88
+ *
89
+ * ## Learn more
90
+ * - {@apilink BrowseTheWeb}
91
+ * - {@apilink MetaQuestion}
92
+ * - {@apilink QuestionAdapter}
93
+ * - {@apilink Question}
94
+ *
95
+ * @group Questions
96
+ */
97
+ class ComputedStyle extends core_1.Question {
98
+ name;
99
+ element;
100
+ pseudoElement;
101
+ subject;
102
+ /**
103
+ * Instantiates a {@apilink Question} that uses
104
+ * the {@apilink Actor|actor's} {@apilink Ability|ability} to {@apilink BrowseTheWeb} to retrieve
105
+ * the value of the specified computed style property of a given {@apilink PageElement}.
106
+ *
107
+ * @param name
108
+ * The name of the computed style property to retrieve
109
+ */
110
+ static called(name) {
111
+ return new ComputedStyle(name);
112
+ }
113
+ constructor(name, element, pseudoElement) {
114
+ super();
115
+ this.name = name;
116
+ this.element = element;
117
+ this.pseudoElement = pseudoElement;
118
+ this.subject = [
119
+ (0, core_1.d) `computed style property ${name}`,
120
+ pseudoElement && (0, core_1.d) `of pseudo-element ${pseudoElement}`,
121
+ element && (0, core_1.d) `of ${element}`,
122
+ ].filter(Boolean).join(' ');
123
+ }
124
+ /**
125
+ * Instantiates a {@apilink Question} that uses
126
+ * the {@apilink Actor|actor's} {@apilink Ability|ability} to {@apilink BrowseTheWeb} to retrieve
127
+ * the value of the specified computed style property of the specified pseudo-element of a given {@apilink PageElement}.
128
+ *
129
+ * @param pseudoElement
130
+ * The pseudo-element to retrieve the computed style property from, such as `::before` or `::after`
131
+ */
132
+ ofPseudoElement(pseudoElement) {
133
+ return core_1.Question.createAdapter(new ComputedStyle(this.name, this.element, pseudoElement));
134
+ }
135
+ /**
136
+ * Resolves to the value of a computed style property of the `pageElement`.
137
+ *
138
+ * #### Learn more
139
+ * - {@apilink MetaQuestion}
140
+ *
141
+ * @param pageElement
142
+ */
143
+ of(pageElement) {
144
+ return core_1.Question.createAdapter(new ComputedStyle(this.name, this.element
145
+ ? models_1.PageElement.of(this.element, pageElement)
146
+ : pageElement, this.pseudoElement));
147
+ }
148
+ /**
149
+ * @inheritDoc
150
+ */
151
+ async answeredBy(actor) {
152
+ const name = await actor.answer(this.name);
153
+ if (!this.element) {
154
+ throw new core_1.LogicError((0, core_1.d) `Couldn't read computed style property ${name} of an unspecified page element`);
155
+ }
156
+ const element = await actor.answer(this.element);
157
+ const pseudoElement = await actor.answer(this.pseudoElement);
158
+ const page = await abilities_1.BrowseTheWeb.as(actor).currentPage();
159
+ return page.executeScript('return window.getComputedStyle(arguments[0], arguments[1]).getPropertyValue(arguments[2])', element, pseudoElement, name);
160
+ }
161
+ /**
162
+ * @inheritDoc
163
+ */
164
+ describedAs(subject) {
165
+ this.subject = subject;
166
+ return this;
167
+ }
168
+ /**
169
+ * @inheritDoc
170
+ */
171
+ toString() {
172
+ return this.subject;
173
+ }
174
+ }
175
+ exports.ComputedStyle = ComputedStyle;
176
+ //# sourceMappingURL=ComputedStyle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ComputedStyle.js","sourceRoot":"","sources":["../../../src/screenplay/questions/ComputedStyle.ts"],"names":[],"mappings":";;;AAQA,4CAA4D;AAE5D,4CAA4C;AAC5C,sCAAwC;AAExC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyFG;AACH,MAAa,aACT,SAAQ,eAAyB;IAkBZ;IACA;IACA;IAjBb,OAAO,CAAS;IAExB;;;;;;;OAOG;IACH,MAAM,CAAC,MAAM,CAAY,IAAwB;QAC7C,OAAO,IAAI,aAAa,CAAM,IAAI,CAAC,CAAC;IACxC,CAAC;IAED,YACqB,IAAwB,EACxB,OAA8F,EAC9F,aAAkC;QAEnD,KAAK,EAAE,CAAC;QAJS,SAAI,GAAJ,IAAI,CAAoB;QACxB,YAAO,GAAP,OAAO,CAAuF;QAC9F,kBAAa,GAAb,aAAa,CAAqB;QAInD,IAAI,CAAC,OAAO,GAAG;YACX,IAAA,QAAC,EAAA,2BAA4B,IAAK,EAAE;YACpC,aAAa,IAAI,IAAA,QAAC,EAAA,qBAAsB,aAAc,EAAE;YACxD,OAAO,IAAI,IAAA,QAAC,EAAA,MAAO,OAAQ,EAAE;SAChC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAChC,CAAC;IAED;;;;;;;OAOG;IACH,eAAe,CAAC,aAAiC;QAC7C,OAAO,eAAQ,CAAC,aAAa,CACzB,IAAI,aAAa,CACb,IAAI,CAAC,IAAI,EACT,IAAI,CAAC,OAAO,EACZ,aAAa,CAChB,CAC6D,CAAC;IACvE,CAAC;IAED;;;;;;;OAOG;IACH,EAAE,CAAC,WAAiG;QAChG,OAAO,eAAQ,CAAC,aAAa,CACzB,IAAI,aAAa,CACb,IAAI,CAAC,IAAI,EACT,IAAI,CAAC,OAAO;YACR,CAAC,CAAC,oBAAW,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC;YAC3C,CAAC,CAAC,WAAW,EACjB,IAAI,CAAC,aAAa,CACrB,CAC6D,CAAC;IACvE,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,UAAU,CAAC,KAAuC;QACpD,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAE3C,IAAI,CAAE,IAAI,CAAC,OAAO,EAAE;YAChB,MAAM,IAAI,iBAAU,CAAC,IAAA,QAAC,EAAA,yCAA0C,IAAK,iCAAiC,CAAC,CAAC;SAC3G;QAED,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACjD,MAAM,aAAa,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAE7D,MAAM,IAAI,GAAG,MAAM,wBAAY,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC;QAExD,OAAO,IAAI,CAAC,aAAa,CAAC,2FAA2F,EAAE,OAAO,EAAE,aAAa,EAAE,IAAI,CAAC,CAAC;IACzJ,CAAC;IAED;;OAEG;IACH,WAAW,CAAC,OAAe;QACvB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,OAAO,IAAI,CAAC;IAChB,CAAC;IAED;;OAEG;IACH,QAAQ;QACJ,OAAO,IAAI,CAAC,OAAO,CAAC;IACxB,CAAC;CACJ;AAtGD,sCAsGC"}
@@ -1,4 +1,5 @@
1
1
  export * from './Attribute';
2
+ export * from './ComputedStyle';
2
3
  export * from './CssClasses';
3
4
  export * from './LastScriptExecution';
4
5
  export * from './Selected';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/screenplay/questions/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,uBAAuB,CAAC;AACtC,cAAc,YAAY,CAAC;AAC3B,cAAc,QAAQ,CAAC;AACvB,cAAc,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/screenplay/questions/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,uBAAuB,CAAC;AACtC,cAAc,YAAY,CAAC;AAC3B,cAAc,QAAQ,CAAC;AACvB,cAAc,SAAS,CAAC"}
@@ -15,6 +15,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./Attribute"), exports);
18
+ __exportStar(require("./ComputedStyle"), exports);
18
19
  __exportStar(require("./CssClasses"), exports);
19
20
  __exportStar(require("./LastScriptExecution"), exports);
20
21
  __exportStar(require("./Selected"), exports);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/screenplay/questions/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,8CAA4B;AAC5B,+CAA6B;AAC7B,wDAAsC;AACtC,6CAA2B;AAC3B,yCAAuB;AACvB,0CAAwB"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/screenplay/questions/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,8CAA4B;AAC5B,kDAAgC;AAChC,+CAA6B;AAC7B,wDAAsC;AACtC,6CAA2B;AAC3B,yCAAuB;AACvB,0CAAwB"}
@@ -175,6 +175,8 @@ const strategies = __importStar(require("./strategies"));
175
175
  * @group Stage
176
176
  */
177
177
  class Photographer {
178
+ photoTakingStrategy;
179
+ stage;
178
180
  /**
179
181
  * Instantiates a new {@apilink Photographer} configured to take photos (screenshots)
180
182
  * as per the specified {@apilink PhotoTakingStrategy}.
@@ -197,8 +199,8 @@ class Photographer {
197
199
  if (availableStrategies.includes(config.strategy)) {
198
200
  return new Photographer(new strategies[config.strategy]());
199
201
  }
200
- throw new core_1.ConfigurationError(`'${config.strategy}' is not an available PhotoTakingStrategy. ` +
201
- `Available strategies: ${availableStrategies.join(', ')}.`);
202
+ throw new core_1.ConfigurationError(`'${config.strategy}' is not an available PhotoTakingStrategy, ` +
203
+ `available strategies: ${availableStrategies.join(', ')}.`);
202
204
  }
203
205
  return new Photographer(new strategies.TakePhotosOfFailures());
204
206
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Photographer.js","sourceRoot":"","sources":["../../../../src/stage/crew/photographer/Photographer.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,4CAAmE;AAEnE,yDAAgF;AAGhF,yDAA2C;AAE3C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkJG;AACH,MAAa,YAAY;IAErB;;;;;;OAMG;IACH,MAAM,CAAC,OAAO,CAAC,QAAkD;QAC7D,OAAO,IAAI,YAAY,CAAC,IAAI,QAAQ,EAAE,CAAC,CAAC;IAC5C,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,QAAQ,CAAC,MAA4E;QACxF,IAAI,MAAM,IAAI,MAAM,CAAC,QAAQ,EAAE;YAC3B,MAAM,mBAAmB,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,KAAK,UAAU,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAA,CAAI,yBAAyB;YAErJ,IAAI,mBAAmB,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAkB,CAAC,EAAE;gBACzD,OAAO,IAAI,YAAY,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,QAAkB,CAAC,EAAE,CAAC,CAAC;aACxE;YAED,MAAM,IAAI,yBAAkB,CACxB,IAAK,MAAM,CAAC,QAAS,6CAA6C;gBAClE,yBAA0B,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAE,GAAG,CAC/D,CAAC;SACL;QAED,OAAO,IAAI,YAAY,CAAC,IAAI,UAAU,CAAC,oBAAoB,EAAE,CAAC,CAAC;IACnE,CAAC;IAED,YACqB,mBAAmD,EAC5D,KAAa;QADJ,wBAAmB,GAAnB,mBAAmB,CAAgC;QAC5D,UAAK,GAAL,KAAK,CAAQ;IAEzB,CAAC;IAED;;;;;OAKG;IACH,UAAU,CAAC,KAAY;QACnB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,OAAO,IAAI,CAAC;IAChB,CAAC;IAED;;;;;OAKG;IACH,QAAQ,CAAC,KAAkB;QACvB,IAAI,CAAE,IAAI,CAAC,KAAK,EAAE;YACd,MAAM,IAAI,iBAAU,CAAC,8FAA8F,CAAC,CAAC;SACxH;QAED,IAAI,CAAE,IAAI,CAAC,KAAK,CAAC,iBAAiB,EAAE,EAAE;YAClC,OAAO,KAAK,CAAC,CAAC;SACjB;QAED,IAAI,KAAK,YAAY,uBAAc,IAAI,KAAK,YAAY,yBAAgB,EAAE;YACtE,IAAI,CAAC,mBAAmB,CAAC,mBAAmB,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;SACnE;IACL,CAAC;CACJ;AAxED,oCAwEC"}
1
+ {"version":3,"file":"Photographer.js","sourceRoot":"","sources":["../../../../src/stage/crew/photographer/Photographer.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,4CAAmE;AAEnE,yDAAgF;AAGhF,yDAA2C;AAE3C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkJG;AACH,MAAa,YAAY;IAqCA;IACT;IApCZ;;;;;;OAMG;IACH,MAAM,CAAC,OAAO,CAAC,QAAkD;QAC7D,OAAO,IAAI,YAAY,CAAC,IAAI,QAAQ,EAAE,CAAC,CAAC;IAC5C,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,QAAQ,CAAC,MAA4E;QACxF,IAAI,MAAM,IAAI,MAAM,CAAC,QAAQ,EAAE;YAC3B,MAAM,mBAAmB,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,KAAK,UAAU,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAA,CAAI,yBAAyB;YAErJ,IAAI,mBAAmB,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAkB,CAAC,EAAE;gBACzD,OAAO,IAAI,YAAY,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,QAAkB,CAAC,EAAE,CAAC,CAAC;aACxE;YAED,MAAM,IAAI,yBAAkB,CACxB,IAAK,MAAM,CAAC,QAAS,6CAA6C;gBAClE,yBAA0B,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAE,GAAG,CAC/D,CAAC;SACL;QAED,OAAO,IAAI,YAAY,CAAC,IAAI,UAAU,CAAC,oBAAoB,EAAE,CAAC,CAAC;IACnE,CAAC;IAED,YACqB,mBAAmD,EAC5D,KAAa;QADJ,wBAAmB,GAAnB,mBAAmB,CAAgC;QAC5D,UAAK,GAAL,KAAK,CAAQ;IAEzB,CAAC;IAED;;;;;OAKG;IACH,UAAU,CAAC,KAAY;QACnB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,OAAO,IAAI,CAAC;IAChB,CAAC;IAED;;;;;OAKG;IACH,QAAQ,CAAC,KAAkB;QACvB,IAAI,CAAE,IAAI,CAAC,KAAK,EAAE;YACd,MAAM,IAAI,iBAAU,CAAC,8FAA8F,CAAC,CAAC;SACxH;QAED,IAAI,CAAE,IAAI,CAAC,KAAK,CAAC,iBAAiB,EAAE,EAAE;YAClC,OAAO,KAAK,CAAC,CAAC;SACjB;QAED,IAAI,KAAK,YAAY,uBAAc,IAAI,KAAK,YAAY,yBAAgB,EAAE;YACtE,IAAI,CAAC,mBAAmB,CAAC,mBAAmB,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;SACnE;IACL,CAAC;CACJ;AAxED,oCAwEC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@serenity-js/web",
3
- "version": "3.13.2",
3
+ "version": "3.14.0",
4
4
  "description": "Serenity/JS Screenplay Pattern APIs for the Web",
5
5
  "author": {
6
6
  "name": "Jan Molak",
@@ -44,19 +44,19 @@
44
44
  "node": "^16.13 || ^18.12 || ^20"
45
45
  },
46
46
  "dependencies": {
47
- "@serenity-js/assertions": "3.13.2",
48
- "@serenity-js/core": "3.13.2",
47
+ "@serenity-js/assertions": "3.14.0",
48
+ "@serenity-js/core": "3.14.0",
49
49
  "tiny-types": "^1.21.0"
50
50
  },
51
51
  "devDependencies": {
52
52
  "@integration/testing-tools": "3.0.0",
53
- "@types/chai": "^4.3.10",
54
- "@types/mocha": "^10.0.4",
53
+ "@types/chai": "^4.3.11",
54
+ "@types/mocha": "^10.0.6",
55
55
  "c8": "8.0.1",
56
56
  "mocha": "^10.2.0",
57
57
  "mocha-multi": "^1.1.7",
58
58
  "ts-node": "^10.9.1",
59
59
  "typescript": "5.1.6"
60
60
  },
61
- "gitHead": "ed08db56c2c947c2c2ac4d9d4e95f9f68e90d2a4"
61
+ "gitHead": "a81b85d03b62c662c00aecebc75ed35a97815a6b"
62
62
  }
@@ -20,13 +20,13 @@ import { PageElement } from '../models';
20
20
  * ## Retrieve an HTML attribute of a given {@apilink PageElement}
21
21
  *
22
22
  * ```ts
23
- * import { actorCalled } from '@serenity-js/core'
24
- * import { Ensure, equals } from '@serenity-js/assertions'
25
- * import { Attribute, By, PageElement } from '@serenity-js/web'
23
+ * import { actorCalled } from '@serenity-js/core'
24
+ * import { Ensure, equals } from '@serenity-js/assertions'
25
+ * import { Attribute, By, PageElement } from '@serenity-js/web'
26
26
  *
27
- * const shoppingList = () =>
28
- * PageElement.located(By.id('shopping-list'))
29
- * .describedAs('shopping list')
27
+ * const shoppingList = () =>
28
+ * PageElement.located(By.id('shopping-list'))
29
+ * .describedAs('shopping list')
30
30
  *
31
31
  * await actorCalled('Lisa')
32
32
  * .attemptsTo(
@@ -95,9 +95,9 @@ import { PageElement } from '../models';
95
95
  *
96
96
  * @group Questions
97
97
  */
98
- export class Attribute
98
+ export class Attribute<Native_Element_Type>
99
99
  extends Question<Promise<string>>
100
- implements MetaQuestion<PageElement, Question<Promise<string>>>
100
+ implements MetaQuestion<PageElement<Native_Element_Type>, Question<Promise<string>>>
101
101
  {
102
102
  private subject: string;
103
103
 
@@ -109,7 +109,7 @@ export class Attribute
109
109
  * @param name
110
110
  * The name of the attribute to retrieve
111
111
  */
112
- static called(name: Answerable<string>): Attribute {
112
+ static called<NET = any>(name: Answerable<string>): Attribute<NET> {
113
113
  return new Attribute(name);
114
114
  }
115
115
 
@@ -131,7 +131,7 @@ export class Attribute
131
131
  *
132
132
  * @param pageElement
133
133
  */
134
- of(pageElement: QuestionAdapter<PageElement> | PageElement): MetaQuestionAdapter<PageElement, string> {
134
+ of(pageElement: QuestionAdapter<PageElement<Native_Element_Type>> | PageElement<Native_Element_Type>): MetaQuestionAdapter<PageElement<Native_Element_Type>, string> {
135
135
  return Question.createAdapter(
136
136
  new Attribute(
137
137
  this.name,
@@ -149,7 +149,7 @@ export class Attribute
149
149
  const name = await actor.answer(this.name);
150
150
 
151
151
  if (! this.element) {
152
- throw new LogicError(d`Couldn't read attribute ${ name } of an unspecified page element.`);
152
+ throw new LogicError(d`Couldn't read attribute ${ name } of an unspecified page element`);
153
153
  }
154
154
 
155
155
  const element = await actor.answer(this.element);
@@ -0,0 +1,206 @@
1
+ import type {
2
+ Answerable,
3
+ AnswersQuestions,
4
+ MetaQuestion,
5
+ MetaQuestionAdapter,
6
+ QuestionAdapter,
7
+ UsesAbilities
8
+ } from '@serenity-js/core';
9
+ import { d, LogicError, Question } from '@serenity-js/core';
10
+
11
+ import { BrowseTheWeb } from '../abilities';
12
+ import { PageElement } from '../models';
13
+
14
+ /**
15
+ * Uses the {@apilink Actor|actor's} {@apilink Ability|ability} to {@apilink BrowseTheWeb} to retrieve
16
+ * the value of the specified computed style property of a given {@apilink PageElement}.
17
+ *
18
+ * ## Example widget
19
+ *
20
+ * ```html
21
+ * <ul id="shopping-list" style="display: block">
22
+ * <li style="display: block">Coffee<li>
23
+ * <li style="display: none">Honey<li>
24
+ * <li style="display: block">Chocolate<li>
25
+ * </ul>
26
+ * ```
27
+ *
28
+ * ## Retrieve a computed style property of a given {@apilink PageElement}
29
+ *
30
+ * ```ts
31
+ * import { actorCalled } from '@serenity-js/core'
32
+ * import { Ensure, equals } from '@serenity-js/assertions'
33
+ * import { ComputedStyle, By, PageElement } from '@serenity-js/web'
34
+ *
35
+ * const shoppingList = () =>
36
+ * PageElement.located(By.id('shopping-list'))
37
+ * .describedAs('shopping list')
38
+ *
39
+ * await actorCalled('Lisa').attemptsTo(
40
+ * Ensure.that(
41
+ * ComputedStyle.called('display').of(shoppingList()),
42
+ * equals('block')
43
+ * ),
44
+ * )
45
+ * ```
46
+ *
47
+ * ## Using `ComputedStyle` as {@apilink QuestionAdapter}
48
+ *
49
+ * ```ts
50
+ * import { actorCalled } from '@serenity-js/core'
51
+ * import { Ensure, equals } from '@serenity-js/assertions'
52
+ * import { Attribute, By, PageElement } from '@serenity-js/web'
53
+ *
54
+ * const shoppingList = () =>
55
+ * PageElement.located(By.css('#shopping-list'))
56
+ * .describedAs('shopping list')
57
+ *
58
+ * await actorCalled('Lisa').attemptsTo(
59
+ * Ensure.that(
60
+ * ComputedStyle.called('display').of(shoppingList()).toLocaleUpperCase(),
61
+ * equals('BLOCK')
62
+ * ),
63
+ * )
64
+ * ```
65
+ *
66
+ * ## Using as filter in {@apilink PageElements|Page Element Query Language}
67
+ *
68
+ * ```ts
69
+ * import { actorCalled } from '@serenity-js/core'
70
+ * import { Ensure, includes } from '@serenity-js/assertions'
71
+ * import { Attribute, By, PageElements } from '@serenity-js/web'
72
+ *
73
+ * class ShoppingList {
74
+ * static items = () =>
75
+ * PageElements.located(By.css('#shopping-list li'))
76
+ * .describedAs('items')
77
+ *
78
+ * static outstandingItems = () =>
79
+ * ShoppingList.items()
80
+ * .where(
81
+ * ComputedStyle.called('display'),
82
+ * equals('block')
83
+ * )
84
+ * }
85
+ *
86
+ * await actorCalled('Lisa')
87
+ * .whoCan(BrowseTheWebWithWebdriverIO.using(browser))
88
+ * .attemptsTo(
89
+ * Ensure.that(
90
+ * Text.ofAll(ShoppingList.outstandingItems()),
91
+ * equals([ 'Honey', 'Chocolate' ])
92
+ * ),
93
+ * )
94
+ * ```
95
+ *
96
+ * ## Learn more
97
+ * - {@apilink BrowseTheWeb}
98
+ * - {@apilink MetaQuestion}
99
+ * - {@apilink QuestionAdapter}
100
+ * - {@apilink Question}
101
+ *
102
+ * @group Questions
103
+ */
104
+ export class ComputedStyle<Native_Element_Type>
105
+ extends Question<Promise<string>>
106
+ implements MetaQuestion<PageElement<Native_Element_Type>, Question<Promise<string>>>
107
+ {
108
+ private subject: string;
109
+
110
+ /**
111
+ * Instantiates a {@apilink Question} that uses
112
+ * the {@apilink Actor|actor's} {@apilink Ability|ability} to {@apilink BrowseTheWeb} to retrieve
113
+ * the value of the specified computed style property of a given {@apilink PageElement}.
114
+ *
115
+ * @param name
116
+ * The name of the computed style property to retrieve
117
+ */
118
+ static called<NET = any>(name: Answerable<string>): ComputedStyle<NET> {
119
+ return new ComputedStyle<NET>(name);
120
+ }
121
+
122
+ protected constructor(
123
+ private readonly name: Answerable<string>,
124
+ private readonly element?: QuestionAdapter<PageElement<Native_Element_Type>> | PageElement<Native_Element_Type>,
125
+ private readonly pseudoElement?: Answerable<string>,
126
+ ) {
127
+ super();
128
+
129
+ this.subject = [
130
+ d`computed style property ${ name }`,
131
+ pseudoElement && d`of pseudo-element ${ pseudoElement }`,
132
+ element && d`of ${ element }`,
133
+ ].filter(Boolean).join(' ');
134
+ }
135
+
136
+ /**
137
+ * Instantiates a {@apilink Question} that uses
138
+ * the {@apilink Actor|actor's} {@apilink Ability|ability} to {@apilink BrowseTheWeb} to retrieve
139
+ * the value of the specified computed style property of the specified pseudo-element of a given {@apilink PageElement}.
140
+ *
141
+ * @param pseudoElement
142
+ * The pseudo-element to retrieve the computed style property from, such as `::before` or `::after`
143
+ */
144
+ ofPseudoElement(pseudoElement: Answerable<string>): MetaQuestionAdapter<PageElement<Native_Element_Type>, string> {
145
+ return Question.createAdapter(
146
+ new ComputedStyle<Native_Element_Type>(
147
+ this.name,
148
+ this.element,
149
+ pseudoElement,
150
+ )
151
+ ) as MetaQuestionAdapter<PageElement<Native_Element_Type>, string>;
152
+ }
153
+
154
+ /**
155
+ * Resolves to the value of a computed style property of the `pageElement`.
156
+ *
157
+ * #### Learn more
158
+ * - {@apilink MetaQuestion}
159
+ *
160
+ * @param pageElement
161
+ */
162
+ of(pageElement: QuestionAdapter<PageElement<Native_Element_Type>> | PageElement<Native_Element_Type>): MetaQuestionAdapter<PageElement<Native_Element_Type>, string> {
163
+ return Question.createAdapter(
164
+ new ComputedStyle<Native_Element_Type>(
165
+ this.name,
166
+ this.element
167
+ ? PageElement.of(this.element, pageElement)
168
+ : pageElement,
169
+ this.pseudoElement,
170
+ )
171
+ ) as MetaQuestionAdapter<PageElement<Native_Element_Type>, string>;
172
+ }
173
+
174
+ /**
175
+ * @inheritDoc
176
+ */
177
+ async answeredBy(actor: AnswersQuestions & UsesAbilities): Promise<string> {
178
+ const name = await actor.answer(this.name);
179
+
180
+ if (! this.element) {
181
+ throw new LogicError(d`Couldn't read computed style property ${ name } of an unspecified page element`);
182
+ }
183
+
184
+ const element = await actor.answer(this.element);
185
+ const pseudoElement = await actor.answer(this.pseudoElement);
186
+
187
+ const page = await BrowseTheWeb.as(actor).currentPage();
188
+
189
+ return page.executeScript('return window.getComputedStyle(arguments[0], arguments[1]).getPropertyValue(arguments[2])', element, pseudoElement, name);
190
+ }
191
+
192
+ /**
193
+ * @inheritDoc
194
+ */
195
+ describedAs(subject: string): this {
196
+ this.subject = subject;
197
+ return this;
198
+ }
199
+
200
+ /**
201
+ * @inheritDoc
202
+ */
203
+ toString(): string {
204
+ return this.subject;
205
+ }
206
+ }
@@ -1,4 +1,5 @@
1
1
  export * from './Attribute';
2
+ export * from './ComputedStyle';
2
3
  export * from './CssClasses';
3
4
  export * from './LastScriptExecution';
4
5
  export * from './Selected';
@@ -180,8 +180,8 @@ export class Photographer implements StageCrewMember {
180
180
  }
181
181
 
182
182
  throw new ConfigurationError(
183
- `'${ config.strategy }' is not an available PhotoTakingStrategy. ` +
184
- `Available strategies: ${ availableStrategies.join(', ') }.`
183
+ `'${ config.strategy }' is not an available PhotoTakingStrategy, ` +
184
+ `available strategies: ${ availableStrategies.join(', ') }.`
185
185
  );
186
186
  }
187
187
 
@@ -4,7 +4,7 @@
4
4
  "outDir": "lib",
5
5
  "rootDir": "src",
6
6
  "lib": [
7
- "es2021",
7
+ "es2022",
8
8
  "dom"
9
9
  ]
10
10
  },