Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 0 additions & 24 deletions docs/src/api/class-keyboard.md
Original file line number Diff line number Diff line change
Expand Up @@ -308,52 +308,35 @@ In most cases, you should use [`method: Locator.fill`] instead. You only need to

Sends a `keydown`, `keypress`/`input`, and `keyup` event for each character in the text.

When [`option: namedKeys`] is `true`, anything inside `{}` is treated as a key name (same format as [`method: Keyboard.press`]).

To press a special key, like `Control` or `ArrowDown`, use [`method: Keyboard.press`].

**Usage**

```js
await page.keyboard.type('Hello'); // Types instantly
await page.keyboard.type('World', { delay: 100 }); // Types slower, like a user

// Mix text and special keys
await page.keyboard.type('Hello{Enter}World', { namedKeys: true });
```

```java
// Types instantly
page.keyboard().type("Hello");
// Types slower, like a user
page.keyboard().type("World", new Keyboard.TypeOptions().setDelay(100));

// Mix text and special keys
page.keyboard().type("Hello{Enter}World", new Keyboard.TypeOptions().setNamedKeys(true));
```

```python async
await page.keyboard.type("Hello") # types instantly
await page.keyboard.type("World", delay=100) # types slower, like a user

# Mix text and special keys
await page.keyboard.type("Hello{Enter}World", named_keys=True)
```

```python sync
page.keyboard.type("Hello") # types instantly
page.keyboard.type("World", delay=100) # types slower, like a user

# Mix text and special keys
page.keyboard.type("Hello{Enter}World", named_keys=True)
```

```csharp
await page.Keyboard.TypeAsync("Hello"); // types instantly
await page.Keyboard.TypeAsync("World", new() { Delay = 100 }); // types slower, like a user

// Mix text and special keys
await page.Keyboard.TypeAsync("Hello{Enter}World", new() { NamedKeys = true });
```

:::note
Expand All @@ -376,13 +359,6 @@ A text to type into a focused element.

Time to wait between key presses in milliseconds. Defaults to 0.

### option: Keyboard.type.namedKeys
* since: v1.61
- `namedKeys` <[boolean]>

When [`option: namedKeys`] is `true`, anything inside `{}` is treated as a key name (same format as [`method: Keyboard.press`]).
Use `{{` to type a literal brace character. Defaults to `false`.

## async method: Keyboard.up
* since: v1.8

Expand Down
28 changes: 1 addition & 27 deletions docs/src/api/class-locator.md
Original file line number Diff line number Diff line change
Expand Up @@ -2103,52 +2103,33 @@ In most cases, you should use [`method: Locator.fill`] instead. You only need to

Focuses the element, and then sends a `keydown`, `keypress`/`input`, and `keyup` event for each character in the text.

When [`option: namedKeys`] is `true`, anything inside `{}` is treated as a key name (same format as [`method: Locator.press`]).

To press a special key, like `Control` or `ArrowDown`, use [`method: Locator.press`].

**Usage**

```js
await locator.pressSequentially('Hello'); // Types instantly
await locator.pressSequentially('World', { delay: 100 }); // Types slower, like a user

// Mix characters and named keys
await locator.pressSequentially('Hello{Enter}World', { namedKeys: true });
// Use modifier combos
await locator.pressSequentially('{Control+A}{Delete}Hello', { namedKeys: true });
```

```java
locator.pressSequentially("Hello"); // Types instantly
locator.pressSequentially("World", new Locator.pressSequentiallyOptions().setDelay(100)); // Types slower, like a user

// Mix characters and named keys
locator.pressSequentially("Hello{Enter}World", new Locator.pressSequentiallyOptions().setNamedKeys(true));
```

```python async
await locator.press_sequentially("hello") # types instantly
await locator.press_sequentially("world", delay=100) # types slower, like a user

# Mix characters and named keys
await locator.press_sequentially("Hello{Enter}World", named_keys=True)
```

```python sync
locator.press_sequentially("hello") # types instantly
locator.press_sequentially("world", delay=100) # types slower, like a user

# Mix characters and named keys
locator.press_sequentially("Hello{Enter}World", named_keys=True)
```

```csharp
await locator.PressSequentiallyAsync("Hello"); // Types instantly
await locator.PressSequentiallyAsync("World", new() { Delay = 100 }); // Types slower, like a user

// Mix characters and named keys
await locator.PressSequentiallyAsync("Hello{Enter}World", new() { NamedKeys = true });
```

