user11783767
user11783767

Reputation:

Problem with puppeteer in combination with testing

I am having a problem. I am new to JavaScript and I can't really solve this error.

I am getting data from a website via puppeteer and then I want to test if it is the right one:

const puppeteer = require('puppeteer');

(async () => {
    const browser = await puppeteer.launch();
    const page = await browser.newPage();
    await page.goto('https://6mr2n.csb.app/#');

    header = await page.evaluate(() => {
        header = document.querySelector('header[class="header"]').innerText;
        return header;
    });

    console.info(`The header is: ${header}`);
    await browser.close
    module.exports = header;
})();

My test file (jest) is:

const index = require('./index');

test('Hallo', () => {
    expect(index.header).toEqual('todos');
  });

Probably I am just stupid, but I really tried a lot to solve this. Running the main file works but running the test (npm run test) gives following:

expect(received).toEqual(expected) // deep equality

Expected: "todos"
Received: undefined

  4 | 
  5 | test('Hallo', () => {
> 6 |     expect(index.header).toEqual('todos');
    |                          ^
  7 |   });

  at Object.<anonymous> (index.test.js:6:26)

And also:

Cannot log after tests are done. Did you forget to wait for something async in your test?
Attempted to log "The header is: todos".

Upvotes: 1

Views: 361

Answers (2)

theDavidBarton
theDavidBarton

Reputation: 8841

You could use a named async function in your puppeteer script (e.g.: header()) which returns the header value that you needed, and finally export it as module.exports.header = header outside the main function.

const puppeteer = require('puppeteer')

const header = async () => {
  const browser = await puppeteer.launch()
  const page = await browser.newPage()
  await page.goto('https://6mr2n.csb.app/#')

  const headerVal = await page.evaluate(() => {
    headerVal = document.querySelector('header[class="header"]').innerText
    return headerVal
  })

  await browser.close()
  console.info(`The header is: ${headerVal}`)
  return headerVal
}

module.exports.header = header

Your test needs an async function as well, so you are able to await it, e.g.:

const index = require('./index')

test('Hallo', async () => {
  const headerVal = await index.header()
  expect(headerVal).toEqual('todos')
})

Note: you need browser.close() to close the browser instance.

Note 2: You can retrieve the innerText like this as well:

const headerVal = await page.evaluate(el => el.innerText, await page.$('.header'))

Upvotes: 1

vsemozhebuty
vsemozhebuty

Reputation: 13782

You set module.exports in async function, but require('./index') does not wait for this setting and returns empty object. (BTW, you need module.exports.header = header to use index.header).

To fix this, you can try to return a Promise and to wait for it:

const puppeteer = require('puppeteer');

module.exports = (async () => { /* ... */ return header; })();
const headerPromise = require('./index');

(async function main() {
  const header = await headerPromise;
  test('Hallo', () => {
    expect(header).toEqual('todos');
  });
})();

Upvotes: 0

Related Questions