@serenity-js/web 3.0.0-rc.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/CHANGELOG.md +50 -0
- package/LICENSE.md +201 -0
- package/NOTICE.md +1 -0
- package/README.md +21 -0
- package/lib/errors/CookieMissingError.d.ts +4 -0
- package/lib/errors/CookieMissingError.js +11 -0
- package/lib/errors/CookieMissingError.js.map +1 -0
- package/lib/errors/index.d.ts +1 -0
- package/lib/errors/index.js +14 -0
- package/lib/errors/index.js.map +1 -0
- package/lib/expectations/ElementExpectation.d.ts +11 -0
- package/lib/expectations/ElementExpectation.js +27 -0
- package/lib/expectations/ElementExpectation.js.map +1 -0
- package/lib/expectations/index.d.ts +6 -0
- package/lib/expectations/index.js +19 -0
- package/lib/expectations/index.js.map +1 -0
- package/lib/expectations/isActive.d.ts +15 -0
- package/lib/expectations/isActive.js +22 -0
- package/lib/expectations/isActive.js.map +1 -0
- package/lib/expectations/isClickable.d.ts +20 -0
- package/lib/expectations/isClickable.js +30 -0
- package/lib/expectations/isClickable.js.map +1 -0
- package/lib/expectations/isEnabled.d.ts +14 -0
- package/lib/expectations/isEnabled.js +20 -0
- package/lib/expectations/isEnabled.js.map +1 -0
- package/lib/expectations/isPresent.d.ts +15 -0
- package/lib/expectations/isPresent.js +22 -0
- package/lib/expectations/isPresent.js.map +1 -0
- package/lib/expectations/isSelected.d.ts +14 -0
- package/lib/expectations/isSelected.js +23 -0
- package/lib/expectations/isSelected.js.map +1 -0
- package/lib/expectations/isVisible.d.ts +14 -0
- package/lib/expectations/isVisible.js +26 -0
- package/lib/expectations/isVisible.js.map +1 -0
- package/lib/index.d.ts +5 -0
- package/lib/index.js +18 -0
- package/lib/index.js.map +1 -0
- package/lib/input/Key.d.ts +73 -0
- package/lib/input/Key.js +84 -0
- package/lib/input/Key.js.map +1 -0
- package/lib/input/index.d.ts +1 -0
- package/lib/input/index.js +14 -0
- package/lib/input/index.js.map +1 -0
- package/lib/screenplay/abilities/BrowseTheWeb.d.ts +58 -0
- package/lib/screenplay/abilities/BrowseTheWeb.js +19 -0
- package/lib/screenplay/abilities/BrowseTheWeb.js.map +1 -0
- package/lib/screenplay/abilities/BrowserCapabilities.d.ts +5 -0
- package/lib/screenplay/abilities/BrowserCapabilities.js +3 -0
- package/lib/screenplay/abilities/BrowserCapabilities.js.map +1 -0
- package/lib/screenplay/abilities/index.d.ts +2 -0
- package/lib/screenplay/abilities/index.js +15 -0
- package/lib/screenplay/abilities/index.js.map +1 -0
- package/lib/screenplay/index.d.ts +4 -0
- package/lib/screenplay/index.js +17 -0
- package/lib/screenplay/index.js.map +1 -0
- package/lib/screenplay/interactions/Clear.d.ts +79 -0
- package/lib/screenplay/interactions/Clear.js +97 -0
- package/lib/screenplay/interactions/Clear.js.map +1 -0
- package/lib/screenplay/interactions/Click.d.ts +73 -0
- package/lib/screenplay/interactions/Click.js +85 -0
- package/lib/screenplay/interactions/Click.js.map +1 -0
- package/lib/screenplay/interactions/DoubleClick.d.ts +90 -0
- package/lib/screenplay/interactions/DoubleClick.js +101 -0
- package/lib/screenplay/interactions/DoubleClick.js.map +1 -0
- package/lib/screenplay/interactions/Enter.d.ts +73 -0
- package/lib/screenplay/interactions/Enter.js +86 -0
- package/lib/screenplay/interactions/Enter.js.map +1 -0
- package/lib/screenplay/interactions/EnterBuilder.d.ts +25 -0
- package/lib/screenplay/interactions/EnterBuilder.js +3 -0
- package/lib/screenplay/interactions/EnterBuilder.js.map +1 -0
- package/lib/screenplay/interactions/ExecuteScript.d.ts +206 -0
- package/lib/screenplay/interactions/ExecuteScript.js +312 -0
- package/lib/screenplay/interactions/ExecuteScript.js.map +1 -0
- package/lib/screenplay/interactions/Hover.d.ts +78 -0
- package/lib/screenplay/interactions/Hover.js +89 -0
- package/lib/screenplay/interactions/Hover.js.map +1 -0
- package/lib/screenplay/interactions/Navigate.d.ts +142 -0
- package/lib/screenplay/interactions/Navigate.js +198 -0
- package/lib/screenplay/interactions/Navigate.js.map +1 -0
- package/lib/screenplay/interactions/PageElementInteraction.d.ts +39 -0
- package/lib/screenplay/interactions/PageElementInteraction.js +54 -0
- package/lib/screenplay/interactions/PageElementInteraction.js.map +1 -0
- package/lib/screenplay/interactions/Press.d.ts +84 -0
- package/lib/screenplay/interactions/Press.js +171 -0
- package/lib/screenplay/interactions/Press.js.map +1 -0
- package/lib/screenplay/interactions/PressBuilder.d.ts +26 -0
- package/lib/screenplay/interactions/PressBuilder.js +3 -0
- package/lib/screenplay/interactions/PressBuilder.js.map +1 -0
- package/lib/screenplay/interactions/RightClick.d.ts +89 -0
- package/lib/screenplay/interactions/RightClick.js +100 -0
- package/lib/screenplay/interactions/RightClick.js.map +1 -0
- package/lib/screenplay/interactions/Scroll.d.ts +83 -0
- package/lib/screenplay/interactions/Scroll.js +97 -0
- package/lib/screenplay/interactions/Scroll.js.map +1 -0
- package/lib/screenplay/interactions/Select.d.ts +212 -0
- package/lib/screenplay/interactions/Select.js +291 -0
- package/lib/screenplay/interactions/Select.js.map +1 -0
- package/lib/screenplay/interactions/SelectBuilder.d.ts +33 -0
- package/lib/screenplay/interactions/SelectBuilder.js +3 -0
- package/lib/screenplay/interactions/SelectBuilder.js.map +1 -0
- package/lib/screenplay/interactions/Switch.d.ts +150 -0
- package/lib/screenplay/interactions/Switch.js +209 -0
- package/lib/screenplay/interactions/Switch.js.map +1 -0
- package/lib/screenplay/interactions/TakeScreenshot.d.ts +67 -0
- package/lib/screenplay/interactions/TakeScreenshot.js +86 -0
- package/lib/screenplay/interactions/TakeScreenshot.js.map +1 -0
- package/lib/screenplay/interactions/Wait.d.ts +143 -0
- package/lib/screenplay/interactions/Wait.js +242 -0
- package/lib/screenplay/interactions/Wait.js.map +1 -0
- package/lib/screenplay/interactions/WaitBuilder.d.ts +32 -0
- package/lib/screenplay/interactions/WaitBuilder.js +3 -0
- package/lib/screenplay/interactions/WaitBuilder.js.map +1 -0
- package/lib/screenplay/interactions/index.d.ts +16 -0
- package/lib/screenplay/interactions/index.js +29 -0
- package/lib/screenplay/interactions/index.js.map +1 -0
- package/lib/screenplay/models/Cookie.d.ts +117 -0
- package/lib/screenplay/models/Cookie.js +176 -0
- package/lib/screenplay/models/Cookie.js.map +1 -0
- package/lib/screenplay/models/CookieData.d.ts +89 -0
- package/lib/screenplay/models/CookieData.js +3 -0
- package/lib/screenplay/models/CookieData.js.map +1 -0
- package/lib/screenplay/models/ModalDialog.d.ts +9 -0
- package/lib/screenplay/models/ModalDialog.js +14 -0
- package/lib/screenplay/models/ModalDialog.js.map +1 -0
- package/lib/screenplay/models/Page.d.ts +83 -0
- package/lib/screenplay/models/Page.js +52 -0
- package/lib/screenplay/models/Page.js.map +1 -0
- package/lib/screenplay/models/PageElement.d.ts +30 -0
- package/lib/screenplay/models/PageElement.js +62 -0
- package/lib/screenplay/models/PageElement.js.map +1 -0
- package/lib/screenplay/models/PageElements.d.ts +20 -0
- package/lib/screenplay/models/PageElements.js +49 -0
- package/lib/screenplay/models/PageElements.js.map +1 -0
- package/lib/screenplay/models/index.d.ts +6 -0
- package/lib/screenplay/models/index.js +19 -0
- package/lib/screenplay/models/index.js.map +1 -0
- package/lib/screenplay/questions/Attribute.d.ts +83 -0
- package/lib/screenplay/questions/Attribute.js +103 -0
- package/lib/screenplay/questions/Attribute.js.map +1 -0
- package/lib/screenplay/questions/CssClasses.d.ts +93 -0
- package/lib/screenplay/questions/CssClasses.js +113 -0
- package/lib/screenplay/questions/CssClasses.js.map +1 -0
- package/lib/screenplay/questions/ElementQuestion.d.ts +34 -0
- package/lib/screenplay/questions/ElementQuestion.js +53 -0
- package/lib/screenplay/questions/ElementQuestion.js.map +1 -0
- package/lib/screenplay/questions/LastScriptExecution.d.ts +14 -0
- package/lib/screenplay/questions/LastScriptExecution.js +22 -0
- package/lib/screenplay/questions/LastScriptExecution.js.map +1 -0
- package/lib/screenplay/questions/Selected.d.ts +185 -0
- package/lib/screenplay/questions/Selected.js +210 -0
- package/lib/screenplay/questions/Selected.js.map +1 -0
- package/lib/screenplay/questions/Text.d.ts +99 -0
- package/lib/screenplay/questions/Text.js +131 -0
- package/lib/screenplay/questions/Text.js.map +1 -0
- package/lib/screenplay/questions/Value.d.ts +64 -0
- package/lib/screenplay/questions/Value.js +78 -0
- package/lib/screenplay/questions/Value.js.map +1 -0
- package/lib/screenplay/questions/index.d.ts +6 -0
- package/lib/screenplay/questions/index.js +19 -0
- package/lib/screenplay/questions/index.js.map +1 -0
- package/lib/stage/crew/index.d.ts +1 -0
- package/lib/stage/crew/index.js +14 -0
- package/lib/stage/crew/index.js.map +1 -0
- package/lib/stage/crew/photographer/Photographer.d.ts +83 -0
- package/lib/stage/crew/photographer/Photographer.js +102 -0
- package/lib/stage/crew/photographer/Photographer.js.map +1 -0
- package/lib/stage/crew/photographer/index.d.ts +2 -0
- package/lib/stage/crew/photographer/index.js +15 -0
- package/lib/stage/crew/photographer/index.js.map +1 -0
- package/lib/stage/crew/photographer/strategies/PhotoTakingStrategy.d.ts +28 -0
- package/lib/stage/crew/photographer/strategies/PhotoTakingStrategy.js +81 -0
- package/lib/stage/crew/photographer/strategies/PhotoTakingStrategy.js.map +1 -0
- package/lib/stage/crew/photographer/strategies/TakePhotosBeforeAndAfterInteractions.d.ts +18 -0
- package/lib/stage/crew/photographer/strategies/TakePhotosBeforeAndAfterInteractions.js +30 -0
- package/lib/stage/crew/photographer/strategies/TakePhotosBeforeAndAfterInteractions.js.map +1 -0
- package/lib/stage/crew/photographer/strategies/TakePhotosOfFailures.d.ts +17 -0
- package/lib/stage/crew/photographer/strategies/TakePhotosOfFailures.js +28 -0
- package/lib/stage/crew/photographer/strategies/TakePhotosOfFailures.js.map +1 -0
- package/lib/stage/crew/photographer/strategies/TakePhotosOfInteractions.d.ts +19 -0
- package/lib/stage/crew/photographer/strategies/TakePhotosOfInteractions.js +28 -0
- package/lib/stage/crew/photographer/strategies/TakePhotosOfInteractions.js.map +1 -0
- package/lib/stage/crew/photographer/strategies/index.d.ts +4 -0
- package/lib/stage/crew/photographer/strategies/index.js +17 -0
- package/lib/stage/crew/photographer/strategies/index.js.map +1 -0
- package/lib/stage/index.d.ts +1 -0
- package/lib/stage/index.js +14 -0
- package/lib/stage/index.js.map +1 -0
- package/package.json +85 -0
- package/src/errors/CookieMissingError.ts +7 -0
- package/src/errors/index.ts +1 -0
- package/src/expectations/ElementExpectation.ts +32 -0
- package/src/expectations/index.ts +6 -0
- package/src/expectations/isActive.ts +22 -0
- package/src/expectations/isClickable.ts +32 -0
- package/src/expectations/isEnabled.ts +19 -0
- package/src/expectations/isPresent.ts +21 -0
- package/src/expectations/isSelected.ts +24 -0
- package/src/expectations/isVisible.ts +28 -0
- package/src/index.ts +5 -0
- package/src/input/Key.ts +83 -0
- package/src/input/index.ts +1 -0
- package/src/screenplay/abilities/BrowseTheWeb.ts +89 -0
- package/src/screenplay/abilities/BrowserCapabilities.ts +5 -0
- package/src/screenplay/abilities/index.ts +2 -0
- package/src/screenplay/index.ts +4 -0
- package/src/screenplay/interactions/Clear.ts +102 -0
- package/src/screenplay/interactions/Click.ts +86 -0
- package/src/screenplay/interactions/DoubleClick.ts +102 -0
- package/src/screenplay/interactions/Enter.ts +92 -0
- package/src/screenplay/interactions/EnterBuilder.ts +28 -0
- package/src/screenplay/interactions/ExecuteScript.ts +345 -0
- package/src/screenplay/interactions/Hover.ts +90 -0
- package/src/screenplay/interactions/Navigate.ts +209 -0
- package/src/screenplay/interactions/PageElementInteraction.ts +59 -0
- package/src/screenplay/interactions/Press.ts +194 -0
- package/src/screenplay/interactions/PressBuilder.ts +29 -0
- package/src/screenplay/interactions/RightClick.ts +100 -0
- package/src/screenplay/interactions/Scroll.ts +99 -0
- package/src/screenplay/interactions/Select.ts +317 -0
- package/src/screenplay/interactions/SelectBuilder.ts +36 -0
- package/src/screenplay/interactions/Switch.ts +225 -0
- package/src/screenplay/interactions/TakeScreenshot.ts +89 -0
- package/src/screenplay/interactions/Wait.ts +264 -0
- package/src/screenplay/interactions/WaitBuilder.ts +34 -0
- package/src/screenplay/interactions/index.ts +16 -0
- package/src/screenplay/models/Cookie.ts +219 -0
- package/src/screenplay/models/CookieData.ts +97 -0
- package/src/screenplay/models/ModalDialog.ts +19 -0
- package/src/screenplay/models/Page.ts +147 -0
- package/src/screenplay/models/PageElement.ts +95 -0
- package/src/screenplay/models/PageElements.ts +70 -0
- package/src/screenplay/models/index.ts +6 -0
- package/src/screenplay/questions/Attribute.ts +112 -0
- package/src/screenplay/questions/CssClasses.ts +118 -0
- package/src/screenplay/questions/ElementQuestion.ts +60 -0
- package/src/screenplay/questions/LastScriptExecution.ts +21 -0
- package/src/screenplay/questions/Selected.ts +212 -0
- package/src/screenplay/questions/Text.ts +153 -0
- package/src/screenplay/questions/Value.ts +82 -0
- package/src/screenplay/questions/index.ts +6 -0
- package/src/stage/crew/index.ts +1 -0
- package/src/stage/crew/photographer/Photographer.ts +108 -0
- package/src/stage/crew/photographer/index.ts +2 -0
- package/src/stage/crew/photographer/strategies/PhotoTakingStrategy.ts +116 -0
- package/src/stage/crew/photographer/strategies/TakePhotosBeforeAndAfterInteractions.ts +28 -0
- package/src/stage/crew/photographer/strategies/TakePhotosOfFailures.ts +26 -0
- package/src/stage/crew/photographer/strategies/TakePhotosOfInteractions.ts +26 -0
- package/src/stage/crew/photographer/strategies/index.ts +4 -0
- package/src/stage/index.ts +1 -0
- package/tsconfig.eslint.json +10 -0
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
import { Answerable, q } from '@serenity-js/core';
|
|
2
|
+
import { commaSeparated, formatted } from '@serenity-js/core/lib/io';
|
|
3
|
+
import { inspected } from '@serenity-js/core/lib/io/inspected';
|
|
4
|
+
import { Interaction } from '@serenity-js/core/lib/screenplay';
|
|
5
|
+
|
|
6
|
+
import { PageElement, PageElements } from '../models';
|
|
7
|
+
import { SelectBuilder } from './SelectBuilder';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @desc
|
|
11
|
+
* Instructs the {@link @serenity-js/core/lib/screenplay/actor~Actor} to
|
|
12
|
+
* select an option from a [HTML `<select>` element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select),
|
|
13
|
+
* either by its display name, or by value.
|
|
14
|
+
*
|
|
15
|
+
* @see {@link Selected}
|
|
16
|
+
*/
|
|
17
|
+
export class Select {
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @desc
|
|
21
|
+
* Instantiates this {@link @serenity-js/core/lib/screenplay~Interaction}
|
|
22
|
+
* with a [`value`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option#attr-value)
|
|
23
|
+
* of a single [`<option>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option)
|
|
24
|
+
* for the {@link @serenity-js/core/lib/screenplay/actor~Actor} to select.
|
|
25
|
+
*
|
|
26
|
+
* @example <caption>Example widget</caption>
|
|
27
|
+
* <select data-test='countries'>
|
|
28
|
+
* <option value='UK'>United Kingdom</option>
|
|
29
|
+
* <option value='PL'>Poland</option>
|
|
30
|
+
* <option value='US'>United States</option>
|
|
31
|
+
* </select>
|
|
32
|
+
*
|
|
33
|
+
* @example <caption>Lean Page Object describing the widget</caption>
|
|
34
|
+
* import { Target } from '@serenity-js/protractor';
|
|
35
|
+
* import { browser, by } from 'protractor';
|
|
36
|
+
*
|
|
37
|
+
* class Countries {
|
|
38
|
+
* static dropdown = Target.the('countries dropdown')
|
|
39
|
+
* .located(by.css('[data-test="countries"]'));
|
|
40
|
+
* }
|
|
41
|
+
*
|
|
42
|
+
* @example <caption>Retrieving the selected value</caption>
|
|
43
|
+
* import { actorCalled } from '@serenity-js/core';
|
|
44
|
+
* import { BrowseTheWeb, Select, Selected } from '@serenity-js/protractor';
|
|
45
|
+
* import { Ensure, equals } from '@serenity-js/assertions';
|
|
46
|
+
* import { protractor } from 'protractor';
|
|
47
|
+
*
|
|
48
|
+
* actorCalled('Nick')
|
|
49
|
+
* .whoCan(BrowseTheWeb.using(protractor.browser))
|
|
50
|
+
* .attemptsTo(
|
|
51
|
+
* Select.value('UK').from(Countries.dropdown),
|
|
52
|
+
* Ensure.that(Selected.valueOf(Countries.dropdown), equals('UK')),
|
|
53
|
+
* );
|
|
54
|
+
*
|
|
55
|
+
* @param {Answerable<string>} value
|
|
56
|
+
* A value of the [`option` element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option)
|
|
57
|
+
* for the {@link @serenity-js/core/lib/screenplay/actor~Actor} to select
|
|
58
|
+
*
|
|
59
|
+
* @returns {SelectBuilder}
|
|
60
|
+
*
|
|
61
|
+
* @see {@link Selected.valueOf}
|
|
62
|
+
* @see {@link BrowseTheWeb}
|
|
63
|
+
* @see {@link Target}
|
|
64
|
+
* @see {@link @serenity-js/assertions~Ensure}
|
|
65
|
+
* @see {@link @serenity-js/assertions/lib/expectations~equals}
|
|
66
|
+
*/
|
|
67
|
+
static value(value: Answerable<string>): SelectBuilder {
|
|
68
|
+
return {
|
|
69
|
+
from: (pageElement: Answerable<PageElement>): Interaction =>
|
|
70
|
+
Interaction.where(formatted `#actor selects value ${ value } from ${ pageElement }`, async actor => {
|
|
71
|
+
return PageElement.locatedByCss(q`option[value=${ value }]`)
|
|
72
|
+
.of(pageElement)
|
|
73
|
+
.click()
|
|
74
|
+
.performAs(actor);
|
|
75
|
+
}),
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* @desc
|
|
81
|
+
* Instantiates this {@link @serenity-js/core/lib/screenplay~Interaction}
|
|
82
|
+
* with [`value`s](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option#attr-value)
|
|
83
|
+
* of multiple [`<option>` elements](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option)
|
|
84
|
+
* for the {@link @serenity-js/core/lib/screenplay/actor~Actor} to select.
|
|
85
|
+
*
|
|
86
|
+
* @example <caption>Example widget</caption>
|
|
87
|
+
* <select multiple data-test='countries'>
|
|
88
|
+
* <option value='UK'>United Kingdom</option>
|
|
89
|
+
* <option value='PL'>Poland</option>
|
|
90
|
+
* <option value='US'>United States</option>
|
|
91
|
+
* </select>
|
|
92
|
+
*
|
|
93
|
+
* @example <caption>Lean Page Object describing the widget</caption>
|
|
94
|
+
* import { Target } from '@serenity-js/protractor';
|
|
95
|
+
* import { browser, by } from 'protractor';
|
|
96
|
+
*
|
|
97
|
+
* class Countries {
|
|
98
|
+
* static dropdown = Target.the('countries dropdown')
|
|
99
|
+
* .located(by.css('[data-test="countries"]'));
|
|
100
|
+
* }
|
|
101
|
+
*
|
|
102
|
+
* @example <caption>Retrieving the selected value</caption>
|
|
103
|
+
* import { actorCalled } from '@serenity-js/core';
|
|
104
|
+
* import { BrowseTheWeb, Select, Selected } from '@serenity-js/protractor';
|
|
105
|
+
* import { Ensure, equals } from '@serenity-js/assertions';
|
|
106
|
+
* import { protractor } from 'protractor';
|
|
107
|
+
*
|
|
108
|
+
* actorCalled('Nick')
|
|
109
|
+
* .whoCan(BrowseTheWeb.using(protractor.browser))
|
|
110
|
+
* .attemptsTo(
|
|
111
|
+
* Select.values('UK').from(Countries.dropdown),
|
|
112
|
+
* Ensure.that(Selected.valuesOf(Countries.dropdown), equals([ 'UK' ])),
|
|
113
|
+
* );
|
|
114
|
+
*
|
|
115
|
+
* @param {Array<Answerable<string[] | string>>} values
|
|
116
|
+
* Values of the [`option` elements](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option)
|
|
117
|
+
* for the {@link @serenity-js/core/lib/screenplay/actor~Actor} to select
|
|
118
|
+
*
|
|
119
|
+
* @returns {SelectBuilder}
|
|
120
|
+
*
|
|
121
|
+
* @see {@link Selected.valuesOf}
|
|
122
|
+
* @see {@link BrowseTheWeb}
|
|
123
|
+
* @see {@link Target}
|
|
124
|
+
* @see {@link @serenity-js/assertions~Ensure}
|
|
125
|
+
* @see {@link @serenity-js/assertions/lib/expectations~equals}
|
|
126
|
+
*/
|
|
127
|
+
static values(...values: Array<Answerable<string[] | string>>): SelectBuilder {
|
|
128
|
+
return {
|
|
129
|
+
from: (pageElement: Answerable<PageElement>): Interaction =>
|
|
130
|
+
Interaction.where(`#actor selects values ${ commaSeparated(values.flat(), item => inspected(item, { inline: true })) } from ${ inspected(pageElement, { inline: true }) }`, async actor => {
|
|
131
|
+
|
|
132
|
+
const desiredValues = (await Promise.all(values.map(value => actor.answer(value)))).flat(); // eslint-disable-line unicorn/no-await-expression-member
|
|
133
|
+
|
|
134
|
+
const options: PageElements = await PageElements.locatedByCss(`option`).of(pageElement).answeredBy(actor);
|
|
135
|
+
const shouldSelect: boolean[] = await options.map(optionsToSelect(hasValueEqualOneOf(desiredValues)));
|
|
136
|
+
|
|
137
|
+
return options.forEach((option, index) => {
|
|
138
|
+
if (shouldSelect[index]) {
|
|
139
|
+
return option.click()
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
}),
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* @desc
|
|
148
|
+
* Instantiates this {@link @serenity-js/core/lib/screenplay~Interaction}
|
|
149
|
+
* with a single [`option`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option)
|
|
150
|
+
* for the {@link @serenity-js/core/lib/screenplay/actor~Actor} to select.
|
|
151
|
+
*
|
|
152
|
+
* @example <caption>Example widget</caption>
|
|
153
|
+
* <select data-test='countries'>
|
|
154
|
+
* <option value='UK'>United Kingdom</option>
|
|
155
|
+
* <option value='PL'>Poland</option>
|
|
156
|
+
* <option value='US'>United States</option>
|
|
157
|
+
* </select>
|
|
158
|
+
*
|
|
159
|
+
* @example <caption>Lean Page Object describing the widget</caption>
|
|
160
|
+
* import { Target } from '@serenity-js/protractor';
|
|
161
|
+
* import { browser, by } from 'protractor';
|
|
162
|
+
*
|
|
163
|
+
* class Countries {
|
|
164
|
+
* static dropdown = Target.the('countries dropdown')
|
|
165
|
+
* .located(by.css('[data-test="countries"]'));
|
|
166
|
+
* }
|
|
167
|
+
*
|
|
168
|
+
* @example <caption>Retrieving the selected value</caption>
|
|
169
|
+
* import { actorCalled } from '@serenity-js/core';
|
|
170
|
+
* import { BrowseTheWeb, Select, Selected } from '@serenity-js/protractor';
|
|
171
|
+
* import { Ensure, equals } from '@serenity-js/assertions';
|
|
172
|
+
* import { protractor } from 'protractor';
|
|
173
|
+
*
|
|
174
|
+
* actorCalled('Nick')
|
|
175
|
+
* .whoCan(BrowseTheWeb.using(protractor.browser))
|
|
176
|
+
* .attemptsTo(
|
|
177
|
+
* Select.option('Poland').from(Countries.dropdown),
|
|
178
|
+
* Ensure.that(
|
|
179
|
+
* Selected.optionIn(Countries.dropdown),
|
|
180
|
+
* equals('Poland')
|
|
181
|
+
* ),
|
|
182
|
+
* );
|
|
183
|
+
*
|
|
184
|
+
* @param {Answerable<string>} value
|
|
185
|
+
* Text of the [`option` element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option)
|
|
186
|
+
* for the {@link @serenity-js/core/lib/screenplay/actor~Actor} to select
|
|
187
|
+
*
|
|
188
|
+
* @returns {SelectBuilder}
|
|
189
|
+
*
|
|
190
|
+
* @see {@link Selected.optionIn}
|
|
191
|
+
* @see {@link BrowseTheWeb}
|
|
192
|
+
* @see {@link Target}
|
|
193
|
+
* @see {@link @serenity-js/assertions~Ensure}
|
|
194
|
+
* @see {@link @serenity-js/assertions/lib/expectations~equals}
|
|
195
|
+
*/
|
|
196
|
+
static option(value: Answerable<string>): SelectBuilder {
|
|
197
|
+
return {
|
|
198
|
+
from: (pageElement: Answerable<PageElement>): Interaction =>
|
|
199
|
+
Interaction.where(formatted `#actor selects ${ value } from ${ pageElement }`, async actor => {
|
|
200
|
+
return PageElement.locatedByCssContainingText('option', value)
|
|
201
|
+
.of(pageElement)
|
|
202
|
+
.click()
|
|
203
|
+
.performAs(actor);
|
|
204
|
+
}),
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* @desc
|
|
210
|
+
* Instantiates this {@link @serenity-js/core/lib/screenplay~Interaction}
|
|
211
|
+
* with [`option`s](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option)
|
|
212
|
+
* for the {@link @serenity-js/core/lib/screenplay/actor~Actor} to select.
|
|
213
|
+
*
|
|
214
|
+
* @example <caption>Example widget</caption>
|
|
215
|
+
* <select multiple data-test='countries'>
|
|
216
|
+
* <option value='UK'>United Kingdom</option>
|
|
217
|
+
* <option value='PL'>Poland</option>
|
|
218
|
+
* <option value='US'>United States</option>
|
|
219
|
+
* </select>
|
|
220
|
+
*
|
|
221
|
+
* @example <caption>Lean Page Object describing the widget</caption>
|
|
222
|
+
* import { Target } from '@serenity-js/protractor';
|
|
223
|
+
* import { browser, by } from 'protractor';
|
|
224
|
+
*
|
|
225
|
+
* class Countries {
|
|
226
|
+
* static dropdown = Target.the('countries dropdown')
|
|
227
|
+
* .located(by.css('[data-test="countries"]'));
|
|
228
|
+
* }
|
|
229
|
+
*
|
|
230
|
+
* @example <caption>Retrieving the selected value</caption>
|
|
231
|
+
* import { actorCalled } from '@serenity-js/core';
|
|
232
|
+
* import { BrowseTheWeb, Select, Selected } from '@serenity-js/protractor';
|
|
233
|
+
* import { Ensure, equals } from '@serenity-js/assertions';
|
|
234
|
+
* import { protractor } from 'protractor';
|
|
235
|
+
*
|
|
236
|
+
* actorCalled('Nick')
|
|
237
|
+
* .whoCan(BrowseTheWeb.using(protractor.browser))
|
|
238
|
+
* .attemptsTo(
|
|
239
|
+
* Select.options('Poland', 'United States').from(Countries.dropdown),
|
|
240
|
+
* Ensure.that(
|
|
241
|
+
* Selected.optionsIn(Countries.dropdown),
|
|
242
|
+
* equals([ 'Poland', 'United States' ])
|
|
243
|
+
* ),
|
|
244
|
+
* );
|
|
245
|
+
*
|
|
246
|
+
* @param {Array<Answerable<string[] | string>>} values
|
|
247
|
+
* Text of the [`option` elements ](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option)
|
|
248
|
+
* for the {@link @serenity-js/core/lib/screenplay/actor~Actor} to select
|
|
249
|
+
*
|
|
250
|
+
* @returns {SelectBuilder}
|
|
251
|
+
*
|
|
252
|
+
* @see {@link Selected.optionsIn}
|
|
253
|
+
* @see {@link BrowseTheWeb}
|
|
254
|
+
* @see {@link Target}
|
|
255
|
+
* @see {@link @serenity-js/assertions~Ensure}
|
|
256
|
+
* @see {@link @serenity-js/assertions/lib/expectations~equals}
|
|
257
|
+
*/
|
|
258
|
+
static options(...values: Array<Answerable<string[] | string>>): SelectBuilder {
|
|
259
|
+
return {
|
|
260
|
+
from: (pageElement: Answerable<PageElement>): Interaction =>
|
|
261
|
+
Interaction.where(`#actor selects ${ commaSeparated(values.flat(), item => inspected(item, { inline: true })) } from ${ inspected(pageElement, { inline: true }) }`, async actor => {
|
|
262
|
+
|
|
263
|
+
const desiredOptions = (await Promise.all(values.map(value => actor.answer(value)))).flat(); // eslint-disable-line unicorn/no-await-expression-member
|
|
264
|
+
|
|
265
|
+
const options: PageElements = await PageElements.locatedByCss(`option`).of(pageElement).answeredBy(actor);
|
|
266
|
+
const shouldSelect: boolean[] = await options.map(optionsToSelect(hasTextEqualOneOf(desiredOptions)));
|
|
267
|
+
|
|
268
|
+
return options.forEach((option, index) => {
|
|
269
|
+
if (shouldSelect[index]) {
|
|
270
|
+
return option.click()
|
|
271
|
+
}
|
|
272
|
+
});
|
|
273
|
+
}),
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/** @package */
|
|
279
|
+
function hasValueEqualOneOf(desiredValues: string[]): (option: PageElement) => Promise<boolean> {
|
|
280
|
+
return async (option: PageElement) => {
|
|
281
|
+
|
|
282
|
+
const value = await option.value()
|
|
283
|
+
|
|
284
|
+
return desiredValues.includes(value);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/** @package */
|
|
289
|
+
function hasTextEqualOneOf(desiredValues: string[]): (option: PageElement) => Promise<boolean> {
|
|
290
|
+
return async (option: PageElement) => {
|
|
291
|
+
|
|
292
|
+
const value = await option.text()
|
|
293
|
+
|
|
294
|
+
return desiredValues.includes(value);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/** @package */
|
|
299
|
+
function optionsToSelect(criterion: (option: PageElement) => Promise<boolean>) {
|
|
300
|
+
return (option: PageElement) =>
|
|
301
|
+
isAlreadySelected(option)
|
|
302
|
+
.then(alreadySelected =>
|
|
303
|
+
criterion(option).then(criterionMet =>
|
|
304
|
+
xor(alreadySelected, criterionMet)
|
|
305
|
+
)
|
|
306
|
+
);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/** @package */
|
|
310
|
+
function isAlreadySelected(option: PageElement): Promise<boolean> {
|
|
311
|
+
return option.isSelected();
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/** @package */
|
|
315
|
+
function xor(first: boolean, second: boolean): boolean {
|
|
316
|
+
return first !== second;
|
|
317
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Answerable } from '@serenity-js/core';
|
|
2
|
+
import { Interaction } from '@serenity-js/core/lib/screenplay';
|
|
3
|
+
|
|
4
|
+
import { PageElement } from '../models';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @desc
|
|
8
|
+
* Configures the {@link Target} representing
|
|
9
|
+
* a [HTML `<select>` element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select)
|
|
10
|
+
* for the {@link @serenity-js/core/lib/screenplay/actor~Actor}
|
|
11
|
+
* to interact with.
|
|
12
|
+
*
|
|
13
|
+
* @interface
|
|
14
|
+
*/
|
|
15
|
+
export interface SelectBuilder {
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @desc
|
|
19
|
+
* Configures the {@link Target} representing
|
|
20
|
+
* a [HTML `<select>` element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select)
|
|
21
|
+
* for the {@link @serenity-js/core/lib/screenplay/actor~Actor}
|
|
22
|
+
* to interact with
|
|
23
|
+
*
|
|
24
|
+
* @param {Answerable<PageElement>} pageElement
|
|
25
|
+
*
|
|
26
|
+
* @returns {@serenity-js/core/lib/screenplay~Interaction}
|
|
27
|
+
*
|
|
28
|
+
* @see {@link Select}
|
|
29
|
+
* @see {@link Select.option}
|
|
30
|
+
* @see {@link Select.options}
|
|
31
|
+
* @see {@link Select.value}
|
|
32
|
+
* @see {@link Select.values}
|
|
33
|
+
* @see {@link Target}
|
|
34
|
+
*/
|
|
35
|
+
from: (pageElement: Answerable<PageElement>) => Interaction;
|
|
36
|
+
}
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import { Activity, Answerable, AnswersQuestions, Interaction, PerformsActivities, Task, UsesAbilities } from '@serenity-js/core';
|
|
2
|
+
|
|
3
|
+
import { BrowseTheWeb } from '../abilities';
|
|
4
|
+
import { PageElement } from '../models';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @desc
|
|
8
|
+
* Instructs the {@link @serenity-js/core/lib/screenplay/actor~Actor}
|
|
9
|
+
* to switch to a different [frame](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/frame),
|
|
10
|
+
* [inline frame](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe),
|
|
11
|
+
* or browser window/tab.
|
|
12
|
+
*
|
|
13
|
+
* @example <caption>Lean Page Object describing a login form, embedded in an iframe</caption>
|
|
14
|
+
*
|
|
15
|
+
* import { Target } from '@serenity-js/protractor';
|
|
16
|
+
* import { by } from 'protractor';
|
|
17
|
+
*
|
|
18
|
+
* class LoginForm {
|
|
19
|
+
* static iframe = Target.the('login form').located(by.tagName('iframe'));
|
|
20
|
+
* static usernameField = Target.the('username field').located(by.css('[data-test="username"]'));
|
|
21
|
+
* static passwordField = Target.the('password field').located(by.css('[data-test="password"]'));
|
|
22
|
+
* static submitButton = Target.the('submit button').located(by.css(`button[type='submit']`));
|
|
23
|
+
* }
|
|
24
|
+
*
|
|
25
|
+
* @example <caption>Switch to an iframe and back</caption>
|
|
26
|
+
*
|
|
27
|
+
* import { actorCalled } from '@serenity-js/core';
|
|
28
|
+
* import { BrowseTheWeb, Switch, Enter, Click } from '@serenity-js/protractor';
|
|
29
|
+
* import { protractor } from 'protractor';
|
|
30
|
+
*
|
|
31
|
+
* actorCalled('Francesca')
|
|
32
|
+
* .whoCan(BrowseTheWeb.using(protractor.browser))
|
|
33
|
+
* .attemptsTo(
|
|
34
|
+
* Switch.toFrame(LoginForm.iframe),
|
|
35
|
+
*
|
|
36
|
+
* Enter.theValue('francesca@example.org').into(LoginForm.usernameField),
|
|
37
|
+
* Enter.theValue('correct-horse-battery-staple').into(LoginForm.passwordField),
|
|
38
|
+
* Click.on(LoginForm.submitButton),
|
|
39
|
+
*
|
|
40
|
+
* Switch.toParentFrame(),
|
|
41
|
+
* );
|
|
42
|
+
*
|
|
43
|
+
* @example <caption>Perform activities in the context of an iframe</caption>
|
|
44
|
+
*
|
|
45
|
+
* import { actorCalled } from '@serenity-js/core';
|
|
46
|
+
* import { BrowseTheWeb, Switch, Enter, Click } from '@serenity-js/protractor';
|
|
47
|
+
* import { protractor } from 'protractor';
|
|
48
|
+
*
|
|
49
|
+
* actorCalled('Francesca')
|
|
50
|
+
* .whoCan(BrowseTheWeb.using(protractor.browser))
|
|
51
|
+
* .attemptsTo(
|
|
52
|
+
* Switch.toFrame(LoginForm.iframe).and(
|
|
53
|
+
* Enter.theValue('francesca@example.org').into(LoginForm.usernameField),
|
|
54
|
+
* Enter.theValue('correct-horse-battery-staple').into(LoginForm.passwordField),
|
|
55
|
+
* Click.on(LoginForm.submitButton),
|
|
56
|
+
* ),
|
|
57
|
+
* // Note that Switch.toParentFrame() is invoked automatically
|
|
58
|
+
* );
|
|
59
|
+
*
|
|
60
|
+
* @example <caption>Switch to a new window/tab and back</caption>
|
|
61
|
+
*
|
|
62
|
+
* import { actorCalled } from '@serenity-js/core';
|
|
63
|
+
* import { BrowseTheWeb, Switch, Close } from '@serenity-js/protractor';
|
|
64
|
+
* import { protractor } from 'protractor';
|
|
65
|
+
*
|
|
66
|
+
* actorCalled('Francesca')
|
|
67
|
+
* .whoCan(BrowseTheWeb.using(protractor.browser))
|
|
68
|
+
* .attemptsTo(
|
|
69
|
+
* Switch.toNewWindow(), // or: Switch.toWindow(...)
|
|
70
|
+
*
|
|
71
|
+
* // perform some activities in the context of the new window
|
|
72
|
+
*
|
|
73
|
+
* Close.currentWindow(),
|
|
74
|
+
*
|
|
75
|
+
* Switch.toOriginalWindow(),
|
|
76
|
+
* );
|
|
77
|
+
*
|
|
78
|
+
* @example <caption>Perform activities in the context of a different window/tab</caption>
|
|
79
|
+
*
|
|
80
|
+
* import { actorCalled } from '@serenity-js/core';
|
|
81
|
+
* import { BrowseTheWeb, Switch, Close } from '@serenity-js/protractor';
|
|
82
|
+
* import { protractor } from 'protractor';
|
|
83
|
+
*
|
|
84
|
+
* actorCalled('Francesca')
|
|
85
|
+
* .whoCan(BrowseTheWeb.using(protractor.browser))
|
|
86
|
+
* .attemptsTo(
|
|
87
|
+
* Switch.toNewWindow().and(
|
|
88
|
+
* // perform some activities in the context of the new window
|
|
89
|
+
*
|
|
90
|
+
* Close.currentWindow()
|
|
91
|
+
* ),
|
|
92
|
+
*
|
|
93
|
+
* // Note that Switch.toOriginalWindow() is invoked automatically
|
|
94
|
+
* );
|
|
95
|
+
*
|
|
96
|
+
* @see {@link Close}
|
|
97
|
+
* @see {@link BrowseTheWeb}
|
|
98
|
+
*/
|
|
99
|
+
export class Switch {
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* @desc
|
|
103
|
+
* Switches the current [browsing context](https://w3c.github.io/webdriver/#dfn-current-browsing-context)
|
|
104
|
+
* for future commands to a [frame](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/frame)
|
|
105
|
+
* or an [inline frame](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe)
|
|
106
|
+
* identified by its name, index or `Question<ElementFinder>`.
|
|
107
|
+
*
|
|
108
|
+
* @param {Answerable<ElementFinder | number | string>} targetOrIndex
|
|
109
|
+
*
|
|
110
|
+
* @returns {SwitchToFrame}
|
|
111
|
+
*
|
|
112
|
+
* @see {@link Switch.toParentFrame}
|
|
113
|
+
* @see {@link Switch.toDefaultContent}
|
|
114
|
+
* @see {@link Target}
|
|
115
|
+
*/
|
|
116
|
+
static toFrame(targetOrIndex: Answerable<PageElement | number | string>): SwitchToFrame {
|
|
117
|
+
return new SwitchToFrame(targetOrIndex);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* @desc
|
|
122
|
+
* Sets the current [browsing context](https://w3c.github.io/webdriver/#dfn-current-browsing-context)
|
|
123
|
+
* for future commands to the parent of the current browsing context,
|
|
124
|
+
* i.e. an `iframe` in which the current `iframe` is nested.
|
|
125
|
+
*
|
|
126
|
+
* If the current context is the top-level browsing context, the context remains unchanged.
|
|
127
|
+
*
|
|
128
|
+
* @returns {@serenity-js/core/lib/screenplay~Interaction}
|
|
129
|
+
*
|
|
130
|
+
* @see {@link Switch.toFrame}
|
|
131
|
+
* @see https://w3c.github.io/webdriver/#switch-to-parent-frame
|
|
132
|
+
* @see https://w3c.github.io/webdriver/#dfn-current-browsing-context
|
|
133
|
+
*/
|
|
134
|
+
static toParentFrame(): Interaction {
|
|
135
|
+
return new SwitchToParentFrame();
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* @desc
|
|
140
|
+
* Switches the current [browsing context](https://w3c.github.io/webdriver/#dfn-current-browsing-context)
|
|
141
|
+
* for future commands to the first frame on the page, or the main document
|
|
142
|
+
* when a page contains [`iframe`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe)s.
|
|
143
|
+
*
|
|
144
|
+
* @returns {@serenity-js/core/lib/screenplay~Interaction}
|
|
145
|
+
*
|
|
146
|
+
* @see {@link Switch.toFrame}
|
|
147
|
+
*/
|
|
148
|
+
static toDefaultContent(): Interaction {
|
|
149
|
+
return new SwitchToDefaultContent();
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* @package
|
|
155
|
+
*/
|
|
156
|
+
class SwitchToFrame extends Interaction {
|
|
157
|
+
constructor(private readonly targetOrIndex: Answerable<PageElement | number | string>) {
|
|
158
|
+
super();
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
and(...activities: Activity[]): Task {
|
|
162
|
+
return new SwitchToFrameAndPerformActivities(this.targetOrIndex, activities);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
performAs(actor: UsesAbilities & AnswersQuestions): PromiseLike<void> {
|
|
166
|
+
return actor.answer(this.targetOrIndex)
|
|
167
|
+
.then((targetOrIndex: PageElement | number | string) => {
|
|
168
|
+
return BrowseTheWeb.as(actor).switchToFrame(targetOrIndex);
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
toString(): string {
|
|
173
|
+
return `#actor switches to frame: ${ this.targetOrIndex }`;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* @package
|
|
179
|
+
*/
|
|
180
|
+
class SwitchToFrameAndPerformActivities extends Task {
|
|
181
|
+
constructor(
|
|
182
|
+
private readonly targetOrIndex: Answerable<PageElement | number | string>,
|
|
183
|
+
private readonly activities: Activity[]
|
|
184
|
+
) {
|
|
185
|
+
super();
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
performAs(actor: PerformsActivities): PromiseLike<void> {
|
|
189
|
+
return actor.attemptsTo(
|
|
190
|
+
new SwitchToFrame(this.targetOrIndex),
|
|
191
|
+
...this.activities,
|
|
192
|
+
new SwitchToParentFrame()
|
|
193
|
+
)
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
toString(): string {
|
|
197
|
+
return `#actor switches to frame: ${ this.targetOrIndex }`;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* @package
|
|
203
|
+
*/
|
|
204
|
+
class SwitchToParentFrame extends Interaction {
|
|
205
|
+
performAs(actor: UsesAbilities & AnswersQuestions): PromiseLike<void> {
|
|
206
|
+
return BrowseTheWeb.as(actor).switchToParentFrame();
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
toString(): string {
|
|
210
|
+
return `#actor switches to parent frame`;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* @package
|
|
216
|
+
*/
|
|
217
|
+
class SwitchToDefaultContent extends Interaction {
|
|
218
|
+
performAs(actor: UsesAbilities & AnswersQuestions): PromiseLike<void> {
|
|
219
|
+
return BrowseTheWeb.as(actor).switchToDefaultContent();
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
toString(): string {
|
|
223
|
+
return `#actor switches to default content`;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { Answerable, AnswersQuestions, CollectsArtifacts, Interaction, UsesAbilities } from '@serenity-js/core';
|
|
2
|
+
import { formatted } from '@serenity-js/core/lib/io';
|
|
3
|
+
import { Name, Photo } from '@serenity-js/core/lib/model';
|
|
4
|
+
|
|
5
|
+
import { BrowseTheWeb } from '../abilities';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @desc
|
|
9
|
+
* Instructs the {@link @serenity-js/core/lib/screenplay/actor~Actor} to
|
|
10
|
+
* take a screenshot and emit an {@link @serenity-js/core/lib/model~Artifact},
|
|
11
|
+
* which can then be persisted by {@link @serenity-js/core/lib/stage/crew/artifact-archiver~ArtifactArchiver}
|
|
12
|
+
* and reported by [Serenity BDD reporter](/modules/serenity-bdd).
|
|
13
|
+
*
|
|
14
|
+
* @example <caption>Clicking on an element</caption>
|
|
15
|
+
* import { actorCalled } from '@serenity-js/core';
|
|
16
|
+
* import { BrowseTheWeb, Navigate, TakeScreenshot } from '@serenity-js/protractor';
|
|
17
|
+
* import { protractor } from 'protractor';
|
|
18
|
+
*
|
|
19
|
+
* actorCalled('Tania')
|
|
20
|
+
* .whoCan(BrowseTheWeb.using(protractor.browser))
|
|
21
|
+
* .attemptsTo(
|
|
22
|
+
* Navigate.to('/app'),
|
|
23
|
+
* TakeScreenshot.of('my app'),
|
|
24
|
+
* );
|
|
25
|
+
*
|
|
26
|
+
* @see {@link BrowseTheWeb}
|
|
27
|
+
* @see {@link @serenity-js/core/lib/screenplay/actor~CollectsArtifacts}
|
|
28
|
+
* @see {@link @serenity-js/core/lib/model~Artifact}
|
|
29
|
+
* @see {@link @serenity-js/core/lib/stage/crew/artifact-archiver~ArtifactArchiver}
|
|
30
|
+
*
|
|
31
|
+
* @extends {@serenity-js/core/lib/screenplay~Interaction}
|
|
32
|
+
*/
|
|
33
|
+
export class TakeScreenshot extends Interaction {
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @desc
|
|
37
|
+
* Instantiates this {@link @serenity-js/core/lib/screenplay~Interaction}.
|
|
38
|
+
*
|
|
39
|
+
* @param {Answerable<string>} name
|
|
40
|
+
* The name to associate the screenshot with
|
|
41
|
+
*
|
|
42
|
+
* @returns {@serenity-js/core/lib/screenplay~Interaction}
|
|
43
|
+
*/
|
|
44
|
+
static of(name: Answerable<string>): Interaction {
|
|
45
|
+
return new TakeScreenshot(name);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* @param {Answerable<string>} name
|
|
50
|
+
* The name to associate the screenshot with
|
|
51
|
+
*/
|
|
52
|
+
constructor(private readonly name: Answerable<string>) {
|
|
53
|
+
super();
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* @desc
|
|
58
|
+
* Makes the provided {@link @serenity-js/core/lib/screenplay/actor~Actor}
|
|
59
|
+
* perform this {@link @serenity-js/core/lib/screenplay~Interaction}.
|
|
60
|
+
*
|
|
61
|
+
* @param {UsesAbilities & AnswersQuestions} actor
|
|
62
|
+
* An {@link @serenity-js/core/lib/screenplay/actor~Actor} to perform this {@link @serenity-js/core/lib/screenplay~Interaction}
|
|
63
|
+
*
|
|
64
|
+
* @returns {PromiseLike<void>}
|
|
65
|
+
*
|
|
66
|
+
* @see {@link @serenity-js/core/lib/screenplay/actor~Actor}
|
|
67
|
+
* @see {@link @serenity-js/core/lib/screenplay/actor~UsesAbilities}
|
|
68
|
+
* @see {@link @serenity-js/core/lib/screenplay/actor~AnswersQuestions}
|
|
69
|
+
*/
|
|
70
|
+
performAs(actor: UsesAbilities & AnswersQuestions & CollectsArtifacts): PromiseLike<void> {
|
|
71
|
+
return Promise.all([
|
|
72
|
+
BrowseTheWeb.as(actor).takeScreenshot(),
|
|
73
|
+
actor.answer(this.name),
|
|
74
|
+
]).then(([ screenshot, name ]) => actor.collect(
|
|
75
|
+
Photo.fromBase64(screenshot),
|
|
76
|
+
new Name(name),
|
|
77
|
+
));
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* @desc
|
|
82
|
+
* Generates a description to be used when reporting this {@link @serenity-js/core/lib/screenplay~Activity}.
|
|
83
|
+
*
|
|
84
|
+
* @returns {string}
|
|
85
|
+
*/
|
|
86
|
+
toString(): string {
|
|
87
|
+
return formatted `#actor takes a screenshot of ${this.name}`;
|
|
88
|
+
}
|
|
89
|
+
}
|