Skip to content

Commit a399966

Browse files
authored
Merge pull request #228 from github/update-attr-tests
Cherry-pick attr tests from `use-delegates`.
2 parents ae48275 + 6af0935 commit a399966

1 file changed

Lines changed: 77 additions & 74 deletions

File tree

test/attr.ts

Lines changed: 77 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,22 @@ import {attr} from '../src/attr.js'
44

55
describe('Attr', () => {
66
@controller
7+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
78
class InitializeAttrTest extends HTMLElement {
89
@attr foo = 'hello'
910
bar = 1
11+
12+
getCount = 0
13+
setCount = 0
14+
#baz = 'world'
15+
get baz() {
16+
this.getCount += 1
17+
return this.#baz
18+
}
19+
@attr set baz(value: string) {
20+
this.setCount += 1
21+
this.#baz = value
22+
}
1023
}
1124

1225
let instance
@@ -18,108 +31,101 @@ describe('Attr', () => {
1831
document.createElement('initialize-attr-test')
1932
})
2033

21-
it('marks attrs as observedAttributes', () => {
22-
expect(InitializeAttrTest.observedAttributes).to.eql(['data-foo'])
23-
})
24-
25-
it('creates a getter/setter pair for each given attr name', () => {
26-
expect(instance.foo).to.equal('hello')
27-
expect(instance).to.have.ownPropertyDescriptor('foo')
34+
it('does not alter field values from their initial value', () => {
35+
expect(instance).to.have.property('foo', 'hello')
36+
expect(instance).to.have.property('bar', 1)
37+
expect(instance).to.have.property('baz', 'world')
2838
})
2939

30-
it('sets the attribute to a previously defined value on the key', () => {
31-
expect(instance.foo).to.equal('hello')
32-
expect(instance.getAttributeNames()).to.include('data-foo')
33-
expect(instance.getAttribute('data-foo')).to.equal('hello')
40+
it('reflects the initial value as an attribute, if not present', () => {
41+
expect(instance).to.have.attribute('data-foo', 'hello')
42+
expect(instance).to.not.have.attribute('data-bar')
43+
expect(instance).to.have.attribute('data-baz', 'world')
3444
})
3545

36-
it('reflects the `data-*` attribute name of the given key', () => {
37-
expect(instance.foo).to.equal('hello')
38-
instance.foo = 'bar'
39-
expect(instance.getAttributeNames()).to.include('data-foo')
40-
expect(instance.getAttribute('data-foo')).to.equal('bar')
41-
instance.setAttribute('data-foo', 'baz')
42-
expect(instance.foo).to.equal('baz')
46+
it('prioritises the value in the attribute over the property', async () => {
47+
instance = await fixture(html`<initialize-attr-test data-foo="goodbye" data-baz="universe" />`)
48+
expect(instance).to.have.property('foo', 'goodbye')
49+
expect(instance).to.have.attribute('data-foo', 'goodbye')
50+
expect(instance).to.have.property('baz', 'universe')
51+
expect(instance).to.have.attribute('data-baz', 'universe')
4352
})
4453

45-
it('sets the attribute to a previously defined value on the key', () => {
46-
instance.foo = 'hello'
47-
expect(instance.foo).to.equal('hello')
48-
expect(instance.getAttributeNames()).to.include('data-foo')
49-
expect(instance.getAttribute('data-foo')).to.equal('hello')
54+
it('changes the property when the attribute changes', async () => {
55+
instance.setAttribute('data-foo', 'goodbye')
56+
await Promise.resolve()
57+
expect(instance).to.have.property('foo', 'goodbye')
58+
instance.setAttribute('data-baz', 'universe')
59+
await Promise.resolve()
60+
expect(instance).to.have.property('baz', 'universe')
5061
})
5162

52-
it('prioritises the value in the attribute over the property', async () => {
53-
instance = await fixture(html`<initialize-attr-test data-foo="goodbye" />`)
54-
expect(instance.foo).to.equal('goodbye')
55-
expect(instance.getAttributeNames()).to.include('data-foo')
56-
expect(instance.getAttribute('data-foo')).to.equal('goodbye')
63+
it('changes the attribute when the property changes', () => {
64+
instance.foo = 'goodbye'
65+
expect(instance).to.have.attribute('data-foo', 'goodbye')
66+
instance.baz = 'universe'
67+
expect(instance).to.have.attribute('data-baz', 'universe')
5768
})
5869

5970
describe('types', () => {
60-
it('infers number types from property and casts as number always', async () => {
61-
@controller
62-
class NumberAttrTest extends HTMLElement {
63-
@attr foo = 1
64-
}
65-
expect(NumberAttrTest).to.have.property('observedAttributes').include('data-foo')
66-
instance = await fixture(html`<number-attr-test />`)
67-
expect(instance.foo).to.equal(1)
68-
expect(instance.getAttributeNames()).to.include('data-foo')
69-
expect(instance.getAttribute('data-foo')).to.equal('1')
70-
instance.setAttribute('data-foo', '7')
71-
expect(instance.foo).to.equal(7)
72-
instance.setAttribute('data-foo', '-3.14')
73-
expect(instance.foo).to.equal(-3.14)
74-
instance.setAttribute('data-foo', 'Not a Number')
75-
expect(Number.isNaN(instance.foo)).to.equal(true)
76-
instance.removeAttribute('data-foo')
77-
expect(instance.foo).to.equal(0)
78-
instance.foo = 3.14
79-
expect(instance.getAttribute('data-foo')).to.equal('3.14')
80-
})
81-
8271
it('infers boolean types from property and uses has/toggleAttribute', async () => {
8372
@controller
73+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
8474
class BooleanAttrTest extends HTMLElement {
8575
@attr foo = false
8676
}
87-
expect(BooleanAttrTest).to.have.property('observedAttributes').include('data-foo')
77+
8878
instance = await fixture(html`<boolean-attr-test />`)
89-
expect(instance.foo).to.equal(false)
90-
expect(instance.getAttributeNames()).to.not.include('data-foo')
91-
expect(instance.getAttribute('data-foo')).to.equal(null)
79+
80+
expect(instance).to.have.property('foo', false)
81+
expect(instance).to.not.have.attribute('data-foo')
9282
instance.setAttribute('data-foo', '7')
93-
expect(instance.foo).to.equal(true)
83+
await Promise.resolve()
84+
expect(instance).to.have.property('foo', true)
9485
instance.setAttribute('data-foo', 'hello')
95-
expect(instance.foo).to.equal(true)
86+
await Promise.resolve()
87+
expect(instance).to.have.property('foo', true)
9688
instance.setAttribute('data-foo', 'false')
97-
expect(instance.foo).to.equal(true)
89+
await Promise.resolve()
90+
expect(instance).to.have.property('foo', true)
9891
instance.removeAttribute('data-foo')
99-
expect(instance.foo).to.equal(false)
100-
instance.foo = '1'
101-
expect(instance.foo).to.equal(true)
102-
expect(instance.getAttributeNames()).to.include('data-foo')
103-
expect(instance.getAttribute('data-foo')).to.equal('')
92+
await Promise.resolve()
93+
expect(instance).to.have.property('foo', false)
94+
instance.foo = true
95+
expect(instance).to.have.attribute('data-foo', '')
10496
instance.foo = false
105-
expect(instance.getAttributeNames()).to.not.include('data-foo')
97+
expect(instance).to.not.have.attribute('data-foo')
98+
instance.removeAttribute('data-foo')
99+
await Promise.resolve()
100+
expect(instance).to.have.property('foo', false)
106101
})
107102

108-
it('defaults to inferring string type for non-boolean non-number types', async () => {
103+
it('avoids infinite loops', async () => {
109104
@controller
110-
class RegExpAttrTest extends HTMLElement {
111-
@attr foo = /^a regexp$/
105+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
106+
class LoopAttrTest extends HTMLElement {
107+
count = 0
108+
@attr
109+
get foo() {
110+
return ++this.count
111+
}
112+
set foo(value) {
113+
this.count += 1
114+
}
112115
}
113-
expect(RegExpAttrTest).to.have.property('observedAttributes').include('data-foo')
114-
instance = await fixture(html`<reg-exp-attr-test />`)
115-
expect(instance.foo).to.equal('/^a regexp$/')
116-
expect(instance.getAttributeNames()).to.include('data-foo')
117-
expect(instance.getAttribute('data-foo')).to.equal('/^a regexp$/')
116+
instance = await fixture(html`<loop-attr-test />`)
117+
118+
expect(instance).to.have.property('foo')
119+
instance.foo = 1
120+
instance.setAttribute('data-foo', '2')
121+
instance.foo = 3
122+
instance.setAttribute('data-foo', '4')
118123
})
119124
})
120125

121126
describe('naming', () => {
122127
@controller
128+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
123129
class NamingAttrTest extends HTMLElement {
124130
@attr fooBarBazBing = 'a'
125131
@attr URLBar = 'b'
@@ -131,21 +137,18 @@ describe('Attr', () => {
131137
})
132138

133139
it('converts camel cased property names to their HTML dasherized equivalents', async () => {
134-
expect(NamingAttrTest).to.have.property('observedAttributes').include('data-foo-bar-baz-bing')
135140
expect(instance.fooBarBazBing).to.equal('a')
136141
instance.fooBarBazBing = 'bar'
137142
expect(instance.getAttributeNames()).to.include('data-foo-bar-baz-bing')
138143
})
139144

140145
it('will intuitively dasherize acryonyms', async () => {
141-
expect(NamingAttrTest).to.have.property('observedAttributes').include('data-url-bar')
142146
expect(instance.URLBar).to.equal('b')
143147
instance.URLBar = 'bar'
144148
expect(instance.getAttributeNames()).to.include('data-url-bar')
145149
})
146150

147151
it('dasherizes cap suffixed names correctly', async () => {
148-
expect(NamingAttrTest).to.have.property('observedAttributes').include('data-clip-x')
149152
expect(instance.ClipX).to.equal('c')
150153
instance.ClipX = 'bar'
151154
expect(instance.getAttributeNames()).to.include('data-clip-x')

0 commit comments

Comments
 (0)