4

Is there a way to enable simulated device mode or emulated print media mode in headless Chrome in Linux?

It can be done manually in DevTools like so:

Enable print media emulation

The goal is to take a full-page screenshot in emulated print media mode without injecting or modifying any CSS. I'm already able take screenshots of web pages via Node.js, but not in emulated print media mode. I've searched, but am also unable to find a helpful CLI switch.

Example:StackOverflow print emulation

How to do this programmatically via CLI or Node.js? Is it even possible?


Reference on using Node.js to interact with headless Chrome DevTools Protocol: https://developers.google.com/web/updates/2017/04/headless-chrome

--

Update: I've researched the Chrome DevTools Protocol Viewer docs under Emulation, and there is a provision for Emulation.setEmulatedMedia. Setting Emulation.setEmulatedMedia({media: "print"}); renders the page in print emulation mode.

Drakes
  • 23,254
  • 3
  • 51
  • 94

3 Answers3

3

Figured out how to do this using in Django (python) with Selenium and Chromedriver.

    def set_media_emulation(self, media):
        """
            This is used to trigger between print mode and screen to allow
            @media (print) css styles to take effect
            call this in your testcase like self.set_media_emulation('print')
            or self.set_media_emulation('screen')
        :param media:
        :return:
        """
        command_url = "/session/{session_id}/chromium/send_command".format(session_id=self.selenium.session_id)
        self.selenium.command_executor._commands["send_command"] = ("POST", command_url)
        params = {'cmd': 'Emulation.setEmulatedMedia', 'params': {'media': media}}
        return self.selenium.execute("send_command", params)

Where self.selenium is

from selenium.webdriver import Chrome

self.selenium = Chrome(desired_capabilities=desired_capabilities,
                                           options=chrome_options,
                                           service_args=['--verbose'],
                                           service_log_path=self.selenium_log_path)
2

In the latest (tip-of-tree) Chrome DevTools Protocol Viewer documentation under Emulation, there is a section about emulated media. This one line will enable print media emulation:

Emulation.setEmulatedMedia({media: "print"});

In addition, if the viewport width is set to that of an 8.5in sheet of paper (~816px @ 96 DPI), then the screenshot will resemble a color print preview.

const viewportWidth = 816;    // 8.5 in
const viewportHeight = 1056;  // 11 in

const deviceMetrics = {
    width: viewportWidth,
    height: viewportHeight,
    deviceScaleFactor: 0,
    mobile: false,
    fitWindow: false
};
Emulation.setDeviceMetricsOverride(deviceMetrics);
Emulation.setVisibleSize({width: viewportWidth, height: viewportHeight});
Drakes
  • 23,254
  • 3
  • 51
  • 94
  • I realize that this is an old post, but I've been trying to figure out where/how to execute this code. I'm using Capybara/Selenium so maybe there's a few layers of indirection between me and the Chrome instance, but just exeucting this as Javascript does not work. Not sure how to actually send these commands to the webdriver :/ – Ibrahim Jul 02 '19 at 00:00
  • Ooh sweet, figured it out for Rspec/capybara/selenium: ` bridge = page.driver.browser.send(:bridge) path = '/session/:session_id/chromium/send_command' path[':session_id'] = bridge.session_id bridge.http.call(:post, path, cmd: 'Emulation.setEmulatedMedia', params: {media: 'print'}) ` – Ibrahim Jul 02 '19 at 01:06
1

For anyone looking for this, I figured out how to do it for Rspec+capybara+selenium:

def enable_print_emulation
  bridge = Capybara.current_session.driver.browser.send(:bridge)
  path = "/session/#{bridge.session_id}/chromium/send_command"

  bridge.http.call(:post, path, cmd: 'Emulation.setEmulatedMedia',
                                params: {media: 'print'})
end

Then just call this method in your spec!

Ibrahim
  • 1,883
  • 19
  • 27