vendredi 14 août 2020

How do I access and manipulate DOM elements with Jest testing for plain JavaScript and HTML?

I'm trying to write tests for plain JavaScript without any frameworks. I'm using Jest for testing, but I'm struggling to access the HTML body (and elements in it) and manipulate it. I don't have problems with access when I try to get a DOM element in the normal JavaScript file (when I run "npm start"). But when I try to do console.log with a DOM element in the testing file (with "npm test"), I get an empty document.

What do you recommend for solving this issue?

I tried two solutions. First, I used this source: https://dev.to/snowleo208/things-i-learned-after-writing-tests-for-js-and-html-page-4lja In this case, I got access to my DOM elements, but when I tried to change something with fireEvent, nothing happened.

test.js:

import { screen } from '@testing-library/dom'

const fs = require('fs');
const path = require('path');
let html = fs.readFileSync(path.resolve(__dirname, './view/index.html'), 'utf8');
document.documentElement.innerHTML = html.toString();

jest
    .dontMock('fs');

const input = document.getElementById('input')
const button = document.getElementById('button')

test('Clicking on Insert button should show alert message', () => {
  fireEvent.change(input, { target: { value: 'horse' } })
  fireEvent.click(button, { button: '0' }) 
  screen.debug()
  console.log(document.body.innerHTML)
})

The second solution was using Jest plus Selenium to run a web server. In this case, the server runs fine but there's no access to DOM elements. What am I doing wrong here?

test.js:

import { fireEvent, cleanup, screen } from '@testing-library/dom'
import '@testing-library/jest-dom/extend-expect'

import {Builder, By} from 'selenium-webdriver'
import chrome from 'selenium-webdriver/chrome'
import chromedriver from 'chromedriver'
import regeneratorRuntime from "regenerator-runtime"
import script from "jest"

const url = 'http://localhost:8000'

let driver

chrome.setDefaultService(new chrome.ServiceBuilder(chromedriver.path).build())

const options = new chrome.Options()
options.addArguments(
    'headless'
)

describe('List View', () => {

  jest.setTimeout(10000)

  beforeAll((done) => {
    driver = new Builder()
    .forBrowser('chrome')
    .setChromeOptions(options)
    .build()
    driver.get(url).then(()=>{
      console.log("Got page")
      done()
    })
  })

  beforeEach(async () => {
     await driver.navigate().refresh();
  })

  afterAll(async () => {
    await driver.quit();
  }, 15000);

  it('Clicking on Insert button should show alert message', async function(){
    console.log(document.body.innerHTML)
    let button = await driver.findElement(By.id("button"))
    screen.debug()
  })

});

Part of my file structure: package.json

"start": "node app.js",
"test": "cross-env NODE_ENV=test ./node_modules/.bin/jest test --verbose --env=jsdom --testResultsProcessor ./node_modules/jest-junit"

app.js

...
app.use(express.static(path.join(__dirname, 'view')));
app.listen(8000, '0.0.0.0', function() {});
module.exports = app;

view/index.html

<body>
    <input id="input" type="text"></input>
    <button id="button">Insert</button>
    <ul id="list"></ul>
    <script type="module" src="js/script.js"></script>
</body>

view/js/script.js - my JavaScript file

Aucun commentaire:

Enregistrer un commentaire