@serenity-js/webdriverio 2.32.2 → 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 +73 -0
- package/lib/adapter/WebdriverIOFrameworkAdapter.js +1 -1
- package/lib/adapter/WebdriverIOFrameworkAdapter.js.map +1 -1
- package/lib/adapter/WebdriverIONotifier.d.ts +35 -1
- package/lib/adapter/WebdriverIONotifier.js +174 -13
- package/lib/adapter/WebdriverIONotifier.js.map +1 -1
- package/lib/index.d.ts +0 -3
- package/lib/index.js +0 -3
- package/lib/index.js.map +1 -1
- package/lib/screenplay/abilities/{BrowseTheWeb.d.ts → BrowseTheWebWithWebdriverIO.d.ts} +79 -23
- package/lib/screenplay/abilities/{BrowseTheWeb.js → BrowseTheWebWithWebdriverIO.js} +160 -25
- package/lib/screenplay/abilities/BrowseTheWebWithWebdriverIO.js.map +1 -0
- package/lib/screenplay/abilities/index.d.ts +1 -1
- package/lib/screenplay/abilities/index.js +1 -1
- package/lib/screenplay/abilities/index.js.map +1 -1
- package/lib/screenplay/index.d.ts +1 -2
- package/lib/screenplay/index.js +1 -2
- package/lib/screenplay/index.js.map +1 -1
- package/lib/screenplay/models/WebdriverIOCookie.d.ts +8 -0
- package/lib/screenplay/models/WebdriverIOCookie.js +39 -0
- package/lib/screenplay/models/WebdriverIOCookie.js.map +1 -0
- package/lib/screenplay/models/WebdriverIOModalDialog.d.ts +11 -0
- package/lib/screenplay/models/WebdriverIOModalDialog.js +40 -0
- package/lib/screenplay/models/WebdriverIOModalDialog.js.map +1 -0
- package/lib/screenplay/models/WebdriverIONativeElementRoot.d.ts +2 -0
- package/lib/screenplay/{interactions/EnterBuilder.js → models/WebdriverIONativeElementRoot.js} +1 -1
- package/lib/screenplay/models/WebdriverIONativeElementRoot.js.map +1 -0
- package/lib/screenplay/models/WebdriverIOPage.d.ts +24 -0
- package/lib/screenplay/models/WebdriverIOPage.js +98 -0
- package/lib/screenplay/models/WebdriverIOPage.js.map +1 -0
- package/lib/screenplay/models/WebdriverIOPageElement.d.ts +22 -0
- package/lib/screenplay/models/WebdriverIOPageElement.js +75 -0
- package/lib/screenplay/models/WebdriverIOPageElement.js.map +1 -0
- package/lib/screenplay/models/WebdriverIOPageElements.d.ts +15 -0
- package/lib/screenplay/models/WebdriverIOPageElements.js +65 -0
- package/lib/screenplay/models/WebdriverIOPageElements.js.map +1 -0
- package/lib/screenplay/models/index.d.ts +6 -0
- package/lib/{input → screenplay/models}/index.js +6 -1
- package/lib/screenplay/models/index.js.map +1 -0
- package/package.json +22 -32
- package/src/adapter/WebdriverIOFrameworkAdapter.ts +2 -0
- package/src/adapter/WebdriverIONotifier.ts +225 -23
- package/src/index.ts +0 -3
- package/src/screenplay/abilities/{BrowseTheWeb.ts → BrowseTheWebWithWebdriverIO.ts} +200 -31
- package/src/screenplay/abilities/index.ts +1 -1
- package/src/screenplay/index.ts +1 -2
- package/src/screenplay/models/WebdriverIOCookie.ts +44 -0
- package/src/screenplay/models/WebdriverIOModalDialog.ts +45 -0
- package/src/screenplay/models/WebdriverIONativeElementRoot.ts +3 -0
- package/src/screenplay/models/WebdriverIOPage.ts +120 -0
- package/src/screenplay/models/WebdriverIOPageElement.ts +92 -0
- package/src/screenplay/models/WebdriverIOPageElements.ts +91 -0
- package/src/screenplay/models/index.ts +6 -0
- package/lib/expectations/ElementExpectation.d.ts +0 -11
- package/lib/expectations/ElementExpectation.js +0 -27
- package/lib/expectations/ElementExpectation.js.map +0 -1
- package/lib/expectations/index.d.ts +0 -6
- package/lib/expectations/index.js +0 -19
- package/lib/expectations/index.js.map +0 -1
- package/lib/expectations/isActive.d.ts +0 -15
- package/lib/expectations/isActive.js +0 -21
- package/lib/expectations/isActive.js.map +0 -1
- package/lib/expectations/isClickable.d.ts +0 -20
- package/lib/expectations/isClickable.js +0 -26
- package/lib/expectations/isClickable.js.map +0 -1
- package/lib/expectations/isEnabled.d.ts +0 -14
- package/lib/expectations/isEnabled.js +0 -20
- package/lib/expectations/isEnabled.js.map +0 -1
- package/lib/expectations/isPresent.d.ts +0 -15
- package/lib/expectations/isPresent.js +0 -21
- package/lib/expectations/isPresent.js.map +0 -1
- package/lib/expectations/isSelected.d.ts +0 -14
- package/lib/expectations/isSelected.js +0 -20
- package/lib/expectations/isSelected.js.map +0 -1
- package/lib/expectations/isVisible.d.ts +0 -14
- package/lib/expectations/isVisible.js +0 -20
- package/lib/expectations/isVisible.js.map +0 -1
- package/lib/input/Key.d.ts +0 -73
- package/lib/input/Key.js +0 -84
- package/lib/input/Key.js.map +0 -1
- package/lib/input/index.d.ts +0 -1
- package/lib/input/index.js.map +0 -1
- package/lib/screenplay/abilities/BrowseTheWeb.js.map +0 -1
- package/lib/screenplay/interactions/Clear.d.ts +0 -79
- package/lib/screenplay/interactions/Clear.js +0 -97
- package/lib/screenplay/interactions/Clear.js.map +0 -1
- package/lib/screenplay/interactions/Click.d.ts +0 -73
- package/lib/screenplay/interactions/Click.js +0 -84
- package/lib/screenplay/interactions/Click.js.map +0 -1
- package/lib/screenplay/interactions/DoubleClick.d.ts +0 -90
- package/lib/screenplay/interactions/DoubleClick.js +0 -101
- package/lib/screenplay/interactions/DoubleClick.js.map +0 -1
- package/lib/screenplay/interactions/Enter.d.ts +0 -73
- package/lib/screenplay/interactions/Enter.js +0 -87
- package/lib/screenplay/interactions/Enter.js.map +0 -1
- package/lib/screenplay/interactions/EnterBuilder.d.ts +0 -25
- package/lib/screenplay/interactions/EnterBuilder.js.map +0 -1
- package/lib/screenplay/interactions/ExecuteScript.d.ts +0 -206
- package/lib/screenplay/interactions/ExecuteScript.js +0 -311
- package/lib/screenplay/interactions/ExecuteScript.js.map +0 -1
- package/lib/screenplay/interactions/Hover.d.ts +0 -78
- package/lib/screenplay/interactions/Hover.js +0 -89
- package/lib/screenplay/interactions/Hover.js.map +0 -1
- package/lib/screenplay/interactions/Navigate.d.ts +0 -141
- package/lib/screenplay/interactions/Navigate.js +0 -197
- package/lib/screenplay/interactions/Navigate.js.map +0 -1
- package/lib/screenplay/interactions/Press.d.ts +0 -84
- package/lib/screenplay/interactions/Press.js +0 -152
- package/lib/screenplay/interactions/Press.js.map +0 -1
- package/lib/screenplay/interactions/PressBuilder.d.ts +0 -26
- package/lib/screenplay/interactions/PressBuilder.js +0 -3
- package/lib/screenplay/interactions/PressBuilder.js.map +0 -1
- package/lib/screenplay/interactions/RightClick.d.ts +0 -89
- package/lib/screenplay/interactions/RightClick.js +0 -100
- package/lib/screenplay/interactions/RightClick.js.map +0 -1
- package/lib/screenplay/interactions/Scroll.d.ts +0 -75
- package/lib/screenplay/interactions/Scroll.js +0 -86
- package/lib/screenplay/interactions/Scroll.js.map +0 -1
- package/lib/screenplay/interactions/Wait.d.ts +0 -143
- package/lib/screenplay/interactions/Wait.js +0 -247
- package/lib/screenplay/interactions/Wait.js.map +0 -1
- package/lib/screenplay/interactions/WaitBuilder.d.ts +0 -32
- package/lib/screenplay/interactions/WaitBuilder.js +0 -3
- package/lib/screenplay/interactions/WaitBuilder.js.map +0 -1
- package/lib/screenplay/interactions/WebElementInteraction.d.ts +0 -37
- package/lib/screenplay/interactions/WebElementInteraction.js +0 -52
- package/lib/screenplay/interactions/WebElementInteraction.js.map +0 -1
- package/lib/screenplay/interactions/index.d.ts +0 -13
- package/lib/screenplay/interactions/index.js +0 -26
- package/lib/screenplay/interactions/index.js.map +0 -1
- package/lib/screenplay/questions/Attribute.d.ts +0 -82
- package/lib/screenplay/questions/Attribute.js +0 -102
- package/lib/screenplay/questions/Attribute.js.map +0 -1
- package/lib/screenplay/questions/CSSClasses.d.ts +0 -92
- package/lib/screenplay/questions/CSSClasses.js +0 -112
- package/lib/screenplay/questions/CSSClasses.js.map +0 -1
- package/lib/screenplay/questions/LastScriptExecution.d.ts +0 -14
- package/lib/screenplay/questions/LastScriptExecution.js +0 -22
- package/lib/screenplay/questions/LastScriptExecution.js.map +0 -1
- package/lib/screenplay/questions/NestedTargetBuilder.d.ts +0 -27
- package/lib/screenplay/questions/NestedTargetBuilder.js +0 -3
- package/lib/screenplay/questions/NestedTargetBuilder.js.map +0 -1
- package/lib/screenplay/questions/TargetBuilder.d.ts +0 -25
- package/lib/screenplay/questions/TargetBuilder.js +0 -3
- package/lib/screenplay/questions/TargetBuilder.js.map +0 -1
- package/lib/screenplay/questions/Text.d.ts +0 -95
- package/lib/screenplay/questions/Text.js +0 -130
- package/lib/screenplay/questions/Text.js.map +0 -1
- package/lib/screenplay/questions/Value.d.ts +0 -63
- package/lib/screenplay/questions/Value.js +0 -78
- package/lib/screenplay/questions/Value.js.map +0 -1
- package/lib/screenplay/questions/Website.d.ts +0 -21
- package/lib/screenplay/questions/Website.js +0 -31
- package/lib/screenplay/questions/Website.js.map +0 -1
- package/lib/screenplay/questions/index.d.ts +0 -10
- package/lib/screenplay/questions/index.js +0 -23
- package/lib/screenplay/questions/index.js.map +0 -1
- package/lib/screenplay/questions/lists.d.ts +0 -86
- package/lib/screenplay/questions/lists.js +0 -137
- package/lib/screenplay/questions/lists.js.map +0 -1
- package/lib/screenplay/questions/locators.d.ts +0 -196
- package/lib/screenplay/questions/locators.js +0 -219
- package/lib/screenplay/questions/locators.js.map +0 -1
- package/lib/screenplay/questions/targets.d.ts +0 -254
- package/lib/screenplay/questions/targets.js +0 -334
- package/lib/screenplay/questions/targets.js.map +0 -1
- package/lib/stage/crew/index.d.ts +0 -1
- package/lib/stage/crew/index.js +0 -14
- package/lib/stage/crew/index.js.map +0 -1
- package/lib/stage/crew/photographer/Photographer.d.ts +0 -83
- package/lib/stage/crew/photographer/Photographer.js +0 -102
- package/lib/stage/crew/photographer/Photographer.js.map +0 -1
- package/lib/stage/crew/photographer/index.d.ts +0 -2
- package/lib/stage/crew/photographer/index.js +0 -15
- package/lib/stage/crew/photographer/index.js.map +0 -1
- package/lib/stage/crew/photographer/strategies/PhotoTakingStrategy.d.ts +0 -28
- package/lib/stage/crew/photographer/strategies/PhotoTakingStrategy.js +0 -65
- package/lib/stage/crew/photographer/strategies/PhotoTakingStrategy.js.map +0 -1
- package/lib/stage/crew/photographer/strategies/TakePhotosBeforeAndAfterInteractions.d.ts +0 -18
- package/lib/stage/crew/photographer/strategies/TakePhotosBeforeAndAfterInteractions.js +0 -30
- package/lib/stage/crew/photographer/strategies/TakePhotosBeforeAndAfterInteractions.js.map +0 -1
- package/lib/stage/crew/photographer/strategies/TakePhotosOfFailures.d.ts +0 -17
- package/lib/stage/crew/photographer/strategies/TakePhotosOfFailures.js +0 -28
- package/lib/stage/crew/photographer/strategies/TakePhotosOfFailures.js.map +0 -1
- package/lib/stage/crew/photographer/strategies/TakePhotosOfInteractions.d.ts +0 -19
- package/lib/stage/crew/photographer/strategies/TakePhotosOfInteractions.js +0 -28
- package/lib/stage/crew/photographer/strategies/TakePhotosOfInteractions.js.map +0 -1
- package/lib/stage/crew/photographer/strategies/index.d.ts +0 -4
- package/lib/stage/crew/photographer/strategies/index.js +0 -17
- package/lib/stage/crew/photographer/strategies/index.js.map +0 -1
- package/lib/stage/index.d.ts +0 -1
- package/lib/stage/index.js +0 -14
- package/lib/stage/index.js.map +0 -1
- package/src/expectations/ElementExpectation.ts +0 -31
- package/src/expectations/index.ts +0 -6
- package/src/expectations/isActive.ts +0 -21
- package/src/expectations/isClickable.ts +0 -26
- package/src/expectations/isEnabled.ts +0 -19
- package/src/expectations/isPresent.ts +0 -20
- package/src/expectations/isSelected.ts +0 -19
- package/src/expectations/isVisible.ts +0 -19
- package/src/input/Key.ts +0 -83
- package/src/input/index.ts +0 -1
- package/src/screenplay/interactions/Clear.ts +0 -102
- package/src/screenplay/interactions/Click.ts +0 -85
- package/src/screenplay/interactions/DoubleClick.ts +0 -102
- package/src/screenplay/interactions/Enter.ts +0 -93
- package/src/screenplay/interactions/EnterBuilder.ts +0 -27
- package/src/screenplay/interactions/ExecuteScript.ts +0 -344
- package/src/screenplay/interactions/Hover.ts +0 -90
- package/src/screenplay/interactions/Navigate.ts +0 -208
- package/src/screenplay/interactions/Press.ts +0 -172
- package/src/screenplay/interactions/PressBuilder.ts +0 -28
- package/src/screenplay/interactions/RightClick.ts +0 -100
- package/src/screenplay/interactions/Scroll.ts +0 -87
- package/src/screenplay/interactions/Wait.ts +0 -267
- package/src/screenplay/interactions/WaitBuilder.ts +0 -34
- package/src/screenplay/interactions/WebElementInteraction.ts +0 -56
- package/src/screenplay/interactions/index.ts +0 -13
- package/src/screenplay/questions/Attribute.ts +0 -112
- package/src/screenplay/questions/CSSClasses.ts +0 -116
- package/src/screenplay/questions/LastScriptExecution.ts +0 -21
- package/src/screenplay/questions/NestedTargetBuilder.ts +0 -30
- package/src/screenplay/questions/TargetBuilder.ts +0 -27
- package/src/screenplay/questions/Text.ts +0 -140
- package/src/screenplay/questions/Value.ts +0 -82
- package/src/screenplay/questions/Website.ts +0 -34
- package/src/screenplay/questions/index.ts +0 -10
- package/src/screenplay/questions/lists.ts +0 -161
- package/src/screenplay/questions/locators.ts +0 -254
- package/src/screenplay/questions/targets.ts +0 -401
- package/src/stage/crew/index.ts +0 -1
- package/src/stage/crew/photographer/Photographer.ts +0 -108
- package/src/stage/crew/photographer/index.ts +0 -2
- package/src/stage/crew/photographer/strategies/PhotoTakingStrategy.ts +0 -103
- package/src/stage/crew/photographer/strategies/TakePhotosBeforeAndAfterInteractions.ts +0 -28
- package/src/stage/crew/photographer/strategies/TakePhotosOfFailures.ts +0 -26
- package/src/stage/crew/photographer/strategies/TakePhotosOfInteractions.ts +0 -26
- package/src/stage/crew/photographer/strategies/index.ts +0 -4
- package/src/stage/index.ts +0 -1
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
import { Answerable, AnswersQuestions, MetaQuestion, Question, UsesAbilities } from '@serenity-js/core';
|
|
2
|
-
import type { Element, ElementArray } from 'webdriverio';
|
|
3
|
-
|
|
4
|
-
import { TargetNestedElement, TargetNestedElements } from './targets';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* @desc
|
|
8
|
-
* Resolves to the visible (i.e. not hidden by CSS) `innerText` of:
|
|
9
|
-
* - a given {@link WebElement}, represented by Answerable<{@link @wdio/types~Element}>
|
|
10
|
-
* - a group of {@link WebElement}s, represented by Answerable<{@link @wdio/types~ElementArray}>
|
|
11
|
-
*
|
|
12
|
-
* The result includes the visible text of any sub-elements, without any leading or trailing whitespace.
|
|
13
|
-
*
|
|
14
|
-
* @example <caption>Example widget</caption>
|
|
15
|
-
* <h1>Shopping list</h1>
|
|
16
|
-
* <ul id="shopping-list">
|
|
17
|
-
* <li>Coffee<li>
|
|
18
|
-
* <li class="bought">Honey<li>
|
|
19
|
-
* <li>Chocolate<li>
|
|
20
|
-
* </ul>
|
|
21
|
-
*
|
|
22
|
-
* @example <caption>Retrieve text of a single element</caption>
|
|
23
|
-
* import { actorCalled } from '@serenity-js/core';
|
|
24
|
-
* import { Ensure, equals } from '@serenity-js/assertions';
|
|
25
|
-
* import { BrowseTheWeb, by, Target, Text } from '@serenity-js/webdriverio';
|
|
26
|
-
*
|
|
27
|
-
* const header = () =>
|
|
28
|
-
* Target.the('header').located(by.tagName('h1'))
|
|
29
|
-
*
|
|
30
|
-
* actorCalled('Lisa')
|
|
31
|
-
* .whoCan(BrowseTheWeb.using(browser))
|
|
32
|
-
* .attemptsTo(
|
|
33
|
-
* Ensure.that(Text.of(header()), equals('Shopping list')),
|
|
34
|
-
* )
|
|
35
|
-
*
|
|
36
|
-
* @example <caption>Retrieve text of a multiple elements</caption>
|
|
37
|
-
* import { actorCalled } from '@serenity-js/core';
|
|
38
|
-
* import { Ensure, equals } from '@serenity-js/assertions';
|
|
39
|
-
* import { BrowseTheWeb, by, Target, Text } from '@serenity-js/webdriverio';
|
|
40
|
-
*
|
|
41
|
-
* const shoppingListItems = () =>
|
|
42
|
-
* Target.the('shopping list items').located(by.css('#shopping-list li'))
|
|
43
|
-
*
|
|
44
|
-
* actorCalled('Lisa')
|
|
45
|
-
* .whoCan(BrowseTheWeb.using(browser))
|
|
46
|
-
* .attemptsTo(
|
|
47
|
-
* Ensure.that(
|
|
48
|
-
* Text.ofAll(shoppingListItems()),
|
|
49
|
-
* equals([ 'Coffee', 'Honey', 'Chocolate' ])
|
|
50
|
-
* ),
|
|
51
|
-
* )
|
|
52
|
-
*
|
|
53
|
-
* @example <caption>Find element with matching text</caption>
|
|
54
|
-
* import { actorCalled } from '@serenity-js/core';
|
|
55
|
-
* import { contain, Ensure } from '@serenity-js/assertions';
|
|
56
|
-
* import { BrowseTheWeb, by, CSSClasses, Target, Text } from '@serenity-js/webdriverio';
|
|
57
|
-
*
|
|
58
|
-
* const shoppingListItemCalled = (name: string) =>
|
|
59
|
-
* Target.the('shopping list items').located(by.css('#shopping-list li'))
|
|
60
|
-
* .where(Text, equals(name))
|
|
61
|
-
* .first()
|
|
62
|
-
*
|
|
63
|
-
* actorCalled('Lisa')
|
|
64
|
-
* .whoCan(BrowseTheWeb.using(browser))
|
|
65
|
-
* .attemptsTo(
|
|
66
|
-
* Ensure.that(
|
|
67
|
-
* CSSClasses.of(shoppingListItemCalled('Honey)),
|
|
68
|
-
* contain('bought')
|
|
69
|
-
* ),
|
|
70
|
-
* )
|
|
71
|
-
*
|
|
72
|
-
* @public
|
|
73
|
-
* @see {@link Target}
|
|
74
|
-
*/
|
|
75
|
-
export class Text {
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* @desc
|
|
79
|
-
* Retrieves text of a single {@link WebElement},
|
|
80
|
-
* represented by Answerable<{@link @wdio/types~Element}>.
|
|
81
|
-
*
|
|
82
|
-
* @param {Answerable<Element<'async'>>} element
|
|
83
|
-
* @returns {Question<Promise<string>> & MetaQuestion<Answerable<Element<'async'>>, Promise<string>>}
|
|
84
|
-
*
|
|
85
|
-
* @see {@link @serenity-js/core/lib/screenplay/questions~MetaQuestion}
|
|
86
|
-
*/
|
|
87
|
-
static of(element: Answerable<Element<'async'>>): Question<Promise<string>> & MetaQuestion<Answerable<Element<'async'>>, Promise<string>> {
|
|
88
|
-
return new TextOfSingleElement(element);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* @desc
|
|
93
|
-
* Retrieves text of a group of {@link WebElement}s,
|
|
94
|
-
* represented by Answerable<{@link @wdio/types~ElementArray}>
|
|
95
|
-
*
|
|
96
|
-
* @param {Answerable<ElementArray>} elements
|
|
97
|
-
* @returns {Question<Promise<string[]>> & MetaQuestion<Answerable<Element<'async'>>, Promise<string[]>>}
|
|
98
|
-
*
|
|
99
|
-
* @see {@link @serenity-js/core/lib/screenplay/questions~MetaQuestion}
|
|
100
|
-
*/
|
|
101
|
-
static ofAll(elements: Answerable<ElementArray>): Question<Promise<string[]>> & MetaQuestion<Answerable<Element<'async'>>, Promise<string[]>> {
|
|
102
|
-
return new TextOfMultipleElements(elements);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
class TextOfSingleElement
|
|
107
|
-
extends Question<Promise<string>>
|
|
108
|
-
implements MetaQuestion<Answerable<Element<'async'>>, Promise<string>>
|
|
109
|
-
{
|
|
110
|
-
constructor(private readonly element: Answerable<Element<'async'>>) {
|
|
111
|
-
super(`the text of ${ element }`);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
of(parent: Answerable<Element<'async'>>): Question<Promise<string>> {
|
|
115
|
-
return new TextOfSingleElement(new TargetNestedElement(parent, this.element));
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
answeredBy(actor: AnswersQuestions & UsesAbilities): Promise<string> {
|
|
119
|
-
return actor.answer(this.element)
|
|
120
|
-
.then(element => element.getText())
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
class TextOfMultipleElements
|
|
125
|
-
extends Question<Promise<string[]>>
|
|
126
|
-
implements MetaQuestion<Answerable<Element<'async'>>, Promise<string[]>>
|
|
127
|
-
{
|
|
128
|
-
constructor(private readonly elements: Answerable<ElementArray>) {
|
|
129
|
-
super(`the text of ${ elements }`);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
of(parent: Answerable<Element<'async'>>): Question<Promise<string[]>> {
|
|
133
|
-
return new TextOfMultipleElements(new TargetNestedElements(parent, this.elements));
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
async answeredBy(actor: AnswersQuestions & UsesAbilities): Promise<string[]> {
|
|
137
|
-
const elements = await actor.answer(this.elements);
|
|
138
|
-
return Promise.all(elements.map(answer => answer.getText()));
|
|
139
|
-
}
|
|
140
|
-
}
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
import { Answerable, AnswersQuestions, MetaQuestion, Question, UsesAbilities } from '@serenity-js/core';
|
|
2
|
-
import { formatted } from '@serenity-js/core/lib/io';
|
|
3
|
-
import { Element } from 'webdriverio';
|
|
4
|
-
|
|
5
|
-
import { TargetNestedElement } from './targets';
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* @desc
|
|
9
|
-
* Returns the `value` attribute of a given {@link WebElement},
|
|
10
|
-
* represented by Answerable<{@link @wdio/types~Element}>
|
|
11
|
-
*
|
|
12
|
-
* @example <caption>Example widget</caption>
|
|
13
|
-
* <input type="text" id="username" value="Alice" />
|
|
14
|
-
*
|
|
15
|
-
* @example <caption>Retrieve CSS classes of a given WebElement</caption>
|
|
16
|
-
* import { actorCalled } from '@serenity-js/core';
|
|
17
|
-
* import { Ensure, equals } from '@serenity-js/assertions';
|
|
18
|
-
* import { BrowseTheWeb, by, Value, Target } from '@serenity-js/webdriverio';
|
|
19
|
-
*
|
|
20
|
-
* const usernameField = () =>
|
|
21
|
-
* Target.the('username field').located(by.id('username'))
|
|
22
|
-
*
|
|
23
|
-
* actorCalled('Lisa')
|
|
24
|
-
* .whoCan(BrowseTheWeb.using(browser))
|
|
25
|
-
* .attemptsTo(
|
|
26
|
-
* Ensure.that(Value.of(usernameField), equals('Alice')),
|
|
27
|
-
* )
|
|
28
|
-
*
|
|
29
|
-
* @extends {@serenity-js/core/lib/screenplay~Question}
|
|
30
|
-
* @implements {@serenity-js/core/lib/screenplay/questions~MetaQuestion}
|
|
31
|
-
*/
|
|
32
|
-
export class Value
|
|
33
|
-
extends Question<Promise<string>>
|
|
34
|
-
implements MetaQuestion<Answerable<Element<'async'>>, Promise<string>>
|
|
35
|
-
{
|
|
36
|
-
/**
|
|
37
|
-
* @param {Answerable<Element<'async'>>} element
|
|
38
|
-
* @returns {Value}
|
|
39
|
-
*/
|
|
40
|
-
static of(element: Answerable<Element<'async'>>): Question<Promise<string>> & MetaQuestion<Answerable<Element<'async'>>, Promise<string>> {
|
|
41
|
-
return new Value(element);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* @param {Answerable<Element<'async'>>} element
|
|
46
|
-
*/
|
|
47
|
-
constructor(private readonly element: Answerable<Element<'async'>>) {
|
|
48
|
-
super(formatted`the value of ${ element }`);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* @desc
|
|
53
|
-
* Resolves to the value of a given [`input`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input)
|
|
54
|
-
* {@link WebElement}, located in the context of a `parent` element.
|
|
55
|
-
*
|
|
56
|
-
* @param {Answerable<Element<'async'>>} parent
|
|
57
|
-
* @returns {Question<Promise<string>>}
|
|
58
|
-
*
|
|
59
|
-
* @see {@link @serenity-js/core/lib/screenplay/questions~MetaQuestion}
|
|
60
|
-
*/
|
|
61
|
-
of(parent: Answerable<Element<'async'>>): Question<Promise<string>> {
|
|
62
|
-
return new Value(new TargetNestedElement(parent, this.element));
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* @desc
|
|
67
|
-
* Makes the provided {@link @serenity-js/core/lib/screenplay/actor~Actor}
|
|
68
|
-
* answer this {@link @serenity-js/core/lib/screenplay~Question}.
|
|
69
|
-
*
|
|
70
|
-
* @param {AnswersQuestions & UsesAbilities} actor
|
|
71
|
-
* @returns {Promise<void>}
|
|
72
|
-
*
|
|
73
|
-
* @see {@link @serenity-js/core/lib/screenplay/actor~Actor}
|
|
74
|
-
* @see {@link @serenity-js/core/lib/screenplay/actor~AnswersQuestions}
|
|
75
|
-
* @see {@link @serenity-js/core/lib/screenplay/actor~UsesAbilities}
|
|
76
|
-
*/
|
|
77
|
-
async answeredBy(actor: AnswersQuestions & UsesAbilities): Promise<string> {
|
|
78
|
-
const element = await actor.answer(this.element);
|
|
79
|
-
|
|
80
|
-
return element.getValue();
|
|
81
|
-
}
|
|
82
|
-
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { Question } from '@serenity-js/core';
|
|
2
|
-
|
|
3
|
-
import { BrowseTheWeb } from '../abilities';
|
|
4
|
-
|
|
5
|
-
export class Website {
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* @desc
|
|
9
|
-
* Retrieves the document title of the current top-level browsing context, equivalent to calling `document.title`.
|
|
10
|
-
*
|
|
11
|
-
* @returns {@serenity-js/core/lib/screenplay~Question<Promise<string>>}
|
|
12
|
-
*
|
|
13
|
-
* @see https://webdriver.io/docs/api/webdriver/#gettitle
|
|
14
|
-
*/
|
|
15
|
-
static title(): Question<Promise<string>> {
|
|
16
|
-
return Question.about(`the title of the current page`, actor =>
|
|
17
|
-
BrowseTheWeb.as(actor).browser.getTitle(),
|
|
18
|
-
);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* @desc
|
|
23
|
-
* Retrieves the URL of the current top-level browsing context.
|
|
24
|
-
*
|
|
25
|
-
* @returns {@serenity-js/core/lib/screenplay~Question<Promise<string>>}
|
|
26
|
-
*
|
|
27
|
-
* @see https://webdriver.io/docs/api/webdriver/#geturl
|
|
28
|
-
*/
|
|
29
|
-
static url(): Question<Promise<string>> {
|
|
30
|
-
return Question.about(`the url of the current page`, actor =>
|
|
31
|
-
BrowseTheWeb.as(actor).browser.getUrl(),
|
|
32
|
-
);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
export * from './Attribute';
|
|
2
|
-
export * from './CSSClasses';
|
|
3
|
-
export * from './LastScriptExecution';
|
|
4
|
-
export * from './locators';
|
|
5
|
-
export * from './NestedTargetBuilder';
|
|
6
|
-
export * from './TargetBuilder';
|
|
7
|
-
export * from './targets';
|
|
8
|
-
export * from './Text';
|
|
9
|
-
export * from './Value';
|
|
10
|
-
export * from './Website';
|
|
@@ -1,161 +0,0 @@
|
|
|
1
|
-
import { Answerable, AnswersQuestions, Expectation, ExpectationMet, MetaQuestion, Question, UsesAbilities } from '@serenity-js/core';
|
|
2
|
-
import { formatted } from '@serenity-js/core/lib/io';
|
|
3
|
-
import { ListAdapter } from '@serenity-js/core/lib/screenplay/questions/lists';
|
|
4
|
-
import type { Element, ElementArray } from 'webdriverio';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* @desc
|
|
8
|
-
* Adapts {@link ElementArray} so that it can be used with {@link @serenity-js/core/lib/screenplay/questions~List}.
|
|
9
|
-
*
|
|
10
|
-
* You most likely won't need to use this class directly. Instead, check out {@link Target} and {@link Target.all}.
|
|
11
|
-
*
|
|
12
|
-
* @see {@link Target}
|
|
13
|
-
*
|
|
14
|
-
* @implements {@serenity-js/core/lib/screenplay/questions/lists~ListAdapter}
|
|
15
|
-
*/
|
|
16
|
-
export class ElementArrayListAdapter implements ListAdapter<Promise<Element<'async'>>, Promise<ElementArray>> {
|
|
17
|
-
|
|
18
|
-
constructor(private readonly collection: Answerable<ElementArray>) {
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* @desc
|
|
23
|
-
* Returns the number of {@link Element}s that the underlying {@link ElementArray} contains,
|
|
24
|
-
* left after applying any filters.
|
|
25
|
-
*
|
|
26
|
-
* @param {AnswersQuestions & UsesAbilities} actor
|
|
27
|
-
* @returns {Promise<number>}
|
|
28
|
-
*/
|
|
29
|
-
async count(actor: AnswersQuestions & UsesAbilities): Promise<number> {
|
|
30
|
-
const elements = await this.elements(actor);
|
|
31
|
-
return elements.length;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* @desc
|
|
36
|
-
* Returns the first of {@link Element}s that the underlying {@link ElementArray} contains,
|
|
37
|
-
* left after applying any filters
|
|
38
|
-
*
|
|
39
|
-
* @param {AnswersQuestions & UsesAbilities} actor
|
|
40
|
-
* @returns {Element<'async'>}
|
|
41
|
-
*/
|
|
42
|
-
async first(actor: AnswersQuestions & UsesAbilities): Promise<Element<'async'>> {
|
|
43
|
-
const elements = await this.elements(actor);
|
|
44
|
-
return elements[0];
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* @desc
|
|
49
|
-
* Returns the last of {@link Element}s that the underlying {@link ElementArray} contains,
|
|
50
|
-
* left after applying any filters
|
|
51
|
-
*
|
|
52
|
-
* @param {AnswersQuestions & UsesAbilities} actor
|
|
53
|
-
* @returns {Element<'async'>}
|
|
54
|
-
*/
|
|
55
|
-
async last(actor: AnswersQuestions & UsesAbilities): Promise<Element<'async'>> {
|
|
56
|
-
const elements = await this.elements(actor);
|
|
57
|
-
return elements[elements.length - 1];
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* @desc
|
|
62
|
-
* Returns the nth of {@link Element}s that the underlying {@link ElementArray} contains,
|
|
63
|
-
* left after applying any filters
|
|
64
|
-
*
|
|
65
|
-
* @param {AnswersQuestions & UsesAbilities} actor
|
|
66
|
-
*
|
|
67
|
-
* @param {number} index
|
|
68
|
-
* Zero-based index of the item to return
|
|
69
|
-
*
|
|
70
|
-
* @returns {Element<'async'>}
|
|
71
|
-
*/
|
|
72
|
-
async get(actor: AnswersQuestions & UsesAbilities, index: number): Promise<Element<'async'>> {
|
|
73
|
-
const elements = await this.elements(actor);
|
|
74
|
-
return elements[index];
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* @desc
|
|
79
|
-
* Returns the underlying {@link ElementArray},
|
|
80
|
-
* with any filters applied.
|
|
81
|
-
*
|
|
82
|
-
* @param {AnswersQuestions & UsesAbilities} actor
|
|
83
|
-
* @returns {Element<'async'>}
|
|
84
|
-
*/
|
|
85
|
-
items(actor: AnswersQuestions & UsesAbilities): Promise<ElementArray> {
|
|
86
|
-
return this.elements(actor);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* @desc
|
|
91
|
-
* Filters the underlying {@link ElementArray} so that the result contains only those {@link Element<'async'>}s that meet the {@link Expectation}
|
|
92
|
-
*
|
|
93
|
-
* @param {@serenity-js/core/lib/screenplay/questions~MetaQuestion<Answerable<Element<'async'>>, Promise<Answer_Type> | Answer_Type>} question
|
|
94
|
-
* @param {@serenity-js/core/lib/screenplay/questions~Expectation<any, Answer_Type>} expectation
|
|
95
|
-
*
|
|
96
|
-
* @returns {@serenity-js/core/lib/screenplay/questions/lists~ListAdapter<Element<'async'>, ElementArrayFinder>}
|
|
97
|
-
*
|
|
98
|
-
* @see {@link @serenity-js/core/lib/screenplay/questions~MetaQuestion}
|
|
99
|
-
*/
|
|
100
|
-
withFilter<Answer_Type>(
|
|
101
|
-
question: MetaQuestion<Answerable<Element<'async'>>, Promise<Answer_Type> | Answer_Type>,
|
|
102
|
-
expectation: Expectation<any, Answer_Type>
|
|
103
|
-
): ListAdapter<Promise<Element<'async'>>, Promise<ElementArray>> {
|
|
104
|
-
return new ElementArrayListAdapter(
|
|
105
|
-
new ElementArrayListFilter(this.collection, question, expectation)
|
|
106
|
-
);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* @desc
|
|
111
|
-
* Returns a human-readable description of the underlying {@link ElementArray}.
|
|
112
|
-
*
|
|
113
|
-
* @returns {string}
|
|
114
|
-
*/
|
|
115
|
-
toString(): string {
|
|
116
|
-
return formatted `${ this.collection }`;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
private elements(actor: AnswersQuestions & UsesAbilities): Promise<ElementArray> {
|
|
120
|
-
return actor.answer(this.collection);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* @private
|
|
126
|
-
*/
|
|
127
|
-
class ElementArrayListFilter<Answer_Type>
|
|
128
|
-
extends Question<Promise<ElementArray>>
|
|
129
|
-
{
|
|
130
|
-
constructor(
|
|
131
|
-
private readonly collection: Answerable<ElementArray>,
|
|
132
|
-
private readonly question: MetaQuestion<Answerable<Element<'async'>>, Promise<Answer_Type> | Answer_Type>,
|
|
133
|
-
private readonly expectation: Expectation<any, Answer_Type>
|
|
134
|
-
) {
|
|
135
|
-
super([
|
|
136
|
-
formatted `${ collection }`,
|
|
137
|
-
collection instanceof ElementArrayListFilter ? 'and' : 'where',
|
|
138
|
-
formatted `${ question } does ${ expectation }`
|
|
139
|
-
].join(' '));
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
async answeredBy(actor: AnswersQuestions & UsesAbilities): Promise<ElementArray> {
|
|
143
|
-
|
|
144
|
-
const collection = await actor.answer(this.collection);
|
|
145
|
-
const outcomes = await Promise.all(
|
|
146
|
-
collection.map((element: Element<'async'>) =>
|
|
147
|
-
actor.answer(this.question.of(element))
|
|
148
|
-
.then((answer: Answer_Type) => this.expectation.answeredBy(actor)(answer))
|
|
149
|
-
)
|
|
150
|
-
);
|
|
151
|
-
|
|
152
|
-
const matching = collection.filter((element: Element<'async'>, index: number) => outcomes[index] instanceof ExpectationMet) as ElementArray;
|
|
153
|
-
|
|
154
|
-
matching.selector = collection.selector;
|
|
155
|
-
matching.parent = collection.parent;
|
|
156
|
-
matching.foundWith = collection.foundWith;
|
|
157
|
-
matching.props = collection.props;
|
|
158
|
-
|
|
159
|
-
return matching;
|
|
160
|
-
}
|
|
161
|
-
}
|
|
@@ -1,254 +0,0 @@
|
|
|
1
|
-
import { Question } from '@serenity-js/core';
|
|
2
|
-
import type { Browser, Element, ElementArray, Selector } from 'webdriverio';
|
|
3
|
-
|
|
4
|
-
import { BrowseTheWeb } from '../abilities';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* @desc
|
|
8
|
-
* Represents a way to retrieve one and multiple Web elements using a given strategy.
|
|
9
|
-
*
|
|
10
|
-
* @see {@link by}
|
|
11
|
-
* @see {@link Locators}
|
|
12
|
-
*/
|
|
13
|
-
export class Locator {
|
|
14
|
-
constructor(
|
|
15
|
-
private readonly description: string,
|
|
16
|
-
private readonly locateOne: (browserInstance: Browser<'async'>) => Promise<Element<'async'>>,
|
|
17
|
-
private readonly locateAll: (browserInstance: Browser<'async'>) => Promise<ElementArray>,
|
|
18
|
-
) {
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* @desc
|
|
23
|
-
* Returns a {@link @serenity-js/core/lib/screenplay~Question} that resolves
|
|
24
|
-
* to the first Web element found using a given strategy.
|
|
25
|
-
*
|
|
26
|
-
* @returns {@serenity-js/core/lib/screenplay~Question<Promise<Element<'async'>>>}
|
|
27
|
-
*/
|
|
28
|
-
firstMatching(): Question<Promise<Element<'async'>>> {
|
|
29
|
-
return Question.about(this.description, actor =>
|
|
30
|
-
this.locateOne(BrowseTheWeb.as(actor).browser)
|
|
31
|
-
)
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* @desc
|
|
36
|
-
* Returns a {@link @serenity-js/core/lib/screenplay~Question} that resolves
|
|
37
|
-
* to all the Web elements found using a given strategy.
|
|
38
|
-
*
|
|
39
|
-
* @returns {@serenity-js/core/lib/screenplay~Question<Promise<ElementArray>>}
|
|
40
|
-
*/
|
|
41
|
-
allMatching(): Question<Promise<ElementArray>> {
|
|
42
|
-
return Question.about(this.description, actor =>
|
|
43
|
-
this.locateAll(BrowseTheWeb.as(actor).browser)
|
|
44
|
-
)
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* @desc
|
|
50
|
-
* {@link Locator} factory. You probably want to use {@link by} instead in your tests.
|
|
51
|
-
*/
|
|
52
|
-
export class Locators {
|
|
53
|
-
/**
|
|
54
|
-
* @desc
|
|
55
|
-
* Locates elements by their `id` attribute.
|
|
56
|
-
*
|
|
57
|
-
* @example <caption>Example widget</caption>
|
|
58
|
-
* <input id="username" />
|
|
59
|
-
*
|
|
60
|
-
* @example
|
|
61
|
-
* import { by, Target } from '@serenity-js/webdriverio';
|
|
62
|
-
*
|
|
63
|
-
* const usernameField = Target.the('username field').located(by.id('username'));
|
|
64
|
-
*
|
|
65
|
-
* @param {string} id
|
|
66
|
-
* @returns {Locator}
|
|
67
|
-
*
|
|
68
|
-
* @see {@link Target}
|
|
69
|
-
* @see https://webdriver.io/docs/selectors/#id
|
|
70
|
-
*/
|
|
71
|
-
id(id: string): Locator {
|
|
72
|
-
return new Locator(
|
|
73
|
-
`by id #${ id }`,
|
|
74
|
-
browser => browser.$(`#${id}`) as unknown as Promise<Element<'async'>>,
|
|
75
|
-
browser => browser.$$(`#${id}`),
|
|
76
|
-
)
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* @desc
|
|
81
|
-
* Locates elements using a CSS selector
|
|
82
|
-
*
|
|
83
|
-
* @example <caption>Example widget</caption>
|
|
84
|
-
* <div id="article">
|
|
85
|
-
* <h1>Title</h1>
|
|
86
|
-
* <h2>Section 1</h2>
|
|
87
|
-
* <h2>Section 2</h2>
|
|
88
|
-
* </div>
|
|
89
|
-
*
|
|
90
|
-
* @example <caption>Locating a single element</caption>
|
|
91
|
-
* import { by, Target } from '@serenity-js/webdriverio';
|
|
92
|
-
*
|
|
93
|
-
* const title = Target.the('article title').located(by.css('#article h1'));
|
|
94
|
-
*
|
|
95
|
-
* @example <caption>Locating multiple elements</caption>
|
|
96
|
-
* import { by, Target } from '@serenity-js/webdriverio';
|
|
97
|
-
*
|
|
98
|
-
* const titles = Target.all('section titles').located(by.css('#article h2'));
|
|
99
|
-
*
|
|
100
|
-
* @param {Selector} selector
|
|
101
|
-
* @returns {Locator}
|
|
102
|
-
*
|
|
103
|
-
* @see {@link Target}
|
|
104
|
-
* @see https://webdriver.io/docs/selectors/#css-query-selector
|
|
105
|
-
*/
|
|
106
|
-
css(selector: Selector): Locator {
|
|
107
|
-
return new Locator(
|
|
108
|
-
`by css ${ selector }`,
|
|
109
|
-
browser => browser.$(selector) as unknown as Promise<Element<'async'>>,
|
|
110
|
-
browser => browser.$$(selector),
|
|
111
|
-
)
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* @desc
|
|
116
|
-
* Locates elements by HTML tag name
|
|
117
|
-
*
|
|
118
|
-
* @example <caption>Example widget</caption>
|
|
119
|
-
* <ul>
|
|
120
|
-
* <li>Item 1</li>
|
|
121
|
-
* <li>Item 2</li>
|
|
122
|
-
* </ul>
|
|
123
|
-
* <span>Total price: £5</span>
|
|
124
|
-
*
|
|
125
|
-
* @example <caption>Locating a single element</caption>
|
|
126
|
-
* import { by, Target } from '@serenity-js/webdriverio';
|
|
127
|
-
*
|
|
128
|
-
* const totalPrice = Target.the('total price').located(by.tagName('span'));
|
|
129
|
-
*
|
|
130
|
-
* @example <caption>Locating multiple elements</caption>
|
|
131
|
-
* import { by, Target } from '@serenity-js/webdriverio';
|
|
132
|
-
*
|
|
133
|
-
* const items = Target.all('shopping basket items').located(by.tagName('li'));
|
|
134
|
-
*
|
|
135
|
-
* @param {string} tagName
|
|
136
|
-
* @returns {Locator}
|
|
137
|
-
*
|
|
138
|
-
* @see {@link Target}
|
|
139
|
-
* @see https://webdriver.io/docs/selectors/#tag-name
|
|
140
|
-
*/
|
|
141
|
-
tagName(tagName: string): Locator {
|
|
142
|
-
return new Locator(
|
|
143
|
-
`by tag name <${ tagName } />`,
|
|
144
|
-
browser => browser.$(`<${ tagName } />`) as unknown as Promise<Element<'async'>>,
|
|
145
|
-
browser => browser.$$(`<${ tagName } />`),
|
|
146
|
-
)
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* @desc
|
|
151
|
-
* Locates an HTML anchor element with a specific text in it.
|
|
152
|
-
*
|
|
153
|
-
* @example <caption>Example widget</caption>
|
|
154
|
-
* <a href="https://serenity-js.org">Serenity/JS</a>
|
|
155
|
-
*
|
|
156
|
-
* @example <caption>Locating a single element</caption>
|
|
157
|
-
* import { by, Target } from '@serenity-js/webdriverio';
|
|
158
|
-
*
|
|
159
|
-
* const serenityWebsite = Target.the('Serenity/JS website link').located(by.linkText('Serenity/JS'));
|
|
160
|
-
*
|
|
161
|
-
* @example <caption>Locating multiple elements</caption>
|
|
162
|
-
* import { by, Target } from '@serenity-js/webdriverio';
|
|
163
|
-
*
|
|
164
|
-
* const items = Target.all('Serenity/JS website links').located(by.linkText('Serenity/JS'));
|
|
165
|
-
*
|
|
166
|
-
* @param {string} linkText
|
|
167
|
-
* @returns {Locator}
|
|
168
|
-
*
|
|
169
|
-
* @see {@link Target}
|
|
170
|
-
* @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a
|
|
171
|
-
* @see https://webdriver.io/docs/selectors/#link-text
|
|
172
|
-
*/
|
|
173
|
-
linkText(linkText: string): Locator {
|
|
174
|
-
return new Locator(
|
|
175
|
-
`by link text ${ linkText }`,
|
|
176
|
-
browser => browser.$(`=${ linkText }`) as unknown as Promise<Element<'async'>>,
|
|
177
|
-
browser => browser.$$(`=${ linkText }`),
|
|
178
|
-
)
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
/**
|
|
182
|
-
* @desc
|
|
183
|
-
* Locates an HTML anchor element with which visible text partially matches `partialLinkText`
|
|
184
|
-
*
|
|
185
|
-
* @example <caption>Example widget</caption>
|
|
186
|
-
* <a href="https://serenity-js.org">Serenity/JS</a>
|
|
187
|
-
* <a href="https://serenity-bdd.info/#/">Serenity BDD</a>
|
|
188
|
-
*
|
|
189
|
-
* @example <caption>Locating a single element</caption>
|
|
190
|
-
* import { by, Target } from '@serenity-js/webdriverio';
|
|
191
|
-
*
|
|
192
|
-
* const serenityWebsite = Target.the('Serenity/JS website link').located(by.partialLinkText('JS'));
|
|
193
|
-
*
|
|
194
|
-
* @example <caption>Locating multiple elements</caption>
|
|
195
|
-
* import { by, Target } from '@serenity-js/webdriverio';
|
|
196
|
-
*
|
|
197
|
-
* const serenityWebsites = Target.all('Serenity frameworks').located(by.partialLinkText('Serenity'));
|
|
198
|
-
*
|
|
199
|
-
* @param {string} partialLinkText
|
|
200
|
-
* @returns {Locator}
|
|
201
|
-
*
|
|
202
|
-
* @see {@link Target}
|
|
203
|
-
* @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a
|
|
204
|
-
* @see https://webdriver.io/docs/selectors/#link-text
|
|
205
|
-
*/
|
|
206
|
-
partialLinkText(partialLinkText: string): Locator {
|
|
207
|
-
return new Locator(
|
|
208
|
-
`by partial link text ${ partialLinkText }`,
|
|
209
|
-
browser => browser.$(`*=${ partialLinkText }`) as unknown as Promise<Element<'async'>>,
|
|
210
|
-
browser => browser.$$(`*=${ partialLinkText }`),
|
|
211
|
-
)
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
/**
|
|
215
|
-
* @desc
|
|
216
|
-
* Locates elements using an [XPath](https://developer.mozilla.org/en-US/docs/Web/XPath) selector.
|
|
217
|
-
*
|
|
218
|
-
* Please note that whenever possible you should use {@link Locators#id} and {@link Locators#css} locators
|
|
219
|
-
* instead of XPath to make your tests more robust.
|
|
220
|
-
*
|
|
221
|
-
* @example <caption>Example widget</caption>
|
|
222
|
-
* <div id="article">
|
|
223
|
-
* <h1>Title</h1>
|
|
224
|
-
* <h2>Section 1</h2>
|
|
225
|
-
* <h2>Section 2</h2>
|
|
226
|
-
* </div>
|
|
227
|
-
*
|
|
228
|
-
* @example <caption>Locating a single element</caption>
|
|
229
|
-
* import { by, Target } from '@serenity-js/webdriverio';
|
|
230
|
-
*
|
|
231
|
-
* const title = Target.the('article title').located(by.xpath('//*[@id="article"]/h1'));
|
|
232
|
-
*
|
|
233
|
-
* @example <caption>Locating multiple elements</caption>
|
|
234
|
-
* import { by, Target } from '@serenity-js/webdriverio';
|
|
235
|
-
*
|
|
236
|
-
* const title = Target.the('article title').located(by.xpath('//*[@id="article"]/h2'));
|
|
237
|
-
*
|
|
238
|
-
* @param {string} xpath
|
|
239
|
-
* @returns {Locator}
|
|
240
|
-
*
|
|
241
|
-
* @see {@link Target}
|
|
242
|
-
* @see https://developer.mozilla.org/en-US/docs/Web/XPath
|
|
243
|
-
* @see https://webdriver.io/docs/selectors/#xpath
|
|
244
|
-
*/
|
|
245
|
-
xpath(xpath: string): Locator {
|
|
246
|
-
return new Locator(
|
|
247
|
-
`by xpath ${ xpath }`,
|
|
248
|
-
browser => browser.$(xpath) as unknown as Promise<Element<'async'>>,
|
|
249
|
-
browser => browser.$$(xpath),
|
|
250
|
-
)
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
export const by = new Locators();
|