Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 25 additions & 38 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,9 @@ function serializeArg(arg: QueryArg): SerializedArg {
}

type SerializedQueryResult =
| {selector: string | false; element: HTMLElement}[]
| {selector: string}[]
| string
| {selector: string | false; element: HTMLElement}
| {selector: string}
| null

function executeQuery(
Expand Down Expand Up @@ -154,46 +154,33 @@ function executeQuery(
return done(null)
}

function makeSelectorResult(element: HTMLElement) {
// use simmer if possible to allow element refetching by position, otherwise
// situations such as a React key change causes refetching to fail.
const selector = window.Simmer(element)
if (selector) return {selector}

// use generated element id as selector if Simmer fails
const elementIdAttributeName = 'data-wdio-testing-lib-element-id'
let elementId = element.getAttribute(elementIdAttributeName)

// if id doesn't already exist create one and add it to element
if (!elementId) {
elementId = (Math.abs(Math.random()) * 1000000000000).toFixed(0)
element.setAttribute(elementIdAttributeName, elementId)
}

return {selector:`[${elementIdAttributeName}="${elementId}"]`}
}

if (Array.isArray(result)) {
return done(
result.map((element) => ({
selector: window.Simmer(element),
element,
})),
)
return done(result.map(makeSelectorResult));
}

return done({
selector: window.Simmer(result),
element: result,
})
return done(makeSelectorResult(result));
})()
}

/*
Always include element key "element-6066-11e4-a52e-4f735466cecf": WebdriverIO
checks whether this key is a string to determine if the selector is actually a
WebElement JSON. If the selector is a WebElement JSON it uses it to create a new
Element. There are valid WebElement JSONs that exclude the key but can be turned
into Elements, such as { ELEMENT: elementId }; this can happen in setups that
aren't generated by @wdio/cli.
*/
async function createElement(
container: ElementBase,
result: {selector: string | false; element: object},
): Promise<WebdriverIO.Element> {
// use selector if possible so that element can be refetched
if (result.selector) {
return container.$(result.selector)
}

// fallback to using WebElement JSON if selector could not be created
return container.$({
'element-6066-11e4-a52e-4f735466cecf': '',
...result.element,
})
}

function createQuery(container: ElementBase, queryName: QueryName) {
return async (...args: QueryArg[]) => {
await injectDOMTestingLibrary(container)
Expand All @@ -215,10 +202,10 @@ function createQuery(container: ElementBase, queryName: QueryName) {
}

if (Array.isArray(result)) {
return Promise.all(result.map(createElement.bind(null, container)))
return Promise.all(result.map(({ selector }) => container.$(selector)))
}

return createElement(container, result)
return container.$(result.selector)
}
}

Expand Down