Skip to content

Commit bf3968f

Browse files
committed
feat: enable nested RegExp options
1 parent 96f1a1e commit bf3968f

File tree

4 files changed

+47
-8
lines changed

4 files changed

+47
-8
lines changed

.eslintrc.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,8 @@ module.exports = {
77
tsconfigRootDir: __dirname,
88
project: ['tsconfig.eslint.json', 'tsconfig.json'],
99
},
10+
rules: {
11+
'no-restricted-syntax': 'off',
12+
'no-underscore-dangle': ['error', {allow: ['__regex', '__flags']}],
13+
},
1014
}

lib/index.ts

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,40 @@ const domLibraryAsString = readFileSync(
1111
).replace(/process.env/g, '{}')
1212

1313
/* istanbul ignore next */
14-
function mapArgument(argument: any, index: number): any {
15-
return index === 0 && typeof argument === 'object' && argument.regex
16-
? new RegExp(argument.regex, argument.flags)
17-
: argument
14+
function convertProxyToRegExp(o: any, depth: number): any {
15+
if (typeof o !== 'object' || !o || depth > 2) return o
16+
if (!o.__regex || typeof o.__flags !== 'string') {
17+
const copy = {...o}
18+
for (const key of Object.keys(copy)) {
19+
copy[key] = convertProxyToRegExp(copy[key], depth + 1)
20+
}
21+
return copy
22+
}
23+
24+
return new RegExp(o.__regex, o.__flags)
25+
}
26+
27+
/* istanbul ignore next */
28+
function mapArgument(o: any): any {
29+
return convertProxyToRegExp(o, 0)
30+
}
31+
32+
function convertRegExpToProxy(o: any, depth: number): any {
33+
if (typeof o !== 'object' || !o || depth > 2) return o
34+
if (!(o instanceof RegExp)) {
35+
const copy = {...o}
36+
for (const key of Object.keys(copy)) {
37+
copy[key] = convertRegExpToProxy(copy[key], depth + 1)
38+
}
39+
return copy
40+
}
41+
42+
return {__regex: o.source, __flags: o.flags}
1843
}
1944

2045
const delegateFnBodyToExecuteInPageInitial = `
2146
${domLibraryAsString};
47+
${convertProxyToRegExp.toString()};
2248
2349
const mappedArgs = args.map(${mapArgument.toString()});
2450
const moduleWithFns = fnName in __dom_testing_library__ ?
@@ -97,8 +123,6 @@ function createDelegateFor<T = DOMReturnType>(
97123
// eslint-disable-next-line no-param-reassign
98124
processHandleFn = processHandleFn || processQuery
99125

100-
const convertRegExp = (regex: RegExp) => ({regex: regex.source, flags: regex.flags})
101-
102126
return async function delegate(...args: any[]): Promise<T> {
103127
// @ts-ignore
104128
const containerHandle: ElementHandle = contextFn ? contextFn.apply(this, args) : this
@@ -107,13 +131,15 @@ function createDelegateFor<T = DOMReturnType>(
107131
// eslint-disable-next-line no-new-func, @typescript-eslint/no-implied-eval
108132
const evaluateFn = new Function('container, [fnName, ...args]', delegateFnBodyToExecuteInPage)
109133

110-
// Convert RegExp to a special format since they don't serialize well
111-
let argsToForward = args.map(arg => (arg instanceof RegExp ? convertRegExp(arg) : arg))
134+
let argsToForward = args
112135
// Remove the container from the argsToForward since it's always the first argument
113136
if (containerHandle === args[0]) {
114137
argsToForward = argsToForward.slice(1)
115138
}
116139

140+
// Convert RegExp to a special format since they don't serialize well
141+
argsToForward = argsToForward.map(convertRegExpToProxy)
142+
117143
return processHandleFn!({fnName, containerHandle, evaluateFn, argsToForward})
118144
}
119145
}

test/extend.test.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,14 @@ describe('lib/extend.ts', () => {
9898
expect(text).toEqual('Hello h2')
9999
})
100100

101+
it('should handle the getBy* methods with a regex name', async () => {
102+
const element = await document.getByRole('button', {name: /getBy.*Test/})
103+
104+
const text = await page.evaluate(el => el.textContent, element)
105+
106+
expect(text).toEqual('getByRole Test')
107+
})
108+
101109
it('should scope results to element', async () => {
102110
const scope = await document.$('#scoped')
103111
const element = await scope!.queryByText(/Hello/)

test/fixtures/page.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ <h2 data-id="second-level-header">Hello h2</h2>
99
<label for="label-text-input" data-testid="testid-label">Label A</label>
1010
<input id="label-text-input" type="text">
1111

12+
<button role="button">getByRole Test</button>
1213
<div id="scoped">
1314
<h3>Hello h3</h3>
1415
</div>

0 commit comments

Comments
 (0)