Skip to content

Commit c7b92ea

Browse files
authored
Merge pull request #232 from github/fix-up-types-in-tests
Fix up types in tests
2 parents 8e9c7dd + 5aa7011 commit c7b92ea

14 files changed

Lines changed: 219 additions & 184 deletions

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ _site
44
lib/
55
.jekyll-cache
66
.lighthouseci
7+
coverage

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,11 @@
2323
"lib"
2424
],
2525
"scripts": {
26-
"build": "tsc --build",
26+
"build": "tsc --build tsconfig.build.json",
2727
"build:docs": "cd docs && JEKYLL_ENV=production bundle exec jekyll build",
28-
"clean": "tsc --build --clean",
28+
"clean": "tsc --build --clean tsconfig.build.json",
2929
"lint": "eslint . --ignore-path .gitignore",
30+
"postlint": "tsc",
3031
"prepack": "npm run build",
3132
"presize": "npm run build",
3233
"size": "size-limit",

src/mark.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
type PropertyType = 'field' | 'getter' | 'setter' | 'method'
2-
type PropertyDecorator = (proto: object, key: PropertyKey) => void
2+
interface PropertyDecorator {
3+
(proto: object, key: PropertyKey, descriptor?: PropertyDescriptor): void
4+
readonly static: unique symbol
5+
}
36
type GetMarks = (instance: object) => Set<PropertyKey>
47
export function createMark(validate: (key: PropertyKey, type: PropertyType) => void): [PropertyDecorator, GetMarks] {
58
const marks = new WeakMap<object, Set<PropertyKey>>()
6-
const sym = Symbol()
79
function get(proto: object): Set<PropertyKey> {
810
if (!marks.has(proto)) {
911
const parent = Object.getPrototypeOf(proto)
@@ -22,13 +24,15 @@ export function createMark(validate: (key: PropertyKey, type: PropertyType) => v
2224
validate(key, type)
2325
get(proto).add(key)
2426
}
25-
marker.static = sym
27+
marker.static = Symbol()
2628

2729
return [
28-
marker,
30+
marker as PropertyDecorator,
2931
(instance: object): Set<PropertyKey> => {
3032
const proto = Object.getPrototypeOf(instance)
31-
for (const key of proto.constructor[sym] || []) marker(proto, key, Object.getOwnPropertyDescriptor(proto, key))
33+
for (const key of proto.constructor[marker.static] || []) {
34+
marker(proto, key, Object.getOwnPropertyDescriptor(proto, key))
35+
}
3236
return new Set(get(proto))
3337
}
3438
]

test/ability.ts

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import {expect, fixture, html} from '@open-wc/testing'
22
import {restore, fake} from 'sinon'
3+
import type {CustomElement} from '../src/custom-element.js'
34
import {createAbility, attachShadowCallback, attachInternalsCallback} from '../src/ability.js'
45

56
describe('ability', () => {
6-
let calls = []
7+
let calls: string[] = []
78
const fakeable = createAbility(
89
Class =>
910
class extends Class {
@@ -22,9 +23,9 @@ describe('ability', () => {
2223
calls.push('fakeable adoptedCallback')
2324
super.adoptedCallback?.()
2425
}
25-
attributeChangedCallback(...args) {
26+
attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null) {
2627
calls.push('fakeable attributeChangedCallback')
27-
super.attributeChangedCallback?.(...args)
28+
super.attributeChangedCallback?.(name, oldValue, newValue)
2829
}
2930
}
3031
)
@@ -46,9 +47,9 @@ describe('ability', () => {
4647
calls.push('otherfakeable adoptedCallback')
4748
super.adoptedCallback?.()
4849
}
49-
attributeChangedCallback(...args) {
50+
attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null) {
5051
calls.push('otherfakeable attributeChangedCallback')
51-
super.attributeChangedCallback?.(...args)
52+
super.attributeChangedCallback?.(name, oldValue, newValue)
5253
}
5354
}
5455
)
@@ -85,41 +86,41 @@ describe('ability', () => {
8586
it('can be called multiple times, but only applies once', async () => {
8687
const MultipleFakeable = fakeable(fakeable(fakeable(fakeable(fakeable(Element)))))
8788
customElements.define('multiple-fakeable', MultipleFakeable)
88-
const instance = await fixture(html`<multiple-fakeable />`)
89+
const instance: CustomElement = await fixture(html`<multiple-fakeable />`)
8990
expect(calls).to.eql(['fakeable connectedCallback'])
90-
instance.connectedCallback()
91+
instance.connectedCallback!()
9192
expect(calls).to.eql(['fakeable connectedCallback', 'fakeable connectedCallback'])
9293
})
9394

9495
describe('subclass behaviour', () => {
9596
const CoreTest = otherfakeable(fakeable(Element))
9697
customElements.define('core-test', CoreTest)
9798

98-
let instance
99+
let instance: CustomElement & typeof CoreTest
99100
beforeEach(async () => {
100101
instance = await fixture(html`<core-test />`)
101102
})
102103

103104
it('applies keys from delegate onto subclass upon instantiation', () => {
104105
expect(instance).to.have.property('foo')
105-
expect(instance.foo()).to.equal('foo!')
106+
expect((instance as unknown as Record<string, () => void>).foo()).to.equal('foo!')
106107
expect(instance).to.have.property('bar')
107-
expect(instance.bar()).to.equal('bar!')
108+
expect((instance as unknown as Record<string, () => void>).bar()).to.equal('bar!')
108109
})
109110

110111
for (const method of ['connectedCallback', 'disconnectedCallback', 'adoptedCallback', 'attributeChangedCallback']) {
111112
it(`delegates to other ${method}s before class ${method}`, () => {
112113
calls = []
113-
instance[method]()
114+
;(instance as unknown as Record<string, () => void>)[method]()
114115
expect(calls).to.eql([`otherfakeable ${method}`, `fakeable ${method}`])
115116
})
116117
}
117118
})
118119

119120
describe('ability extension behaviour', () => {
120121
describe('attachShadowCallback', () => {
121-
let attachShadowFake
122-
let shadow
122+
let attachShadowFake: (shadow: ShadowRoot) => void
123+
let shadow: ShadowRoot | null
123124
beforeEach(() => {
124125
shadow = null
125126
attachShadowFake = fake()
@@ -128,8 +129,8 @@ describe('ability', () => {
128129
const declarable = createAbility(
129130
Class =>
130131
class extends Class {
131-
[attachShadowCallback](...args) {
132-
super[attachShadowCallback](...args)
132+
[attachShadowCallback](...args: [ShadowRoot]) {
133+
super[attachShadowCallback]!(...args)
133134
return attachShadowFake.apply(this, args)
134135
}
135136
}
@@ -211,8 +212,8 @@ describe('ability', () => {
211212
})
212213

213214
describe('attachInternalsCallback', () => {
214-
let attachInternalsFake
215-
let internals
215+
let attachInternalsFake: (internals: ElementInternals) => void
216+
let internals: ElementInternals | null
216217
beforeEach(() => {
217218
internals = null
218219
attachInternalsFake = fake()
@@ -221,8 +222,8 @@ describe('ability', () => {
221222
const internable = createAbility(
222223
Class =>
223224
class extends Class {
224-
[attachInternalsCallback](...args) {
225-
super[attachInternalsCallback](...args)
225+
[attachInternalsCallback](...args: [ElementInternals]) {
226+
super[attachInternalsCallback]!(...args)
226227
return attachInternalsFake.apply(this, args)
227228
}
228229
}
@@ -261,7 +262,7 @@ describe('ability', () => {
261262
})
262263

263264
it('errors if userland calls attachInternals more than once', async () => {
264-
const instance = await fixture(html`<manual-internals-ability></manual-internals-ability>`)
265+
const instance = await fixture<CustomElement>(html`<manual-internals-ability></manual-internals-ability>`)
265266
internals = instance.attachInternals()
266267
expect(internals).to.exist.and.be.instanceof(ElementInternals)
267268
expect(attachInternalsFake).to.be.calledOnce.calledOn(instance).and.calledWithExactly(internals)

test/attr.ts

Lines changed: 60 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -3,79 +3,79 @@ import {controller} from '../src/controller.js'
33
import {attr} from '../src/attr.js'
44

55
describe('Attr', () => {
6-
@controller
7-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
8-
class InitializeAttrTest extends HTMLElement {
9-
@attr fooBar = 'hello'
10-
fooBaz = 1
11-
12-
getCount = 0
13-
setCount = 0
14-
#bing = 'world'
15-
get bingBaz() {
16-
this.getCount += 1
17-
return this.#bing
18-
}
19-
@attr set bingBaz(value: string) {
20-
this.setCount += 1
21-
this.#bing = value
6+
{
7+
@controller
8+
class InitializeAttrTest extends HTMLElement {
9+
@attr fooBar = 'hello'
10+
fooBaz = 1
11+
12+
getCount = 0
13+
setCount = 0
14+
#bing = 'world'
15+
get bingBaz() {
16+
this.getCount += 1
17+
return this.#bing
18+
}
19+
@attr set bingBaz(value: string) {
20+
this.setCount += 1
21+
this.#bing = value
22+
}
2223
}
23-
}
2424

25-
let instance
26-
beforeEach(async () => {
27-
instance = await fixture(html`<initialize-attr-test />`)
28-
})
25+
let instance: InitializeAttrTest
26+
beforeEach(async () => {
27+
instance = await fixture(html`<initialize-attr-test />`)
28+
})
2929

30-
it('does not error during creation', () => {
31-
document.createElement('initialize-attr-test')
32-
})
30+
it('does not error during creation', () => {
31+
document.createElement('initialize-attr-test')
32+
})
3333

34-
it('does not alter field values from their initial value', () => {
35-
expect(instance).to.have.property('fooBar', 'hello')
36-
expect(instance).to.have.property('fooBaz', 1)
37-
expect(instance).to.have.property('bingBaz', 'world')
38-
})
34+
it('does not alter field values from their initial value', () => {
35+
expect(instance).to.have.property('fooBar', 'hello')
36+
expect(instance).to.have.property('fooBaz', 1)
37+
expect(instance).to.have.property('bingBaz', 'world')
38+
})
3939

40-
it('reflects the initial value as an attribute, if not present', () => {
41-
expect(instance).to.have.attribute('data-foo-bar', 'hello')
42-
expect(instance).to.not.have.attribute('data-foo-baz')
43-
expect(instance).to.have.attribute('data-bing-baz', 'world')
44-
})
40+
it('reflects the initial value as an attribute, if not present', () => {
41+
expect(instance).to.have.attribute('data-foo-bar', 'hello')
42+
expect(instance).to.not.have.attribute('data-foo-baz')
43+
expect(instance).to.have.attribute('data-bing-baz', 'world')
44+
})
4545

46-
it('prioritises the value in the attribute over the property', async () => {
47-
instance = await fixture(html`<initialize-attr-test data-foo-bar="goodbye" data-bing-baz="universe" />`)
48-
expect(instance).to.have.property('fooBar', 'goodbye')
49-
expect(instance).to.have.attribute('data-foo-bar', 'goodbye')
50-
expect(instance).to.have.property('bingBaz', 'universe')
51-
expect(instance).to.have.attribute('data-bing-baz', 'universe')
52-
})
46+
it('prioritises the value in the attribute over the property', async () => {
47+
instance = await fixture(html`<initialize-attr-test data-foo-bar="goodbye" data-bing-baz="universe" />`)
48+
expect(instance).to.have.property('fooBar', 'goodbye')
49+
expect(instance).to.have.attribute('data-foo-bar', 'goodbye')
50+
expect(instance).to.have.property('bingBaz', 'universe')
51+
expect(instance).to.have.attribute('data-bing-baz', 'universe')
52+
})
5353

54-
it('changes the property when the attribute changes', async () => {
55-
instance.setAttribute('data-foo-bar', 'goodbye')
56-
await Promise.resolve()
57-
expect(instance).to.have.property('fooBar', 'goodbye')
58-
instance.setAttribute('data-bing-baz', 'universe')
59-
await Promise.resolve()
60-
expect(instance).to.have.property('bingBaz', 'universe')
61-
})
54+
it('changes the property when the attribute changes', async () => {
55+
instance.setAttribute('data-foo-bar', 'goodbye')
56+
await Promise.resolve()
57+
expect(instance).to.have.property('fooBar', 'goodbye')
58+
instance.setAttribute('data-bing-baz', 'universe')
59+
await Promise.resolve()
60+
expect(instance).to.have.property('bingBaz', 'universe')
61+
})
6262

63-
it('changes the attribute when the property changes', () => {
64-
instance.fooBar = 'goodbye'
65-
expect(instance).to.have.attribute('data-foo-bar', 'goodbye')
66-
instance.bingBaz = 'universe'
67-
expect(instance).to.have.attribute('data-bing-baz', 'universe')
68-
})
63+
it('changes the attribute when the property changes', () => {
64+
instance.fooBar = 'goodbye'
65+
expect(instance).to.have.attribute('data-foo-bar', 'goodbye')
66+
instance.bingBaz = 'universe'
67+
expect(instance).to.have.attribute('data-bing-baz', 'universe')
68+
})
69+
}
6970

7071
describe('types', () => {
7172
it('infers boolean types from property and uses has/toggleAttribute', async () => {
7273
@controller
73-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
7474
class BooleanAttrTest extends HTMLElement {
7575
@attr fooBar = false
7676
}
7777

78-
instance = await fixture(html`<boolean-attr-test />`)
78+
const instance = await fixture<BooleanAttrTest>(html`<boolean-attr-test />`)
7979

8080
expect(instance).to.have.property('fooBar', false)
8181
expect(instance).to.not.have.attribute('data-foo-bar')
@@ -104,7 +104,6 @@ describe('Attr', () => {
104104

105105
it('avoids infinite loops', async () => {
106106
@controller
107-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
108107
class LoopAttrTest extends HTMLElement {
109108
count = 0
110109
@attr
@@ -115,7 +114,8 @@ describe('Attr', () => {
115114
this.count += 1
116115
}
117116
}
118-
instance = await fixture(html`<loop-attr-test />`)
117+
118+
const instance = await fixture<LoopAttrTest>(html`<loop-attr-test />`)
119119

120120
expect(instance).to.have.property('fooBar')
121121
instance.fooBar = 1
@@ -127,13 +127,13 @@ describe('Attr', () => {
127127

128128
describe('naming', () => {
129129
@controller
130-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
131130
class NamingAttrTest extends HTMLElement {
132131
@attr fooBarBazBing = 'a'
133132
@attr URLBar = 'b'
134133
@attr ClipX = 'c'
135134
}
136135

136+
let instance: NamingAttrTest
137137
beforeEach(async () => {
138138
instance = await fixture(html`<naming-attr-test />`)
139139
})

test/auto-shadow-root.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@ import {replace, fake} from 'sinon'
33
import {autoShadowRoot} from '../src/auto-shadow-root.js'
44

55
describe('autoShadowRoot', () => {
6-
window.customElements.define('shadowroot-test-element', class extends HTMLElement {})
6+
class ShadowRootTestElement extends HTMLElement {
7+
declare shadowRoot: ShadowRoot
8+
}
9+
window.customElements.define('shadowroot-test-element', ShadowRootTestElement)
710

8-
let instance
11+
let instance: ShadowRootTestElement
912
beforeEach(async () => {
1013
instance = await fixture(html`<shadowroot-test-element />`)
1114
})
@@ -58,7 +61,7 @@ describe('autoShadowRoot', () => {
5861
instance = await fixture(html`<shadowroot-test-element>
5962
<template data-shadowroot="closed">Hello World</template>
6063
</shadowroot-test-element>`)
61-
let shadowRoot = null
64+
let shadowRoot: ShadowRoot | null = null
6265
replace(
6366
instance,
6467
'attachShadow',

0 commit comments

Comments
 (0)