Search code examples
javascripteslint

Javascript Only ESLint 'HTMLElement' is not defined no-undef error?


Not a Typescript Question

I've asked this question once already at it was closed saying that it is already answered here:

ReferenceError: HTMLElement is not defined in TypeScript

Please note that this is not a typescript project, so the typescript answer does not fit.

Here's the question again.

For the source files in this project this ESLint configuration creates these errors.


/Users/oleersoy/Temp/Remove/fs-javascript-starter/src/hello-world.component.js
   7:42  error  'HTMLElement' is not defined     no-undef
  52:3   error  'customElements' is not defined  no-undef

/Users/oleersoy/Temp/Remove/fs-javascript-starter/src/hello-world.component.spec.js
  3:1  error  'suite' is not defined  no-undef
  4:3  error  'test' is not defined   no-undef

✖ 4 problems (4 errors, 0 warnings)

How do we switch these off so that ESLint allows suite, test, HTMLElement, and customElements?

Here are the source files for reference:

eslint.config.js

import eslint from "@eslint/js";

export default [
    // apply recommended rules to JS files
    {
        files: ["**/*.js", "**/*.cjs", "**/*.mjs"],
        rules: eslint.configs.recommended.rules
    },
    {
        ignores: ["rollup.config.js", "web-test-runner.config.js"]
    }
]

src/hello-world.component.js

/**
 *  @category WebComponent
 *
 * Hello World Web Component
 * that renders a greeting.
 */
export class HelloWorldComponent extends HTMLElement {
    static get observedAttributes() {
      return ['name'];
    }
  
    /**
     * The name to greet
     * @defaultValue World
     */
    name = 'World';
    something
    /**
     * Initializes the name property to `World`.
     */
    constructor() {
      super();
      //    this.name = 'World';
    }
  
    /**
     * Sets the component inner
     * html to the greeting.
     */
    connectedCallback() {
      this.textContent = `Hello ${this.name}!`;
    }
  
    //========================================
    // attribute change callback
    //========================================
    attributeChangedCallback(
      property,
      oldValue,
      newValue
    ) {
      if (oldValue === newValue) return;
      switch (property) {
        case 'name':
          this.name = newValue;
          break;
        default:
          throw new Error(`Unhandled attribute: ${property}`);
      }
    }
  }
  customElements.define('hello-world', HelloWorldComponent);

src/hello-world.component.spec.js

import {expect, fixture, html} from '@open-wc/testing';

suite('hello-world.component tests', () => {
  test('fixture instantiation', async () => {
    const el = (await fixture(
      html`<hello-world></hello-world> `
    ));
    expect(el).not.to.equal(null);
    //    expect(true).to.equal(false);
  });
});

Solution

  • OK - one solution is to add global comments like this.

    This will fix the test linting errors.

    /*global suite*/
    /*global test*/
    

    And these comments fixes the globals in the component.

    /*global HTMLElement*/
    /*global customElements*/
    
    

    Another way to fix both the component and component spec linting errors it is to add ...globals.browser and ...globals.mocha to eslint.config.js. First install globals with npm i -D globals.

    import eslint from "@eslint/js";
    import globals from "globals";
    
    export default [
        // apply recommended rules to JS files
        
        {
            languageOptions: {
                globals: {
                    ...globals.browser,
                    ...globals.mocha
                }
            }
        },
        {
    
            files: ["**/*.js", "**/*.cjs", "**/*.mjs"],
            rules: eslint.configs.recommended.rules
        },
        {
            ignores: ["rollup.config.js", "web-test-runner.config.js", "src/index.bundle.js"]
        }
    ]