简体   繁体   中英

Undefined property testing Lit typescript web component

I recently converted a lit web component over to Typescript and can't seem to figure out why my tests are failing now.. everything was working fine before the conversion.

These are my dependencies for testing:

"@open-wc/testing": "^3.1.2",
"@web/dev-server-esbuild": "^0.2.16",
"@web/test-runner": "^0.13.27"

So I run "test": "web-test-runner", with the following config in web-test-runner.config.mjs (Also got the same error using tsc to transpile the code):

import { esbuildPlugin } from '@web/dev-server-esbuild';

const filteredLogs = ['Running in dev mode', 'Lit is in dev mode'];

export default /** @type {import("@web/test-runner").TestRunnerConfig} */ ({
  files: 'lib/**/*.test.ts',
  nodeResolve: {
    exportConditions: ['browser', 'development'],
  },
  plugins: [esbuildPlugin({ ts: true })],
  filterBrowserLogs(log) {
    for (const arg of log.args) {
      if (typeof arg === 'string' && filteredLogs.some(l => arg.includes(l))) {
        return false;
      }
    }
    return true;
  }
});

and get this error:

components: > web-test-runner
components: Chrome: |██████████████████████████████| 0/1 test files | 0 passed, 0 failed
components: Running tests...
lib/MyElement/index.test.ts:
components:  ❌ MyElement > has a default title "World" and count 0
components:       AssertionError: expected undefined to equal 'World'
components:         at o.<anonymous> (lib/MyElement/index.test.ts:11:23)
components: Chrome: |██████████████████████████████| 1/1 test files | 0 passed, 1 failed
components: Finished running tests in 2.7s with 1 failed tests.
components: npm ERR! code ELIFECYCLE
components: npm ERR! errno 1
components: npm ERR! components@1.0.0 test: `web-test-runner`
components: npm ERR! Exit status 1
components: npm ERR! 
components: npm ERR! Failed at the components@1.0.0 test script.
components: npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
components: npm ERR! A complete log of this run can be found in:
components: npm ERR!     /Users/shawn/.npm/_logs/2022-03-21T22_11_54_084Z-debug.log
lerna ERR! npm run test exited 1 in 'components'

This is the component code:

import {LitElement, html, css} from 'lit';
import {customElement, property, state} from 'lit/decorators.js';

@customElement('my-element')
 export class MyElement extends LitElement {
   static styles = css`
     :host {
       display: block;
       border: solid 1px gray;
       padding: 16px;
       max-width: 800px;
     }
   `;

   @property() name: string = 'World';

   @state() count: number = 0;

   _onClick() {
    this.count++;
    this.dispatchEvent(new CustomEvent('count-changed'));
  }

  sayHello(name: string) {
    return `Hello, ${name}`;
  }
 
  render() {
    return html`
      <h1>${this.sayHello(this.name)}!</h1>
      <button @click=${this._onClick} part="button">
        Click Count: ${this.count}
      </button>
      <slot></slot>
    `;
  }
 }

And finally, the test code:

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

import { MyElement } from '.';

describe('MyElement', () => {
  it('has a default title "World" and count 0', async () => {
    const el = await fixture<MyElement>(html`
      <my-element></my-element>
    `);

    expect(el.name).to.equal('World');
    expect(el.count).to.equal(0);
  });
});

So I believe it's something related to transpiling the typescript, but I have not been successful in finding out what exactly it is. Anybody notice anything wrong that would cause these properties to be undefined now?

EDIT:

This is the original JS implementation to show the diff between this and the TS one.

import {LitElement, html, css} from 'lit';

 export class MyElement extends LitElement {
   static get styles() {
     return css`
       :host {
         display: block;
         border: solid 1px gray;
         padding: 16px;
         max-width: 800px;
       }
     `;
   }
 
   static get properties() {
     return {
       name: {type: String},
       count: {type: Number},
     };
   }
 
   constructor() {
     super();
     this.name = 'World';
     this.count = 0;
   }
 
   render() {
     return html`
       <h1>${this.sayHello(this.name)}!</h1>
       <button @click=${this._onClick} part="button">
         Click Count: ${this.count}
       </button>
       <slot></slot>
     `;
   }
 
   _onClick() {
     this.count++;
     this.dispatchEvent(new CustomEvent('count-changed'));
   }

   sayHello(name) {
     return `Hello, ${name}`;
   }
 }
 
 window.customElements.define('my-element', MyElement);

Can you try

@property({type: String}) name = 'World';

https://lit.dev/docs/api/decorators/#property

The issue is that you're not using the instance of MyElement in your test file but only its type and tag. Thus the compile process will throw out the import statement import { MyElement } from '.'; . If you would compile your test file using tsc you would see that the import statement is missing in the .js -output.

Fix it by importing the whole file in your test:

import './index.js';

Note: In the test file of the lit-element-starter-ts repo (find it here ) this scenario is not appearing since they are using the Element's instance in their first test case, thus the named import won't be removed by the tsc/esbuild:

  import {MyElement} from '../my-element.js';

  // ...

  test('is defined', () => {
    const el = document.createElement('my-element');
    assert.instanceOf(el, MyElement);
  });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM