spyne 0.24.0 → 0.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,178 @@
1
+ const { expect } = require('chai')
2
+ import { ViewStreamSelector } from '../../spyne/views/view-stream-selector'
3
+
4
+ describe('ViewStreamSelector', () => {
5
+ let container
6
+
7
+ const el$ = (sel) => ViewStreamSelector(container, sel)
8
+
9
+ beforeEach(() => {
10
+ container = document.createElement('div')
11
+ container.innerHTML =
12
+ '<ul>' +
13
+ '<li class="item">A</li>' +
14
+ '<li class="item">A</li>' +
15
+ '<li class="item special">C</li>' +
16
+ '</ul>' +
17
+ '<p class="solo">only</p>'
18
+ document.body.appendChild(container)
19
+ })
20
+
21
+ afterEach(() => {
22
+ container.remove()
23
+ })
24
+
25
+ describe('el (always a single element)', () => {
26
+ it('should return the element for a single match', () => {
27
+ const el = el$('.solo').el
28
+ expect(el.nodeType).to.equal(1)
29
+ expect(el.textContent).to.equal('only')
30
+ })
31
+
32
+ it('should return the first element for multiple matches', () => {
33
+ const el = el$('.item').el
34
+ expect(el.nodeType).to.equal(1)
35
+ expect(el.textContent).to.equal('A')
36
+ })
37
+
38
+ it('should return null for no matches, mirroring querySelector', () => {
39
+ expect(el$('.nope').el).to.equal(null)
40
+ })
41
+
42
+ it('should support direct element methods on multi-match selectors', () => {
43
+ el$('.item').el.setAttribute('data-first', 'true')
44
+ const items = container.querySelectorAll('.item')
45
+ expect(items[0].dataset.first).to.equal('true')
46
+ expect(items[1].dataset.first).to.be.undefined
47
+ })
48
+ })
49
+
50
+ describe('els (always an Array)', () => {
51
+ it('should return an Array for multiple matches', () => {
52
+ const els = el$('.item').els
53
+ expect(Array.isArray(els)).to.be.true
54
+ expect(els).to.have.length(3)
55
+ })
56
+
57
+ it('should return a single-item Array for one match', () => {
58
+ const els = el$('.solo').els
59
+ expect(Array.isArray(els)).to.be.true
60
+ expect(els).to.have.length(1)
61
+ })
62
+
63
+ it('should return an empty Array for no matches', () => {
64
+ const els = el$('.nope').els
65
+ expect(Array.isArray(els)).to.be.true
66
+ expect(els).to.have.length(0)
67
+ })
68
+
69
+ it('should support Array methods directly', () => {
70
+ const texts = el$('.item').els.map(el => el.textContent)
71
+ expect(texts).to.deep.equal(['A', 'A', 'C'])
72
+ })
73
+
74
+ it('should keep arr as an equivalent legacy alias', () => {
75
+ expect(el$('.item').arr).to.deep.equal(el$('.item').els)
76
+ expect(Array.isArray(el$('.item').arr)).to.be.true
77
+ })
78
+ })
79
+
80
+ describe('length and len', () => {
81
+ it('should return the match count from length', () => {
82
+ expect(el$('.item').length).to.equal(3)
83
+ expect(el$('.solo').length).to.equal(1)
84
+ expect(el$('.nope').length).to.equal(0)
85
+ })
86
+
87
+ it('should keep len in agreement with length', () => {
88
+ expect(el$('.item').len).to.equal(el$('.item').length)
89
+ })
90
+ })
91
+
92
+ describe('chainability', () => {
93
+ it('should chain class mutators', () => {
94
+ el$('.item').addClass('x').toggleClass('y', true).removeClass('x')
95
+
96
+ const item = container.querySelector('.item')
97
+ expect(item.classList.contains('y')).to.be.true
98
+ expect(item.classList.contains('x')).to.be.false
99
+ })
100
+
101
+ it('should return the selector from mutators', () => {
102
+ const s = el$('.item')
103
+ expect(s.addClass('z')).to.equal(s)
104
+ expect(s.toggleClass('z')).to.equal(s)
105
+ expect(s.setClass('q')).to.equal(s)
106
+ expect(s.setActiveItem('active', '.special')).to.equal(s)
107
+ })
108
+ })
109
+
110
+ describe('appendChild', () => {
111
+ it('should append to the first element on a multi-match selector', () => {
112
+ const span = document.createElement('span')
113
+ span.className = 'appended'
114
+
115
+ el$('.item').appendChild(span)
116
+
117
+ const items = container.querySelectorAll('.item')
118
+ expect(items[0].querySelector('.appended')).to.not.be.null
119
+ expect(items[1].querySelector('.appended')).to.be.null
120
+ })
121
+
122
+ it('should warn and not throw on a non-matching selector', () => {
123
+ expect(() => el$('.nope').appendChild(document.createElement('b'))).to.not.throw()
124
+ })
125
+ })
126
+
127
+ describe('setActiveItem', () => {
128
+ it('should activate only the exact matching node', () => {
129
+ el$('.item').setActiveItem('active', '.special')
130
+
131
+ const items = container.querySelectorAll('.item')
132
+ expect(items[0].classList.contains('active')).to.be.false
133
+ expect(items[1].classList.contains('active')).to.be.false
134
+ expect(items[2].classList.contains('active')).to.be.true
135
+ })
136
+
137
+ it('should use identity, not deep equality, for duplicate siblings', () => {
138
+ const items = container.querySelectorAll('.item')
139
+
140
+ // items[0] and items[1] are identical markup; only the exact node activates
141
+ el$('.item').setActiveItem('active', items[1])
142
+
143
+ expect(items[0].classList.contains('active')).to.be.false
144
+ expect(items[1].classList.contains('active')).to.be.true
145
+ })
146
+ })
147
+
148
+ describe('elLegacy (undocumented pre-0.24 el contract)', () => {
149
+ it('should return a single element for a single match', () => {
150
+ expect(el$('.solo').elLegacy.nodeType).to.equal(1)
151
+ })
152
+
153
+ it('should return a NodeList for multiple matches', () => {
154
+ const el = el$('.item').elLegacy
155
+ expect(el.length).to.equal(3)
156
+ expect(el.nodeType).to.be.undefined
157
+ })
158
+
159
+ it('should return an empty list for no matches', () => {
160
+ expect(el$('.nope').elLegacy.length).to.equal(0)
161
+ })
162
+ })
163
+
164
+ describe('removed legacy members', () => {
165
+ it('should no longer define setActiveItem2, element, exist, nodeList, or getNodeListArray', () => {
166
+ const s = el$('.item')
167
+ expect(s.setActiveItem2).to.be.undefined
168
+ expect(s.element).to.be.undefined
169
+ expect(s.exist).to.be.undefined
170
+ expect(s.nodeList).to.be.undefined
171
+ expect(s.getNodeListArray).to.be.undefined
172
+ })
173
+
174
+ it('should keep unmount as a callable no-op for legacy apps', () => {
175
+ expect(() => el$('.item').unmount()).to.not.throw()
176
+ })
177
+ })
178
+ })