forked from matthewp/haunted
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
tests: convert attributes test file to TypeScript
- Loading branch information
1 parent
57d69b4
commit 0613862
Showing
1 changed file
with
145 additions
and
93 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,184 +1,236 @@ | ||
import { component, html } from '../haunted.js'; | ||
import { attach, mount, cycle } from './helpers.js'; | ||
import { component, html } from '../src/haunted'; | ||
import { fixture, expect, nextFrame } from '@open-wc/testing'; | ||
|
||
|
||
describe('Observed attributes', () => { | ||
it('Trigger rerenders', async () => { | ||
const tag = 'attrs-test'; | ||
|
||
function app({ name = '' }) { | ||
return html`<div>Hello ${name}</div>`; | ||
interface Props { | ||
name: string; | ||
} | ||
|
||
app.observedAttributes = ['name']; | ||
|
||
customElements.define(tag, component(app)); | ||
function App({ name = '' }) { | ||
return html`<div>Hello ${name}</div>`; | ||
} | ||
|
||
let teardown = attach(tag); | ||
await cycle(); | ||
customElements.define( | ||
tag, | ||
component<HTMLElement & Props>(App, {observedAttributes: ['name']}) | ||
); | ||
|
||
let inst = document.querySelector(tag); | ||
const el = await fixture(html`<attrs-test></attrs-test>`); | ||
const inst = document.querySelector(tag); | ||
inst.setAttribute('name', 'world'); | ||
|
||
await cycle(); | ||
await nextFrame(); | ||
|
||
let div = host.firstChild.shadowRoot.firstElementChild; | ||
assert.equal(div.textContent, 'Hello world'); | ||
teardown(); | ||
expect(el.shadowRoot.firstElementChild.textContent).to.equal('Hello world'); | ||
}); | ||
|
||
it('Can observe the "title" attribute', async () => { | ||
const tag = 'attrs-test-title'; | ||
|
||
function app() { | ||
this.setAttribute('title', 'bar'); | ||
interface Props { | ||
title: string; | ||
} | ||
|
||
app.observedAttributes = ['title']; | ||
function App(this: unknown) { | ||
(this as HTMLElement).setAttribute('title', 'bar'); | ||
} | ||
|
||
customElements.define(tag, component(app)); | ||
customElements.define( | ||
tag, | ||
component<HTMLElement & Props>(App, {observedAttributes: ['title']}) | ||
); | ||
|
||
let teardown = attach(tag); | ||
await cycle(); | ||
const el = await fixture(html`<attrs-test-title></attrs-test-title>`); | ||
|
||
let inst = document.querySelector(tag); | ||
assert.equal(inst.getAttribute('title'), 'bar', 'on the instance'); | ||
teardown(); | ||
expect(el.getAttribute('title')).to.equal('bar'); | ||
}); | ||
|
||
it('Trigger rerenders while declared as an option', async () => { | ||
const tag = 'attrs-options-test'; | ||
|
||
function app({ name = '' }) { | ||
interface Props { | ||
name: string; | ||
} | ||
|
||
function App({ name = '' }) { | ||
return html`<div>Hello ${name}</div>`; | ||
} | ||
|
||
customElements.define(tag, component(app, {observedAttributes: ['name']})); | ||
customElements.define( | ||
tag, | ||
component<HTMLElement & Props>(App, {observedAttributes: ['name']}) | ||
); | ||
|
||
let teardown = attach(tag); | ||
await cycle(); | ||
const el = await fixture(html`<attrs-options-test></attrs-options-test>`); | ||
|
||
let inst = document.querySelector(tag); | ||
inst.setAttribute('name', 'world'); | ||
el.setAttribute('name', 'world'); | ||
|
||
await cycle(); | ||
await nextFrame(); | ||
|
||
let div = host.firstChild.shadowRoot.firstElementChild; | ||
assert.equal(div.textContent, 'Hello world'); | ||
teardown(); | ||
expect(el.shadowRoot.textContent).to.equal('Hello world'); | ||
}); | ||
|
||
it('Initial attributes are reflected', async () => { | ||
const tag = 'attrs-initial-test'; | ||
|
||
function app({ name = '' }) { | ||
interface Props { | ||
name: string; | ||
} | ||
|
||
function App({ name = '' }) { | ||
return html`<div>Hello ${name}</div>`; | ||
} | ||
|
||
app.observedAttributes = ['name']; | ||
customElements.define( | ||
tag, | ||
component<HTMLElement & Props>(App, {observedAttributes: ['name']}) | ||
); | ||
|
||
customElements.define(tag, component(app)); | ||
const el = await fixture | ||
(html`<attrs-initial-test name="world"></attrs-initial-test>`); | ||
|
||
let template = document.createElement('template'); | ||
template.innerHTML = ` | ||
<attrs-initial-test name="world"></attrs-initial-test> | ||
`; | ||
let frag = template.content.cloneNode(true); | ||
host.appendChild(frag); | ||
await cycle(); | ||
await nextFrame(); | ||
|
||
let div = host.firstElementChild.shadowRoot.firstElementChild; | ||
assert.equal(div.textContent, 'Hello world'); | ||
host.innerHTML = ''; | ||
expect(el.shadowRoot.textContent).to.equal('Hello world'); | ||
}); | ||
|
||
it('Boolean attributes are turned into booleans', async () => { | ||
const tag = 'attrs-boolean-test'; | ||
let val; | ||
let val: boolean; | ||
|
||
interface Props { | ||
open: boolean; | ||
} | ||
|
||
function Drawer({ open }) { | ||
val = open; | ||
return html`Test`; | ||
} | ||
|
||
Drawer.observedAttributes = ['open']; | ||
customElements.define( | ||
tag, | ||
component<HTMLElement & Props>(Drawer, {observedAttributes: ['open']}) | ||
); | ||
|
||
customElements.define(tag, component(Drawer)); | ||
let teardown = mount(` | ||
<attrs-boolean-test open></attrs-boolean-test> | ||
`); | ||
const el = await fixture | ||
(html`<attrs-boolean-test open></attrs-boolean-test>`) as HTMLElement & Props; | ||
|
||
await cycle(); | ||
teardown(); | ||
expect(typeof el.open).to.equal('boolean'); | ||
expect(typeof val).to.equal('boolean'); | ||
expect(el.open ).to.be.true; | ||
expect(val).to.be.true; | ||
}); | ||
|
||
it('Boolean attributes are undefined when not present', async () => { | ||
const tag = 'attrs-boolean-false-test'; | ||
let val: boolean; | ||
|
||
interface Props { | ||
open: boolean; | ||
} | ||
|
||
assert.equal(typeof val, 'boolean'); | ||
assert.equal(val, true, 'is a boolean'); | ||
function Drawer({ open }) { | ||
val = open; | ||
return html`Test`; | ||
} | ||
|
||
customElements.define( | ||
tag, | ||
component<HTMLElement & Props>(Drawer, {observedAttributes: ['open']}) | ||
); | ||
|
||
const el = await fixture | ||
(html`<attrs-boolean-false-test></attrs-boolean-false-test>`) as HTMLElement & Props; | ||
|
||
expect(el.open).to.be.undefined; | ||
expect(val).to.be.undefined; | ||
}); | ||
|
||
it('renderer receives component as this context', async () => { | ||
const tag = 'attrs-test-2'; | ||
|
||
function app({ name = '' }) { | ||
return html`<div>${name} ${this.name}</div>`; | ||
interface Props { | ||
name: string; | ||
} | ||
|
||
app.observedAttributes = ['name']; | ||
function App({ name = '' }) { | ||
return html`<div>${name} ${this.name}</div>`; | ||
} | ||
|
||
customElements.define(tag, component(app)); | ||
customElements.define( | ||
tag, | ||
component<HTMLElement & Props>(App, {observedAttributes: ['name']}) | ||
); | ||
|
||
let teardown = attach(tag); | ||
await cycle(); | ||
const el = await fixture | ||
(html`<attrs-test-2></attrs-test-2>`); | ||
|
||
let inst = document.querySelector(tag); | ||
inst.setAttribute('name', 'test'); | ||
el.setAttribute('name', 'test'); | ||
|
||
await cycle(); | ||
await nextFrame(); | ||
|
||
let div = host.firstChild.shadowRoot.firstElementChild; | ||
assert.equal(div.textContent, 'test test'); | ||
teardown(); | ||
let div = el.shadowRoot.firstElementChild; | ||
expect(div.textContent).to.equal('test test'); | ||
}); | ||
|
||
it('observed attribute names turn into camelCase props', async () => { | ||
const tag = 'attrs-camelcase-test'; | ||
let el; | ||
|
||
interface Props { | ||
'open': boolean; | ||
'open-a': boolean; | ||
'open-b-b': boolean; | ||
'openc-': boolean; | ||
'open-d': boolean; | ||
'open-ee': boolean; | ||
'open--fff': boolean; | ||
} | ||
|
||
function Drawer(element) { | ||
el = element; | ||
return html`Test`; | ||
} | ||
|
||
Drawer.observedAttributes = [ | ||
'open', | ||
'open-a', | ||
'open-b-b', | ||
'openc-', | ||
'open-d', | ||
'open-ee', | ||
'open--fff' | ||
]; | ||
|
||
customElements.define(tag, component(Drawer)); | ||
let teardown = mount(` | ||
<attrs-camelcase-test | ||
customElements.define( | ||
tag, | ||
component<HTMLElement & Props>(Drawer, {observedAttributes: [ | ||
'open', | ||
'open-a', | ||
'open-b-b', | ||
'openc-', | ||
'open-d', | ||
'open-ee', | ||
'open--fff' | ||
]}) | ||
); | ||
|
||
await fixture | ||
(html` | ||
<attrs-camelcase-test | ||
open | ||
open-a | ||
open-b-b | ||
openc- | ||
open-d | ||
open-ee | ||
open--fff | ||
></attrs-camelcase-test> | ||
`); | ||
|
||
await cycle(); | ||
teardown(); | ||
assert.equal(el.open, true, 'is defined'); | ||
assert.equal(el.openA, true, 'is defined'); | ||
assert.equal(el.openBB, true, 'is defined'); | ||
assert.equal(el.openc, true, 'is defined'); | ||
assert.equal(el.openD, true, 'is defined'); | ||
assert.equal(el.openEe, true, 'is defined'); | ||
assert.equal(el.openFff, true, 'is defined'); | ||
></attrs-camelcase-test>`) as HTMLElement & Props; | ||
|
||
|
||
await nextFrame(); | ||
|
||
expect(el.open).to.be.true; | ||
expect(el.openA).to.be.true; | ||
expect(el.openBB).to.be.true; | ||
expect(el.openc).to.be.true; | ||
expect(el.openD).to.be.true; | ||
expect(el.openEe).to.be.true; | ||
expect(el.openFff).to.be.true; | ||
}); | ||
|
||
}) |