* Change deviceScaleFactor + viewport size atomically. * * deviceScaleFactor is a context-level option, so Playwright requires a full context * recreation. This method validates the input, stores the new values, calls * recreateContext(), and rolls back the fields on failure so a bad cal
(scale: number, width: number, height: number)
| 1478 | * (state may have been lost, per recreateContext's fallback behavior). |
| 1479 | */ |
| 1480 | async setDeviceScaleFactor(scale: number, width: number, height: number): Promise<string | null> { |
| 1481 | if (!Number.isFinite(scale)) { |
| 1482 | throw new Error(`viewport --scale: value must be a finite number, got ${scale}`); |
| 1483 | } |
| 1484 | if (scale < 1 || scale > 3) { |
| 1485 | throw new Error(`viewport --scale: value must be between 1 and 3 (gstack policy cap), got ${scale}`); |
| 1486 | } |
| 1487 | if (this.connectionMode === 'headed') { |
| 1488 | throw new Error('viewport --scale is not supported in headed mode — scale is controlled by the real browser window.'); |
| 1489 | } |
| 1490 | |
| 1491 | const prevScale = this.deviceScaleFactor; |
| 1492 | const prevViewport = { ...this.currentViewport }; |
| 1493 | this.deviceScaleFactor = scale; |
| 1494 | this.currentViewport = { width, height }; |
| 1495 | |
| 1496 | const err = await this.recreateContext(); |
| 1497 | if (err !== null) { |
| 1498 | // recreateContext's fallback path built a blank context using the NEW scale + |
| 1499 | // viewport (the fields we just set). Rolling the fields back without a second |
| 1500 | // recreate would leave the live context at new-scale while state says old-scale. |
| 1501 | // Roll back fields FIRST, then force a second recreate against the old values |
| 1502 | // so live state matches tracked state. |
| 1503 | this.deviceScaleFactor = prevScale; |
| 1504 | this.currentViewport = prevViewport; |
| 1505 | const rollbackErr = await this.recreateContext(); |
| 1506 | if (rollbackErr !== null) { |
| 1507 | // Second recreate also failed — we're in a clean blank slate via fallback, but |
| 1508 | // with old scale. Return the original error so the caller sees the primary failure. |
| 1509 | return `${err} (rollback also encountered: ${rollbackErr})`; |
| 1510 | } |
| 1511 | return err; |
| 1512 | } |
| 1513 | return null; |
| 1514 | } |
| 1515 | |
| 1516 | /** Read current deviceScaleFactor (for tests + debug). */ |
| 1517 | getDeviceScaleFactor(): number { |
no test coverage detected