@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,32 @@
|
|
|
1
|
+
import { AnswersQuestions, Expectation, ExpectationMet, ExpectationNotMet, ExpectationOutcome } from '@serenity-js/core';
|
|
2
|
+
|
|
3
|
+
import { PageElement } from '../screenplay';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @access private
|
|
7
|
+
*/
|
|
8
|
+
export class ElementExpectation extends Expectation<any, PageElement> {
|
|
9
|
+
static forElementTo(message: string, fn: (actual: PageElement) => Promise<boolean>): Expectation<any, PageElement> {
|
|
10
|
+
return new ElementExpectation(message, fn);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
constructor(
|
|
14
|
+
subject: string,
|
|
15
|
+
private readonly fn: (actual: PageElement) => Promise<boolean>,
|
|
16
|
+
) {
|
|
17
|
+
super(subject);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
answeredBy(actor: AnswersQuestions): (actual: PageElement) => Promise<ExpectationOutcome<boolean, PageElement>> {
|
|
21
|
+
return (actual: PageElement) =>
|
|
22
|
+
this.fn(actual)
|
|
23
|
+
.then(expectationMet =>
|
|
24
|
+
expectationMet
|
|
25
|
+
? new ExpectationMet(this.toString(), undefined, actual)
|
|
26
|
+
: new ExpectationNotMet(this.toString(), undefined, actual),
|
|
27
|
+
)
|
|
28
|
+
.catch(error => {
|
|
29
|
+
return new ExpectationNotMet(`${ this.toString() } (${ error.message })`, undefined, actual);
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Expectation } from '@serenity-js/core';
|
|
2
|
+
|
|
3
|
+
import { PageElement } from '../screenplay';
|
|
4
|
+
import { ElementExpectation } from './ElementExpectation';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @desc
|
|
8
|
+
* Expectation that the element is active (has focus).
|
|
9
|
+
* If the selector matches multiple elements, it will return true if one of the elements has focus.
|
|
10
|
+
*
|
|
11
|
+
* @returns {@serenity-js/core/lib/screenplay/questions~Expectation<boolean, Element<'async'>>}
|
|
12
|
+
*
|
|
13
|
+
* @see https://webdriver.io/docs/api/element/isFocused/
|
|
14
|
+
* @see {@link @serenity-js/assertions~Ensure}
|
|
15
|
+
* @see {@link @serenity-js/core/lib/screenplay/questions~Check}
|
|
16
|
+
* @see {@link Wait}
|
|
17
|
+
*/
|
|
18
|
+
// todo: isFocused?
|
|
19
|
+
export function isActive(): Expectation<boolean, PageElement> {
|
|
20
|
+
return ElementExpectation.forElementTo('become active', actual => actual.isActive());
|
|
21
|
+
}
|
|
22
|
+
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { and } from '@serenity-js/assertions';
|
|
2
|
+
import { Expectation } from '@serenity-js/core';
|
|
3
|
+
|
|
4
|
+
import { PageElement } from '../screenplay';
|
|
5
|
+
import { ElementExpectation } from './ElementExpectation';
|
|
6
|
+
import { isEnabled } from './isEnabled';
|
|
7
|
+
import { isVisible } from './isVisible';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @desc
|
|
11
|
+
* Expectation that an element is clickable, which means:
|
|
12
|
+
* - it exists
|
|
13
|
+
* - it is visible
|
|
14
|
+
* - it is within viewport (if not, try to scroll to it)
|
|
15
|
+
* - its center is not overlapped with another element
|
|
16
|
+
* - it is not disabled
|
|
17
|
+
* otherwise return false.
|
|
18
|
+
*
|
|
19
|
+
* @returns {@serenity-js/core/lib/screenplay/questions~Expectation<boolean, Element<'async'>>}
|
|
20
|
+
*
|
|
21
|
+
* @see https://webdriver.io/docs/api/element/isClickable/
|
|
22
|
+
* @see {@link @serenity-js/assertions~Ensure}
|
|
23
|
+
* @see {@link @serenity-js/core/lib/screenplay/questions~Check}
|
|
24
|
+
* @see {@link Wait}
|
|
25
|
+
*/
|
|
26
|
+
export function isClickable(): Expectation<boolean, PageElement> {
|
|
27
|
+
return Expectation.to<PageElement>('become clickable').soThatActual(and(
|
|
28
|
+
isVisible(),
|
|
29
|
+
isEnabled(),
|
|
30
|
+
ElementExpectation.forElementTo('become clickable', actual => actual.isClickable())
|
|
31
|
+
));
|
|
32
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Expectation } from '@serenity-js/core';
|
|
2
|
+
|
|
3
|
+
import { PageElement } from '../screenplay';
|
|
4
|
+
import { ElementExpectation } from './ElementExpectation';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @desc
|
|
8
|
+
* Expectation that the element is enabled.
|
|
9
|
+
*
|
|
10
|
+
* @returns {@serenity-js/core/lib/screenplay/questions~Expectation<boolean, Element<'async'>>}
|
|
11
|
+
*
|
|
12
|
+
* @see https://webdriver.io/docs/api/element/isEnabled/
|
|
13
|
+
* @see {@link @serenity-js/assertions~Ensure}
|
|
14
|
+
* @see {@link @serenity-js/core/lib/screenplay/questions~Check}
|
|
15
|
+
* @see {@link Wait}
|
|
16
|
+
*/
|
|
17
|
+
export function isEnabled(): Expectation<boolean, PageElement> {
|
|
18
|
+
return ElementExpectation.forElementTo('become enabled', actual => actual.isEnabled());
|
|
19
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Expectation } from '@serenity-js/core';
|
|
2
|
+
|
|
3
|
+
import { PageElement } from '../screenplay';
|
|
4
|
+
import { ElementExpectation } from './ElementExpectation';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @desc
|
|
8
|
+
* Expectation that the element is present in the DOM of a page.
|
|
9
|
+
* Please note that this does not necessarily mean that the element is visible.
|
|
10
|
+
*
|
|
11
|
+
* @returns {@serenity-js/core/lib/screenplay/questions~Expectation<boolean, Element<'async'>>}
|
|
12
|
+
*
|
|
13
|
+
* @see https://webdriver.io/docs/api/element/isExisting/
|
|
14
|
+
* @see {@link @serenity-js/assertions~Ensure}
|
|
15
|
+
* @see {@link @serenity-js/core/lib/screenplay/questions~Check}
|
|
16
|
+
* @see {@link Wait}
|
|
17
|
+
*/
|
|
18
|
+
// todo: make it generic isPresent: Promise<boolean> | boolean
|
|
19
|
+
export function isPresent(): Expectation<boolean, PageElement> {
|
|
20
|
+
return ElementExpectation.forElementTo('become present', actual => actual.isPresent());
|
|
21
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { and } from '@serenity-js/assertions';
|
|
2
|
+
import { Expectation } from '@serenity-js/core';
|
|
3
|
+
|
|
4
|
+
import { PageElement } from '../screenplay';
|
|
5
|
+
import { ElementExpectation } from './ElementExpectation';
|
|
6
|
+
import { isPresent } from './isPresent';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @desc
|
|
10
|
+
* Expectation that an `<option>` or `<input>` element of type checkbox or radio is currently selected.
|
|
11
|
+
*
|
|
12
|
+
* @returns {@serenity-js/core/lib/screenplay/questions~Expectation<boolean, Element<'async'>>}
|
|
13
|
+
*
|
|
14
|
+
* @see https://webdriver.io/docs/api/element/isSelected/
|
|
15
|
+
* @see {@link @serenity-js/assertions~Ensure}
|
|
16
|
+
* @see {@link @serenity-js/core/lib/screenplay/questions~Check}
|
|
17
|
+
* @see {@link Wait}
|
|
18
|
+
*/
|
|
19
|
+
export function isSelected(): Expectation<boolean, PageElement> {
|
|
20
|
+
return Expectation.to<PageElement>('become selected').soThatActual(and(
|
|
21
|
+
isPresent(),
|
|
22
|
+
ElementExpectation.forElementTo('become selected', actual => actual.isSelected()),
|
|
23
|
+
));
|
|
24
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { and } from '@serenity-js/assertions';
|
|
2
|
+
import { Expectation } from '@serenity-js/core';
|
|
3
|
+
|
|
4
|
+
import { PageElement } from '../screenplay';
|
|
5
|
+
import { ElementExpectation } from './ElementExpectation';
|
|
6
|
+
import { isPresent } from './isPresent';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @desc
|
|
10
|
+
* Expectation that the element is present in the DOM of the page and visible.
|
|
11
|
+
*
|
|
12
|
+
* @returns {@serenity-js/core/lib/screenplay/questions~Expectation<boolean, Element<'async'>>}
|
|
13
|
+
*
|
|
14
|
+
* @see https://webdriver.io/docs/api/element/isDisplayed/
|
|
15
|
+
* @see {@link @serenity-js/assertions~Ensure}
|
|
16
|
+
* @see {@link @serenity-js/core/lib/screenplay/questions~Check}
|
|
17
|
+
* @see {@link Wait}
|
|
18
|
+
*/
|
|
19
|
+
export function isVisible(): Expectation<boolean, PageElement> {
|
|
20
|
+
return Expectation.to<PageElement>('become visible').soThatActual(and(
|
|
21
|
+
isPresent(),
|
|
22
|
+
isDisplayed(),
|
|
23
|
+
));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function isDisplayed(): Expectation<any, PageElement> {
|
|
27
|
+
return ElementExpectation.forElementTo('become displayed', actual => actual.isDisplayed());
|
|
28
|
+
}
|
package/src/index.ts
ADDED
package/src/input/Key.ts
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @desc
|
|
3
|
+
* Represents pressable keys that aren't text to be used with {@link Press}.
|
|
4
|
+
*
|
|
5
|
+
* Note that modifier like Shift, Alt and Meta (a.k.a. Command on Mac) will stay pressed
|
|
6
|
+
*
|
|
7
|
+
* @enum {string}
|
|
8
|
+
* @see {@link Press}
|
|
9
|
+
* @see https://w3c.github.io/webdriver/webdriver-spec.html#keyboard-actions
|
|
10
|
+
* @see https://github.com/puppeteer/puppeteer/blob/v7.1.0/src/common/USKeyboardLayout.ts
|
|
11
|
+
* @see https://github.com/SeleniumHQ/selenium/blob/trunk/javascript/node/selenium-webdriver/lib/input.js#L46
|
|
12
|
+
* @see https://github.com/webdriverio/webdriverio/blob/main/packages/wdio-utils/src/constants.ts#L5
|
|
13
|
+
*/
|
|
14
|
+
export class Key {
|
|
15
|
+
public static Alt = new Key('Alt', '\uE00A', true);
|
|
16
|
+
public static ArrowDown = new Key('ArrowDown', '\uE015');
|
|
17
|
+
public static ArrowLeft = new Key('ArrowLeft', '\uE012');
|
|
18
|
+
public static ArrowRight = new Key('ArrowRight', '\uE014');
|
|
19
|
+
public static ArrowUp = new Key('ArrowUp', '\uE013');
|
|
20
|
+
public static Backspace = new Key('Backspace', '\uE003');
|
|
21
|
+
public static Cancel = new Key('Cancel', '\uE001');
|
|
22
|
+
public static Clear = new Key('Clear', '\uE005');
|
|
23
|
+
public static Control = new Key('Control', '\uE009', true);
|
|
24
|
+
public static Delete = new Key('Delete', '\uE017');
|
|
25
|
+
public static End = new Key('End', '\uE010');
|
|
26
|
+
public static Enter = new Key('Enter', '\uE007');
|
|
27
|
+
public static Escape = new Key('Escape', '\uE00C');
|
|
28
|
+
public static F1 = new Key('F1', '\uE031');
|
|
29
|
+
public static F2 = new Key('F2', '\uE032');
|
|
30
|
+
public static F3 = new Key('F3', '\uE033');
|
|
31
|
+
public static F4 = new Key('F4', '\uE034');
|
|
32
|
+
public static F5 = new Key('F5', '\uE035');
|
|
33
|
+
public static F6 = new Key('F6', '\uE036');
|
|
34
|
+
public static F7 = new Key('F7', '\uE037');
|
|
35
|
+
public static F8 = new Key('F8', '\uE038');
|
|
36
|
+
public static F9 = new Key('F9', '\uE039');
|
|
37
|
+
public static F10 = new Key('F10', '\uE03A');
|
|
38
|
+
public static F11 = new Key('F11', '\uE03B');
|
|
39
|
+
public static F12 = new Key('F12', '\uE03C');
|
|
40
|
+
public static Help = new Key('Help', '\uE002');
|
|
41
|
+
public static Home = new Key('Home', '\uE011');
|
|
42
|
+
public static Insert = new Key('Insert', '\uE016');
|
|
43
|
+
public static Meta = new Key('Meta', '\uE03D', true);
|
|
44
|
+
public static Numpad0 = new Key('Numpad0', '\uE01A');
|
|
45
|
+
public static Numpad1 = new Key('Numpad1', '\uE01B');
|
|
46
|
+
public static Numpad2 = new Key('Numpad2', '\uE01C');
|
|
47
|
+
public static Numpad3 = new Key('Numpad3', '\uE01D');
|
|
48
|
+
public static Numpad4 = new Key('Numpad4', '\uE01E');
|
|
49
|
+
public static Numpad5 = new Key('Numpad5', '\uE01F');
|
|
50
|
+
public static Numpad6 = new Key('Numpad6', '\uE020');
|
|
51
|
+
public static Numpad7 = new Key('Numpad7', '\uE021');
|
|
52
|
+
public static Numpad8 = new Key('Numpad8', '\uE022');
|
|
53
|
+
public static Numpad9 = new Key('Numpad9', '\uE023');
|
|
54
|
+
public static NumpadAdd = new Key('NumpadAdd', '\uE025');
|
|
55
|
+
public static NumpadDecimal = new Key('NumpadDecimal', '\uE028');
|
|
56
|
+
public static NumpadDivide = new Key('NumpadDivide', '\uE029');
|
|
57
|
+
public static NumpadEqual = new Key('NumpadEqual', '\uE019');
|
|
58
|
+
public static NumpadMultiply = new Key('NumpadMultiply', '\uE024');
|
|
59
|
+
public static NumpadSubtract = new Key('NumpadSubtract', '\uE027');
|
|
60
|
+
public static PageDown = new Key('PageDown', '\uE00F');
|
|
61
|
+
public static PageUp = new Key('PageUp', '\uE00E');
|
|
62
|
+
public static Pause = new Key('Pause', '\uE00B');
|
|
63
|
+
public static Semicolon = new Key('Semicolon', '\uE018');
|
|
64
|
+
public static Shift = new Key('Shift', '\uE008', true);
|
|
65
|
+
public static Space = new Key('Space', '\uE00D');
|
|
66
|
+
public static Tab = new Key('Tab', '\uE004');
|
|
67
|
+
|
|
68
|
+
public static isKey(maybeKey: unknown): maybeKey is Key {
|
|
69
|
+
return !! maybeKey
|
|
70
|
+
&& maybeKey instanceof Key;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
constructor(
|
|
74
|
+
public readonly devtoolsName: string,
|
|
75
|
+
public readonly utf16codePoint: string,
|
|
76
|
+
public readonly isModifier: boolean = false,
|
|
77
|
+
) {
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
toString(): string {
|
|
81
|
+
return this.devtoolsName.replace(/([a-z])([\dA-Z])/g, '$1 $2');
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './Key';
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { Ability, Duration, UsesAbilities } from '@serenity-js/core';
|
|
2
|
+
|
|
3
|
+
import { Key } from '../../input';
|
|
4
|
+
import { Cookie, CookieData, ModalDialog, Page, PageElement, PageElements } from '../models';
|
|
5
|
+
import { BrowserCapabilities } from './BrowserCapabilities';
|
|
6
|
+
|
|
7
|
+
export abstract class BrowseTheWeb implements Ability {
|
|
8
|
+
/**
|
|
9
|
+
* @desc
|
|
10
|
+
* Used to access the Actor's ability to {@link BrowseTheWeb}
|
|
11
|
+
* from within the {@link @serenity-js/core/lib/screenplay~Interaction} classes,
|
|
12
|
+
* such as {@link Click}.
|
|
13
|
+
*
|
|
14
|
+
* @param {@serenity-js/core/lib/screenplay/actor~UsesAbilities} actor
|
|
15
|
+
* @return {BrowseTheWeb}
|
|
16
|
+
*/
|
|
17
|
+
static as(actor: UsesAbilities): BrowseTheWeb {
|
|
18
|
+
return actor.abilityTo(BrowseTheWeb);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
abstract navigateTo(destination: string): Promise<void>;
|
|
22
|
+
|
|
23
|
+
abstract navigateBack(): Promise<void>;
|
|
24
|
+
|
|
25
|
+
abstract navigateForward(): Promise<void>;
|
|
26
|
+
|
|
27
|
+
abstract reloadPage(): Promise<void>;
|
|
28
|
+
|
|
29
|
+
abstract waitFor(duration: Duration): Promise<void>;
|
|
30
|
+
|
|
31
|
+
abstract waitUntil(condition: () => boolean | Promise<boolean>, timeout: Duration): Promise<void>;
|
|
32
|
+
|
|
33
|
+
abstract findByCss(selector: string): PageElement;
|
|
34
|
+
abstract findByCssContainingText(selector: string, text: string): PageElement;
|
|
35
|
+
abstract findById(selector: string): PageElement;
|
|
36
|
+
abstract findByTagName(selector: string): PageElement;
|
|
37
|
+
abstract findByXPath(selector: string): PageElement;
|
|
38
|
+
|
|
39
|
+
abstract findAllByCss(selector: string): PageElements;
|
|
40
|
+
abstract findAllByTagName(selector: string): PageElements;
|
|
41
|
+
abstract findAllByXPath(selector: string): PageElements;
|
|
42
|
+
|
|
43
|
+
abstract browserCapabilities(): Promise<BrowserCapabilities>;
|
|
44
|
+
|
|
45
|
+
abstract sendKeys(keys: Array<Key | string>): Promise<void>;
|
|
46
|
+
|
|
47
|
+
abstract executeScript<Result, InnerArguments extends any[]>(
|
|
48
|
+
script: string | ((...parameters: InnerArguments) => Result),
|
|
49
|
+
...args: InnerArguments
|
|
50
|
+
): Promise<Result>;
|
|
51
|
+
|
|
52
|
+
abstract executeAsyncScript<Result, Parameters extends any[]>(
|
|
53
|
+
script: string | ((...args: [ ...parameters: Parameters, callback: (result: Result) => void ]) => void),
|
|
54
|
+
...args: Parameters
|
|
55
|
+
): Promise<Result>;
|
|
56
|
+
|
|
57
|
+
abstract lastScriptExecutionResult<R = any>(): R;
|
|
58
|
+
|
|
59
|
+
abstract takeScreenshot(): Promise<string>;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* @desc
|
|
63
|
+
* Returns a {@link Page} representing the currently active top-level browsing context.
|
|
64
|
+
*
|
|
65
|
+
* @returns {Promise<Page>}
|
|
66
|
+
*/
|
|
67
|
+
abstract currentPage(): Promise<Page>;
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* @desc
|
|
71
|
+
* Returns an array of {@link Page} objects representing all the available
|
|
72
|
+
* top-level browsing context, e.g. all the open browser tabs.
|
|
73
|
+
*
|
|
74
|
+
* @returns {Promise<Array<Page>>}
|
|
75
|
+
*/
|
|
76
|
+
abstract allPages(): Promise<Array<Page>>;
|
|
77
|
+
|
|
78
|
+
abstract cookie(name: string): Promise<Cookie>;
|
|
79
|
+
abstract setCookie(cookieData: CookieData): Promise<void>;
|
|
80
|
+
abstract deleteAllCookies(): Promise<void>;
|
|
81
|
+
|
|
82
|
+
abstract modalDialog(): Promise<ModalDialog>;
|
|
83
|
+
|
|
84
|
+
// todo: remove
|
|
85
|
+
abstract switchToFrame(targetOrIndex: PageElement | number | string): Promise<void>;
|
|
86
|
+
abstract switchToParentFrame(): Promise<void>;
|
|
87
|
+
abstract switchToDefaultContent(): Promise<void>;
|
|
88
|
+
}
|
|
89
|
+
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { Answerable, AnswersQuestions, Interaction, LogicError, UsesAbilities } from '@serenity-js/core';
|
|
2
|
+
import { formatted } from '@serenity-js/core/lib/io';
|
|
3
|
+
|
|
4
|
+
import { PageElement } from '../models';
|
|
5
|
+
import { PageElementInteraction } from './PageElementInteraction';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @desc
|
|
9
|
+
* Instructs the {@link @serenity-js/core/lib/screenplay/actor~Actor} to
|
|
10
|
+
* clear the `value` of a [form `input`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input).
|
|
11
|
+
*
|
|
12
|
+
* @example <caption>Example widget</caption>
|
|
13
|
+
* <form>
|
|
14
|
+
* <input type="text" name="example" id="example" />
|
|
15
|
+
* </form>
|
|
16
|
+
*
|
|
17
|
+
* @example <caption>Lean Page Object describing the widget</caption>
|
|
18
|
+
* import { by, Target } from '@serenity-js/webdriverio';
|
|
19
|
+
*
|
|
20
|
+
* class Form {
|
|
21
|
+
* static exampleInput = Target.the('example input')
|
|
22
|
+
* .located(by.id('example'));
|
|
23
|
+
* }
|
|
24
|
+
*
|
|
25
|
+
* @example <caption>Clearing the value of an input field</caption>
|
|
26
|
+
* import { actorCalled } from '@serenity-js/core';
|
|
27
|
+
* import { BrowseTheWeb, Clear, Enter, Value } from '@serenity-js/webdriverio';
|
|
28
|
+
* import { Ensure, equals } from '@serenity-js/assertions';
|
|
29
|
+
*
|
|
30
|
+
* actorCalled('Inés')
|
|
31
|
+
* .whoCan(BrowseTheWeb.using(browser))
|
|
32
|
+
* .attemptsTo(
|
|
33
|
+
* Enter.theValue('Hello world!').into(Form.exampleInput),
|
|
34
|
+
* Ensure.that(Value.of(Form.exampleInput), equals('Hello world!')),
|
|
35
|
+
*
|
|
36
|
+
* Clear.theValueOf(Form.exampleInput),
|
|
37
|
+
* Ensure.that(Value.of(Form.exampleInput), equals('')),
|
|
38
|
+
* );
|
|
39
|
+
*
|
|
40
|
+
* @see {@link BrowseTheWeb}
|
|
41
|
+
* @see {@link Enter}
|
|
42
|
+
* @see {@link Value}
|
|
43
|
+
* @see {@link Target}
|
|
44
|
+
* @see {@link @serenity-js/assertions~Ensure}
|
|
45
|
+
* @see {@link @serenity-js/assertions/lib/expectations~equals}
|
|
46
|
+
*
|
|
47
|
+
* @extends {@serenity-js/core/lib/screenplay~Interaction}
|
|
48
|
+
*/
|
|
49
|
+
export class Clear extends PageElementInteraction {
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* @desc
|
|
53
|
+
* Instantiates this {@link @serenity-js/core/lib/screenplay~Interaction}.
|
|
54
|
+
*
|
|
55
|
+
* @param {Answerable<PageElement>} field
|
|
56
|
+
* The field to be cleared
|
|
57
|
+
*
|
|
58
|
+
* @returns {@serenity-js/core/lib/screenplay~Interaction}
|
|
59
|
+
*/
|
|
60
|
+
static theValueOf(field: Answerable<PageElement>): Interaction {
|
|
61
|
+
return new Clear(field);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* @param {Answerable<PageElement>} field
|
|
66
|
+
* The element to be clicked on
|
|
67
|
+
*/
|
|
68
|
+
constructor(private readonly field: Answerable<PageElement>) {
|
|
69
|
+
super(formatted `#actor clears the value of ${ field }`);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* @desc
|
|
74
|
+
* Makes the provided {@link @serenity-js/core/lib/screenplay/actor~Actor}
|
|
75
|
+
* perform this {@link @serenity-js/core/lib/screenplay~Interaction}.
|
|
76
|
+
*
|
|
77
|
+
* @param {UsesAbilities & AnswersQuestions} actor
|
|
78
|
+
* An {@link @serenity-js/core/lib/screenplay/actor~Actor} to perform this {@link @serenity-js/core/lib/screenplay~Interaction}
|
|
79
|
+
*
|
|
80
|
+
* @returns {PromiseLike<void>}
|
|
81
|
+
*
|
|
82
|
+
* @see {@link @serenity-js/core/lib/screenplay/actor~Actor}
|
|
83
|
+
* @see {@link @serenity-js/core/lib/screenplay/actor~UsesAbilities}
|
|
84
|
+
* @see {@link @serenity-js/core/lib/screenplay/actor~AnswersQuestions}
|
|
85
|
+
*/
|
|
86
|
+
async performAs(actor: UsesAbilities & AnswersQuestions): Promise<void> {
|
|
87
|
+
const element = await this.resolve(actor, this.field);
|
|
88
|
+
const value = await element.value();
|
|
89
|
+
|
|
90
|
+
if (value === null || value === undefined) {
|
|
91
|
+
throw new LogicError(
|
|
92
|
+
this.capitaliseFirstLetter(formatted `${ this.field } doesn't seem to have a 'value' attribute that could be cleared.`),
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return element.clearValue();
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
private capitaliseFirstLetter(text: string) {
|
|
100
|
+
return text.charAt(0).toUpperCase() + text.slice(1);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { Answerable, AnswersQuestions, Interaction, UsesAbilities } from '@serenity-js/core';
|
|
2
|
+
import { formatted } from '@serenity-js/core/lib/io';
|
|
3
|
+
|
|
4
|
+
import { PageElement } from '../models';
|
|
5
|
+
import { PageElementInteraction } from './PageElementInteraction';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @desc
|
|
9
|
+
* Instructs the {@link @serenity-js/core/lib/screenplay/actor~Actor} to
|
|
10
|
+
* [click](https://developer.mozilla.org/en-US/docs/Web/API/Element/click_event) on a given Web element.
|
|
11
|
+
*
|
|
12
|
+
* @example <caption>Example widget</caption>
|
|
13
|
+
* <form>
|
|
14
|
+
* <input type="text" name="example" id="example" />
|
|
15
|
+
* </form>
|
|
16
|
+
*
|
|
17
|
+
* @example <caption>Lean Page Object describing the widget</caption>
|
|
18
|
+
* import { by, Target } from '@serenity-js/webdriverio';
|
|
19
|
+
*
|
|
20
|
+
* class Form {
|
|
21
|
+
* static exampleInput = Target.the('example input')
|
|
22
|
+
* .located(by.id('example'));
|
|
23
|
+
* }
|
|
24
|
+
*
|
|
25
|
+
* @example <caption>Clicking on an element</caption>
|
|
26
|
+
* import { actorCalled } from '@serenity-js/core';
|
|
27
|
+
* import { BrowseTheWeb, Click, isSelected } from '@serenity-js/webdriverio';
|
|
28
|
+
* import { Ensure } from '@serenity-js/assertions';
|
|
29
|
+
*
|
|
30
|
+
* actorCalled('Chloé')
|
|
31
|
+
* .whoCan(BrowseTheWeb.using(browser))
|
|
32
|
+
* .attemptsTo(
|
|
33
|
+
* Click.on(Form.exampleInput),
|
|
34
|
+
* Ensure.that(Form.exampleInput, isSelected()),
|
|
35
|
+
* );
|
|
36
|
+
*
|
|
37
|
+
* @see {@link BrowseTheWeb}
|
|
38
|
+
* @see {@link Target}
|
|
39
|
+
* @see {@link @serenity-js/assertions~Ensure}
|
|
40
|
+
* @see {@link isSelected}
|
|
41
|
+
*
|
|
42
|
+
* @extends {ElementInteraction}
|
|
43
|
+
*/
|
|
44
|
+
export class Click extends PageElementInteraction {
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* @desc
|
|
48
|
+
* Instantiates this {@link @serenity-js/core/lib/screenplay~Interaction}.
|
|
49
|
+
*
|
|
50
|
+
* @param {Answerable<PageElement>} pageElement
|
|
51
|
+
* The element to be clicked on
|
|
52
|
+
*
|
|
53
|
+
* @returns {@serenity-js/core/lib/screenplay~Interaction}
|
|
54
|
+
*/
|
|
55
|
+
static on(pageElement: Answerable<PageElement>): Interaction {
|
|
56
|
+
return new Click(pageElement);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* @param {Answerable<PageElement>} element
|
|
61
|
+
* The element to be clicked on
|
|
62
|
+
*/
|
|
63
|
+
constructor(private readonly element: Answerable<PageElement>) {
|
|
64
|
+
super(formatted `#actor clicks on ${ element }`);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* @desc
|
|
69
|
+
* Makes the provided {@link @serenity-js/core/lib/screenplay/actor~Actor}
|
|
70
|
+
* perform this {@link @serenity-js/core/lib/screenplay~Interaction}.
|
|
71
|
+
*
|
|
72
|
+
* @param {UsesAbilities & AnswersQuestions} actor
|
|
73
|
+
* An {@link @serenity-js/core/lib/screenplay/actor~Actor} to perform this {@link @serenity-js/core/lib/screenplay~Interaction}
|
|
74
|
+
*
|
|
75
|
+
* @returns {PromiseLike<void>}
|
|
76
|
+
*
|
|
77
|
+
* @see {@link @serenity-js/core/lib/screenplay/actor~Actor}
|
|
78
|
+
* @see {@link @serenity-js/core/lib/screenplay/actor~UsesAbilities}
|
|
79
|
+
* @see {@link @serenity-js/core/lib/screenplay/actor~AnswersQuestions}
|
|
80
|
+
*/
|
|
81
|
+
async performAs(actor: UsesAbilities & AnswersQuestions): Promise<void> {
|
|
82
|
+
const element = await this.resolve(actor, this.element);
|
|
83
|
+
await element.scrollIntoView();
|
|
84
|
+
return element.click();
|
|
85
|
+
}
|
|
86
|
+
}
|