decue 1.0.1 → 1.1.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/README.md +15 -1
- package/dist/decue.js +309 -172
- package/dist/decue.min.js +1 -1
- package/eslint.config.js +53 -0
- package/examples.html +29 -13
- package/npm.sh +1 -1
- package/package.json +17 -8
- package/src/decue.js +309 -172
- package/test/debug.test.js +201 -0
- package/test/decue.test.js +78 -0
- package/test/errors.test.js +212 -0
- package/test/eventHandlers.test.js +95 -0
- package/test/formAssociated.test.js +477 -0
- package/test/init.test.js +43 -0
- package/test/lifecycle.test.js +110 -0
- package/test/memory.test.js +283 -0
- package/test/piped.test.js +152 -0
- package/test/placeholders.test.js +396 -0
- package/test/predefined.test.js +131 -0
- package/test/scriptAttributes.test.js +464 -0
- package/test/slots.test.js +293 -0
- package/test/test-helpers.js +36 -0
- package/tsconfig.json +1 -1
- package/web-test-runner.config.mjs +30 -0
- package/serve.sh +0 -4
- package/test/decue-tests.js +0 -84
- package/test/index.html +0 -65
- package/test/util/util.js +0 -17
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
import { expect } from '@esm-bundle/chai';
|
|
2
|
+
import { createTemplate, createElement, getContentRoot } from './test-helpers.js';
|
|
3
|
+
|
|
4
|
+
// Unique counter for element names
|
|
5
|
+
let elementCounter = 0;
|
|
6
|
+
function uniqueName(prefix) {
|
|
7
|
+
return `${prefix}-${++elementCounter}`;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// Clean up after each test
|
|
11
|
+
afterEach(() => {
|
|
12
|
+
// Remove all test templates and elements
|
|
13
|
+
document.querySelectorAll('template[decue]').forEach(el => el.remove());
|
|
14
|
+
document.querySelectorAll('[data-test-element]').forEach(el => el.remove());
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
describe('slots', () => {
|
|
18
|
+
|
|
19
|
+
// Execute each test for all three custom element variants:
|
|
20
|
+
// 1. No shadow DOM
|
|
21
|
+
// 2. Shadow DOM open
|
|
22
|
+
// 3. Shadow DOM closed
|
|
23
|
+
['none', 'open', 'closed'].forEach(shadow => {
|
|
24
|
+
describe("shadowmode: " + shadow, function() {
|
|
25
|
+
it('named slot with default value', function () {
|
|
26
|
+
const name = uniqueName('test-named-slot-default');
|
|
27
|
+
createTemplate(name, '<slot name="content"><div class="default">Default slot content</div></slot>', { shadow: shadow !== 'none' ? shadow : undefined });
|
|
28
|
+
|
|
29
|
+
const el = createElement(name, {
|
|
30
|
+
'data-test-element': '',
|
|
31
|
+
...(shadow !== 'none' ? { shadow } : {})
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
// Verify element was created
|
|
35
|
+
expect(el).to.exist;
|
|
36
|
+
|
|
37
|
+
const root = getContentRoot(el, shadow);
|
|
38
|
+
if (shadow !== 'closed') {
|
|
39
|
+
// When no slotted content is provided, default should be used
|
|
40
|
+
const defaultContent = root.querySelector('.default');
|
|
41
|
+
expect(defaultContent).to.exist;
|
|
42
|
+
expect(defaultContent.textContent).to.equal('Default slot content');
|
|
43
|
+
} else {
|
|
44
|
+
// For closed shadow, verify element exists and is connected
|
|
45
|
+
expect(el.shadowRoot).to.be.null;
|
|
46
|
+
expect(el.isConnected).to.be.true;
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('named slot with given value', function () {
|
|
51
|
+
const name = uniqueName('test-named-slot-given');
|
|
52
|
+
createTemplate(name, '<slot name="content"><div class="default">Default slot content</div></slot>', { shadow: shadow !== 'none' ? shadow : undefined });
|
|
53
|
+
|
|
54
|
+
const el = createElement(name, {
|
|
55
|
+
'data-test-element': '',
|
|
56
|
+
...(shadow !== 'none' ? { shadow } : {})
|
|
57
|
+
}, '<div slot="content" class="custom">Custom slot content</div>');
|
|
58
|
+
|
|
59
|
+
// Verify element was created
|
|
60
|
+
expect(el).to.exist;
|
|
61
|
+
|
|
62
|
+
if (shadow !== 'closed') {
|
|
63
|
+
if (shadow === 'none') {
|
|
64
|
+
// In light DOM (no shadow), slotted content replaces the slot in place
|
|
65
|
+
const root = getContentRoot(el, shadow);
|
|
66
|
+
const customContent = root.querySelector('.custom');
|
|
67
|
+
expect(customContent).to.exist;
|
|
68
|
+
expect(customContent.textContent).to.equal('Custom slot content');
|
|
69
|
+
|
|
70
|
+
// Default should not be present
|
|
71
|
+
const defaultContent = root.querySelector('.default');
|
|
72
|
+
expect(defaultContent).to.not.exist;
|
|
73
|
+
} else {
|
|
74
|
+
// In shadow DOM (open), slotted content stays in light DOM
|
|
75
|
+
// and is projected through the slot
|
|
76
|
+
const customContent = el.querySelector('.custom');
|
|
77
|
+
expect(customContent).to.exist;
|
|
78
|
+
expect(customContent.textContent).to.equal('Custom slot content');
|
|
79
|
+
|
|
80
|
+
// Shadow root should have the slot element
|
|
81
|
+
const slot = el.shadowRoot.querySelector('slot[name="content"]');
|
|
82
|
+
expect(slot).to.exist;
|
|
83
|
+
|
|
84
|
+
// Default should be in the shadow root
|
|
85
|
+
const defaultContent = el.shadowRoot.querySelector('.default');
|
|
86
|
+
expect(defaultContent).to.exist;
|
|
87
|
+
}
|
|
88
|
+
} else {
|
|
89
|
+
// For closed shadow, verify element exists and is connected
|
|
90
|
+
expect(el.shadowRoot).to.be.null;
|
|
91
|
+
expect(el.isConnected).to.be.true;
|
|
92
|
+
|
|
93
|
+
// Slotted content should be in the light DOM
|
|
94
|
+
const customContent = el.querySelector('.custom');
|
|
95
|
+
expect(customContent).to.exist;
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it('default slot with default value', function () {
|
|
100
|
+
const name = uniqueName('test-default-slot-default');
|
|
101
|
+
createTemplate(name, '<slot><div class="default">Default content</div></slot>', { shadow: shadow !== 'none' ? shadow : undefined });
|
|
102
|
+
|
|
103
|
+
const el = createElement(name, {
|
|
104
|
+
'data-test-element': '',
|
|
105
|
+
...(shadow !== 'none' ? { shadow } : {})
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// Verify element was created
|
|
109
|
+
expect(el).to.exist;
|
|
110
|
+
|
|
111
|
+
const root = getContentRoot(el, shadow);
|
|
112
|
+
if (shadow !== 'closed') {
|
|
113
|
+
// When no content is provided, default slot content should be used
|
|
114
|
+
const defaultContent = root.querySelector('.default');
|
|
115
|
+
expect(defaultContent).to.exist;
|
|
116
|
+
expect(defaultContent.textContent).to.equal('Default content');
|
|
117
|
+
} else {
|
|
118
|
+
// For closed shadow, verify element exists and is connected
|
|
119
|
+
expect(el.shadowRoot).to.be.null;
|
|
120
|
+
expect(el.isConnected).to.be.true;
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it('default slot with given value', function () {
|
|
125
|
+
const name = uniqueName('test-default-slot-given');
|
|
126
|
+
createTemplate(name, '<slot><div class="default">Default content</div></slot>', { shadow: shadow !== 'none' ? shadow : undefined });
|
|
127
|
+
|
|
128
|
+
const el = createElement(name, {
|
|
129
|
+
'data-test-element': '',
|
|
130
|
+
...(shadow !== 'none' ? { shadow } : {})
|
|
131
|
+
}, '<div class="custom">Custom content</div>');
|
|
132
|
+
|
|
133
|
+
// Verify element was created
|
|
134
|
+
expect(el).to.exist;
|
|
135
|
+
|
|
136
|
+
if (shadow !== 'closed') {
|
|
137
|
+
if (shadow === 'none') {
|
|
138
|
+
// In light DOM (no shadow), slotted content replaces the slot in place
|
|
139
|
+
const root = getContentRoot(el, shadow);
|
|
140
|
+
const customContent = root.querySelector('.custom');
|
|
141
|
+
expect(customContent).to.exist;
|
|
142
|
+
expect(customContent.textContent).to.equal('Custom content');
|
|
143
|
+
|
|
144
|
+
// Default should not be present
|
|
145
|
+
const defaultContent = root.querySelector('.default');
|
|
146
|
+
expect(defaultContent).to.not.exist;
|
|
147
|
+
} else {
|
|
148
|
+
// In shadow DOM (open), slotted content stays in light DOM
|
|
149
|
+
const customContent = el.querySelector('.custom');
|
|
150
|
+
expect(customContent).to.exist;
|
|
151
|
+
expect(customContent.textContent).to.equal('Custom content');
|
|
152
|
+
|
|
153
|
+
// Shadow root should have the slot element
|
|
154
|
+
const slot = el.shadowRoot.querySelector('slot:not([name])');
|
|
155
|
+
expect(slot).to.exist;
|
|
156
|
+
}
|
|
157
|
+
} else {
|
|
158
|
+
// For closed shadow, verify element exists and is connected
|
|
159
|
+
expect(el.shadowRoot).to.be.null;
|
|
160
|
+
expect(el.isConnected).to.be.true;
|
|
161
|
+
|
|
162
|
+
// Slotted content should be in the light DOM
|
|
163
|
+
const customContent = el.querySelector('.custom');
|
|
164
|
+
expect(customContent).to.exist;
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
it('multiple named slots', function () {
|
|
169
|
+
const name = uniqueName('test-multiple-named-slots');
|
|
170
|
+
createTemplate(name,
|
|
171
|
+
'<slot name="header"><div class="default-header">Default Header</div></slot>' +
|
|
172
|
+
'<slot name="body"><div class="default-body">Default Body</div></slot>' +
|
|
173
|
+
'<slot name="footer"><div class="default-footer">Default Footer</div></slot>',
|
|
174
|
+
{ shadow: shadow !== 'none' ? shadow : undefined }
|
|
175
|
+
);
|
|
176
|
+
|
|
177
|
+
const el = createElement(name, {
|
|
178
|
+
'data-test-element': '',
|
|
179
|
+
...(shadow !== 'none' ? { shadow } : {})
|
|
180
|
+
},
|
|
181
|
+
'<div slot="header" class="custom-header">Custom Header</div>' +
|
|
182
|
+
'<div slot="body" class="custom-body">Custom Body</div>'
|
|
183
|
+
);
|
|
184
|
+
|
|
185
|
+
// Verify element was created
|
|
186
|
+
expect(el).to.exist;
|
|
187
|
+
|
|
188
|
+
if (shadow !== 'closed') {
|
|
189
|
+
if (shadow === 'none') {
|
|
190
|
+
// In light DOM, slotted content replaces slots in place
|
|
191
|
+
const root = getContentRoot(el, shadow);
|
|
192
|
+
|
|
193
|
+
const customHeader = root.querySelector('.custom-header');
|
|
194
|
+
expect(customHeader).to.exist;
|
|
195
|
+
expect(customHeader.textContent).to.equal('Custom Header');
|
|
196
|
+
|
|
197
|
+
const customBody = root.querySelector('.custom-body');
|
|
198
|
+
expect(customBody).to.exist;
|
|
199
|
+
expect(customBody.textContent).to.equal('Custom Body');
|
|
200
|
+
|
|
201
|
+
// Footer should still use default (not provided)
|
|
202
|
+
const defaultFooter = root.querySelector('.default-footer');
|
|
203
|
+
expect(defaultFooter).to.exist;
|
|
204
|
+
expect(defaultFooter.textContent).to.equal('Default Footer');
|
|
205
|
+
|
|
206
|
+
// Defaults for header and body should not be present
|
|
207
|
+
expect(root.querySelector('.default-header')).to.not.exist;
|
|
208
|
+
expect(root.querySelector('.default-body')).to.not.exist;
|
|
209
|
+
} else {
|
|
210
|
+
// In shadow DOM (open), slotted content stays in light DOM
|
|
211
|
+
const customHeader = el.querySelector('.custom-header');
|
|
212
|
+
expect(customHeader).to.exist;
|
|
213
|
+
expect(customHeader.textContent).to.equal('Custom Header');
|
|
214
|
+
|
|
215
|
+
const customBody = el.querySelector('.custom-body');
|
|
216
|
+
expect(customBody).to.exist;
|
|
217
|
+
expect(customBody.textContent).to.equal('Custom Body');
|
|
218
|
+
|
|
219
|
+
// Shadow root should have slots
|
|
220
|
+
expect(el.shadowRoot.querySelector('slot[name="header"]')).to.exist;
|
|
221
|
+
expect(el.shadowRoot.querySelector('slot[name="body"]')).to.exist;
|
|
222
|
+
expect(el.shadowRoot.querySelector('slot[name="footer"]')).to.exist;
|
|
223
|
+
|
|
224
|
+
// Default for footer should be in shadow root
|
|
225
|
+
const defaultFooter = el.shadowRoot.querySelector('.default-footer');
|
|
226
|
+
expect(defaultFooter).to.exist;
|
|
227
|
+
}
|
|
228
|
+
} else {
|
|
229
|
+
// For closed shadow, verify element exists and is connected
|
|
230
|
+
expect(el.shadowRoot).to.be.null;
|
|
231
|
+
expect(el.isConnected).to.be.true;
|
|
232
|
+
|
|
233
|
+
// Slotted content should be in light DOM
|
|
234
|
+
expect(el.querySelector('.custom-header')).to.exist;
|
|
235
|
+
expect(el.querySelector('.custom-body')).to.exist;
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
it('multiple default slots', function () {
|
|
240
|
+
const name = uniqueName('test-multiple-default-slots');
|
|
241
|
+
// Multiple default slots is unusual but should work by distributing content
|
|
242
|
+
createTemplate(name,
|
|
243
|
+
'<div class="section1"><slot><span>Default 1</span></slot></div>' +
|
|
244
|
+
'<div class="section2"><slot><span>Default 2</span></slot></div>',
|
|
245
|
+
{ shadow: shadow !== 'none' ? shadow : undefined }
|
|
246
|
+
);
|
|
247
|
+
|
|
248
|
+
const el = createElement(name, {
|
|
249
|
+
'data-test-element': '',
|
|
250
|
+
...(shadow !== 'none' ? { shadow } : {})
|
|
251
|
+
}, '<div class="custom">Custom content</div>');
|
|
252
|
+
|
|
253
|
+
// Verify element was created
|
|
254
|
+
expect(el).to.exist;
|
|
255
|
+
|
|
256
|
+
if (shadow !== 'closed') {
|
|
257
|
+
if (shadow === 'none') {
|
|
258
|
+
// In light DOM, first slot gets replaced with custom content
|
|
259
|
+
const root = getContentRoot(el, shadow);
|
|
260
|
+
const section1 = root.querySelector('.section1');
|
|
261
|
+
expect(section1).to.exist;
|
|
262
|
+
const customInSection1 = section1.querySelector('.custom');
|
|
263
|
+
expect(customInSection1).to.exist;
|
|
264
|
+
|
|
265
|
+
// Second slot gets its default
|
|
266
|
+
const section2 = root.querySelector('.section2');
|
|
267
|
+
expect(section2).to.exist;
|
|
268
|
+
const defaultInSection2 = section2.querySelector('span');
|
|
269
|
+
expect(defaultInSection2).to.exist;
|
|
270
|
+
expect(defaultInSection2.textContent).to.equal('Default 2');
|
|
271
|
+
} else {
|
|
272
|
+
// In shadow DOM (open), slotted content stays in light DOM
|
|
273
|
+
const customContent = el.querySelector('.custom');
|
|
274
|
+
expect(customContent).to.exist;
|
|
275
|
+
expect(customContent.textContent).to.equal('Custom content');
|
|
276
|
+
|
|
277
|
+
// Shadow root should have both sections with slots
|
|
278
|
+
expect(el.shadowRoot.querySelector('.section1')).to.exist;
|
|
279
|
+
expect(el.shadowRoot.querySelector('.section2')).to.exist;
|
|
280
|
+
}
|
|
281
|
+
} else {
|
|
282
|
+
// For closed shadow, verify element exists and is connected
|
|
283
|
+
expect(el.shadowRoot).to.be.null;
|
|
284
|
+
expect(el.isConnected).to.be.true;
|
|
285
|
+
|
|
286
|
+
// Slotted content should be in light DOM
|
|
287
|
+
const customContent = el.querySelector('.custom');
|
|
288
|
+
expect(customContent).to.exist;
|
|
289
|
+
}
|
|
290
|
+
});
|
|
291
|
+
});
|
|
292
|
+
});
|
|
293
|
+
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// Helper to create a template and process it
|
|
2
|
+
export function createTemplate(name, content, options = {}) {
|
|
3
|
+
const template = document.createElement('template');
|
|
4
|
+
template.setAttribute('decue', name);
|
|
5
|
+
if (options.shadow) {
|
|
6
|
+
template.setAttribute('shadow', options.shadow);
|
|
7
|
+
}
|
|
8
|
+
if (options.formAssociated) {
|
|
9
|
+
template.setAttribute('form-associated', '');
|
|
10
|
+
}
|
|
11
|
+
template.innerHTML = content;
|
|
12
|
+
document.body.appendChild(template);
|
|
13
|
+
decue.processTemplate(template);
|
|
14
|
+
return template;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Helper to create and append a custom element
|
|
18
|
+
export function createElement(tagName, attributes = {}, innerHTML = '') {
|
|
19
|
+
const el = document.createElement(tagName);
|
|
20
|
+
for (const [key, value] of Object.entries(attributes)) {
|
|
21
|
+
el.setAttribute(key, value);
|
|
22
|
+
}
|
|
23
|
+
if (innerHTML) {
|
|
24
|
+
el.innerHTML = innerHTML;
|
|
25
|
+
}
|
|
26
|
+
document.body.appendChild(el);
|
|
27
|
+
return el;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Helper to get content root (shadowRoot or the element itself)
|
|
31
|
+
export function getContentRoot(el, shadow) {
|
|
32
|
+
if (shadow === 'none') {
|
|
33
|
+
return el;
|
|
34
|
+
}
|
|
35
|
+
return el.shadowRoot || el;
|
|
36
|
+
}
|
package/tsconfig.json
CHANGED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { playwrightLauncher } from '@web/test-runner-playwright';
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
files: 'test/**/*.test.js',
|
|
5
|
+
nodeResolve: true,
|
|
6
|
+
coverage: true,
|
|
7
|
+
coverageConfig: {
|
|
8
|
+
include: ['src/**/*.js'],
|
|
9
|
+
},
|
|
10
|
+
browserLogs: true,
|
|
11
|
+
browsers: [
|
|
12
|
+
playwrightLauncher({ product: 'chromium' }),
|
|
13
|
+
playwrightLauncher({ product: 'chromium', launchOptions: { channel: 'chrome' } }),
|
|
14
|
+
playwrightLauncher({ product: 'chromium', launchOptions: { channel: 'msedge' } }),
|
|
15
|
+
playwrightLauncher({ product: 'firefox' }),
|
|
16
|
+
playwrightLauncher({ product: 'webkit' }),
|
|
17
|
+
],
|
|
18
|
+
testRunnerHtml: testFramework => `
|
|
19
|
+
<!DOCTYPE html>
|
|
20
|
+
<html>
|
|
21
|
+
<head>
|
|
22
|
+
<meta http-equiv="Content-Security-Policy" content="default-src 'self'" />
|
|
23
|
+
<script src="/src/decue.js"></script>
|
|
24
|
+
</head>
|
|
25
|
+
<body>
|
|
26
|
+
<script type="module" src="${testFramework}"></script>
|
|
27
|
+
</body>
|
|
28
|
+
</html>
|
|
29
|
+
`
|
|
30
|
+
};
|
package/serve.sh
DELETED
package/test/decue-tests.js
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
var assert = chai.assert;
|
|
2
|
-
|
|
3
|
-
describe("decue", function() {
|
|
4
|
-
beforeEach(function () {
|
|
5
|
-
clearWorkArea();
|
|
6
|
-
});
|
|
7
|
-
|
|
8
|
-
['none', 'open', 'closed'].forEach(shadow => {
|
|
9
|
-
describe("shadowmode: " + shadow, function() {
|
|
10
|
-
it('shadowroot', function () {
|
|
11
|
-
make(`<my-element shadow="${shadow}"></my-element>`)
|
|
12
|
-
if (shadow === 'open') {
|
|
13
|
-
assert.isNotNull(document.querySelector('my-element').shadowRoot);
|
|
14
|
-
} else {
|
|
15
|
-
assert.isNull(document.querySelector('my-element').shadowRoot);
|
|
16
|
-
}
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
it('no-attributes', function () {
|
|
20
|
-
make(`<my-element></my-element>`)
|
|
21
|
-
assert.isDefined(document.querySelector('my-element'));
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
it('unknown attribute placeholder is not replaced', function () {
|
|
25
|
-
make(`<my-element></my-element>`)
|
|
26
|
-
assert.equal('Target: {target}', document.querySelector('my-element span').getAttribute('data-target'));
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
it('attribute placeholder is replaced', function () {
|
|
30
|
-
make(`<my-element target="World"></my-element>`)
|
|
31
|
-
assert.equal('Target: World', document.querySelector('my-element span').getAttribute('data-target'));
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
it('attribute with placeholder and functions updates asynchronously', function (done) {
|
|
35
|
-
make(`<my-element target="World"></my-element>`)
|
|
36
|
-
assert.equal('WORLD', document.querySelector('my-element span').getAttribute('data-method'));
|
|
37
|
-
document.querySelector('my-element').setAttribute('target', 'Universe');
|
|
38
|
-
setTimeout(() => {
|
|
39
|
-
assert.equal('UNIVERSE', document.querySelector('my-element span').getAttribute('data-method'));
|
|
40
|
-
done();
|
|
41
|
-
});
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
it('attribute with functions', function () {
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
it('attribute with method', function () {
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
it('text content placeholder is replaced', function () {
|
|
51
|
-
make(`<my-element target="World"></my-element>`)
|
|
52
|
-
assert.equal('Hello World', document.querySelector('my-element span').innerText);
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
it('text content updates synchronously for predefined elements', function () {
|
|
56
|
-
make(`<my-predefined-element target="World"></my-predefined-element>`)
|
|
57
|
-
assert.equal('Hello World', document.querySelector('my-predefined-element span').innerText);
|
|
58
|
-
document.querySelector('my-predefined-element').setAttribute('target', 'Universe');
|
|
59
|
-
assert.equal('Hello Universe', document.querySelector('my-predefined-element span').innerText);
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
it('named slot with default value', function () {
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
it('named slot with given value', function () {
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
it('default slot with default value', function () {
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
it('default slot with given value', function () {
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
it('multiple named slots', function () {
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
it('multiple default slots', function () {
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
it('some form tests...?', function () {
|
|
81
|
-
});
|
|
82
|
-
});
|
|
83
|
-
});
|
|
84
|
-
});
|
package/test/index.html
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
<html lang="en">
|
|
2
|
-
<head>
|
|
3
|
-
<meta charset="utf-8" />
|
|
4
|
-
<title>Mocha Tests</title>
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
-
<link rel="stylesheet" href="../node_modules/mocha/mocha.css" />
|
|
7
|
-
<meta http-equiv="cache-control" content="no-cache, must-revalidate, post-check=0, pre-check=0" />
|
|
8
|
-
<meta http-equiv="cache-control" content="max-age=0" />
|
|
9
|
-
<meta http-equiv="expires" content="0" />
|
|
10
|
-
<meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />
|
|
11
|
-
<meta http-equiv="pragma" content="no-cache" />
|
|
12
|
-
</head>
|
|
13
|
-
<body style="padding:20px;font-family: sans-serif">
|
|
14
|
-
|
|
15
|
-
<h1 style="margin-top: 40px">decue test suite</h1>
|
|
16
|
-
|
|
17
|
-
<h2>Mocha Test Suite</h2>
|
|
18
|
-
<a href="/test/">[ALL]</a>
|
|
19
|
-
|
|
20
|
-
<script src="../node_modules/chai/chai.js"></script>
|
|
21
|
-
<script src="../node_modules/mocha/mocha.js"></script>
|
|
22
|
-
<script class="mocha-init">
|
|
23
|
-
mocha.setup('bdd');
|
|
24
|
-
mocha.checkLeaks();
|
|
25
|
-
</script>
|
|
26
|
-
|
|
27
|
-
<script src="util/util.js"></script>
|
|
28
|
-
|
|
29
|
-
<script>
|
|
30
|
-
function toLower(str) {
|
|
31
|
-
str.toLowerCase();
|
|
32
|
-
}
|
|
33
|
-
</script>
|
|
34
|
-
|
|
35
|
-
<script src="../src/decue.js" elements="my-predefined-element my-predefined-element-with-attributes[target]"></script>
|
|
36
|
-
<script src="decue-tests.js"></script>
|
|
37
|
-
|
|
38
|
-
<div id="mocha"></div>
|
|
39
|
-
|
|
40
|
-
<script class="mocha-exec">
|
|
41
|
-
mocha.run();
|
|
42
|
-
</script>
|
|
43
|
-
<em>Work Area</em>
|
|
44
|
-
<hr/>
|
|
45
|
-
<div id="work-area">
|
|
46
|
-
</div>
|
|
47
|
-
|
|
48
|
-
<template decue="nested-element">
|
|
49
|
-
nested
|
|
50
|
-
</template>
|
|
51
|
-
<template decue="my-element">
|
|
52
|
-
<span data-target="Target: {target}" data-method="{target|.toUpperCase}" data-function="{target|toLower}" data-piped="{target|.toUpperCase|toLower}">Hello {target}</span>
|
|
53
|
-
<slot name="slot1">slot1</slot>
|
|
54
|
-
<slot>default slot</slot>
|
|
55
|
-
<nested-element></nested-element>
|
|
56
|
-
</template>
|
|
57
|
-
<template decue="my-predefined-element">
|
|
58
|
-
<span>Hello {target}</span>
|
|
59
|
-
</template>
|
|
60
|
-
<template decue="my-predefined-element-with-attributes">
|
|
61
|
-
<span>Hello {target}</span>
|
|
62
|
-
</template>
|
|
63
|
-
|
|
64
|
-
</body>
|
|
65
|
-
</html>
|
package/test/util/util.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
function make(htmlStr) {
|
|
3
|
-
var range = document.createRange();
|
|
4
|
-
var fragment = range.createContextualFragment(htmlStr);
|
|
5
|
-
var wa = document.getElementById("work-area");
|
|
6
|
-
var child = null;
|
|
7
|
-
var children = fragment.children || fragment.childNodes; // IE
|
|
8
|
-
while(children.length > 0) {
|
|
9
|
-
child = children[0];
|
|
10
|
-
wa.appendChild(child);
|
|
11
|
-
}
|
|
12
|
-
return child;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
function clearWorkArea() {
|
|
16
|
-
document.getElementById("work-area").innerHTML = "";
|
|
17
|
-
}
|