Merge branch 'main' of https://github.com/JacksonLei123/playwright
This commit is contained in:
commit
40d8f2cb71
|
|
@ -32,6 +32,12 @@ if ! command -v curl >/dev/null; then
|
||||||
apt-get install -y curl
|
apt-get install -y curl
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# GnuPG is not preinstalled in slim images
|
||||||
|
if ! command -v gpg >/dev/null; then
|
||||||
|
apt-get update
|
||||||
|
apt-get install -y gpg
|
||||||
|
fi
|
||||||
|
|
||||||
# 3. Add the GPG key, the apt repo, update the apt cache, and install the package
|
# 3. Add the GPG key, the apt repo, update the apt cache, and install the package
|
||||||
curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > /tmp/microsoft.gpg
|
curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > /tmp/microsoft.gpg
|
||||||
install -o root -g root -m 644 /tmp/microsoft.gpg /etc/apt/trusted.gpg.d/
|
install -o root -g root -m 644 /tmp/microsoft.gpg /etc/apt/trusted.gpg.d/
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,12 @@ if ! command -v curl >/dev/null; then
|
||||||
apt-get install -y curl
|
apt-get install -y curl
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# GnuPG is not preinstalled in slim images
|
||||||
|
if ! command -v gpg >/dev/null; then
|
||||||
|
apt-get update
|
||||||
|
apt-get install -y gpg
|
||||||
|
fi
|
||||||
|
|
||||||
# 3. Add the GPG key, the apt repo, update the apt cache, and install the package
|
# 3. Add the GPG key, the apt repo, update the apt cache, and install the package
|
||||||
curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > /tmp/microsoft.gpg
|
curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > /tmp/microsoft.gpg
|
||||||
install -o root -g root -m 644 /tmp/microsoft.gpg /etc/apt/trusted.gpg.d/
|
install -o root -g root -m 644 /tmp/microsoft.gpg /etc/apt/trusted.gpg.d/
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,12 @@ if ! command -v curl >/dev/null; then
|
||||||
apt-get install -y curl
|
apt-get install -y curl
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# GnuPG is not preinstalled in slim images
|
||||||
|
if ! command -v gpg >/dev/null; then
|
||||||
|
apt-get update
|
||||||
|
apt-get install -y gpg
|
||||||
|
fi
|
||||||
|
|
||||||
# 3. Add the GPG key, the apt repo, update the apt cache, and install the package
|
# 3. Add the GPG key, the apt repo, update the apt cache, and install the package
|
||||||
curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > /tmp/microsoft.gpg
|
curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > /tmp/microsoft.gpg
|
||||||
install -o root -g root -m 644 /tmp/microsoft.gpg /etc/apt/trusted.gpg.d/
|
install -o root -g root -m 644 /tmp/microsoft.gpg /etc/apt/trusted.gpg.d/
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ import type * as types from '../types';
|
||||||
import type { BidiSession } from './bidiConnection';
|
import type { BidiSession } from './bidiConnection';
|
||||||
import * as bidi from './third_party/bidiProtocol';
|
import * as bidi from './third_party/bidiProtocol';
|
||||||
import { getBidiKeyValue } from './third_party/bidiKeyboard';
|
import { getBidiKeyValue } from './third_party/bidiKeyboard';
|
||||||
|
import { resolveSmartModifierString } from '../input';
|
||||||
|
|
||||||
export class RawKeyboardImpl implements input.RawKeyboard {
|
export class RawKeyboardImpl implements input.RawKeyboard {
|
||||||
private _session: BidiSession;
|
private _session: BidiSession;
|
||||||
|
|
@ -32,12 +33,14 @@ export class RawKeyboardImpl implements input.RawKeyboard {
|
||||||
}
|
}
|
||||||
|
|
||||||
async keydown(modifiers: Set<types.KeyboardModifier>, keyName: string, description: input.KeyDescription, autoRepeat: boolean): Promise<void> {
|
async keydown(modifiers: Set<types.KeyboardModifier>, keyName: string, description: input.KeyDescription, autoRepeat: boolean): Promise<void> {
|
||||||
|
keyName = resolveSmartModifierString(keyName);
|
||||||
const actions: bidi.Input.KeySourceAction[] = [];
|
const actions: bidi.Input.KeySourceAction[] = [];
|
||||||
actions.push({ type: 'keyDown', value: getBidiKeyValue(keyName) });
|
actions.push({ type: 'keyDown', value: getBidiKeyValue(keyName) });
|
||||||
await this._performActions(actions);
|
await this._performActions(actions);
|
||||||
}
|
}
|
||||||
|
|
||||||
async keyup(modifiers: Set<types.KeyboardModifier>, keyName: string, description: input.KeyDescription): Promise<void> {
|
async keyup(modifiers: Set<types.KeyboardModifier>, keyName: string, description: input.KeyDescription): Promise<void> {
|
||||||
|
keyName = resolveSmartModifierString(keyName);
|
||||||
const actions: bidi.Input.KeySourceAction[] = [];
|
const actions: bidi.Input.KeySourceAction[] = [];
|
||||||
actions.push({ type: 'keyUp', value: getBidiKeyValue(keyName) });
|
actions.push({ type: 'keyUp', value: getBidiKeyValue(keyName) });
|
||||||
await this._performActions(actions);
|
await this._performActions(actions);
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ export function parseCSS(selector: string, customNames: Set<string>): { selector
|
||||||
if (!(tokens[tokens.length - 1] instanceof css.EOFToken))
|
if (!(tokens[tokens.length - 1] instanceof css.EOFToken))
|
||||||
tokens.push(new css.EOFToken());
|
tokens.push(new css.EOFToken());
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
const newMessage = e.message + ` while parsing selector "${selector}"`;
|
const newMessage = e.message + ` while parsing css selector "${selector}". Did you mean to CSS.escape it?`;
|
||||||
const index = (e.stack || '').indexOf(e.message);
|
const index = (e.stack || '').indexOf(e.message);
|
||||||
if (index !== -1)
|
if (index !== -1)
|
||||||
e.stack = e.stack.substring(0, index) + newMessage + e.stack.substring(index + e.message.length);
|
e.stack = e.stack.substring(0, index) + newMessage + e.stack.substring(index + e.message.length);
|
||||||
|
|
@ -68,13 +68,13 @@ export function parseCSS(selector: string, customNames: Set<string>): { selector
|
||||||
(token instanceof css.PercentageToken);
|
(token instanceof css.PercentageToken);
|
||||||
});
|
});
|
||||||
if (unsupportedToken)
|
if (unsupportedToken)
|
||||||
throw new InvalidSelectorError(`Unsupported token "${unsupportedToken.toSource()}" while parsing selector "${selector}"`);
|
throw new InvalidSelectorError(`Unsupported token "${unsupportedToken.toSource()}" while parsing css selector "${selector}". Did you mean to CSS.escape it?`);
|
||||||
|
|
||||||
let pos = 0;
|
let pos = 0;
|
||||||
const names = new Set<string>();
|
const names = new Set<string>();
|
||||||
|
|
||||||
function unexpected() {
|
function unexpected() {
|
||||||
return new InvalidSelectorError(`Unexpected token "${tokens[pos].toSource()}" while parsing selector "${selector}"`);
|
return new InvalidSelectorError(`Unexpected token "${tokens[pos].toSource()}" while parsing css selector "${selector}". Did you mean to CSS.escape it?`);
|
||||||
}
|
}
|
||||||
|
|
||||||
function skipWhitespace() {
|
function skipWhitespace() {
|
||||||
|
|
@ -246,7 +246,7 @@ export function parseCSS(selector: string, customNames: Set<string>): { selector
|
||||||
if (!isEOF())
|
if (!isEOF())
|
||||||
throw unexpected();
|
throw unexpected();
|
||||||
if (result.some(arg => typeof arg !== 'object' || !('simples' in arg)))
|
if (result.some(arg => typeof arg !== 'object' || !('simples' in arg)))
|
||||||
throw new InvalidSelectorError(`Error while parsing selector "${selector}"`);
|
throw new InvalidSelectorError(`Error while parsing css selector "${selector}". Did you mean to CSS.escape it?`);
|
||||||
return { selector: result as CSSComplexSelector[], names: Array.from(names) };
|
return { selector: result as CSSComplexSelector[], names: Array.from(names) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,8 @@ it('should throw on malformed css', async () => {
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
error = e;
|
error = e;
|
||||||
}
|
}
|
||||||
expect(error.message).toContain(`while parsing selector "${selector}"`);
|
expect(error.message).toContain(`while parsing css selector "${selector}"`);
|
||||||
|
expect(error.message).toContain(`Did you mean to CSS.escape it?`);
|
||||||
}
|
}
|
||||||
|
|
||||||
expectError('');
|
expectError('');
|
||||||
|
|
|
||||||
|
|
@ -479,7 +479,7 @@ test('should print unknown engine error', async ({ page }) => {
|
||||||
|
|
||||||
test('should print selector syntax error', async ({ page }) => {
|
test('should print selector syntax error', async ({ page }) => {
|
||||||
const error = await expect(page.locator('row]')).toBeVisible().catch(e => e);
|
const error = await expect(page.locator('row]')).toBeVisible().catch(e => e);
|
||||||
expect(error.message).toContain(`Unexpected token "]" while parsing selector "row]"`);
|
expect(error.message).toContain(`Unexpected token "]" while parsing css selector "row]"`);
|
||||||
});
|
});
|
||||||
|
|
||||||
test.describe(() => {
|
test.describe(() => {
|
||||||
|
|
|
||||||
|
|
@ -415,7 +415,7 @@ it('should work with internal:has=', async ({ page, server }) => {
|
||||||
const error3 = await page.$(`div >> internal:has=33`).catch(e => e);
|
const error3 = await page.$(`div >> internal:has=33`).catch(e => e);
|
||||||
expect(error3.message).toContain('Malformed selector: internal:has=33');
|
expect(error3.message).toContain('Malformed selector: internal:has=33');
|
||||||
const error4 = await page.$(`div >> internal:has="span!"`).catch(e => e);
|
const error4 = await page.$(`div >> internal:has="span!"`).catch(e => e);
|
||||||
expect(error4.message).toContain('Unexpected token "!" while parsing selector "span!"');
|
expect(error4.message).toContain('Unexpected token "!" while parsing css selector "span!"');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should work with internal:has-not=', async ({ page }) => {
|
it('should work with internal:has-not=', async ({ page }) => {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue