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);