|
| 1 | +import fs from 'fs' |
| 2 | +import { fileURLToPath } from 'url' |
| 3 | + |
| 4 | +let resqScript |
| 5 | + |
1 | 6 | async function findReact(matcher, locator) { |
2 | | - // Handle both Locator objects and raw locator objects |
3 | 7 | const reactLocator = locator.locator || locator |
4 | | - let _locator = `_react=${reactLocator.react}`; |
5 | | - let props = ''; |
| 8 | + const page = typeof matcher.page === 'function' ? matcher.page() : matcher |
6 | 9 |
|
7 | | - if (reactLocator.props) { |
8 | | - props += propBuilder(reactLocator.props); |
9 | | - _locator += props; |
| 10 | + if (!resqScript) { |
| 11 | + resqScript = fs.readFileSync(fileURLToPath(import.meta.resolve('resq'))).toString() |
10 | 12 | } |
11 | | - return matcher.locator(_locator).all(); |
12 | | -} |
| 13 | + await page.evaluate(resqScript) |
| 14 | + await page.evaluate(() => window.resq.waitToLoadReact()) |
| 15 | + |
| 16 | + const arrayHandle = await page.evaluateHandle( |
| 17 | + ({ selector, props, state }) => { |
| 18 | + let elements = window.resq.resq$$(selector) |
| 19 | + if (Object.keys(props).length) elements = elements.byProps(props) |
| 20 | + if (Object.keys(state).length) elements = elements.byState(state) |
| 21 | + if (!elements.length) return [] |
13 | 22 |
|
14 | | -async function findVue(matcher, locator) { |
15 | | - // Handle both Locator objects and raw locator objects |
16 | | - const vueLocator = locator.locator || locator |
17 | | - let _locator = `_vue=${vueLocator.vue}`; |
18 | | - let props = ''; |
| 23 | + let nodes = [] |
| 24 | + elements.forEach(element => { |
| 25 | + let { node, isFragment } = element |
| 26 | + if (!node) { |
| 27 | + isFragment = true |
| 28 | + node = element.children |
| 29 | + } |
| 30 | + if (isFragment) nodes = nodes.concat(node) |
| 31 | + else nodes.push(node) |
| 32 | + }) |
| 33 | + return [...nodes] |
| 34 | + }, |
| 35 | + { |
| 36 | + selector: reactLocator.react, |
| 37 | + props: reactLocator.props || {}, |
| 38 | + state: reactLocator.state || {}, |
| 39 | + }, |
| 40 | + ) |
19 | 41 |
|
20 | | - if (vueLocator.props) { |
21 | | - props += propBuilder(vueLocator.props); |
22 | | - _locator += props; |
| 42 | + const properties = await arrayHandle.getProperties() |
| 43 | + await arrayHandle.dispose() |
| 44 | + const result = [] |
| 45 | + for (const property of properties.values()) { |
| 46 | + const elementHandle = property.asElement() |
| 47 | + if (elementHandle) result.push(elementHandle) |
23 | 48 | } |
24 | | - return matcher.locator(_locator).all(); |
| 49 | + return result |
25 | 50 | } |
26 | 51 |
|
27 | 52 | async function findByPlaywrightLocator(matcher, locator) { |
28 | | - // Handle both Locator objects and raw locator objects |
29 | 53 | const pwLocator = locator.locator || locator |
30 | 54 | if (pwLocator && pwLocator.toString && pwLocator.toString().includes(process.env.testIdAttribute)) { |
31 | | - return matcher.getByTestId(pwLocator.pw.value.split('=')[1]); |
| 55 | + return matcher.getByTestId(pwLocator.pw.value.split('=')[1]) |
32 | 56 | } |
33 | 57 | const pwValue = typeof pwLocator.pw === 'string' ? pwLocator.pw : pwLocator.pw |
34 | | - return matcher.locator(pwValue).all(); |
35 | | -} |
36 | | - |
37 | | -function propBuilder(props) { |
38 | | - let _props = ''; |
39 | | - |
40 | | - for (const [key, value] of Object.entries(props)) { |
41 | | - if (typeof value === 'object') { |
42 | | - for (const [k, v] of Object.entries(value)) { |
43 | | - _props += `[${key}.${k} = "${v}"]`; |
44 | | - } |
45 | | - } else { |
46 | | - _props += `[${key} = "${value}"]`; |
47 | | - } |
48 | | - } |
49 | | - return _props; |
| 58 | + return matcher.locator(pwValue).all() |
50 | 59 | } |
51 | 60 |
|
52 | | -export { findReact, findVue, findByPlaywrightLocator }; |
| 61 | +export { findReact, findByPlaywrightLocator } |
0 commit comments