Skip to content

Commit 66ede52

Browse files
committed
PRO-15771 feat: support testId parts in filterByTestId and findByTestId
1 parent a315d56 commit 66ede52

4 files changed

Lines changed: 43 additions & 16 deletions

File tree

autotests/tests/internalTypeTests/selectors.skip.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,18 @@ import type {Selector} from 'e2ed/types';
44

55
// @ts-expect-error: wrong number of arguments
66
htmlElementSelector.findByTestId();
7-
// @ts-expect-error: wrong type of arguments
8-
htmlElementSelector.findByTestId(0);
7+
// ok
8+
htmlElementSelector.filterByTestId(0);
9+
// ok
10+
htmlElementSelector.findByTestId(true);
11+
// ok
12+
htmlElementSelector.filterByTestId(undefined);
13+
// ok
14+
htmlElementSelector.filterByTestId(null);
15+
// ok
16+
htmlElementSelector.findByTestId(1, 2, 2);
17+
// ok
18+
htmlElementSelector.filterByTestId('foo', 'bar', 'baz');
919
// ok
1020
htmlElementSelector.findByTestId('id') satisfies Selector;
1121
// ok

src/actions/scroll.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ export const scroll = ((...args) => {
3737
cssString: 'html',
3838
parameterAttributePrefix: 'data-test-',
3939
testIdAttribute: 'data-testid',
40+
testIdSeparator: '-',
4041
});
4142

4243
log(

src/selectors/createSelectorFunction.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,5 @@ export const createSelectorFunction = (
1111
): CreateSelector => {
1212
generalLog('Create selector function', {attributesOptions});
1313

14-
const {parameterAttributePrefix, testIdAttribute} = attributesOptions;
15-
16-
return (cssString) => Selector.create({cssString, parameterAttributePrefix, testIdAttribute});
14+
return (cssString) => Selector.create({cssString, ...attributesOptions});
1715
};

src/utils/selectors/Selector.ts

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,18 @@ import {inspect} from 'node:util';
44

55
import {RETRY_KEY} from '../../constants/internal';
66
import {getFrameContext} from '../../context/frameContext';
7+
import {
8+
type AttributesOptions,
9+
createTestLocator,
10+
type LocatorFunction,
11+
type Stringifiable,
12+
} from '../../createLocator';
713
import {getPlaywrightPage} from '../../useContext';
814

915
import {getAttributeCssSelector} from './getAttributeCssSelector';
1016

1117
import type {Locator as PlaywrightLocator} from '@playwright/test';
1218

13-
import type {AttributesOptions} from '../../createLocator';
1419
import type {SelectorPropertyRetryData} from '../../types/internal';
1520

1621
const setRetryData = (
@@ -35,7 +40,7 @@ type Options = Readonly<{
3540
kind?: Kind;
3641
parentSelector?: Selector;
3742
}> &
38-
Omit<AttributesOptions, 'testIdSeparator'>;
43+
AttributesOptions;
3944

4045
/**
4146
* Selector.
@@ -49,28 +54,39 @@ class Selector {
4954

5055
private readonly kind: 'css' | 'filter' | 'find' | 'nth' | 'parent' | 'withText';
5156

57+
private readonly locator: LocatorFunction<string>;
58+
5259
private readonly parameterAttributePrefix: string;
5360

5461
private readonly parentSelector: Selector | undefined;
5562

5663
private readonly testIdAttribute: string;
5764

65+
private readonly testIdSeparator: string;
66+
5867
protected constructor({
5968
args,
6069
cssString,
6170
kind = 'css',
6271
parameterAttributePrefix,
6372
parentSelector,
6473
testIdAttribute,
74+
testIdSeparator,
6575
}: Options) {
6676
this.args = args;
6777
this.cssString = cssString;
6878
this.description =
6979
kind === 'css' ? cssString : `${parentSelector!.description}.${kind}(${args?.join(', ')})`;
7080
this.kind = kind;
81+
this.locator = createTestLocator({
82+
attributesOptions: {parameterAttributePrefix, testIdAttribute, testIdSeparator},
83+
createLocatorByCssSelector: (selector) => selector,
84+
supportWildcardsInCssSelectors: true,
85+
}).locator;
7186
this.parameterAttributePrefix = parameterAttributePrefix;
7287
this.parentSelector = parentSelector;
7388
this.testIdAttribute = testIdAttribute;
89+
this.testIdSeparator = testIdSeparator;
7490
}
7591

7692
get boundingClientRect(): Promise<DOMRectReadOnly> {
@@ -182,14 +198,15 @@ class Selector {
182198
cssString,
183199
parameterAttributePrefix,
184200
testIdAttribute,
185-
}: Pick<Options, 'cssString' | 'parameterAttributePrefix' | 'testIdAttribute'>): Selector {
186-
return new Selector({cssString, parameterAttributePrefix, testIdAttribute});
201+
testIdSeparator,
202+
}: Pick<Options, keyof AttributesOptions | 'cssString'>): Selector {
203+
return new Selector({cssString, parameterAttributePrefix, testIdAttribute, testIdSeparator});
187204
}
188205

189206
createSelector(cssString: string): Selector {
190-
const {parameterAttributePrefix, testIdAttribute} = this;
207+
const {parameterAttributePrefix, testIdAttribute, testIdSeparator} = this;
191208

192-
return new Selector({cssString, parameterAttributePrefix, testIdAttribute});
209+
return new Selector({cssString, parameterAttributePrefix, testIdAttribute, testIdSeparator});
193210
}
194211

195212
filter(cssSelectorString: string): Selector {
@@ -200,8 +217,8 @@ class Selector {
200217
return this.filter(getAttributeCssSelector(this.getParameterAttribute(parameter), value));
201218
}
202219

203-
filterByTestId(testId: string): Selector {
204-
return this.filter(getAttributeCssSelector(this.testIdAttribute, testId));
220+
filterByTestId(...args: readonly [Stringifiable, ...Stringifiable[]]): Selector {
221+
return this.filter(this.locator(...(args as [Stringifiable])));
205222
}
206223

207224
find(cssSelectorString: string): Selector {
@@ -212,8 +229,8 @@ class Selector {
212229
return this.find(getAttributeCssSelector(this.getParameterAttribute(parameter), value));
213230
}
214231

215-
findByTestId(testId: string): Selector {
216-
return this.find(getAttributeCssSelector(this.testIdAttribute, testId));
232+
findByTestId(...args: readonly [Stringifiable, ...Stringifiable[]]): Selector {
233+
return this.find(this.locator(...(args as [Stringifiable])));
217234
}
218235

219236
getAttribute(attributeName: string): Promise<string | null> {
@@ -316,7 +333,7 @@ class Selector {
316333
}
317334

318335
private createChildSelector(kind: Kind, args?: Args): Selector {
319-
const {cssString, parameterAttributePrefix, testIdAttribute} = this;
336+
const {cssString, parameterAttributePrefix, testIdAttribute, testIdSeparator} = this;
320337

321338
return new Selector({
322339
args,
@@ -325,6 +342,7 @@ class Selector {
325342
parameterAttributePrefix,
326343
parentSelector: this,
327344
testIdAttribute,
345+
testIdSeparator,
328346
});
329347
}
330348

0 commit comments

Comments
 (0)