mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
chore: make asLocator()
always safe (#28207)
This commit is contained in:
parent
738155d85d
commit
5488c03d7f
@ -355,7 +355,7 @@ export class Locator implements api.Locator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
toString() {
|
toString() {
|
||||||
return asLocator('javascript', this._selector, undefined, true);
|
return asLocator('javascript', this._selector);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,21 +35,17 @@ export interface LocatorFactory {
|
|||||||
chainLocators(locators: string[]): string;
|
chainLocators(locators: string[]): string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function asLocator(lang: Language, selector: string, isFrameLocator: boolean = false, playSafe: boolean = false): string {
|
export function asLocator(lang: Language, selector: string, isFrameLocator: boolean = false): string {
|
||||||
return asLocators(lang, selector, isFrameLocator, playSafe)[0];
|
return asLocators(lang, selector, isFrameLocator)[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function asLocators(lang: Language, selector: string, isFrameLocator: boolean = false, playSafe: boolean = false, maxOutputSize = 20, preferredQuote?: Quote): string[] {
|
export function asLocators(lang: Language, selector: string, isFrameLocator: boolean = false, maxOutputSize = 20, preferredQuote?: Quote): string[] {
|
||||||
if (playSafe) {
|
|
||||||
try {
|
try {
|
||||||
return innerAsLocators(new generators[lang](preferredQuote), parseSelector(selector), isFrameLocator, maxOutputSize);
|
return innerAsLocators(new generators[lang](preferredQuote), parseSelector(selector), isFrameLocator, maxOutputSize);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Tolerate invalid input.
|
// Tolerate invalid input.
|
||||||
return [selector];
|
return [selector];
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
return innerAsLocators(new generators[lang](preferredQuote), parseSelector(selector), isFrameLocator, maxOutputSize);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function innerAsLocators(factory: LocatorFactory, parsed: ParsedSelector, isFrameLocator: boolean = false, maxOutputSize = 20): string[] {
|
function innerAsLocators(factory: LocatorFactory, parsed: ParsedSelector, isFrameLocator: boolean = false, maxOutputSize = 20): string[] {
|
||||||
|
@ -219,7 +219,7 @@ export function locatorOrSelectorAsSelector(language: Language, locator: string,
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const { selector, preferredQuote } = parseLocator(locator, testIdAttributeName);
|
const { selector, preferredQuote } = parseLocator(locator, testIdAttributeName);
|
||||||
const locators = asLocators(language, selector, undefined, undefined, undefined, preferredQuote);
|
const locators = asLocators(language, selector, undefined, undefined, preferredQuote);
|
||||||
const digest = digestForComparison(locator);
|
const digest = digestForComparison(locator);
|
||||||
if (locators.some(candidate => digestForComparison(candidate) === digest))
|
if (locators.some(candidate => digestForComparison(candidate) === digest))
|
||||||
return selector;
|
return selector;
|
||||||
|
@ -729,7 +729,7 @@ function renderApiCall(apiName: string, params: any) {
|
|||||||
continue;
|
continue;
|
||||||
let value;
|
let value;
|
||||||
if (name === 'selector' && isString(params[name]) && params[name].startsWith('internal:')) {
|
if (name === 'selector' && isString(params[name]) && params[name].startsWith('internal:')) {
|
||||||
const getter = asLocator('javascript', params[name], false, true);
|
const getter = asLocator('javascript', params[name]);
|
||||||
apiName = apiName.replace(/^locator\./, 'locator.' + getter + '.');
|
apiName = apiName.replace(/^locator\./, 'locator.' + getter + '.');
|
||||||
apiName = apiName.replace(/^page\./, 'page.' + getter + '.');
|
apiName = apiName.replace(/^page\./, 'page.' + getter + '.');
|
||||||
apiName = apiName.replace(/^frame\./, 'frame.' + getter + '.');
|
apiName = apiName.replace(/^frame\./, 'frame.' + getter + '.');
|
||||||
|
@ -40,8 +40,7 @@ export const CallLogView: React.FC<CallLogProps> = ({
|
|||||||
{log.map(callLog => {
|
{log.map(callLog => {
|
||||||
const expandOverride = expandOverrides.get(callLog.id);
|
const expandOverride = expandOverrides.get(callLog.id);
|
||||||
const isExpanded = typeof expandOverride === 'boolean' ? expandOverride : callLog.status !== 'done';
|
const isExpanded = typeof expandOverride === 'boolean' ? expandOverride : callLog.status !== 'done';
|
||||||
const locator = callLog.params.selector ? asLocator(language, callLog.params.selector, false) : null;
|
const locator = callLog.params.selector ? asLocator(language, callLog.params.selector) : null;
|
||||||
const locatorCall = `page.${locator}`;
|
|
||||||
let titlePrefix = callLog.title;
|
let titlePrefix = callLog.title;
|
||||||
let titleSuffix = '';
|
let titleSuffix = '';
|
||||||
if (callLog.title.startsWith('expect.to') || callLog.title.startsWith('expect.not.to')) {
|
if (callLog.title.startsWith('expect.to') || callLog.title.startsWith('expect.not.to')) {
|
||||||
@ -63,7 +62,7 @@ export const CallLogView: React.FC<CallLogProps> = ({
|
|||||||
}}></span>
|
}}></span>
|
||||||
{ titlePrefix }
|
{ titlePrefix }
|
||||||
{ callLog.params.url ? <span className='call-log-details'><span className='call-log-url' title={callLog.params.url}>{callLog.params.url}</span></span> : undefined }
|
{ callLog.params.url ? <span className='call-log-details'><span className='call-log-url' title={callLog.params.url}>{callLog.params.url}</span></span> : undefined }
|
||||||
{ locator ? <span className='call-log-details'><span className='call-log-selector' title={locatorCall}>{locatorCall}</span></span> : undefined }
|
{ locator ? <span className='call-log-details'><span className='call-log-selector' title={`page.${locator}`}>{`page.${locator}`}</span></span> : undefined }
|
||||||
{ titleSuffix }
|
{ titleSuffix }
|
||||||
<span className={'codicon ' + iconClass(callLog)}></span>
|
<span className={'codicon ' + iconClass(callLog)}></span>
|
||||||
{ typeof callLog.duration === 'number' ? <span className='call-log-time'>— {msToString(callLog.duration)}</span> : undefined}
|
{ typeof callLog.duration === 'number' ? <span className='call-log-time'>— {msToString(callLog.duration)}</span> : undefined}
|
||||||
|
@ -88,7 +88,7 @@ export const renderAction = (
|
|||||||
}) => {
|
}) => {
|
||||||
const { sdkLanguage, revealConsole, isLive, showDuration, showBadges } = options;
|
const { sdkLanguage, revealConsole, isLive, showDuration, showBadges } = options;
|
||||||
const { errors, warnings } = modelUtil.stats(action);
|
const { errors, warnings } = modelUtil.stats(action);
|
||||||
const locator = action.params.selector ? asLocator(sdkLanguage || 'javascript', action.params.selector, false /* isFrameLocator */, true /* playSafe */) : undefined;
|
const locator = action.params.selector ? asLocator(sdkLanguage || 'javascript', action.params.selector) : undefined;
|
||||||
|
|
||||||
let time: string = '';
|
let time: string = '';
|
||||||
if (action.endTime)
|
if (action.endTime)
|
||||||
|
@ -86,7 +86,7 @@ function propertyToString(event: ActionTraceEvent, name: string, value: any, sdk
|
|||||||
if ((name === 'value' && isEval) || (name === 'received' && event.method === 'expect'))
|
if ((name === 'value' && isEval) || (name === 'received' && event.method === 'expect'))
|
||||||
value = parseSerializedValue(value, new Array(10).fill({ handle: '<handle>' }));
|
value = parseSerializedValue(value, new Array(10).fill({ handle: '<handle>' }));
|
||||||
if (name === 'selector')
|
if (name === 'selector')
|
||||||
return { text: asLocator(sdkLanguage || 'javascript', event.params.selector, false /* isFrameLocator */, true /* playSafe */), type: 'locator', name: 'locator' };
|
return { text: asLocator(sdkLanguage || 'javascript', event.params.selector), type: 'locator', name: 'locator' };
|
||||||
const type = typeof value;
|
const type = typeof value;
|
||||||
if (type !== 'object' || value === null)
|
if (type !== 'object' || value === null)
|
||||||
return { text: String(value), type, name };
|
return { text: String(value), type, name };
|
||||||
|
@ -245,7 +245,7 @@ export const InspectModeController: React.FunctionComponent<{
|
|||||||
overlay: { offsetX: 0 },
|
overlay: { offsetX: 0 },
|
||||||
}, {
|
}, {
|
||||||
async setSelector(selector: string) {
|
async setSelector(selector: string) {
|
||||||
setHighlightedLocator(asLocator(sdkLanguage, frameSelector + selector, false /* isFrameLocator */, true /* playSafe */));
|
setHighlightedLocator(asLocator(sdkLanguage, frameSelector + selector));
|
||||||
},
|
},
|
||||||
highlightUpdated() {
|
highlightUpdated() {
|
||||||
for (const r of recorders) {
|
for (const r of recorders) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user