Skip to content

Commit 768d2ab

Browse files
fix: queries when Simmer cannot create selector
When Simmer fails to create a unique selector, usually because it would need to go to a higher depth than 3 to generate it, queries will fail. Simmer was added to allow refetching of elements when they become stale but if it fails it would be better to fallback to using WebElement JSONs to create the WebdriverIO.Element instances so that the queries don't fail. When falling back to using WebElement JSONs refetching elements won't be possible anymore. Maybe in future we want to allow users to configure Simmer themselves so that they can set the depth etc. We may also want to add an info log at some point.
1 parent 14cd90f commit 768d2ab

File tree

3 files changed

+73
-8
lines changed

3 files changed

+73
-8
lines changed

Diff for: src/index.ts

+40-8
Original file line numberDiff line numberDiff line change
@@ -124,21 +124,53 @@ function executeQuery(
124124
}
125125

126126
if (Array.isArray(result)) {
127-
return done(result.map((element) => ({selector: window.Simmer(element)})))
127+
return done(
128+
result.map((element) => ({
129+
selector: window.Simmer(element),
130+
element,
131+
})),
132+
)
128133
}
129134

130-
return done({selector: window.Simmer(result)})
135+
return done({
136+
selector: window.Simmer(result),
137+
element: result,
138+
})
131139
})()
132140
}
133141

134-
function createQuery(element: ElementBase, queryName: string) {
142+
/*
143+
Always include element key "element-6066-11e4-a52e-4f735466cecf": WebdriverIO
144+
checks whether this key is a string to determine if the selector is actually a
145+
WebElement JSON. If the selector is a WebElement JSON it uses it to create a new
146+
Element. There are valid WebElement JSONs that exclude the key but can be turned
147+
into Elements, such as { ELEMENT: elementId }; this can happen in setups that
148+
aren't generated by @wdio/cli.
149+
*/
150+
function createElement(
151+
container: ElementBase,
152+
result: {selector: string | false; element: any},
153+
) {
154+
// use selector if possible so that element can be refetched
155+
if (result.selector) {
156+
return container.$(result.selector)
157+
}
158+
159+
// fallback to using WebElement JSON if selector could not be created
160+
return container.$({
161+
'element-6066-11e4-a52e-4f735466cecf': '',
162+
...result.element,
163+
})
164+
}
165+
166+
function createQuery(container: ElementBase, queryName: string) {
135167
return async (...args: any[]) => {
136-
await injectDOMTestingLibrary(element)
168+
await injectDOMTestingLibrary(container)
137169

138-
const result = await element.executeAsync(
170+
const result = await container.executeAsync(
139171
executeQuery,
140172
queryName,
141-
element,
173+
container,
142174
...args.map(serializeArg),
143175
)
144176

@@ -151,10 +183,10 @@ function createQuery(element: ElementBase, queryName: string) {
151183
}
152184

153185
if (Array.isArray(result)) {
154-
return Promise.all(result.map(({selector}) => element.$(selector)))
186+
return Promise.all(result.map(createElement.bind(null, container)))
155187
}
156188

157-
return element.$(result.selector)
189+
return createElement(container, result)
158190
}
159191
}
160192

Diff for: test-app/index.html

+21
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,27 @@ <h2>getAllByText</h2>
114114
<h2>navigate</h2>
115115
<a href="page2.html">Go to Page 2</a>
116116
</section>
117+
<section>
118+
<h2>Simmer</h2>
119+
<div>
120+
<div>
121+
<div>
122+
<div>
123+
High depth non-specific div one
124+
</div>
125+
</div>
126+
</div>
127+
</div>
128+
<div>
129+
<div>
130+
<div>
131+
<div>
132+
High depth non-specific div two
133+
</div>
134+
</div>
135+
</div>
136+
</div>
137+
</section>
117138
<!-- Prettier unindents the script tag below -->
118139
<script>
119140
document

Diff for: test/async/queries.e2e.ts

+12
Original file line numberDiff line numberDiff line change
@@ -169,4 +169,16 @@ describe('queries', () => {
169169
JSON.stringify(await refetchElement(button, 'click')),
170170
)
171171
})
172+
173+
it('getAllBy works when Simmer cannot create a unique selector', async () => {
174+
const {getAllByText} = setupBrowser(browser)
175+
176+
expect(await getAllByText(/High depth non-specific div/)).toHaveLength(2)
177+
})
178+
179+
it('getBy works when Simmer cannot create a unique selector', async () => {
180+
const {getByText} = setupBrowser(browser)
181+
182+
expect(await getByText('High depth non-specific div one')).not.toBeNull()
183+
})
172184
})

0 commit comments

Comments
 (0)