2

I'm trying to test for an alert box in Puppeteer:

    msg = '';
    await page.goto('http://localhost:8080/', {
      waitUntil: 'networkidle2'
    });
    await page.$eval('#value', el => el.value = '<script>alert("BLEH")</script>');
    page.on('dialog', async dialog => {
      msg = dialog.message();
      await dialog.dismiss()
    })
    // submit comment
    await page.$eval('#message', form => form.submit());
    expect(msg).toEqual('BLEH');

However, it doesn't seem to return the message inside the alert box (even though I've confirmed it works doing it manually). Any ideas why page.on('dialog', async dialog => { isn't being entered?

  • 1
    so `#value` is this id of an element? – Vivek Bani Jul 30 '21 at 05:48
  • Yes, it's an element within a form on the webpage. – seriouslyg0e Jul 30 '21 at 05:58
  • 1
    it's a good idea to show a minimal markup you're working with so others can run your code without guesswork. That said, assuming this is all OK, I don't see that `await page.$eval("#message")` is going to wait for the handler to set `msg = dialog.message()`. That's in a totally different promise chain. You might need to promisify the handler if you want to be sure `msg` has been set. A bit more context would make this easier to help with and make it possible to provide working, runnable code. – ggorlen Jul 30 '21 at 06:35

1 Answers1

2

I'm not sure what's going on with your page -- it looks like you're testing XSS, but in any case, you can promisify the dialog handler to resolve to the dialog.message() value as in this example.

Note that I'm submitting the form with Enter -- calling form.submit() seems to override the default prevention, killing the page, but if it works on your site, that modification doesn't change the fundamental point of the code below.

Keep in mind that await dialogDismissed; will never time out since it's not a Puppeteer function. If you want that, call setTimeout(reject, someDelay) in the promise.

const puppeteer = require("puppeteer");

let browser;
(async () => {
  const html = `
    <form id="message"><input id="value"></form>
    <script>
      document
        .getElementById("message")
        .addEventListener("submit", e => {
          e.preventDefault();
          alert(document.getElementById("value").value);
        })
      ;
    </script>
  `;
  browser = await puppeteer.launch();
  const [page] = await browser.pages();
  const dialogDismissed = new Promise((resolve, reject) => {
    const handler = async dialog => {
      await dialog.dismiss();
      resolve(dialog.message());
    };
    page.once("dialog", handler);
  });
  await page.setContent(html);
  const inputEl = await page.$("#value");
  await inputEl.type("hello world");
  await inputEl.press("Enter");
  const msg = await dialogDismissed;
  console.log(msg); // => hello world
  await page.close();
})()
  .catch(err => console.error(err))
  .finally(() => browser?.close())
;
ggorlen
  • 44,755
  • 7
  • 76
  • 106