Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to simulate mobile environment with Node.js?

I want to simulate a mobile browser using Node.js, meaning that all mobile browser features should be available in the JavaScript side (on the client), even if they are mocked.

The webpages should think that they are loaded in a mobile environment. For instance, if we have a webpage which says:

if ('ontouchstart' in window) {
  document.body.innerHTML = "Mobile";
} else {
  document.body.innerHTML = "Not mobile";
}

...then when the page is loaded in the simulation, the body content should be Mobile.

What's the right way to do that? I'd avoid simply using PhantomJS (or anything similar) and executing a script which will do:

window.ontouchstart = function () {};

I was thinking to use JSDom, but it looks there's no easy way to just say mobile:true which would add all these properties.

What's the best way to create a browser which would have these APIs exposed, simulating a mobile browser?

A better example

From the Node.js side I want to communicate with the browser emulation and get some results back. Let's assume we have an index.html page like this:

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="content-type" content="text/html; charset=utf-8">
    </head>
    <body>
        <script>
        if ('ontouchstart' in window && window.orientation) {
          document.body.innerHTML = "Mobile";
        } else {
          document.body.innerHTML = "Not mobile";
        }
        </script>
    </body>
</html>

Using node-horseman (which uses Phantomjs), we can do the following:

const Horseman = require('node-horseman');
const horseman = new Horseman();

const iPhone6 = "Mozilla/5.0 (iPhone; CPU iPhone OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5376e Safari/8536.25";    

horseman
  .userAgent(iPhone6)
  .open('index.html')
  .evaluate(function () {
    return document.body.innerHTML;
  })
  .then(html => {
      console.log(html);
  })
  .evaluate(function () {
    return navigator.userAgent;
  })
  .then(ua => {
      console.log(ua);
  })
  .close();

This outputs Not mobile, while the user agent is the one I've provided (iPhone 6). Expected would be Mobile.

It simply shows that the window.orientation is not available, since it's not a mobile browser.

like image 629
Ionică Bizău Avatar asked Jan 09 '17 07:01

Ionică Bizău


People also ask

Can NodeJS be used for mobile app development?

The power of Node. js into mobile applications. Its core component is a library - available for Android and iOS - that lets you add a Node. js background worker to any mobile app. It also includes plugins for React Native and Cordova.

Can we make Android app using node js?

Android JS provides Node JS runtime environment, So you can write your code in Node. JS and can use any `npm` package which helps to build your app in a quick way.

Can I use node js with Flutter?

Buddy CI/CD allows you to instantly integrate Node. js with Build Flutter app to automate your development and build better apps faster.


2 Answers

Just an update in 2021:

To use emulation mode with selenium-webdriver, now the right way to do it is:

var webdriver = require('selenium-webdriver'),

var driver = new webdriver.Builder()
.forBrowser('chrome')
.setChromeOptions(new chrome.Options()
.setMobileEmulation({deviceName: 'Apple iPhone 5'})
//.setMobileEmulation({deviceName: ‘Pixel 2 XL’})         //<--- tested
//.setMobileEmulation({deviceName: ‘Google Nexus 7’})
//.addArguments('start-maximized')
)
.build();

//Rest of the operations will be done in emulation mode
// this links shows what user agent you are currently using
driver.get('https://www.whatismybrowser.com/detect/what-is-my-user-agent');

driver.quit();
like image 109
Don Diego Avatar answered Sep 24 '22 15:09

Don Diego


As you mentioned Phantom and Horseman I believe you want a browser automation framework with mobile support. You can use selenium with chrome (ChromeDriver) instead of Phantom, and chrome supports mobile emulation.

Here you can find selenium client for NodeJS: https://www.npmjs.com/package/selenium-webdriver chrome driver fo selenium: https://sites.google.com/a/chromium.org/chromedriver/

Starting chrome in mobile emulation mode:

var webdriver = require('selenium-webdriver');
var capabilities = {
    browserName: 'chrome',
    chromeOptions: {
        mobileEmulation: {
            deviceName: 'Apple iPhone 6'
        }
    }
};

var driver = new webdriver
    .Builder()
    .withCapabilities(capabilities)
    .build();

Here you can find list of available devices: https://stackoverflow.com/a/41104964/893432

you can also define your custom device: https://sites.google.com/a/chromium.org/chromedriver/mobile-emulation

if you want it headless the latest chrome build supports it: https://chromium.googlesource.com/chromium/src/+/lkgr/headless/README.md

You can also run your test on a real android device or emulator using selenium: https://sites.google.com/a/chromium.org/chromedriver/getting-started/getting-started---android

like image 20
Ali Avatar answered Sep 23 '22 15:09

Ali