Merge pull request #232 from github/fix-up-types-in-tests

Fix up types in tests
This commit is contained in:
Keith Cirkel 2022-05-12 15:14:09 +01:00 коммит произвёл GitHub
Родитель 8e9c7dd7e3 5aa70115bd
Коммит c7b92eacb1
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
14 изменённых файлов: 224 добавлений и 189 удалений

1
.gitignore поставляемый
Просмотреть файл

@ -4,3 +4,4 @@ _site
lib/
.jekyll-cache
.lighthouseci
coverage

Просмотреть файл

@ -23,10 +23,11 @@
"lib"
],
"scripts": {
"build": "tsc --build",
"build": "tsc --build tsconfig.build.json",
"build:docs": "cd docs && JEKYLL_ENV=production bundle exec jekyll build",
"clean": "tsc --build --clean",
"clean": "tsc --build --clean tsconfig.build.json",
"lint": "eslint . --ignore-path .gitignore",
"postlint": "tsc",
"prepack": "npm run build",
"presize": "npm run build",
"size": "size-limit",

Просмотреть файл

@ -1,9 +1,11 @@
type PropertyType = 'field' | 'getter' | 'setter' | 'method'
type PropertyDecorator = (proto: object, key: PropertyKey) => void
interface PropertyDecorator {
(proto: object, key: PropertyKey, descriptor?: PropertyDescriptor): void
readonly static: unique symbol
}
type GetMarks = (instance: object) => Set<PropertyKey>
export function createMark(validate: (key: PropertyKey, type: PropertyType) => void): [PropertyDecorator, GetMarks] {
const marks = new WeakMap<object, Set<PropertyKey>>()
const sym = Symbol()
function get(proto: object): Set<PropertyKey> {
if (!marks.has(proto)) {
const parent = Object.getPrototypeOf(proto)
@ -22,13 +24,15 @@ export function createMark(validate: (key: PropertyKey, type: PropertyType) => v
validate(key, type)
get(proto).add(key)
}
marker.static = sym
marker.static = Symbol()
return [
marker,
marker as PropertyDecorator,
(instance: object): Set<PropertyKey> => {
const proto = Object.getPrototypeOf(instance)
for (const key of proto.constructor[sym] || []) marker(proto, key, Object.getOwnPropertyDescriptor(proto, key))
for (const key of proto.constructor[marker.static] || []) {
marker(proto, key, Object.getOwnPropertyDescriptor(proto, key))
}
return new Set(get(proto))
}
]

Просмотреть файл

@ -1,9 +1,10 @@
import {expect, fixture, html} from '@open-wc/testing'
import {restore, fake} from 'sinon'
import type {CustomElement} from '../src/custom-element.js'
import {createAbility, attachShadowCallback, attachInternalsCallback} from '../src/ability.js'
describe('ability', () => {
let calls = []
let calls: string[] = []
const fakeable = createAbility(
Class =>
class extends Class {
@ -22,9 +23,9 @@ describe('ability', () => {
calls.push('fakeable adoptedCallback')
super.adoptedCallback?.()
}
attributeChangedCallback(...args) {
attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null) {
calls.push('fakeable attributeChangedCallback')
super.attributeChangedCallback?.(...args)
super.attributeChangedCallback?.(name, oldValue, newValue)
}
}
)
@ -46,9 +47,9 @@ describe('ability', () => {
calls.push('otherfakeable adoptedCallback')
super.adoptedCallback?.()
}
attributeChangedCallback(...args) {
attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null) {
calls.push('otherfakeable attributeChangedCallback')
super.attributeChangedCallback?.(...args)
super.attributeChangedCallback?.(name, oldValue, newValue)
}
}
)
@ -85,9 +86,9 @@ describe('ability', () => {
it('can be called multiple times, but only applies once', async () => {
const MultipleFakeable = fakeable(fakeable(fakeable(fakeable(fakeable(Element)))))
customElements.define('multiple-fakeable', MultipleFakeable)
const instance = await fixture(html`<multiple-fakeable />`)
const instance: CustomElement = await fixture(html`<multiple-fakeable />`)
expect(calls).to.eql(['fakeable connectedCallback'])
instance.connectedCallback()
instance.connectedCallback!()
expect(calls).to.eql(['fakeable connectedCallback', 'fakeable connectedCallback'])
})
@ -95,22 +96,22 @@ describe('ability', () => {
const CoreTest = otherfakeable(fakeable(Element))
customElements.define('core-test', CoreTest)
let instance
let instance: CustomElement & typeof CoreTest
beforeEach(async () => {
instance = await fixture(html`<core-test />`)
})
it('applies keys from delegate onto subclass upon instantiation', () => {
expect(instance).to.have.property('foo')
expect(instance.foo()).to.equal('foo!')
expect((instance as unknown as Record<string, () => void>).foo()).to.equal('foo!')
expect(instance).to.have.property('bar')
expect(instance.bar()).to.equal('bar!')
expect((instance as unknown as Record<string, () => void>).bar()).to.equal('bar!')
})
for (const method of ['connectedCallback', 'disconnectedCallback', 'adoptedCallback', 'attributeChangedCallback']) {
it(`delegates to other ${method}s before class ${method}`, () => {
calls = []
instance[method]()
;(instance as unknown as Record<string, () => void>)[method]()
expect(calls).to.eql([`otherfakeable ${method}`, `fakeable ${method}`])
})
}
@ -118,8 +119,8 @@ describe('ability', () => {
describe('ability extension behaviour', () => {
describe('attachShadowCallback', () => {
let attachShadowFake
let shadow
let attachShadowFake: (shadow: ShadowRoot) => void
let shadow: ShadowRoot | null
beforeEach(() => {
shadow = null
attachShadowFake = fake()
@ -128,8 +129,8 @@ describe('ability', () => {
const declarable = createAbility(
Class =>
class extends Class {
[attachShadowCallback](...args) {
super[attachShadowCallback](...args)
[attachShadowCallback](...args: [ShadowRoot]) {
super[attachShadowCallback]!(...args)
return attachShadowFake.apply(this, args)
}
}
@ -211,8 +212,8 @@ describe('ability', () => {
})
describe('attachInternalsCallback', () => {
let attachInternalsFake
let internals
let attachInternalsFake: (internals: ElementInternals) => void
let internals: ElementInternals | null
beforeEach(() => {
internals = null
attachInternalsFake = fake()
@ -221,8 +222,8 @@ describe('ability', () => {
const internable = createAbility(
Class =>
class extends Class {
[attachInternalsCallback](...args) {
super[attachInternalsCallback](...args)
[attachInternalsCallback](...args: [ElementInternals]) {
super[attachInternalsCallback]!(...args)
return attachInternalsFake.apply(this, args)
}
}
@ -261,7 +262,7 @@ describe('ability', () => {
})
it('errors if userland calls attachInternals more than once', async () => {
const instance = await fixture(html`<manual-internals-ability></manual-internals-ability>`)
const instance = await fixture<CustomElement>(html`<manual-internals-ability></manual-internals-ability>`)
internals = instance.attachInternals()
expect(internals).to.exist.and.be.instanceof(ElementInternals)
expect(attachInternalsFake).to.be.calledOnce.calledOn(instance).and.calledWithExactly(internals)

Просмотреть файл

@ -3,79 +3,79 @@ import {controller} from '../src/controller.js'
import {attr} from '../src/attr.js'
describe('Attr', () => {
@controller
// eslint-disable-next-line @typescript-eslint/no-unused-vars
class InitializeAttrTest extends HTMLElement {
@attr fooBar = 'hello'
fooBaz = 1
{
@controller
class InitializeAttrTest extends HTMLElement {
@attr fooBar = 'hello'
fooBaz = 1
getCount = 0
setCount = 0
#bing = 'world'
get bingBaz() {
this.getCount += 1
return this.#bing
}
@attr set bingBaz(value: string) {
this.setCount += 1
this.#bing = value
getCount = 0
setCount = 0
#bing = 'world'
get bingBaz() {
this.getCount += 1
return this.#bing
}
@attr set bingBaz(value: string) {
this.setCount += 1
this.#bing = value
}
}
let instance: InitializeAttrTest
beforeEach(async () => {
instance = await fixture(html`<initialize-attr-test />`)
})
it('does not error during creation', () => {
document.createElement('initialize-attr-test')
})
it('does not alter field values from their initial value', () => {
expect(instance).to.have.property('fooBar', 'hello')
expect(instance).to.have.property('fooBaz', 1)
expect(instance).to.have.property('bingBaz', 'world')
})
it('reflects the initial value as an attribute, if not present', () => {
expect(instance).to.have.attribute('data-foo-bar', 'hello')
expect(instance).to.not.have.attribute('data-foo-baz')
expect(instance).to.have.attribute('data-bing-baz', 'world')
})
it('prioritises the value in the attribute over the property', async () => {
instance = await fixture(html`<initialize-attr-test data-foo-bar="goodbye" data-bing-baz="universe" />`)
expect(instance).to.have.property('fooBar', 'goodbye')
expect(instance).to.have.attribute('data-foo-bar', 'goodbye')
expect(instance).to.have.property('bingBaz', 'universe')
expect(instance).to.have.attribute('data-bing-baz', 'universe')
})
it('changes the property when the attribute changes', async () => {
instance.setAttribute('data-foo-bar', 'goodbye')
await Promise.resolve()
expect(instance).to.have.property('fooBar', 'goodbye')
instance.setAttribute('data-bing-baz', 'universe')
await Promise.resolve()
expect(instance).to.have.property('bingBaz', 'universe')
})
it('changes the attribute when the property changes', () => {
instance.fooBar = 'goodbye'
expect(instance).to.have.attribute('data-foo-bar', 'goodbye')
instance.bingBaz = 'universe'
expect(instance).to.have.attribute('data-bing-baz', 'universe')
})
}
let instance
beforeEach(async () => {
instance = await fixture(html`<initialize-attr-test />`)
})
it('does not error during creation', () => {
document.createElement('initialize-attr-test')
})
it('does not alter field values from their initial value', () => {
expect(instance).to.have.property('fooBar', 'hello')
expect(instance).to.have.property('fooBaz', 1)
expect(instance).to.have.property('bingBaz', 'world')
})
it('reflects the initial value as an attribute, if not present', () => {
expect(instance).to.have.attribute('data-foo-bar', 'hello')
expect(instance).to.not.have.attribute('data-foo-baz')
expect(instance).to.have.attribute('data-bing-baz', 'world')
})
it('prioritises the value in the attribute over the property', async () => {
instance = await fixture(html`<initialize-attr-test data-foo-bar="goodbye" data-bing-baz="universe" />`)
expect(instance).to.have.property('fooBar', 'goodbye')
expect(instance).to.have.attribute('data-foo-bar', 'goodbye')
expect(instance).to.have.property('bingBaz', 'universe')
expect(instance).to.have.attribute('data-bing-baz', 'universe')
})
it('changes the property when the attribute changes', async () => {
instance.setAttribute('data-foo-bar', 'goodbye')
await Promise.resolve()
expect(instance).to.have.property('fooBar', 'goodbye')
instance.setAttribute('data-bing-baz', 'universe')
await Promise.resolve()
expect(instance).to.have.property('bingBaz', 'universe')
})
it('changes the attribute when the property changes', () => {
instance.fooBar = 'goodbye'
expect(instance).to.have.attribute('data-foo-bar', 'goodbye')
instance.bingBaz = 'universe'
expect(instance).to.have.attribute('data-bing-baz', 'universe')
})
describe('types', () => {
it('infers boolean types from property and uses has/toggleAttribute', async () => {
@controller
// eslint-disable-next-line @typescript-eslint/no-unused-vars
class BooleanAttrTest extends HTMLElement {
@attr fooBar = false
}
instance = await fixture(html`<boolean-attr-test />`)
const instance = await fixture<BooleanAttrTest>(html`<boolean-attr-test />`)
expect(instance).to.have.property('fooBar', false)
expect(instance).to.not.have.attribute('data-foo-bar')
@ -104,7 +104,6 @@ describe('Attr', () => {
it('avoids infinite loops', async () => {
@controller
// eslint-disable-next-line @typescript-eslint/no-unused-vars
class LoopAttrTest extends HTMLElement {
count = 0
@attr
@ -115,7 +114,8 @@ describe('Attr', () => {
this.count += 1
}
}
instance = await fixture(html`<loop-attr-test />`)
const instance = await fixture<LoopAttrTest>(html`<loop-attr-test />`)
expect(instance).to.have.property('fooBar')
instance.fooBar = 1
@ -127,13 +127,13 @@ describe('Attr', () => {
describe('naming', () => {
@controller
// eslint-disable-next-line @typescript-eslint/no-unused-vars
class NamingAttrTest extends HTMLElement {
@attr fooBarBazBing = 'a'
@attr URLBar = 'b'
@attr ClipX = 'c'
}
let instance: NamingAttrTest
beforeEach(async () => {
instance = await fixture(html`<naming-attr-test />`)
})

Просмотреть файл

@ -3,9 +3,12 @@ import {replace, fake} from 'sinon'
import {autoShadowRoot} from '../src/auto-shadow-root.js'
describe('autoShadowRoot', () => {
window.customElements.define('shadowroot-test-element', class extends HTMLElement {})
class ShadowRootTestElement extends HTMLElement {
declare shadowRoot: ShadowRoot
}
window.customElements.define('shadowroot-test-element', ShadowRootTestElement)
let instance
let instance: ShadowRootTestElement
beforeEach(async () => {
instance = await fixture(html`<shadowroot-test-element />`)
})
@ -58,7 +61,7 @@ describe('autoShadowRoot', () => {
instance = await fixture(html`<shadowroot-test-element>
<template data-shadowroot="closed">Hello World</template>
</shadowroot-test-element>`)
let shadowRoot = null
let shadowRoot: ShadowRoot | null = null
replace(
instance,
'attachShadow',

Просмотреть файл

@ -3,18 +3,16 @@ import {replace, fake} from 'sinon'
import {bind, listenForBind} from '../src/bind.js'
describe('bind', () => {
window.customElements.define(
'bind-test-element',
class extends HTMLElement {
foo = fake()
bar = fake()
handleEvent = fake()
}
)
class BindTestElement extends HTMLElement {
foo = fake()
bar = fake()
handleEvent = fake()
}
window.customElements.define('bind-test-element', BindTestElement)
let instance
let instance: BindTestElement
beforeEach(async () => {
instance = await fixture(html`<bind-test-element />`)
instance = await fixture<BindTestElement>(html`<bind-test-element />`)
})
it('binds events on elements based on their data-action attribute', () => {
@ -47,7 +45,7 @@ describe('bind', () => {
it('does not bind elements whose closest selector is not this controller', () => {
const el = document.createElement('div')
el.getAttribute('data-action', 'click:bind-test-element#foo')
el.setAttribute('data-action', 'click:bind-test-element#foo')
const container = document.createElement('div')
container.append(instance, el)
bind(instance)
@ -157,7 +155,7 @@ describe('bind', () => {
const el2 = document.createElement('div')
el1.setAttribute('data-action', 'click:bind-test-element#foo')
el2.setAttribute('data-action', 'submit:bind-test-element#foo')
instance.shadowRoot.append(el1, el2)
instance.shadowRoot!.append(el1, el2)
bind(instance)
expect(instance.foo).to.have.callCount(0)
el1.click()
@ -173,8 +171,8 @@ describe('bind', () => {
el1.setAttribute('data-action', 'click:bind-test-element#foo')
el2.setAttribute('data-action', 'submit:bind-test-element#foo')
bind(instance)
instance.shadowRoot.append(el1)
instance.shadowRoot.append(el2)
instance.shadowRoot!.append(el1)
instance.shadowRoot!.append(el2)
// We need to wait for one microtask after injecting the HTML into to
// controller so that the actions have been bound to the controller.
await Promise.resolve()
@ -267,7 +265,7 @@ describe('bind', () => {
// We need to wait for one microtask after injecting the HTML into to
// controller so that the actions have been bound to the controller.
await Promise.resolve()
instance.querySelector('button').click()
instance.querySelector('button')!.click()
expect(instance.foo).to.have.callCount(1)
})
@ -277,7 +275,7 @@ describe('bind', () => {
</bind-test-element>`)
bind(instance)
expect(instance.foo).to.have.callCount(0)
const el = instance.querySelector('div')
const el = instance.querySelector('div')!
el.click()
expect(instance.foo).to.have.callCount(1)
el.setAttribute('data-action', 'click:other-element#foo')
@ -292,7 +290,7 @@ describe('bind', () => {
bind(instance)
listenForBind(instance.ownerDocument)
await Promise.resolve()
const button = instance.querySelector('button')
const button = instance.querySelector('button')!
button.click()
expect(instance.foo).to.have.callCount(0)
button.setAttribute('data-action', 'click:bind-test-element#foo')

Просмотреть файл

@ -25,7 +25,6 @@ describe('controller', () => {
it('binds controllers before custom connectedCallback behaviour', async () => {
@controller
// eslint-disable-next-line @typescript-eslint/no-unused-vars
class ControllerBindOrderElement extends HTMLElement {
foo = fake()
}
@ -36,7 +35,7 @@ describe('controller', () => {
this.dispatchEvent(new CustomEvent('loaded'))
}
}
instance = await fixture(html`
instance = await fixture<ControllerBindOrderElement>(html`
<controller-bind-order>
<controller-bind-order-sub data-action="loaded:controller-bind-order#foo" />
</controller-bind-order>
@ -46,36 +45,34 @@ describe('controller', () => {
it('binds shadowRoots after connectedCallback behaviour', async () => {
@controller
// eslint-disable-next-line @typescript-eslint/no-unused-vars
class ControllerBindShadowElement extends HTMLElement {
connectedCallback() {
this.attachShadow({mode: 'open'})
const button = document.createElement('button')
button.setAttribute('data-action', 'click:controller-bind-shadow#foo')
this.shadowRoot.appendChild(button)
this.shadowRoot!.appendChild(button)
}
foo() {
return 'foo'
}
}
instance = await fixture(html`<controller-bind-shadow />`)
instance = await fixture<ControllerBindShadowElement>(html`<controller-bind-shadow />`)
replace(instance, 'foo', fake(instance.foo))
instance.shadowRoot.querySelector('button').click()
instance.shadowRoot!.querySelector('button')!.click()
expect(instance.foo).to.have.callCount(1)
})
it('binds auto shadowRoots', async () => {
@controller
// eslint-disable-next-line @typescript-eslint/no-unused-vars
class ControllerBindAutoShadowElement extends HTMLElement {
foo() {
return 'foo'
}
}
instance = await fixture(html`
instance = await fixture<ControllerBindAutoShadowElement>(html`
<controller-bind-auto-shadow>
<template data-shadowroot="open">
<button data-action="click:controller-bind-auto-shadow#foo" />
@ -86,8 +83,8 @@ describe('controller', () => {
expect(instance.shadowRoot).to.exist
expect(instance).to.have.property('shadowRoot').not.equal(null)
expect(instance.shadowRoot.children).to.have.lengthOf(1)
instance.shadowRoot.querySelector('button').click()
expect(instance.shadowRoot!.children).to.have.lengthOf(1)
instance.shadowRoot!.querySelector('button')!.click()
expect(instance.foo).to.have.callCount(1)
})
@ -97,15 +94,14 @@ describe('controller', () => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
class ChildElementElement extends HTMLElement {}
@controller
// eslint-disable-next-line @typescript-eslint/no-unused-vars
class ParentElementElement extends HTMLElement {
connectedCallback() {
const child = this.querySelector('child-element')
const child = this.querySelector('child-element')!
expect(child.matches(':defined')).to.equal(true)
}
}
instance = await fixture(html`
instance = await fixture<ParentElementElement>(html`
<parent-element>
<child-element />
</parent-element>
@ -113,12 +109,12 @@ describe('controller', () => {
})
describe('attrs', () => {
let attrValues = []
let attrValues: string[] = []
@controller
class AttributeTestElement extends HTMLElement {
foo = 'baz'
attributeChangedCallback() {
attrValues.push(this.getAttribute('data-foo'))
attrValues.push(this.getAttribute('data-foo')!)
attrValues.push(this.foo)
}
}
@ -129,14 +125,14 @@ describe('controller', () => {
})
it('initializes attrs as attributes in attributeChangedCallback', async () => {
instance = await fixture(html`<attribute-test></attribute-test>`)
instance = await fixture<AttributeTestElement>(html`<attribute-test></attribute-test>`)
instance.foo = 'bar'
instance.attributeChangedCallback()
expect(attrValues).to.eql(['bar', 'bar'])
})
it('initializes attributes as attrs in attributeChangedCallback', async () => {
instance = await fixture(html`<attribute-test />`)
instance = await fixture<AttributeTestElement>(html`<attribute-test />`)
instance.setAttribute('data-foo', 'bar')
instance.attributeChangedCallback()
expect(attrValues).to.eql(['bar', 'bar'])

Просмотреть файл

@ -2,7 +2,7 @@ import {expect} from '@open-wc/testing'
import {dasherize} from '../src/dasherize.js'
describe('dasherize', () => {
const tests = [
const tests: Array<[PropertyKey, string]> = [
['json', 'json'],
['fooBar', 'foo-bar'],
['FooBar', 'foo-bar'],

Просмотреть файл

@ -6,8 +6,8 @@ describe('createMark', () => {
it('returns a tuple of functions: a mark and getMarks', () => {
const mark = createMark(() => {})
expect(mark).to.be.an('array').with.lengthOf(2)
expect(mark).to.have.property(0).a('function')
expect(mark).to.have.property(1).a('function')
expect(mark).to.have.property('0').a('function')
expect(mark).to.have.property('1').a('function')
})
it('attaches a `static` unique symbol to the first function', () => {
@ -20,7 +20,7 @@ describe('createMark', () => {
it('can be added to class fields without errors', () => {
const [mark] = createMark(() => {})
class FooBar {
@mark foo
@mark foo: unknown
@mark bar = 1
@mark baz = 'hi'
}
@ -30,11 +30,15 @@ describe('createMark', () => {
it('can be added to getters or setters without errors', () => {
const [mark] = createMark(() => {})
class FooBar {
@mark get foo() {}
set foo(v) {}
@mark get foo() {
return 1
}
set foo(v: number) {}
@mark get bar() {}
@mark set baz(v) {}
@mark get bar() {
return 1
}
@mark set baz(v: number) {}
}
new FooBar()
})
@ -50,13 +54,17 @@ describe('createMark', () => {
it('retrieves all marked fields with the get mark function', () => {
const [mark, getMark] = createMark(() => {})
class FooBar {
@mark foo
@mark foo: unknown
@mark bar = 1
@mark baz = 'hi'
@mark get bing() {}
@mark get qux() {}
@mark set quuz(v) {}
@mark set corge(v) {}
@mark get bing() {
return 1
}
@mark get qux() {
return 1
}
@mark set quuz(v: number) {}
@mark set corge(v: number) {}
@mark grault() {}
}
expect(getMark(new FooBar())).to.eql(new Set(['foo', 'bar', 'baz', 'bing', 'qux', 'quuz', 'corge', 'grault']))
@ -75,13 +83,17 @@ describe('createMark', () => {
const [mark, getMark] = createMark(() => {})
class FooBar {
static [mark.static] = ['bar', 'bing', 'quuz', 'grault']
@mark foo
@mark foo: unknown
bar = 1
@mark baz = 'hi'
get bing() {}
@mark get qux() {}
set quuz(v) {}
@mark set corge(v) {}
get bing() {
return 1
}
@mark get qux() {
return 1
}
set quuz(v: number) {}
@mark set corge(v: number) {}
grault() {}
}
const instance = new FooBar()
@ -92,13 +104,17 @@ describe('createMark', () => {
const [mark, getMark] = createMark(() => {})
class FooBar {
static [mark.static] = ['bar', 'bing', 'quuz', 'grault']
@mark foo
@mark foo: unknown
@mark bar = 1
@mark baz = 'hi'
@mark get bing() {}
@mark get qux() {}
@mark set quuz(v) {}
@mark set corge(v) {}
@mark get bing() {
return 1
}
@mark get qux() {
return 1
}
@mark set quuz(v: number) {}
@mark set corge(v: number) {}
@mark grault() {}
}
expect(getMark(new FooBar())).to.eql(new Set(['foo', 'bar', 'baz', 'bing', 'qux', 'quuz', 'corge', 'grault']))
@ -109,13 +125,17 @@ describe('createMark', () => {
const [mark] = createMark(validate)
const sym = Symbol('garply')
class FooBar {
@mark foo
@mark foo: unknown
@mark bar = 1
@mark baz = 'hi'
@mark get bing() {}
@mark get qux() {}
@mark set quuz(v) {}
@mark set corge(v) {}
@mark get bing() {
return 1
}
@mark get qux() {
return 1
}
@mark set quuz(v: number) {}
@mark set corge(v: number) {}
@mark grault() {}
@mark [sym]() {}
}
@ -136,13 +156,17 @@ describe('createMark', () => {
const [mark, getMark] = createMark(validate)
class FooBar {
static [mark.static] = ['foo', 'bar', 'baz', 'bing', 'qux', 'quuz', 'corge', 'grault']
foo
foo: unknown
bar = 1
baz = 'hi'
get bing() {}
get qux() {}
set quuz(v) {}
set corge(v) {}
get bing() {
return 1
}
get qux() {
return 1
}
set quuz(v: number) {}
set corge(v: number) {}
grault() {}
}
getMark(new FooBar())

Просмотреть файл

@ -9,19 +9,19 @@ describe('register', () => {
it('registers the class as a custom element, normalising the class name', () => {
@register
class MyFirstClass {}
class MyFirstClass extends HTMLElement {}
expect(window.customElements.get('my-first-class')).to.equal(MyFirstClass)
})
it('does not register controllers that already exist', () => {
{
@register
class MySecondClass {}
class MySecondClass extends HTMLElement {}
expect(window.customElements.get('my-second-class')).to.equal(MySecondClass)
}
{
@register
class MySecondClass {}
class MySecondClass extends HTMLElement {}
expect(window.customElements.get('my-second-class')).to.not.equal(MySecondClass)
}
})
@ -31,23 +31,23 @@ describe('register', () => {
replace(
customElements,
'get',
fake(() => class {})
fake(() => class extends HTMLElement {})
)
{
@register
class MyThirdClass {}
class MyThirdClass extends HTMLElement {}
expect(customElements.define).to.be.calledOnceWithExactly('my-third-class', MyThirdClass)
}
expect(() => {
@register
class MyThirdClass {}
class MyThirdClass extends HTMLElement {}
expect(customElements.define).to.be.calledOnceWithExactly('my-third-class', MyThirdClass)
}).to.throw(Error)
})
it('dasherises class names', () => {
@register
class ThisIsAnExampleOfDasherisedClassNames {}
class ThisIsAnExampleOfDasherisedClassNames extends HTMLElement {}
expect(window.customElements.get('this-is-an-example-of-dasherised-class-names')).to.equal(
ThisIsAnExampleOfDasherisedClassNames
)
@ -55,19 +55,19 @@ describe('register', () => {
it('will intuitively dasherize acryonyms', () => {
@register
class URLBar {}
class URLBar extends HTMLElement {}
expect(window.customElements.get('url-bar')).to.equal(URLBar)
})
it('dasherizes cap suffixed names correctly', () => {
@register
class ClipX {}
class ClipX extends HTMLElement {}
expect(window.customElements.get('clip-x')).to.equal(ClipX)
})
it('automatically drops the `Element` suffix', () => {
@register
class FirstSuffixElement {}
class FirstSuffixElement extends HTMLElement {}
expect(window.customElements.get('first-suffix')).to.equal(FirstSuffixElement)
})
})

Просмотреть файл

@ -6,20 +6,20 @@ describe('Targetable', () => {
@controller
// eslint-disable-next-line @typescript-eslint/no-unused-vars
class TargetTestElement extends HTMLElement {
@target foo
@target foo!: Element
bar = 'hello'
@target baz
@target qux
@target shadow
@target baz!: Element
@target qux!: Element
@target shadow!: Element
@target bing
@targets foos
@target bing!: Element
@targets foos!: Element[]
bars = 'hello'
@target quxs
@target shadows
@target quxs!: Element[]
@target shadows!: Element[]
}
let instance
let instance: HTMLElement
beforeEach(async () => {
instance = await fixture(html`<target-test>
<target-test>
@ -61,7 +61,7 @@ describe('Targetable', () => {
instance.attachShadow({mode: 'open'})
const el = document.createElement('div')
el.setAttribute('data-target', 'target-test.shadow')
instance.shadowRoot.appendChild(el)
instance.shadowRoot!.appendChild(el)
expect(instance).to.have.property('shadow', el)
})
@ -69,7 +69,7 @@ describe('Targetable', () => {
instance.attachShadow({mode: 'open'})
const shadowEl = document.createElement('div')
shadowEl.setAttribute('data-target', 'target-test.foo')
instance.shadowRoot.appendChild(shadowEl)
instance.shadowRoot!.appendChild(shadowEl)
expect(instance).to.have.property('foo', shadowEl)
})
})
@ -85,7 +85,7 @@ describe('Targetable', () => {
instance.attachShadow({mode: 'open'})
const els = [document.createElement('div'), document.createElement('div'), document.createElement('div')]
for (const el of els) el.setAttribute('data-targets', 'target-test.foos')
instance.shadowRoot.append(...els)
instance.shadowRoot!.append(...els)
expect(instance).to.have.property('foos').with.lengthOf(5)
expect(instance).to.have.nested.property('foos[0]', els[0])

10
tsconfig.build.json Normal file
Просмотреть файл

@ -0,0 +1,10 @@
{
"exclude": ["test"],
"extends": "./tsconfig.json",
"compilerOptions": {
"declaration": true,
"declarationMap": true,
"outDir": "./lib",
"noEmit": false
}
}

Просмотреть файл

@ -1,16 +1,13 @@
{
"include": ["src"],
"include": ["src", "test"],
"compilerOptions": {
"baseUrl": ".",
"declaration": true,
"declarationMap": true,
"esModuleInterop": true,
"experimentalDecorators": true,
"lib": ["es6", "dom", "dom.iterable"],
"module": "ESNext",
"moduleResolution": "node",
"noEmit": false,
"outDir": "./lib",
"noEmit": true,
"sourceMap": true,
"strict": true,
"target": "ES2020"