Did you know that Chrome now ships with the feature Headless Chrome it is a tool for automated testing. For example, you may want to run some tests against a real web page, create a PDF of a page, or just inspect how the browser renders an URL, you can use these techniques to test your Oracle APEX applications.

What is Headless Chrome

Headless Chrome allows you to run the browser from the command line without actually opening a Chrome window, it is also possible to watch your script running in the browser.


Headless Chrome has a rather low-level API, it’s preferred to access it via a library. For this example I am using Puppeteer. Puppeteer is maintained by the Chrome DevTools team.


To use Puppeteer you need to have Node.js installed. You can find out how to do it here. Puppeteer requires at least Node v6.4.0, but the examples below use async/await which is only supported in Node v7.6.0 or greater.

You can check by using the following command in your terminal:

node --version
node –v

Create yourself a directory where you want Puppeteer installed. Open a terminal inside the directory you just created and Install Puppeteer using the following command in your terminal.

npm i puppeteer

The installation may take a couple of minutes. Because it will automatically download a version of Chromium(browser) for you. So you don’t have to setup and maintain a local instance of Chrome manually.

How to run the script

Create yourself a .js file with code of one of the examples. You need to be in the same folder as the file in order to run the code.

node yourfile.js

Taking screenshots with puppeteer

When Puppeteer is taking a screenshot it will simulate a browser window with the desired width. If the page you are testing is responsive, You will see a snapshot of what it looks like at that viewport. You can change its dimensions via the setViewport method.

const puppeteer = require('puppeteer');
 const viewports = [1920, 800, 600, 375];
 (async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();

  await page.goto('https://apex.oracle.com/pls/apex/f?p=51138:LOGIN_DESKTOP::::::');

  await page.focus('#P101_USERNAME');
  await page.type('guest', {delay: 100});
  await page.focus('#P101_PASSWORD');
  await page.type('apex_demo' , {delay: 100});
  await page.click('#P101_LOGIN');
  await page.waitForNavigation();

 for(viewport in viewports) {
   let vw = viewports[viewport];
   await page.setViewport({
   width: vw,
   // The height parameter is needed but has no function in our
   // case since we are using fullPage: true @page.screenshot
   height: 0

  await page.screenshot({
   path: `screenshot-W${vw}.png`,
   fullPage: true

Running this script will generate 4 images inside the folder of the script.



Interacting with Items on the page

With Puppeteer you can access all the elements on the page. Using Puppeteer you can scrape websites, test links, validate forms, etc.
By default headless mode is activated, you have to turn it off in your script. When you run your script it will now open Chromium.

const browser = await puppeteer.launch({
 headless: false,

in this example you log into the application and will add a customer and turn headless mode off so that you can see what’s going on.

const puppeteer = require('puppeteer');
(async () => {
 const browser = await puppeteer.launch({
 headless: false,
 slowMo: 350,
 args: [
 const page = await browser.newPage();
  width: 1920,
  height: 1080

 await page.goto('https://apex.oracle.com/pls/apex/f?p=51138:LOGIN_DESKTOP::::::');
 await page.focus('#P101_USERNAME');
 await page.type('guest', {delay: 50});
 await page.focus('#P101_PASSWORD');
 await page.type('apex_demo' , {delay: 50});
 await page.click('#P101_LOGIN');
 await page.waitForNavigation();
 await page.click('#t_TreeNav_1');
 await page.waitForNavigation();
 await page.click('#NEW_CUSTOMER');
 await page.waitForNavigation();
 await page.focus('#P7_CUST_FIRST_NAME');
 await page.type('Test' , {delay: 50});
 await page.focus('#P7_CUST_STREET_ADDRESS1');
 await page.type('123456 Test Drive' , {delay: 50});
 await page.focus('#P7_CUST_CITY');
 await page.type('Atlanta' , {delay: 50});
 await page.focus('#P7_CUST_POSTAL_CODE');
 await page.type('20166' , {delay: 50});
 await page.focus('#P7_CREDIT_LIMIT');
 await page.type('1000' , {delay: 50});
 await page.focus('#P7_CUST_EMAIL');
 await page.type('testusermail.@email.com' , {delay: 50});
 await page.focus('#P7_CUST_LAST_NAME');
 await page.type('User' , {delay: 50});
 await page.click('#P7_CUST_STATE')
 await page.type('D' , {delay: 50});
 await page.press('Enter');
 await page.click('#B34382662543207696578');
Testing APEX Application using Node.js and Puppeteer

Testing APEX Application using Node.js and Puppeteer


Stefan · 11 October, 2017 at 3:19 pm

Hi Chris,

did you also make some tests with puppeteer for modal windows? I see you have Page 7 at apex sample application as a normal window. I assume you have some issues with modal pages, like me. Do you have more informations how to catch items for a modal page?

Stefan · 13 October, 2017 at 7:21 pm

Hi Chris,

sure with iframes it should work, but it doesn’t work. It seems puppeteer has some issues with iframes. Do you have a workaround or coding fragment for this?

    Chris Jansen · 13 October, 2017 at 9:33 pm

    Hi Stefan,

    The .type function is not working for now, when they update the puppeteer libary it wil work.
    You can test if you can click a button in a iframe because that should work already using the code snippet below.

    const Frame = await page.frames()[1];
    const button = ‘#B34558108453242558706’;
    const textInput = await Frame.$(‘#P6_PRODUCT_NAME’);
    await Frame.$eval(button, el => el.click());

      bernard · 31 March, 2020 at 9:15 am

      Hello , Know this is been idle for a while. Got myself into an apex environment and now puppeteer. I have done some searching and tried many ways. Perhaps there is more insight after posting this comment.

      i don have an issue with selenium where it can detect this #apex_dialog_1 > iframe.

      Got myself into this issue https://github.com/puppeteer/puppeteer/issues/5558

      in summary: starting from here current page.iframe (click element in iframe ) -> dialog/modal/iframe (popup) and then puppeteer hangs.

      my issue is how do tell puppeter what to do next for going into this modal? using a new page promise or an page.iframe ? or an popup?

      cannot exit as the modal is not closed.

      appreciate if there is any help.

Leave a Reply

Your email address will not be published. Required fields are marked *