An example of typing into a text field and then submitting the form:
Expand Down Expand Up @@ -2187,21 +2168,14 @@ await locator.PressAsync("Enter");
* since: v1.38
- `text` <[string]>

String of characters to sequentially press into a focused element. When [`option: namedKeys`] is `true`, anything inside `{}` is treated as a key name (same format as [`method: Locator.press`]).
String of characters to sequentially press into a focused element.

### option: Locator.pressSequentially.delay
* since: v1.38
- `delay` <[float]>

Time to wait between key presses in milliseconds. Defaults to 0.

### option: Locator.pressSequentially.namedKeys
* since: v1.61
- `namedKeys` <[boolean]>

When [`option: namedKeys`] is `true`, anything inside `{}` is treated as a key name (same format as [`method: Locator.press`]).
Use `{{` to type a literal brace character. Defaults to `false`.

### option: Locator.pressSequentially.noWaitAfter = %%-input-no-wait-after-removed-%%
* since: v1.38

Expand Down
37 changes: 1 addition & 36 deletions packages/playwright-client/types/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14731,10 +14731,6 @@ export interface Locator {
* Focuses the element, and then sends a `keydown`, `keypress`/`input`, and `keyup` event for each character in the
* text.
*
* When [`namedKeys`](https://playwright.dev/docs/api/class-locator#locator-press-sequentially-option-named-keys) is
* `true`, anything inside `{}` is treated as a key name (same format as
* [locator.press(key[, options])](https://playwright.dev/docs/api/class-locator#locator-press)).
*
* To press a special key, like `Control` or `ArrowDown`, use
* [locator.press(key[, options])](https://playwright.dev/docs/api/class-locator#locator-press).
*
Expand All @@ -14743,11 +14739,6 @@ export interface Locator {
* ```js
* await locator.pressSequentially('Hello'); // Types instantly
* await locator.pressSequentially('World', { delay: 100 }); // Types slower, like a user
*
* // Mix characters and named keys
* await locator.pressSequentially('Hello{Enter}World', { namedKeys: true });
* // Use modifier combos
* await locator.pressSequentially('{Control+A}{Delete}Hello', { namedKeys: true });
* ```
*
* An example of typing into a text field and then submitting the form:
Expand All @@ -14758,10 +14749,7 @@ export interface Locator {
* await locator.press('Enter');
* ```
*
* @param text String of characters to sequentially press into a focused element. When
* [`namedKeys`](https://playwright.dev/docs/api/class-locator#locator-press-sequentially-option-named-keys) is
* `true`, anything inside `{}` is treated as a key name (same format as
* [locator.press(key[, options])](https://playwright.dev/docs/api/class-locator#locator-press)).
* @param text String of characters to sequentially press into a focused element.
* @param options
*/
pressSequentially(text: string, options?: {
Expand All @@ -14770,14 +14758,6 @@ export interface Locator {
*/
delay?: number;

/**
* When [`namedKeys`](https://playwright.dev/docs/api/class-locator#locator-press-sequentially-option-named-keys) is
* `true`, anything inside `{}` is treated as a key name (same format as
* [locator.press(key[, options])](https://playwright.dev/docs/api/class-locator#locator-press)). Use `{{` to type a
* literal brace character. Defaults to `false`.
*/
namedKeys?: boolean;

/**
* This option has no effect.
* @deprecated This option has no effect.
Expand Down Expand Up @@ -19963,10 +19943,6 @@ export interface Keyboard {
*
* Sends a `keydown`, `keypress`/`input`, and `keyup` event for each character in the text.
*
* When [`namedKeys`](https://playwright.dev/docs/api/class-keyboard#keyboard-type-option-named-keys) is `true`,
* anything inside `{}` is treated as a key name (same format as
* [keyboard.press(key[, options])](https://playwright.dev/docs/api/class-keyboard#keyboard-press)).
*
* To press a special key, like `Control` or `ArrowDown`, use
* [keyboard.press(key[, options])](https://playwright.dev/docs/api/class-keyboard#keyboard-press).
*
Expand All @@ -19975,9 +19951,6 @@ export interface Keyboard {
* ```js
* await page.keyboard.type('Hello'); // Types instantly
* await page.keyboard.type('World', { delay: 100 }); // Types slower, like a user
*
* // Mix text and special keys
* await page.keyboard.type('Hello{Enter}World', { namedKeys: true });
* ```
*
* **NOTE** Modifier keys DO NOT effect `keyboard.type`. Holding down `Shift` will not type the text in upper case.
Expand All @@ -19992,14 +19965,6 @@ export interface Keyboard {
* Time to wait between key presses in milliseconds. Defaults to 0.
*/
delay?: number;

/**
* When [`namedKeys`](https://playwright.dev/docs/api/class-keyboard#keyboard-type-option-named-keys) is `true`,
* anything inside `{}` is treated as a key name (same format as
* [keyboard.press(key[, options])](https://playwright.dev/docs/api/class-keyboard#keyboard-press)). Use `{{` to type
* a literal brace character. Defaults to `false`.
*/
namedKeys?: boolean;
}): Promise<void>;

/**
Expand Down
2 changes: 1 addition & 1 deletion packages/playwright-core/browsers.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
},
{
"name": "firefox",
"revision": "1528",
"revision": "1530",
"installByDefault": true,
"browserVersion": "151.0",
"title": "Firefox"
Expand Down
3 changes: 0 additions & 3 deletions packages/playwright-core/src/cli/browserActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,6 @@ async function launchContext(options: Options, extraOptions: LaunchOptions): Pro
delete contextOptions.isMobile;
}

if (contextOptions.isMobile && browserType.name() === 'firefox')
contextOptions.isMobile = undefined;

if (options.blockServiceWorkers)
contextOptions.serviceWorkers = 'block';

Expand Down
2 changes: 0 additions & 2 deletions packages/playwright-core/src/protocol/validator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1605,7 +1605,6 @@ scheme.FrameTypeParams = tObject({
strict: tOptional(tBoolean),
text: tString,
delay: tOptional(tFloat),
namedKeys: tOptional(tBoolean),
timeout: tFloat,
});
scheme.FrameTypeResult = tOptional(tObject({}));
Expand Down Expand Up @@ -2491,7 +2490,6 @@ scheme.PageKeyboardInsertTextResult = tOptional(tObject({}));
scheme.PageKeyboardTypeParams = tObject({
text: tString,
delay: tOptional(tFloat),
namedKeys: tOptional(tBoolean),
});
scheme.PageKeyboardTypeResult = tOptional(tObject({}));
scheme.PageKeyboardPressParams = tObject({
Expand Down
9 changes: 0 additions & 9 deletions packages/playwright-core/src/server/artifact.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ type CancelCallback = () => Promise<void>;
export class Artifact extends SdkObject {
private _localPath: string;
private _unaccessibleErrorMessage: string | undefined;
private _missingFileErrorMessage: string | undefined;
private _cancelCallback: CancelCallback | undefined;
private _finishedPromise = new ManualPromise<void>();
private _saveCallbacks: SaveCallback[] = [];
Expand All @@ -44,14 +43,6 @@ export class Artifact extends SdkObject {
this._cancelCallback = cancelCallback;
}

markMissingFileErrorMessage(errorMessage: string) {
this._missingFileErrorMessage = errorMessage;
}

missingFileErrorMessage(): string | undefined {
return this._missingFileErrorMessage;
}

async localPathAfterFinished(progress: Progress): Promise<string> {
return await progress.race(this._localPathAfterFinished());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,11 @@ export class ArtifactDispatcher extends Dispatcher<Artifact, channels.ArtifactCh
}

async pathAfterFinished(params: channels.ArtifactPathAfterFinishedParams, progress: Progress): Promise<channels.ArtifactPathAfterFinishedResult> {
this._assertFileAccessible();
const path = await this._object.localPathAfterFinished(progress);
return { value: path };
}

async saveAs(params: channels.ArtifactSaveAsParams, progress: Progress): Promise<channels.ArtifactSaveAsResult> {
this._assertFileAccessible();
return await progress.race(new Promise((resolve, reject) => {
this._object.saveAs(progress, async (localPath, error) => {
if (error) {
Expand All @@ -70,14 +68,7 @@ export class ArtifactDispatcher extends Dispatcher<Artifact, channels.ArtifactCh
}));
}

private _assertFileAccessible(): void {
const errorMessage = this._object.missingFileErrorMessage();
if (errorMessage)
throw new Error(errorMessage);
}

async saveAsStream(params: channels.ArtifactSaveAsStreamParams, progress: Progress): Promise<channels.ArtifactSaveAsStreamResult> {
this._assertFileAccessible();
return await progress.race(new Promise((resolve, reject) => {
this._object.saveAs(progress, async (localPath, error) => {
if (error) {
Expand All @@ -103,7 +94,6 @@ export class ArtifactDispatcher extends Dispatcher<Artifact, channels.ArtifactCh
}

async stream(params: channels.ArtifactStreamParams, progress: Progress): Promise<channels.ArtifactStreamResult> {
this._assertFileAccessible();
const fileName = await this._object.localPathAfterFinished(progress);
const readable = fs.createReadStream(fileName, { highWaterMark: 1024 * 1024 });
return { stream: new StreamDispatcher(this, readable) };
Expand Down
4 changes: 2 additions & 2 deletions packages/playwright-core/src/server/dom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -774,13 +774,13 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
return await progress.race(this.evaluateInUtility(([injected, node]) => injected.blurNode(node), {}));
}

async type(progress: Progress, text: string, options: { delay?: number, namedKeys?: boolean } & types.StrictOptions): Promise<void> {
async type(progress: Progress, text: string, options: { delay?: number } & types.StrictOptions): Promise<void> {
await this._markAsTargetElement(progress);
const result = await this._type(progress, text, options);
return assertDone(throwRetargetableDOMError(result));
}

async _type(progress: Progress, text: string, options: { delay?: number, namedKeys?: boolean } & types.StrictOptions): Promise<'error:notconnected' | 'done'> {
async _type(progress: Progress, text: string, options: { delay?: number } & types.StrictOptions): Promise<'error:notconnected' | 'done'> {
progress.log(`elementHandle.type("${text}")`);
await progress.race(this.instrumentation.onBeforeInputAction(this, progress.metadata));
const result = await this._focus(progress, true /* resetSelectionIfNotFocused */);
Expand Down
5 changes: 0 additions & 5 deletions packages/playwright-core/src/server/download.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,6 @@ export class Download {
if (!downloadPath)
throw new Error(`Download filename '${downloadFilename}' escapes download directory`);
this.artifact = new Artifact(page, downloadPath, unaccessibleErrorMessage, () => this.cancel());
if (!page.browserContext._browser._isBrowserCollocatedWithServer) {
this.artifact.markMissingFileErrorMessage(
`Downloaded file is not accessible from the Playwright server because the browser is running on a different host ` +
`(e.g. connected over CDP to a remote browser). Saving downloads requires the browser and the Playwright server to share a filesystem.`);
}
this._page = page;
this.url = url;
this._uuid = uuid;
Expand Down
4 changes: 2 additions & 2 deletions packages/playwright-core/src/server/firefox/ffBrowser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,6 @@ export class FFBrowser extends Browser {
}

async doCreateNewContext(options: types.BrowserContextOptions): Promise<BrowserContext> {
if (options.isMobile)
throw new Error('options.isMobile is not supported in Firefox');
const { browserContextId } = await this.session.send('Browser.createBrowserContext', { removeOnDetach: true });
const context = new FFBrowserContext(this, browserContextId, options);
await context.initialize();
Expand Down Expand Up @@ -359,7 +357,9 @@ export class FFBrowserContext extends BrowserContext {
return;
const viewport = {
viewportSize: { width: this._options.viewport.width, height: this._options.viewport.height },
screenSize: this._options.screen,
deviceScaleFactor: this._options.deviceScaleFactor || 1,
isMobile: !!this._options.isMobile,
};
await this._browser.session.send('Browser.setDefaultViewport', { browserContextId: this._browserContextId, viewport });
}
Expand Down
8 changes: 6 additions & 2 deletions packages/playwright-core/src/server/firefox/ffPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -380,8 +380,12 @@ export class FFPage implements PageDelegate {
}

async updateEmulatedViewportSize(): Promise<void> {
const viewportSize = this._page.emulatedSize()?.viewport ?? null;
await this._session.send('Page.setViewportSize', { viewportSize });
const emulatedSize = this._page.emulatedSize();
await this._session.send('Page.setViewportSize', {
viewportSize: emulatedSize?.viewport ?? null,
screenSize: emulatedSize?.screen,
isMobile: !!this._browserContext._options.isMobile,
});
}

async bringToFront(): Promise<void> {
Expand Down
Loading
Loading