@knowark/componarkjs 1.13.3 → 1.14.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.
- package/lib/base/component/component.js +17 -1
- package/lib/base/component/component.test.js +475 -389
- package/lib/base/utils/define.js +28 -6
- package/lib/base/utils/define.test.js +129 -42
- package/lib/base/utils/format.test.js +16 -16
- package/lib/base/utils/helpers.js +11 -4
- package/lib/base/utils/helpers.test.js +134 -115
- package/lib/base/utils/slots.test.js +38 -38
- package/lib/base/utils/uuid.test.js +13 -13
- package/lib/components/audio/components/audio.js +22 -3
- package/lib/components/audio/components/audio.test.js +120 -90
- package/lib/components/camera/components/camera.js +8 -3
- package/lib/components/camera/components/camera.test.js +96 -91
- package/lib/components/capture/components/capture.js +33 -5
- package/lib/components/capture/components/capture.test.js +165 -97
- package/lib/components/droparea/components/droparea-preview.js +66 -15
- package/lib/components/droparea/components/droparea-preview.test.js +262 -78
- package/lib/components/droparea/components/droparea.js +47 -8
- package/lib/components/droparea/components/droparea.test.js +309 -298
- package/lib/components/emit/components/emit.js +24 -4
- package/lib/components/emit/components/emit.test.js +192 -134
- package/lib/components/index.js +1 -1
- package/lib/components/list/components/{list.item.js → item.js} +1 -1
- package/lib/components/list/components/item.test.js +70 -69
- package/lib/components/list/components/list.js +35 -5
- package/lib/components/list/components/list.test.js +358 -227
- package/lib/components/list/index.js +1 -1
- package/lib/components/paginator/components/paginator.js +3 -2
- package/lib/components/paginator/components/paginator.test.js +146 -143
- package/lib/components/spinner/components/spinner.js +1 -1
- package/lib/components/spinner/components/spinner.test.js +36 -41
- package/lib/components/splitview/components/splitview.detail.js +1 -1
- package/lib/components/splitview/components/splitview.detail.test.js +78 -74
- package/lib/components/splitview/components/splitview.js +40 -10
- package/lib/components/splitview/components/splitview.master.js +29 -3
- package/lib/components/splitview/components/splitview.master.test.js +52 -52
- package/lib/components/splitview/components/splitview.test.js +136 -32
- package/lib/components/translate/components/translate.js +32 -10
- package/lib/components/translate/components/translate.test.js +492 -133
- package/package.json +7 -27
- package/scripts/node-test-setup.js +94 -0
- package/showcase/components/index.html +1 -1
- package/{jsconfig.json → tsconfig.json} +6 -4
- package/types/base/component/component.d.ts +48 -0
- package/types/base/component/component.d.ts.map +1 -0
- package/types/base/component/component.test.d.ts +2 -0
- package/types/base/component/component.test.d.ts.map +1 -0
- package/types/base/component/index.d.ts +8 -0
- package/types/base/component/index.d.ts.map +1 -0
- package/types/base/index.d.ts +2 -0
- package/types/base/index.d.ts.map +1 -0
- package/types/base/styles/index.d.ts +3 -0
- package/types/base/styles/index.d.ts.map +1 -0
- package/types/base/styles/styles.d.ts +3 -0
- package/types/base/styles/styles.d.ts.map +1 -0
- package/types/base/utils/define.d.ts +5 -0
- package/types/base/utils/define.d.ts.map +1 -0
- package/types/base/utils/define.test.d.ts +2 -0
- package/types/base/utils/define.test.d.ts.map +1 -0
- package/types/base/utils/format.d.ts +13 -0
- package/types/base/utils/format.d.ts.map +1 -0
- package/types/base/utils/format.test.d.ts +2 -0
- package/types/base/utils/format.test.d.ts.map +1 -0
- package/types/base/utils/helpers.d.ts +11 -0
- package/types/base/utils/helpers.d.ts.map +1 -0
- package/types/base/utils/helpers.test.d.ts +2 -0
- package/types/base/utils/helpers.test.d.ts.map +1 -0
- package/types/base/utils/index.d.ts +6 -0
- package/types/base/utils/index.d.ts.map +1 -0
- package/types/base/utils/slots.d.ts +15 -0
- package/types/base/utils/slots.d.ts.map +1 -0
- package/types/base/utils/slots.test.d.ts +2 -0
- package/types/base/utils/slots.test.d.ts.map +1 -0
- package/types/base/utils/uuid.d.ts +3 -0
- package/types/base/utils/uuid.d.ts.map +1 -0
- package/types/base/utils/uuid.test.d.ts +2 -0
- package/types/base/utils/uuid.test.d.ts.map +1 -0
- package/types/components/audio/components/audio.d.ts +18 -0
- package/types/components/audio/components/audio.d.ts.map +1 -0
- package/types/components/audio/components/audio.test.d.ts +2 -0
- package/types/components/audio/components/audio.test.d.ts.map +1 -0
- package/types/components/audio/index.d.ts +2 -0
- package/types/components/audio/index.d.ts.map +1 -0
- package/types/components/audio/styles/ark.css.d.ts +3 -0
- package/types/components/audio/styles/ark.css.d.ts.map +1 -0
- package/types/components/audio/styles/index.d.ts +3 -0
- package/types/components/audio/styles/index.d.ts.map +1 -0
- package/types/components/camera/components/camera.d.ts +18 -0
- package/types/components/camera/components/camera.d.ts.map +1 -0
- package/types/components/camera/components/camera.test.d.ts +2 -0
- package/types/components/camera/components/camera.test.d.ts.map +1 -0
- package/types/components/camera/index.d.ts +2 -0
- package/types/components/camera/index.d.ts.map +1 -0
- package/types/components/camera/styles/ark.css.d.ts +3 -0
- package/types/components/camera/styles/ark.css.d.ts.map +1 -0
- package/types/components/camera/styles/index.d.ts +3 -0
- package/types/components/camera/styles/index.d.ts.map +1 -0
- package/types/components/capture/components/capture.d.ts +10 -0
- package/types/components/capture/components/capture.d.ts.map +1 -0
- package/types/components/capture/components/capture.test.d.ts +2 -0
- package/types/components/capture/components/capture.test.d.ts.map +1 -0
- package/types/components/capture/index.d.ts +2 -0
- package/types/components/capture/index.d.ts.map +1 -0
- package/types/components/droparea/components/droparea-preview.d.ts +21 -0
- package/types/components/droparea/components/droparea-preview.d.ts.map +1 -0
- package/types/components/droparea/components/droparea-preview.test.d.ts +2 -0
- package/types/components/droparea/components/droparea-preview.test.d.ts.map +1 -0
- package/types/components/droparea/components/droparea.d.ts +32 -0
- package/types/components/droparea/components/droparea.d.ts.map +1 -0
- package/types/components/droparea/components/droparea.test.d.ts +2 -0
- package/types/components/droparea/components/droparea.test.d.ts.map +1 -0
- package/types/components/droparea/index.d.ts +2 -0
- package/types/components/droparea/index.d.ts.map +1 -0
- package/types/components/droparea/styles/ark.css.d.ts +3 -0
- package/types/components/droparea/styles/ark.css.d.ts.map +1 -0
- package/types/components/droparea/styles/index.d.ts +3 -0
- package/types/components/droparea/styles/index.d.ts.map +1 -0
- package/types/components/emit/components/emit.d.ts +10 -0
- package/types/components/emit/components/emit.d.ts.map +1 -0
- package/types/components/emit/components/emit.test.d.ts +2 -0
- package/types/components/emit/components/emit.test.d.ts.map +1 -0
- package/types/components/emit/index.d.ts +2 -0
- package/types/components/emit/index.d.ts.map +1 -0
- package/types/components/index.d.ts +10 -0
- package/types/components/index.d.ts.map +1 -0
- package/types/components/list/components/item.d.ts +8 -0
- package/types/components/list/components/item.d.ts.map +1 -0
- package/types/components/list/components/item.test.d.ts +2 -0
- package/types/components/list/components/item.test.d.ts.map +1 -0
- package/types/components/list/components/list.d.ts +13 -0
- package/types/components/list/components/list.d.ts.map +1 -0
- package/types/components/list/components/list.test.d.ts +2 -0
- package/types/components/list/components/list.test.d.ts.map +1 -0
- package/types/components/list/index.d.ts +3 -0
- package/types/components/list/index.d.ts.map +1 -0
- package/types/components/paginator/components/paginator.d.ts +32 -0
- package/types/components/paginator/components/paginator.d.ts.map +1 -0
- package/types/components/paginator/components/paginator.test.d.ts +2 -0
- package/types/components/paginator/components/paginator.test.d.ts.map +1 -0
- package/types/components/paginator/index.d.ts +2 -0
- package/types/components/paginator/index.d.ts.map +1 -0
- package/types/components/paginator/styles/ark.css.d.ts +3 -0
- package/types/components/paginator/styles/ark.css.d.ts.map +1 -0
- package/types/components/paginator/styles/index.d.ts +3 -0
- package/types/components/paginator/styles/index.d.ts.map +1 -0
- package/types/components/spinner/components/spinner.d.ts +11 -0
- package/types/components/spinner/components/spinner.d.ts.map +1 -0
- package/types/components/spinner/components/spinner.test.d.ts +2 -0
- package/types/components/spinner/components/spinner.test.d.ts.map +1 -0
- package/types/components/spinner/index.d.ts +2 -0
- package/types/components/spinner/index.d.ts.map +1 -0
- package/types/components/spinner/styles/ark.css.d.ts +3 -0
- package/types/components/spinner/styles/ark.css.d.ts.map +1 -0
- package/types/components/spinner/styles/index.d.ts +3 -0
- package/types/components/spinner/styles/index.d.ts.map +1 -0
- package/types/components/splitview/components/splitview.d.ts +12 -0
- package/types/components/splitview/components/splitview.d.ts.map +1 -0
- package/types/components/splitview/components/splitview.detail.d.ts +10 -0
- package/types/components/splitview/components/splitview.detail.d.ts.map +1 -0
- package/types/components/splitview/components/splitview.detail.test.d.ts +2 -0
- package/types/components/splitview/components/splitview.detail.test.d.ts.map +1 -0
- package/types/components/splitview/components/splitview.master.d.ts +8 -0
- package/types/components/splitview/components/splitview.master.d.ts.map +1 -0
- package/types/components/splitview/components/splitview.master.test.d.ts +2 -0
- package/types/components/splitview/components/splitview.master.test.d.ts.map +1 -0
- package/types/components/splitview/components/splitview.test.d.ts +2 -0
- package/types/components/splitview/components/splitview.test.d.ts.map +1 -0
- package/types/components/splitview/index.d.ts +4 -0
- package/types/components/splitview/index.d.ts.map +1 -0
- package/types/components/translate/components/translate.d.ts +18 -0
- package/types/components/translate/components/translate.d.ts.map +1 -0
- package/types/components/translate/components/translate.test.d.ts +2 -0
- package/types/components/translate/components/translate.test.d.ts.map +1 -0
- package/types/components/translate/index.d.ts +2 -0
- package/types/components/translate/index.d.ts.map +1 -0
- package/types/index.d.ts +3 -0
- package/types/index.d.ts.map +1 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { it, mock } from 'node:test'
|
|
2
|
+
import assert from 'node:assert/strict'
|
|
2
3
|
import { Component } from './component.js'
|
|
3
4
|
|
|
4
5
|
class MockComponent extends Component {
|
|
@@ -42,486 +43,571 @@ class MockContentComponent extends Component {
|
|
|
42
43
|
}
|
|
43
44
|
Component.define('mock-content-component', MockContentComponent)
|
|
44
45
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
component = container.querySelector('mock-component')
|
|
52
|
-
document.body.append(container)
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
afterEach(() => {
|
|
56
|
-
container.remove()
|
|
57
|
-
container = null
|
|
58
|
-
component = null
|
|
59
|
-
})
|
|
46
|
+
class AsyncLoadComponent extends Component {
|
|
47
|
+
async load () {
|
|
48
|
+
throw new Error('Async Load Error!')
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
Component.define('async-load-component', AsyncLoadComponent)
|
|
60
52
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
53
|
+
class SyncLoadComponent extends Component {
|
|
54
|
+
load () {
|
|
55
|
+
throw new Error('Sync Load Error!')
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
Component.define('sync-load-component', SyncLoadComponent)
|
|
64
59
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
expect(typeof component.load).toEqual('function')
|
|
72
|
-
expect(typeof component.select).toEqual('function')
|
|
73
|
-
expect(typeof component.selectAll).toEqual('function')
|
|
74
|
-
expect(typeof component.emit).toEqual('function')
|
|
75
|
-
expect(typeof component.content).toBeDefined()
|
|
76
|
-
})
|
|
60
|
+
class PlainLoadComponent extends Component {
|
|
61
|
+
load () {
|
|
62
|
+
return null
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
Component.define('plain-load-component', PlainLoadComponent)
|
|
77
66
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
expect(response).toBe(component)
|
|
81
|
-
})
|
|
67
|
+
let container = null
|
|
68
|
+
let component = null
|
|
82
69
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
70
|
+
const setup = () => {
|
|
71
|
+
document.body.innerHTML = ''
|
|
72
|
+
container = document.createElement('div')
|
|
73
|
+
container.innerHTML = '<mock-component code="XYZ123"></mock-component>'
|
|
74
|
+
component = container.querySelector('mock-component')
|
|
75
|
+
document.body.append(container)
|
|
76
|
+
}
|
|
89
77
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
expect(await component.load()).toBeUndefined()
|
|
95
|
-
})
|
|
78
|
+
it('can be instantiated', () => {
|
|
79
|
+
setup()
|
|
80
|
+
assert.ok(component)
|
|
81
|
+
})
|
|
96
82
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
83
|
+
it('has an stable public api', () => {
|
|
84
|
+
setup()
|
|
85
|
+
assert.deepStrictEqual(typeof component.constructor.define, 'function')
|
|
86
|
+
assert.deepStrictEqual(typeof component.init, 'function')
|
|
87
|
+
assert.deepStrictEqual(typeof component.reflectedProperties, 'function')
|
|
88
|
+
assert.deepStrictEqual(typeof component.connectedCallback, 'function')
|
|
89
|
+
assert.deepStrictEqual(typeof component.render, 'function')
|
|
90
|
+
assert.deepStrictEqual(typeof component.load, 'function')
|
|
91
|
+
assert.deepStrictEqual(typeof component.select, 'function')
|
|
92
|
+
assert.deepStrictEqual(typeof component.selectAll, 'function')
|
|
93
|
+
assert.deepStrictEqual(typeof component.emit, 'function')
|
|
94
|
+
assert.notStrictEqual(typeof component.content, undefined)
|
|
95
|
+
})
|
|
101
96
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
expect(component.className).toEqual(
|
|
108
|
-
'mock-component custom-class special-class')
|
|
109
|
-
})
|
|
97
|
+
it('has an init method through which state is set', () => {
|
|
98
|
+
setup()
|
|
99
|
+
const response = component.init({ attribute: 'value' })
|
|
100
|
+
assert.strictEqual(response, component)
|
|
101
|
+
})
|
|
110
102
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
103
|
+
it('can set its content via a property', () => {
|
|
104
|
+
setup()
|
|
105
|
+
component.content = '<p>Hello World</p>'
|
|
106
|
+
const paragraph = component.querySelector('p')
|
|
107
|
+
assert.strictEqual(component.content, '<p>Hello World</p>')
|
|
108
|
+
assert.strictEqual(paragraph.outerHTML, '<p>Hello World</p>')
|
|
109
|
+
})
|
|
115
110
|
|
|
116
|
-
|
|
111
|
+
it('can have some of its attributes reflected as properties', () => {
|
|
112
|
+
setup()
|
|
113
|
+
assert.strictEqual(component.code, 'XYZ123')
|
|
114
|
+
})
|
|
115
|
+
it('has an asynchronous load method which is empty by default', async () => {
|
|
116
|
+
setup()
|
|
117
|
+
assert.strictEqual(await component.load(), undefined)
|
|
118
|
+
})
|
|
117
119
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
+
it('sets its tag name as class when rendered', () => {
|
|
121
|
+
setup()
|
|
122
|
+
component.render()
|
|
123
|
+
assert.deepStrictEqual(component.className, 'mock-component')
|
|
124
|
+
})
|
|
120
125
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
126
|
+
it('keeps its previous classes after rendering', () => {
|
|
127
|
+
setup()
|
|
128
|
+
component.classList.add('custom-class')
|
|
129
|
+
component.classList.add('custom-class')
|
|
130
|
+
component.classList.add('special-class')
|
|
131
|
+
component.render()
|
|
132
|
+
assert.deepStrictEqual(component.className, 'mock-component custom-class special-class')
|
|
133
|
+
})
|
|
127
134
|
|
|
128
|
-
|
|
135
|
+
it('emits custom events', () => {
|
|
136
|
+
setup()
|
|
137
|
+
let detail = null
|
|
138
|
+
const handler = (event) => { detail = event.detail }
|
|
139
|
+
component.addEventListener('fire', handler)
|
|
129
140
|
|
|
130
|
-
|
|
131
|
-
expect(renderSpy).toHaveBeenCalledTimes(1)
|
|
132
|
-
expect(loadSpy).toHaveBeenCalledTimes(1)
|
|
133
|
-
})
|
|
141
|
+
component.emit('fire', { location: 'indoors' })
|
|
134
142
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
const component = /** @type {Component} */ (
|
|
138
|
-
document.createElement('mock-component'))
|
|
139
|
-
const consoleError = console.error
|
|
140
|
-
console.error = jest.fn()
|
|
141
|
-
component.render = () => {
|
|
142
|
-
throw new Error('Render Error!')
|
|
143
|
-
}
|
|
143
|
+
assert.deepStrictEqual(detail, { location: 'indoors' })
|
|
144
|
+
})
|
|
144
145
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
146
|
+
it('calls the load method on connectedCallback', async () => {
|
|
147
|
+
setup()
|
|
148
|
+
const component = /** @type {Component} */ (
|
|
149
|
+
document.createElement('mock-component'))
|
|
150
|
+
const initSpy = mock.method(component, 'init')
|
|
151
|
+
const renderSpy = mock.method(component, 'render')
|
|
152
|
+
const loadSpy = mock.method(component, 'load')
|
|
153
|
+
|
|
154
|
+
document.body.append(component)
|
|
155
|
+
|
|
156
|
+
assert.strictEqual(initSpy.mock.calls.length, 1)
|
|
157
|
+
assert.strictEqual(renderSpy.mock.calls.length, 1)
|
|
158
|
+
assert.strictEqual(loadSpy.mock.calls.length, 1)
|
|
159
|
+
initSpy.mock.restore()
|
|
160
|
+
renderSpy.mock.restore()
|
|
161
|
+
loadSpy.mock.restore()
|
|
162
|
+
})
|
|
150
163
|
|
|
151
|
-
|
|
152
|
-
|
|
164
|
+
it('catches and re-raises connectedCallback errors', async () => {
|
|
165
|
+
setup()
|
|
166
|
+
const component = /** @type {Component} */ (
|
|
167
|
+
document.createElement('mock-component'))
|
|
168
|
+
const consoleErrorMock = mock.method(console, 'error', () => {})
|
|
169
|
+
component.render = () => {
|
|
170
|
+
throw new Error('Render Error!')
|
|
171
|
+
}
|
|
153
172
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
const component = container.querySelector('mock-component')
|
|
173
|
+
try {
|
|
174
|
+
component.connectedCallback()
|
|
175
|
+
} catch (error) {
|
|
176
|
+
assert.deepStrictEqual(error.message, 'Render Error!')
|
|
177
|
+
} finally {
|
|
178
|
+
consoleErrorMock.mock.restore()
|
|
179
|
+
}
|
|
180
|
+
})
|
|
163
181
|
|
|
164
|
-
|
|
165
|
-
|
|
182
|
+
it('emits an error event when async load fails', async () => {
|
|
183
|
+
setup()
|
|
184
|
+
const component = document.createElement('async-load-component')
|
|
185
|
+
let errorEvent = null
|
|
166
186
|
|
|
167
|
-
|
|
168
|
-
|
|
187
|
+
component.addEventListener('error', (event) => {
|
|
188
|
+
errorEvent = event
|
|
169
189
|
})
|
|
170
190
|
|
|
171
|
-
|
|
172
|
-
container.innerHTML = `
|
|
173
|
-
<mock-component>
|
|
174
|
-
<div slot="header" class="header"></div>
|
|
175
|
-
<div class="body"></div>
|
|
176
|
-
<div class="aside"></div>
|
|
177
|
-
<div slot="footer" class="footer"></div>
|
|
178
|
-
</mock-component>
|
|
179
|
-
`
|
|
180
|
-
const component = container.querySelector('mock-component')
|
|
181
|
-
|
|
182
|
-
expect(component.slots).toEqual({
|
|
183
|
-
header: [component.select('.header')],
|
|
184
|
-
general: [component.select('.body'), component.select('.aside')],
|
|
185
|
-
footer: [component.select('.footer')]
|
|
186
|
-
})
|
|
187
|
-
})
|
|
191
|
+
document.body.appendChild(component)
|
|
188
192
|
|
|
189
|
-
|
|
190
|
-
container.innerHTML = `
|
|
191
|
-
<mock-component>
|
|
192
|
-
<input type="text" listen on-input="{{ data.value = data }}"></input>
|
|
193
|
-
</mock-component>
|
|
194
|
-
`
|
|
193
|
+
await new Promise(resolve => setTimeout(resolve, 0))
|
|
195
194
|
|
|
196
|
-
|
|
197
|
-
|
|
195
|
+
assert.ok(errorEvent)
|
|
196
|
+
assert.deepStrictEqual(errorEvent.detail.message, 'Async Load Error!')
|
|
197
|
+
})
|
|
198
198
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
199
|
+
it('emits an error event and throws when sync load fails', () => {
|
|
200
|
+
setup()
|
|
201
|
+
const component = document.createElement('sync-load-component')
|
|
202
|
+
let errorEvent = null
|
|
202
203
|
|
|
203
|
-
|
|
204
|
+
component.addEventListener('error', (event) => {
|
|
205
|
+
errorEvent = event
|
|
204
206
|
})
|
|
205
207
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
<input type="text"
|
|
210
|
-
listen
|
|
211
|
-
on-input="{{ data.value = data }}"
|
|
212
|
-
on-input-1="{{ data.value1 = data }}"
|
|
213
|
-
on-input-2="{{ data.value2 = data }}"
|
|
214
|
-
on-input-3="{{ data.value3 = data }}"
|
|
215
|
-
></input>
|
|
216
|
-
</mock-component>
|
|
217
|
-
`
|
|
208
|
+
assert.throws(() => {
|
|
209
|
+
component.connectedCallback()
|
|
210
|
+
}, /Sync Load Error!/)
|
|
218
211
|
|
|
219
|
-
|
|
220
|
-
|
|
212
|
+
assert.ok(errorEvent)
|
|
213
|
+
assert.deepStrictEqual(errorEvent.detail.message, 'Sync Load Error!')
|
|
214
|
+
})
|
|
221
215
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
216
|
+
it('supports load implementations that do not return promises', () => {
|
|
217
|
+
setup()
|
|
218
|
+
const component = document.createElement('plain-load-component')
|
|
225
219
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
expect(component.data.value2).toEqual('E')
|
|
229
|
-
expect(component.data.value3).toEqual('E')
|
|
220
|
+
assert.doesNotThrow(() => {
|
|
221
|
+
component.connectedCallback()
|
|
230
222
|
})
|
|
223
|
+
})
|
|
231
224
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
225
|
+
it('selects the children matching a selector', () => {
|
|
226
|
+
setup();
|
|
227
|
+
container.innerHTML = `
|
|
228
|
+
<mock-component>
|
|
229
|
+
<div class="blue"></div>
|
|
230
|
+
<div class="red"></div>
|
|
231
|
+
<div class="red"></div>
|
|
232
|
+
</mock-component>
|
|
233
|
+
`
|
|
234
|
+
const component = container.querySelector('mock-component')
|
|
235
|
+
|
|
236
|
+
const blue = component.select('.blue')
|
|
237
|
+
assert.deepStrictEqual(blue.tagName, 'DIV')
|
|
238
|
+
|
|
239
|
+
const red = component.selectAll('.red')
|
|
240
|
+
assert.deepStrictEqual(red.length, 2)
|
|
241
|
+
})
|
|
246
242
|
|
|
247
|
-
|
|
243
|
+
it('retrieves its slots through the slots method', () => {
|
|
244
|
+
setup();
|
|
245
|
+
container.innerHTML = `
|
|
246
|
+
<mock-component>
|
|
247
|
+
<div slot="header" class="header"></div>
|
|
248
|
+
<div class="body"></div>
|
|
249
|
+
<div class="aside"></div>
|
|
250
|
+
<div slot="footer" class="footer"></div>
|
|
251
|
+
</mock-component>
|
|
252
|
+
`
|
|
253
|
+
const component = container.querySelector('mock-component')
|
|
254
|
+
|
|
255
|
+
assert.deepStrictEqual(component.slots, {
|
|
256
|
+
header: [component.select('.header')],
|
|
257
|
+
general: [component.select('.body'), component.select('.aside')],
|
|
258
|
+
footer: [component.select('.footer')]
|
|
248
259
|
})
|
|
260
|
+
})
|
|
249
261
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
const component = container.querySelector('mock-component')
|
|
258
|
-
const input = component.select('input')
|
|
262
|
+
it('binds its properties to children events', async () => {
|
|
263
|
+
setup();
|
|
264
|
+
container.innerHTML = `
|
|
265
|
+
<mock-component>
|
|
266
|
+
<input type="text" listen on-input="{{ data.value = data }}"></input>
|
|
267
|
+
</mock-component>
|
|
268
|
+
`
|
|
259
269
|
|
|
260
|
-
|
|
261
|
-
|
|
270
|
+
const component = container.querySelector('mock-component')
|
|
271
|
+
const input = component.select('input')
|
|
262
272
|
|
|
263
|
-
|
|
264
|
-
|
|
273
|
+
input.dispatchEvent(
|
|
274
|
+
new globalThis.InputEvent('input', { bubbles: true, data: 'E' })
|
|
275
|
+
)
|
|
265
276
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
<mock-component>
|
|
269
|
-
<input type="text" listen on-alter="{{ data.value | number }}"></input>
|
|
270
|
-
</mock-component>
|
|
271
|
-
`
|
|
277
|
+
assert.deepStrictEqual(component.data.value, 'E')
|
|
278
|
+
})
|
|
272
279
|
|
|
273
|
-
|
|
274
|
-
|
|
280
|
+
it('binds multiple handlers to the same event', async () => {
|
|
281
|
+
setup();
|
|
282
|
+
container.innerHTML = `
|
|
283
|
+
<mock-component>
|
|
284
|
+
<input type="text"
|
|
285
|
+
listen
|
|
286
|
+
on-input="{{ data.value = data }}"
|
|
287
|
+
on-input-1="{{ data.value1 = data }}"
|
|
288
|
+
on-input-2="{{ data.value2 = data }}"
|
|
289
|
+
on-input-3="{{ data.value3 = data }}"
|
|
290
|
+
></input>
|
|
291
|
+
</mock-component>
|
|
292
|
+
`
|
|
293
|
+
|
|
294
|
+
const component = container.querySelector('mock-component')
|
|
295
|
+
const input = component.select('input')
|
|
296
|
+
|
|
297
|
+
input.dispatchEvent(
|
|
298
|
+
new globalThis.InputEvent('input', { bubbles: true, data: 'E' })
|
|
299
|
+
)
|
|
300
|
+
|
|
301
|
+
assert.deepStrictEqual(component.data.value, 'E')
|
|
302
|
+
assert.deepStrictEqual(component.data.value1, 'E')
|
|
303
|
+
assert.deepStrictEqual(component.data.value2, 'E')
|
|
304
|
+
assert.deepStrictEqual(component.data.value3, 'E')
|
|
305
|
+
})
|
|
275
306
|
|
|
276
|
-
|
|
277
|
-
|
|
307
|
+
it('binds to the target.value event property by default', async () => {
|
|
308
|
+
setup()
|
|
309
|
+
container.innerHTML = `
|
|
310
|
+
<mock-component>
|
|
311
|
+
<input type="text" listen on-input="{{ data.value }}"></input>
|
|
312
|
+
</mock-component>
|
|
313
|
+
`
|
|
314
|
+
const component = container.querySelector('mock-component')
|
|
315
|
+
const input = component.select('input')
|
|
316
|
+
input.value = 'X'
|
|
317
|
+
const inputEvent = new globalThis.InputEvent('input', { bubbles: true })
|
|
318
|
+
|
|
319
|
+
input.dispatchEvent(inputEvent)
|
|
320
|
+
|
|
321
|
+
assert.deepStrictEqual(component.data.value, 'X')
|
|
322
|
+
})
|
|
278
323
|
|
|
279
|
-
|
|
280
|
-
|
|
324
|
+
it('binds to the detail custom event property', async () => {
|
|
325
|
+
setup();
|
|
326
|
+
container.innerHTML = `
|
|
327
|
+
<mock-component>
|
|
328
|
+
<input type="text" listen on-alter="{{ data.value }}"></input>
|
|
329
|
+
</mock-component>
|
|
330
|
+
`
|
|
281
331
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
<mock-component>
|
|
285
|
-
<input type="text" listen on-alter="{{ local | object }}"></input>
|
|
286
|
-
</mock-component>
|
|
287
|
-
`
|
|
332
|
+
const component = container.querySelector('mock-component')
|
|
333
|
+
const input = component.select('input')
|
|
288
334
|
|
|
289
|
-
|
|
290
|
-
|
|
335
|
+
input.dispatchEvent(
|
|
336
|
+
new globalThis.CustomEvent('alter', { bubbles: true, detail: 'A' }))
|
|
291
337
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
new globalThis.CustomEvent('alter', { bubbles: true, detail }))
|
|
338
|
+
assert.deepStrictEqual(component.data.value, 'A')
|
|
339
|
+
})
|
|
295
340
|
|
|
296
|
-
|
|
297
|
-
|
|
341
|
+
it('performs basic transformations to event properties', async () => {
|
|
342
|
+
setup();
|
|
343
|
+
container.innerHTML = `
|
|
344
|
+
<mock-component>
|
|
345
|
+
<input type="text" listen on-alter="{{ data.value | number }}"></input>
|
|
346
|
+
</mock-component>
|
|
347
|
+
`
|
|
298
348
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
<mock-component>
|
|
302
|
-
<input type="text" listen on-alter="{{ local.zone | object }}"></input>
|
|
303
|
-
</mock-component>
|
|
304
|
-
`
|
|
349
|
+
const component = container.querySelector('mock-component')
|
|
350
|
+
const input = component.select('input')
|
|
305
351
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
const input = component.select('input')
|
|
352
|
+
input.dispatchEvent(
|
|
353
|
+
new globalThis.CustomEvent('alter', { bubbles: true, detail: '777' }))
|
|
309
354
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
new globalThis.CustomEvent('alter', { bubbles: true, detail }))
|
|
355
|
+
assert.deepStrictEqual(component.data.value, 777)
|
|
356
|
+
})
|
|
313
357
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
358
|
+
it('performs object assignment of event details', async () => {
|
|
359
|
+
setup();
|
|
360
|
+
container.innerHTML = `
|
|
361
|
+
<mock-component>
|
|
362
|
+
<input type="text" listen on-alter="{{ local | object }}"></input>
|
|
363
|
+
</mock-component>
|
|
364
|
+
`
|
|
321
365
|
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
<mock-component code="ABC123">
|
|
325
|
-
<input type="text" listen on-alter="customHandler"></input>
|
|
326
|
-
</mock-component>
|
|
327
|
-
`
|
|
366
|
+
const component = container.querySelector('mock-component')
|
|
367
|
+
const input = component.select('input')
|
|
328
368
|
|
|
329
|
-
|
|
330
|
-
|
|
369
|
+
const detail = { name: 'Sprite', brand: 'Coca-Cola' }
|
|
370
|
+
input.dispatchEvent(
|
|
371
|
+
new globalThis.CustomEvent('alter', { bubbles: true, detail }))
|
|
331
372
|
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
input.dispatchEvent(event)
|
|
373
|
+
assert.deepStrictEqual(component.local, { name: 'Sprite', brand: 'Coca-Cola' })
|
|
374
|
+
})
|
|
335
375
|
|
|
336
|
-
|
|
376
|
+
it('performs nested object assignment of event details', async () => {
|
|
377
|
+
setup();
|
|
378
|
+
container.innerHTML = `
|
|
379
|
+
<mock-component>
|
|
380
|
+
<input type="text" listen on-alter="{{ local.zone | object }}"></input>
|
|
381
|
+
</mock-component>
|
|
382
|
+
`
|
|
383
|
+
|
|
384
|
+
const component = container.querySelector('mock-component')
|
|
385
|
+
component.local.zone = {}
|
|
386
|
+
const input = component.select('input')
|
|
387
|
+
|
|
388
|
+
const detail = { country: 'USA', city: 'Atlanta' }
|
|
389
|
+
input.dispatchEvent(
|
|
390
|
+
new globalThis.CustomEvent('alter', { bubbles: true, detail }))
|
|
391
|
+
|
|
392
|
+
assert.deepStrictEqual(component.local, {
|
|
393
|
+
zone: {
|
|
394
|
+
country: 'USA',
|
|
395
|
+
city: 'Atlanta'
|
|
396
|
+
}
|
|
337
397
|
})
|
|
398
|
+
})
|
|
338
399
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
400
|
+
it('listens to events and handles them with its own methods', async () => {
|
|
401
|
+
setup();
|
|
402
|
+
container.innerHTML = `
|
|
403
|
+
<mock-component code="ABC123">
|
|
404
|
+
<input type="text" listen on-alter="customHandler"></input>
|
|
405
|
+
</mock-component>
|
|
406
|
+
`
|
|
346
407
|
|
|
347
|
-
|
|
348
|
-
|
|
408
|
+
const component = container.querySelector('mock-component')
|
|
409
|
+
const input = component.select('input')
|
|
349
410
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
411
|
+
const event = new globalThis.CustomEvent(
|
|
412
|
+
'alter', { bubbles: true, detail: { code: [] } })
|
|
413
|
+
input.dispatchEvent(event)
|
|
353
414
|
|
|
354
|
-
|
|
355
|
-
|
|
415
|
+
assert.deepStrictEqual(event.detail.code, ['ABC123'])
|
|
416
|
+
})
|
|
356
417
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
418
|
+
it('listens to events and redirects them to target components', async () => {
|
|
419
|
+
setup();
|
|
420
|
+
container.innerHTML = `
|
|
421
|
+
<mock-component code="ABC123">
|
|
422
|
+
<input type="text" listen on-alter="customHandler@#child"></input>
|
|
423
|
+
<mock-component id="child" code="XYZ890"></mock-component>
|
|
424
|
+
</mock-component>
|
|
425
|
+
`
|
|
364
426
|
|
|
365
|
-
|
|
366
|
-
|
|
427
|
+
const component = container.querySelector('mock-component')
|
|
428
|
+
const input = component.select('input')
|
|
367
429
|
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
430
|
+
const event = new globalThis.CustomEvent(
|
|
431
|
+
'alter', { bubbles: true, detail: { code: [] } })
|
|
432
|
+
input.dispatchEvent(event)
|
|
371
433
|
|
|
372
|
-
|
|
373
|
-
|
|
434
|
+
assert.deepStrictEqual(event.detail.code, ['XYZ890'])
|
|
435
|
+
})
|
|
374
436
|
|
|
437
|
+
it('does not launch and event if the target is not found', async () => {
|
|
438
|
+
setup();
|
|
439
|
+
container.innerHTML = `
|
|
440
|
+
<mock-component code="ABC123">
|
|
441
|
+
<input type="text" listen on-alter="customHandler@#missing"></input>
|
|
442
|
+
<mock-component id="child" code="XYZ890"></mock-component>
|
|
443
|
+
</mock-component>
|
|
444
|
+
`
|
|
375
445
|
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
<mock-component code="ABC123">
|
|
379
|
-
<div type="text" listen on-click="customHandler@#child">
|
|
380
|
-
<button id="action">Action</button>
|
|
381
|
-
</div>
|
|
382
|
-
<mock-component id="child" code="XYZ890"></mock-component>
|
|
383
|
-
</mock-component>
|
|
384
|
-
`
|
|
446
|
+
const component = container.querySelector('mock-component')
|
|
447
|
+
const input = component.select('input')
|
|
385
448
|
|
|
386
|
-
|
|
387
|
-
|
|
449
|
+
const event = new globalThis.CustomEvent(
|
|
450
|
+
'alter', { bubbles: true, detail: { code: [] } })
|
|
451
|
+
input.dispatchEvent(event)
|
|
388
452
|
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
button.dispatchEvent(event)
|
|
453
|
+
assert.deepStrictEqual(event.detail.code, [])
|
|
454
|
+
})
|
|
392
455
|
|
|
393
|
-
expect(event.detail.code).toEqual(['XYZ890'])
|
|
394
|
-
})
|
|
395
456
|
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
</
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
const child = container.querySelector('#child')
|
|
415
|
-
expect(child.textContent.trim()).toEqual('World')
|
|
416
|
-
})
|
|
457
|
+
it('listens to clicks and redirects them to target components', async () => {
|
|
458
|
+
setup();
|
|
459
|
+
container.innerHTML = `
|
|
460
|
+
<mock-component code="ABC123">
|
|
461
|
+
<div type="text" listen on-click="customHandler@#child">
|
|
462
|
+
<button id="action">Action</button>
|
|
463
|
+
</div>
|
|
464
|
+
<mock-component id="child" code="XYZ890"></mock-component>
|
|
465
|
+
</mock-component>
|
|
466
|
+
`
|
|
467
|
+
|
|
468
|
+
const component = container.querySelector('mock-component')
|
|
469
|
+
const button = component.select('#action')
|
|
470
|
+
|
|
471
|
+
const event = new globalThis.CustomEvent(
|
|
472
|
+
'click', { bubbles: true, detail: { code: [] } })
|
|
473
|
+
button.dispatchEvent(event)
|
|
417
474
|
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
475
|
+
assert.deepStrictEqual(event.detail.code, ['XYZ890'])
|
|
476
|
+
})
|
|
477
|
+
|
|
478
|
+
it('listens to events and pipes them to target components', async () => {
|
|
479
|
+
setup();
|
|
480
|
+
container.innerHTML = `
|
|
481
|
+
<mock-component code="ABC123">
|
|
482
|
+
<div type="text" listen on-change="replaceChildren%detail.name@#child">
|
|
483
|
+
<button id="action">Action</button>
|
|
484
|
+
</div>
|
|
485
|
+
<div id="child">
|
|
486
|
+
Hello
|
|
487
|
+
</div>
|
|
422
488
|
</mock-component>
|
|
423
|
-
|
|
489
|
+
`
|
|
490
|
+
const component = container.querySelector('mock-component')
|
|
491
|
+
const button = component.select('#action')
|
|
424
492
|
|
|
425
|
-
|
|
493
|
+
const event = new globalThis.CustomEvent(
|
|
494
|
+
'change', { bubbles: true, detail: { name: 'World' } })
|
|
495
|
+
button.dispatchEvent(event)
|
|
426
496
|
|
|
427
|
-
|
|
428
|
-
|
|
497
|
+
const child = container.querySelector('#child')
|
|
498
|
+
assert.deepStrictEqual(child.textContent.trim(), 'World')
|
|
499
|
+
})
|
|
429
500
|
|
|
430
|
-
|
|
501
|
+
it('emits an error event on declared listeners', async () => {
|
|
502
|
+
setup();
|
|
503
|
+
container.innerHTML = `
|
|
504
|
+
<mock-component>
|
|
505
|
+
<input type="text" listen on-alter="erroringHandler"></input>
|
|
506
|
+
</mock-component>
|
|
507
|
+
`
|
|
431
508
|
|
|
432
|
-
|
|
433
|
-
new globalThis.CustomEvent(
|
|
434
|
-
'alter', { bubbles: true, detail: 'I will error!' }
|
|
435
|
-
))
|
|
509
|
+
const component = container.querySelector('mock-component')
|
|
436
510
|
|
|
437
|
-
|
|
438
|
-
})
|
|
511
|
+
let errorEvent = {}
|
|
512
|
+
component.addEventListener('error', (event) => { errorEvent = event })
|
|
439
513
|
|
|
440
|
-
|
|
441
|
-
container.innerHTML = `
|
|
442
|
-
<mock-component>
|
|
443
|
-
<input type="text" listen on-alter="asyncErroringHandler"></input>
|
|
444
|
-
</mock-component>
|
|
445
|
-
`
|
|
514
|
+
const input = component.select('input')
|
|
446
515
|
|
|
447
|
-
|
|
516
|
+
input.dispatchEvent(
|
|
517
|
+
new globalThis.CustomEvent(
|
|
518
|
+
'alter', { bubbles: true, detail: 'I will error!' }
|
|
519
|
+
))
|
|
448
520
|
|
|
449
|
-
|
|
450
|
-
|
|
521
|
+
assert.deepStrictEqual(errorEvent.detail.message, 'Something went wrong!')
|
|
522
|
+
})
|
|
451
523
|
|
|
452
|
-
|
|
524
|
+
it('emits an error event on declared async listeners', async () => {
|
|
525
|
+
setup();
|
|
526
|
+
container.innerHTML = `
|
|
527
|
+
<mock-component>
|
|
528
|
+
<input type="text" listen on-alter="asyncErroringHandler"></input>
|
|
529
|
+
</mock-component>
|
|
530
|
+
`
|
|
453
531
|
|
|
454
|
-
|
|
455
|
-
new globalThis.CustomEvent(
|
|
456
|
-
'alter', { bubbles: true, detail: 'I will error!' }
|
|
457
|
-
))
|
|
532
|
+
const component = container.querySelector('mock-component')
|
|
458
533
|
|
|
459
|
-
|
|
460
|
-
|
|
534
|
+
let errorEvent = {}
|
|
535
|
+
component.addEventListener('error', (event) => { errorEvent = event })
|
|
461
536
|
|
|
462
|
-
|
|
463
|
-
})
|
|
537
|
+
const input = component.select('input')
|
|
464
538
|
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
}
|
|
470
|
-
document.addEventListener('resolve', listener)
|
|
471
|
-
container.innerHTML = `
|
|
472
|
-
<mock-component></mock-component>
|
|
473
|
-
`
|
|
474
|
-
const component = container.querySelector('mock-component')
|
|
475
|
-
|
|
476
|
-
expect(component.dependency).toEqual('RESOLVED_DEPENDENCY')
|
|
477
|
-
document.removeEventListener('resolve', listener)
|
|
478
|
-
})
|
|
539
|
+
input.dispatchEvent(
|
|
540
|
+
new globalThis.CustomEvent(
|
|
541
|
+
'alter', { bubbles: true, detail: 'I will error!' }
|
|
542
|
+
))
|
|
479
543
|
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
544
|
+
// Sleep
|
|
545
|
+
await new Promise(resolve => setTimeout(resolve, 0))
|
|
546
|
+
|
|
547
|
+
assert.deepStrictEqual(errorEvent.detail.message, 'Something went async wrong!')
|
|
548
|
+
})
|
|
549
|
+
|
|
550
|
+
it('resolves its resource dependencies using events propagation', () => {
|
|
551
|
+
setup();
|
|
552
|
+
const listener = (event) => {
|
|
553
|
+
const resource = event.detail.resource
|
|
554
|
+
event.detail[resource] = 'RESOLVED_DEPENDENCY'
|
|
555
|
+
}
|
|
556
|
+
document.addEventListener('resolve', listener)
|
|
557
|
+
container.innerHTML = `
|
|
558
|
+
<mock-component></mock-component>
|
|
559
|
+
`
|
|
560
|
+
const component = container.querySelector('mock-component')
|
|
561
|
+
|
|
562
|
+
assert.deepStrictEqual(component.dependency, 'RESOLVED_DEPENDENCY')
|
|
563
|
+
document.removeEventListener('resolve', listener)
|
|
564
|
+
})
|
|
565
|
+
|
|
566
|
+
it('provides the dependencies requested to it by child components', () => {
|
|
567
|
+
setup();
|
|
568
|
+
class ParentComponent extends MockComponent {
|
|
569
|
+
provide (resource) {
|
|
570
|
+
if (resource === 'Dependency') {
|
|
571
|
+
return `RESOURCE: ${resource} PROVIDED BY: ${this.id}`
|
|
487
572
|
}
|
|
573
|
+
if (resource === 'state') return { key: 'value' }
|
|
488
574
|
}
|
|
489
|
-
|
|
575
|
+
}
|
|
576
|
+
Component.define('parent-component', ParentComponent)
|
|
490
577
|
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
578
|
+
container.innerHTML = `
|
|
579
|
+
<parent-component id="parent">
|
|
580
|
+
<mock-component id="child"></mock-component>
|
|
581
|
+
</parent-component>
|
|
582
|
+
`
|
|
496
583
|
|
|
497
|
-
|
|
584
|
+
const child = container.querySelector('#child')
|
|
498
585
|
|
|
499
|
-
|
|
500
|
-
'RESOURCE: Dependency PROVIDED BY: parent')
|
|
586
|
+
assert.deepStrictEqual(child.dependency, 'RESOURCE: Dependency PROVIDED BY: parent')
|
|
501
587
|
|
|
502
|
-
|
|
503
|
-
|
|
588
|
+
const state = child.resolve('state')
|
|
589
|
+
assert.deepStrictEqual(state, { key: 'value' })
|
|
504
590
|
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
591
|
+
const unknown = child.resolve('unknown')
|
|
592
|
+
assert.strictEqual(unknown, undefined)
|
|
593
|
+
})
|
|
508
594
|
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
}
|
|
595
|
+
it('provides a styleNames utility function for setting styles', () => {
|
|
596
|
+
setup();
|
|
597
|
+
container.innerHTML = `
|
|
598
|
+
<mock-component class></mock-component>
|
|
599
|
+
`
|
|
600
|
+
const component = container.querySelector('mock-component')
|
|
601
|
+
const background = 'primary'
|
|
602
|
+
const shadow = 'small'
|
|
603
|
+
const color = ''
|
|
604
|
+
const styleMap = {
|
|
605
|
+
[`background-${background}`]: background,
|
|
606
|
+
[`color-${color}`]: color,
|
|
607
|
+
[`shadow-${shadow}`]: shadow
|
|
608
|
+
}
|
|
522
609
|
|
|
523
|
-
|
|
610
|
+
const result = component.styleNames(styleMap)
|
|
524
611
|
|
|
525
|
-
|
|
526
|
-
})
|
|
612
|
+
assert.deepStrictEqual(result, 'background-primary shadow-small')
|
|
527
613
|
})
|