Home > Blockchain >  'ElementHandle<Element> | null' is not assignable to parameter of type 'Element
'ElementHandle<Element> | null' is not assignable to parameter of type 'Element

Time:01-20

I'm using Puppeteer and Jest to test if #keys becomes display: flex if the / key is pressed:

import * as puppeteer from 'puppeteer';
import { log } from 'console';

describe('Puppeteer Test', () => {
    let browser: puppeteer.Browser;
    let page: puppeteer.Page;

    beforeAll(async () => {
        browser = await puppeteer.launch({
            headless: true,
            defaultViewport: null,
        });
        page = await browser.newPage();
        await page.goto('http://localhost:5500/dist/dummy.html');
    });

    test('`#keys` has display: flex after pressing `/`', async () => {
        const keysElement = await page.$('#keys');
        await page.keyboard.press('/');

        expect(window.getComputedStyle(keysElement).display).toBe('flex');
    });

    afterAll(async () => {
        await browser.close();
    });
});

I'm getting this TypeScript Error:

const keysElement: puppeteer.ElementHandle | null

Argument of type 'ElementHandle | null' is not assignable to parameter of type > 'Element'. Type 'null' is not assignable to type 'Element'.ts(2345)

I know what it means. getComputedStyle() is expecting an Element, but keysElement is an ElementHandle<Element> | null. But I'm not sure how to convert it into an element.

If I write window.getComputedStyle(keysElement).display, I get another error:

Conversion of type 'ElementHandle | null' to type 'Element' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first. Type 'ElementHandle' is missing the following properties from type 'Element': attributes, classList, className, clientHeight, and 164 more.ts(2352)

Note: Sorry, I don't know how to share live Jest Puppeteer TypeScript code.

CodePudding user response:

I'm not sure what window would refer to. I'd try using an evaluate block to access the browser's window:

test('`#keys` has display: flex after pressing `/`', async () => {
    await page.keyboard.press('/');
    const display = await page.$eval('#keys', el => getComputedStyle(el).display);
    expect(display).toBe('flex');
});

Minimal, runnable example:

const puppeteer = require("puppeteer"); // ^19.4.1

const html = `
<style>.foo {display: flex;}</style>
<p>x</p>
<script>
document.addEventListener("keydown", e => {
  if (e.code === "NumpadDivide") {
    document.querySelector("p").classList.add("foo");
  }
});
</script>`;

let browser;
(async () => {
  browser = await puppeteer.launch();
  const [page] = await browser.pages();
  await page.setContent(html);
  const displayBefore = await page.$eval("p", el => getComputedStyle(el).display);
  console.log(displayBefore); // => block
  await page.keyboard.press("/");
  const displayAfter = await page.$eval("p", el => getComputedStyle(el).display);
  console.log(displayAfter); // => flex
})()
  .catch(err => console.error(err))
  .finally(() => browser?.close());
  • Related