Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: Iphone Emulation Viewport Issues - (Simular to #32406) #34188

Closed
harryfinn101 opened this issue Jan 1, 2025 · 3 comments
Closed

[Bug]: Iphone Emulation Viewport Issues - (Simular to #32406) #34188

harryfinn101 opened this issue Jan 1, 2025 · 3 comments

Comments

@harryfinn101
Copy link

harryfinn101 commented Jan 1, 2025

Version

@playwright/[email protected]

Steps to reproduce

This script loads up www.google.com;

Using node iphonetest.js

const { webkit, devices } = require("playwright");

(async () => {
  const iPhone12 = {
    ...devices["iPhone 12"],
    deviceScaleFactor: 1,
    hasTouch: true,
    defaultBrowserType: "webkit",
    isMobile: true,
    // Add specific iOS platform settings
    userAgentMetadata: {
      platform: "iPhone",
      platformVersion: "16.0",
      architecture: "",
      model: "iPhone",
      mobile: true,
    },
  };

  const browser = await webkit.launch({
    headless: false,
  });

  const context = await browser.newContext({
    ...iPhone12,
    viewport: { width: 390, height: 844 },
    isMobile: true,
    hasTouch: true,
    userAgent:
      "Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1",
    // Add specific WebKit settings
    deviceScaleFactor: 3,
    isMobile: true,
    hasTouch: true,
    defaultBrowserType: "webkit",
    // Add iOS-specific features
    contextOptions: {
      iosDevice: "iPhone 12",
      forcedColors: "none",
      reducedMotion: "no-preference",
      viewport: { width: 390, height: 844 },
    },
  });

  const page = await context.newPage();

  // Add hooks for WebKit-specific behaviors
  await page.addInitScript(() => {
    Object.defineProperty(navigator, "platform", {
      get: function () {
        return "iPhone";
      },
    });

    Object.defineProperty(navigator, "maxTouchPoints", {
      get: function () {
        return 5;
      },
    });

    // Add iOS-specific window properties
    window.safari = {};
    window.ApplePaySession = class {};
    window.webkit = {
      messageHandlers: {},
      messageHandlersMap: new Map(),
    };
  });

  await page.goto("http://www.google.com", {
    waitUntil: "networkidle",
    timeout: 30000,
  });

  await page.waitForLoadState("domcontentloaded");
  await page.waitForLoadState("networkidle");

  // Enhanced viewport meta handling
  await page.evaluate(() => {
    const setViewport = () => {
      const meta =
        document.querySelector('meta[name="viewport"]') ||
        document.createElement("meta");
      meta.name = "viewport";
      meta.content =
        "width=device-width, initial-scale=1, viewport-fit=cover, maximum-scale=1, user-scalable=no, shrink-to-fit=no";
      if (!meta.parentNode) {
        document.head.insertBefore(meta, document.head.firstChild);
      }
    };

    setViewport();

    // Prevent other scripts from modifying viewport
    const originalDefineProperty = Object.defineProperty;
    Object.defineProperty = function (obj, prop, descriptor) {
      if (
        obj instanceof HTMLMetaElement &&
        prop === "content" &&
        obj.name === "viewport"
      ) {
        return obj;
      }
      return originalDefineProperty(obj, prop, descriptor);
    };
  });

  // Log enhanced device info
  console.log(
    "Enhanced device info:",
    await page.evaluate(() => ({
      viewport: {
        width: window.innerWidth,
        height: window.innerHeight,
        devicePixelRatio: window.devicePixelRatio,
        visualViewport: window.visualViewport
          ? {
              width: window.visualViewport.width,
              height: window.visualViewport.height,
              scale: window.visualViewport.scale,
            }
          : null,
      },
      device: {
        platform: navigator.platform,
        userAgent: navigator.userAgent,
        vendor: navigator.vendor,
        maxTouchPoints: navigator.maxTouchPoints,
        standalone: navigator.standalone,
        hasWebKit: typeof window.webkit !== "undefined",
        hasSafari: typeof window.safari !== "undefined",
        hasApplePay: typeof window.ApplePaySession !== "undefined",
      },
      screen: {
        width: window.screen.width,
        height: window.screen.height,
        availWidth: window.screen.availWidth,
        availHeight: window.screen.availHeight,
        colorDepth: window.screen.colorDepth,
        orientation: window.screen.orientation?.type,
      },
    }))
  );

  await page.screenshot({
    path: "webkit-iphone12-screenshot.png",
    fullPage: true,
    scale: "device",
  });

  await page.pause();
  await browser.close();
})();

Here is the debug output

Enhanced device info: {
  viewport: {
    width: 390,
    height: 844,
    devicePixelRatio: 3,
    visualViewport: { width: 390, height: 844, scale: 1 }
  },
  device: {
    platform: 'iPhone',
    userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1',
    vendor: 'Apple Computer, Inc.',
    maxTouchPoints: 5,
    standalone: undefined,
    hasWebKit: true,
    hasSafari: true,
    hasApplePay: true
  },
  screen: {
    width: 390,
    height: 844,
    availWidth: 390,
    availHeight: 844,
    colorDepth: 24,
    orientation: 'portrait-primary'
  }
}

Simpler Version of code - Same result in screenshots below

const { webkit, devices } = require("playwright");

(async () => {
  const iPhone12 = devices["iPhone 12"];

  // Launch WebKit browser
  const browser = await webkit.launch({ headless: false });

  // Create a browser context with iPhone 12 configuration
  const context = await browser.newContext({
    ...iPhone12,
    isMobile: true, // Enable mobile emulation
  });

  const page = await context.newPage();

  // Navigate to the target page
  await page.goto("https://www.google.com");

  // Inject <meta> viewport tag if missing
  await page.evaluate(() => {
    if (!document.querySelector('meta[name="apple-mobile-web-app-capable"]')) {
      const meta = document.createElement("meta");
      meta.name = "apple-mobile-web-app-capable";
      meta.content = "yes";
      document.head.appendChild(meta);
    }
  });
  // Force viewport size explicitly after page load
  await page.setViewportSize({ width: 390, height: 844 });

  // Log viewport and window dimensions for debugging
  console.log("Viewport size:", await page.viewportSize());
  console.log(
    "Window dimensions:",
    await page.evaluate(() => ({
      width: window.innerWidth,
      height: window.innerHeight,
    }))
  );

  // Take a screenshot for verification
  await page.screenshot({
    path: "webkit-debug-screenshot.png",
    fullPage: true,
  });

  // Pause for manual inspection using Playwright Inspector
  await page.pause();

  // Close the browser
  await browser.close();
})();



### Expected behavior

Expected google to load like this - example is chrome

![Image](https://github.com/user-attachments/assets/05f765cf-decc-4316-ad09-606a8dc38941)


### Actual behavior

This is what I see thought - which is very simular to issue #32406 which was closed.

![Image](https://github.com/user-attachments/assets/137ad2e1-5734-4f47-85ce-14b92b7629b3)

I tested other sites as well - same issue - here is screen shot of www.news.ocm.au

![Image](https://github.com/user-attachments/assets/db1808f9-8598-4c37-a220-8cdf6dd547fd)




### Additional context

I think that covers it all - if you need anything else or can't reproduce just reach out.

### Environment

```shell
System:
    OS: Windows 11 10.0.22631
    CPU: (8) x64 Intel(R) Core(TM) i7-4700MQ CPU @ 2.40GHz
    Memory: 3.32 GB / 15.93 GB
  Binaries:
    Node: 18.15.0 - C:\Program Files\nodejs\node.EXE
    npm: 9.5.0 - C:\Program Files\nodejs\npm.CMD
  IDEs:
    VSCode: 1.92.0 - C:\Users\Harry\AppData\Local\Programs\Microsoft VS Code\bin\code.CMD
  npmPackages:
    @playwright/test: ^1.49.1 => 1.49.1

Getting the following (www.google.com)

Image

Also fails for other sites; (www.news.com.au)

Image

Works fine if I change to Chromium

const { chromium, devices } = require("playwright");

(async () => {
  const iPhone12 = devices["iPhone 12"];

  // Launch WebKit browser
  const browser = await chromium.launch({ headless: false });

Image

@harryfinn101
Copy link
Author

Hi All - appears to a DPR scalling issue, this fixes it.

// Create a browser context with iPhone 12 configuration
const context = await browser.newContext({
...iPhone12,
deviceScaleFactor: 1, // Override the default DPR
isMobile: true, // Enable mobile emulation
});

@mxschmitt
Copy link
Member

Looks like a duplicate of #33702

@yury-s
Copy link
Member

yury-s commented Jan 3, 2025

Folding into #33702, there is being fixed upstream.

@yury-s yury-s closed this as completed Jan 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants