kempo 1.0.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/.gitattributes +2 -0
- package/LICENSE +21 -0
- package/README.md +2 -0
- package/dist/components/Card.js +1 -0
- package/dist/components/CodeEditor.js +1 -0
- package/dist/components/Component.js +1 -0
- package/dist/components/Dialog.js +1 -0
- package/dist/components/FocusCapture.js +1 -0
- package/dist/components/Icon.js +1 -0
- package/dist/components/Import.js +1 -0
- package/dist/components/LazyComponent.js +1 -0
- package/dist/components/ReactiveComponent.js +1 -0
- package/dist/components/ReactiveLazyComponent.js +1 -0
- package/dist/components/Resize.js +1 -0
- package/dist/components/Search.js +1 -0
- package/dist/components/ShowMore.js +1 -0
- package/dist/components/SideMenu.js +1 -0
- package/dist/components/Split.js +1 -0
- package/dist/components/Tabs.js +1 -0
- package/dist/components/ThemeSwitcher.js +1 -0
- package/dist/components/Timestamp.js +1 -0
- package/dist/components/WebSnippetEditor.js +1 -0
- package/dist/index.js +1 -0
- package/dist/kempo-hljs.css +1 -0
- package/dist/kempo-styles.css +1 -0
- package/dist/kempo-vars.css +1 -0
- package/dist/kempo.css +1 -0
- package/dist/kempo.js +1 -0
- package/dist/utils/cli.js +1 -0
- package/dist/utils/cookie.js +1 -0
- package/dist/utils/debounce.js +1 -0
- package/dist/utils/drag.js +1 -0
- package/dist/utils/element.js +1 -0
- package/dist/utils/formatTimestamp.js +1 -0
- package/dist/utils/fuzzyMatch.js +1 -0
- package/dist/utils/getPreferredTheme.js +1 -0
- package/dist/utils/loadCss.js +1 -0
- package/dist/utils/loadScript.js +1 -0
- package/dist/utils/object.js +1 -0
- package/dist/utils/string.js +1 -0
- package/dist/utils/toFunction.js +1 -0
- package/dist/utils/type.js +1 -0
- package/dist/utils/waitFrames.js +1 -0
- package/docs/components/_template.html +22 -0
- package/docs/components/card.html +35 -0
- package/docs/components/codeeditor.html +29 -0
- package/docs/components/component.html +88 -0
- package/docs/components/dialog.html +89 -0
- package/docs/components/icon.html +73 -0
- package/docs/components/import.html +34 -0
- package/docs/components/lazycomponent.html +50 -0
- package/docs/components/resize.html +107 -0
- package/docs/components/show-more.html +92 -0
- package/docs/components/sidemenu.html +97 -0
- package/docs/components/split.html +70 -0
- package/docs/components/tabs.html +33 -0
- package/docs/components/websnippeteditor.html +42 -0
- package/docs/index.html +17 -0
- package/docs/kempo/components/Card.js +1 -0
- package/docs/kempo/components/CodeEditor.js +1 -0
- package/docs/kempo/components/Collapse.js +1 -0
- package/docs/kempo/components/Component.js +1 -0
- package/docs/kempo/components/Dialog.js +1 -0
- package/docs/kempo/components/FocusCapture.js +1 -0
- package/docs/kempo/components/Icon.js +1 -0
- package/docs/kempo/components/Import.js +1 -0
- package/docs/kempo/components/LazyComponent.js +1 -0
- package/docs/kempo/components/ReactiveComponent.js +1 -0
- package/docs/kempo/components/ReactiveLazyComponent.js +1 -0
- package/docs/kempo/components/Resize.js +1 -0
- package/docs/kempo/components/Search.js +1 -0
- package/docs/kempo/components/ShowMore.js +1 -0
- package/docs/kempo/components/SideMenu.js +1 -0
- package/docs/kempo/components/Split.js +1 -0
- package/docs/kempo/components/Tabs.js +1 -0
- package/docs/kempo/components/ThemeSwitcher.js +1 -0
- package/docs/kempo/components/Timestamp.js +1 -0
- package/docs/kempo/components/WebSnippetEditor.js +1 -0
- package/docs/kempo/icons/arrow-down-double.svg +1 -0
- package/docs/kempo/icons/arrow-up-double.svg +1 -0
- package/docs/kempo/icons/close.svg +2 -0
- package/docs/kempo/icons/compare.svg +1 -0
- package/docs/kempo/icons/dark-mode.svg +1 -0
- package/docs/kempo/icons/delete.svg +1 -0
- package/docs/kempo/icons/filter-off.svg +1 -0
- package/docs/kempo/icons/filter.svg +1 -0
- package/docs/kempo/icons/light-mode.svg +1 -0
- package/docs/kempo/icons/menu.svg +1 -0
- package/docs/kempo/icons/pause.svg +1 -0
- package/docs/kempo/icons/play.svg +1 -0
- package/docs/kempo/icons/search.svg +1 -0
- package/docs/kempo/icons/settings.svg +1 -0
- package/docs/kempo/icons/storage.svg +1 -0
- package/docs/kempo/icons/trash-x.svg +1 -0
- package/docs/kempo/index.js +1 -0
- package/docs/kempo/kempo-hljs.css +1 -0
- package/docs/kempo/kempo-styles.css +1 -0
- package/docs/kempo/kempo-vars.css +1 -0
- package/docs/kempo/kempo.css +1 -0
- package/docs/kempo/kempo.js +1 -0
- package/docs/kempo/utils/cli.js +1 -0
- package/docs/kempo/utils/cookie.js +1 -0
- package/docs/kempo/utils/debounce.js +1 -0
- package/docs/kempo/utils/drag.js +1 -0
- package/docs/kempo/utils/element.js +1 -0
- package/docs/kempo/utils/formatTimestamp.js +1 -0
- package/docs/kempo/utils/fuzzyMatch.js +1 -0
- package/docs/kempo/utils/getPreferredTheme.js +1 -0
- package/docs/kempo/utils/loadCss.js +1 -0
- package/docs/kempo/utils/loadScript.js +1 -0
- package/docs/kempo/utils/object.js +1 -0
- package/docs/kempo/utils/string.js +1 -0
- package/docs/kempo/utils/toFunction.js +1 -0
- package/docs/kempo/utils/type.js +1 -0
- package/docs/kempo/utils/waitFrames.js +1 -0
- package/docs/nav-1.inc.html +66 -0
- package/docs/nav.inc.html +66 -0
- package/docs/search.json +94 -0
- package/docs/styles/_template.html +22 -0
- package/docs/styles/borders-spacing.html +193 -0
- package/docs/styles/buttons.html +113 -0
- package/docs/styles/colors.html +65 -0
- package/docs/styles/displays-layouts.html +156 -0
- package/docs/styles/embed-1.html +35 -0
- package/docs/styles/inputs.html +89 -0
- package/docs/styles/tables.html +143 -0
- package/docs/styles/typography.html +116 -0
- package/icons/arrow-down-double.svg +1 -0
- package/icons/arrow-up-double.svg +1 -0
- package/icons/close.svg +2 -0
- package/icons/compare.svg +1 -0
- package/icons/dark-mode.svg +1 -0
- package/icons/delete.svg +1 -0
- package/icons/filter-off.svg +1 -0
- package/icons/filter.svg +1 -0
- package/icons/light-mode.svg +1 -0
- package/icons/menu.svg +1 -0
- package/icons/pause.svg +1 -0
- package/icons/play.svg +1 -0
- package/icons/search.svg +1 -0
- package/icons/settings.svg +1 -0
- package/icons/storage.svg +1 -0
- package/icons/trash-x.svg +1 -0
- package/kempo/components/Card.js +65 -0
- package/kempo/components/CodeEditor.js +141 -0
- package/kempo/components/Component.js +109 -0
- package/kempo/components/Dialog.js +277 -0
- package/kempo/components/FocusCapture.js +30 -0
- package/kempo/components/Icon.js +60 -0
- package/kempo/components/Import.js +40 -0
- package/kempo/components/LazyComponent.js +40 -0
- package/kempo/components/ReactiveComponent.js +11 -0
- package/kempo/components/ReactiveLazyComponent.js +11 -0
- package/kempo/components/Resize.js +168 -0
- package/kempo/components/Search.js +136 -0
- package/kempo/components/ShowMore.js +82 -0
- package/kempo/components/SideMenu.js +156 -0
- package/kempo/components/Split.js +133 -0
- package/kempo/components/Tabs.js +254 -0
- package/kempo/components/ThemeSwitcher.js +77 -0
- package/kempo/components/Timestamp.js +25 -0
- package/kempo/components/WebSnippetEditor.js +159 -0
- package/kempo/kempo-hljs.css +145 -0
- package/kempo/kempo-styles.css +893 -0
- package/kempo/kempo-vars.css +154 -0
- package/kempo/kempo.js +48 -0
- package/kempo/utils/cli.js +54 -0
- package/kempo/utils/cookie.js +16 -0
- package/kempo/utils/debounce.js +9 -0
- package/kempo/utils/drag.js +74 -0
- package/kempo/utils/element.js +69 -0
- package/kempo/utils/formatTimestamp.js +11 -0
- package/kempo/utils/fuzzyMatch.js +55 -0
- package/kempo/utils/getPreferredTheme.js +1 -0
- package/kempo/utils/loadCss.js +10 -0
- package/kempo/utils/loadScript.js +10 -0
- package/kempo/utils/object.js +177 -0
- package/kempo/utils/string.js +54 -0
- package/kempo/utils/toFunction.js +24 -0
- package/kempo/utils/type.js +8 -0
- package/kempo/utils/waitFrames.js +17 -0
- package/package.json +33 -0
- package/scripts/build.js +131 -0
- package/scripts/docs.js +14 -0
- package/test/components/SuiteList.js +26 -0
- package/test/components/Test.js +357 -0
- package/test/index.html +49 -0
- package/test/index.js +25 -0
- package/test/suite.html +45 -0
- package/test/suites.inc.html +4 -0
- package/test/tests/components/Component.test.js +138 -0
- package/test/tests/utils/cli.test.js +113 -0
- package/test/tests/utils/cookie.test.js +87 -0
- package/test/tests/utils/debounce.test.js +71 -0
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
import Component from '../kempo/components/Component.js';
|
|
2
|
+
|
|
3
|
+
const html = str => new DOMParser().parseFromString(str, 'text/html').body.childNodes[0];
|
|
4
|
+
const runClickHandler = Symbol('runClickHandler'),
|
|
5
|
+
toggleLogsClickHandler = Symbol('toggleLogsClickHandler'),
|
|
6
|
+
testUpdatedHandler = Symbol('testUpdatedHandler');
|
|
7
|
+
|
|
8
|
+
export default class TestSuite extends Component {
|
|
9
|
+
constructor(){
|
|
10
|
+
super();
|
|
11
|
+
|
|
12
|
+
this[runClickHandler] = () => {
|
|
13
|
+
this.runAll();
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
this.registerAttribute('name', '');
|
|
17
|
+
}
|
|
18
|
+
async render(force){
|
|
19
|
+
if(await super.render(force)){
|
|
20
|
+
await this.loadTests();
|
|
21
|
+
this.shadowRoot.getElementById('runAll').addEventListener('click', this[runClickHandler]);
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
disconnectedCallback(){
|
|
27
|
+
if(this.rendered){
|
|
28
|
+
this.shadowRoot.getElementById('runAll').removeEventListener('click', this[runClickHandler]);
|
|
29
|
+
}
|
|
30
|
+
super.disconnectedCallback();
|
|
31
|
+
}
|
|
32
|
+
async loadTests(){
|
|
33
|
+
const {
|
|
34
|
+
name,
|
|
35
|
+
description,
|
|
36
|
+
tests
|
|
37
|
+
} = await import(`../tests/${this.name}.test.js`);
|
|
38
|
+
const testSuiteLink = `/suite.html?name=${this.name}`;
|
|
39
|
+
const currentPath = location.pathname + location.search;
|
|
40
|
+
if(testSuiteLink === currentPath){
|
|
41
|
+
this.shadowRoot.getElementById('name').innerHTML = name;
|
|
42
|
+
} else {
|
|
43
|
+
this.shadowRoot.getElementById('name').innerHTML = `<a href="${testSuiteLink}">${name}</a>`;
|
|
44
|
+
}
|
|
45
|
+
this.shadowRoot.getElementById('description').innerHTML = description;
|
|
46
|
+
tests.forEach( ({name, description, test}) => {
|
|
47
|
+
this.appendChild(new Test(name, description, test));
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
async runAll(){
|
|
51
|
+
const $tests = [...this.querySelectorAll('k-test')];
|
|
52
|
+
for(const $test of $tests){
|
|
53
|
+
await $test.run();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
get shadowTemplate(){
|
|
57
|
+
return /*html*/`
|
|
58
|
+
<h3 id="name"></h3>
|
|
59
|
+
<p id="description"></p>
|
|
60
|
+
<button
|
|
61
|
+
id="runAll"
|
|
62
|
+
class="secondary mb"
|
|
63
|
+
>
|
|
64
|
+
Run All Tests in this Suite
|
|
65
|
+
</button>
|
|
66
|
+
<slot name="test"></slot>
|
|
67
|
+
${super.shadowTemplate}
|
|
68
|
+
`;
|
|
69
|
+
}
|
|
70
|
+
get shadowStyles(){
|
|
71
|
+
return /*css*/`
|
|
72
|
+
${super.shadowStyles}
|
|
73
|
+
:host {
|
|
74
|
+
display: block;
|
|
75
|
+
border: 1px solid var(--c_border);
|
|
76
|
+
border-radius: var(--radius);
|
|
77
|
+
padding: var(--spacer);
|
|
78
|
+
margin-bottom: var(--spacer);
|
|
79
|
+
}
|
|
80
|
+
`;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
window.customElements.define('k-test-suite', TestSuite);
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class Test extends Component {
|
|
87
|
+
constructor(name, description, test){
|
|
88
|
+
super();
|
|
89
|
+
|
|
90
|
+
this[runClickHandler] = () => this.run();
|
|
91
|
+
this[toggleLogsClickHandler] = () => {
|
|
92
|
+
this.showLogs = !this.showLogs;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
this.registerAttribute('status', 'Not Ran');
|
|
96
|
+
this.registerAttribute('name', name);
|
|
97
|
+
this.registerAttribute('description', description);
|
|
98
|
+
this.registerAttribute('showLogs', false);
|
|
99
|
+
this.registerProp('test', test);
|
|
100
|
+
this.registerProp('logs', []);
|
|
101
|
+
}
|
|
102
|
+
async render(force){
|
|
103
|
+
if(super.render(force)){
|
|
104
|
+
this.shadowRoot.getElementById('name').innerHTML = this.name;
|
|
105
|
+
this.shadowRoot.getElementById('description').innerHTML = this.description;
|
|
106
|
+
this.shadowRoot.getElementById('run').addEventListener('click', this[runClickHandler]);
|
|
107
|
+
this.shadowRoot.getElementById('toggleLogs').addEventListener('click', this[toggleLogsClickHandler]);
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
connectedCallback(){
|
|
113
|
+
super.connectedCallback();
|
|
114
|
+
this.dispatchEvent(new CustomEvent('testadded', {
|
|
115
|
+
bubbles: true,
|
|
116
|
+
test: this
|
|
117
|
+
}));
|
|
118
|
+
}
|
|
119
|
+
disconnectedCallback(){
|
|
120
|
+
super.disconnectedCallback();
|
|
121
|
+
this.shadowRoot.getElementById('run').removeEventListener('click', this[runClickHandler]);
|
|
122
|
+
this.shadowRoot.getElementById('toggleLogs').removeEventListener('click', this[toggleLogsClickHandler]);
|
|
123
|
+
}
|
|
124
|
+
log(...args){
|
|
125
|
+
let type = 'log',
|
|
126
|
+
messages = [...args];
|
|
127
|
+
if(['log', 'error', 'warning', 'success'].includes(args[0])){
|
|
128
|
+
type = args[0];
|
|
129
|
+
messages = [...args].slice(1);
|
|
130
|
+
}
|
|
131
|
+
this.logs.push({ type, messages });
|
|
132
|
+
if(this.rendered){
|
|
133
|
+
this.shadowRoot.getElementById('logs').appendChild(html(/*html*/`
|
|
134
|
+
<div class="log log-${type}">${
|
|
135
|
+
messages.map(message => /*html*/`<div class="log-message">${message}</div>`).join('')
|
|
136
|
+
}</div>
|
|
137
|
+
`));
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
logError(...messages){
|
|
141
|
+
this.log('error', messages);
|
|
142
|
+
}
|
|
143
|
+
logWarning(...messages){
|
|
144
|
+
this.log('warning', messages);
|
|
145
|
+
}
|
|
146
|
+
logSuccess(...messages){
|
|
147
|
+
this.log('success', messages);
|
|
148
|
+
}
|
|
149
|
+
renderLogs(){
|
|
150
|
+
return this.logs.reverse().map( ({type, messages}) => /*html*/`
|
|
151
|
+
<div class="log log-${type}">${
|
|
152
|
+
messages.map(message => /*html*/`<div class="log-message">${message}</div>`).join('')
|
|
153
|
+
}</div>
|
|
154
|
+
`).join('');
|
|
155
|
+
}
|
|
156
|
+
async run(){
|
|
157
|
+
if(this.status !== 'Not Ran') this.log('<br />-----<br /><br />');
|
|
158
|
+
this.log('Starting Test');
|
|
159
|
+
const pass = (...messages) => {
|
|
160
|
+
const msg = messages.length?messages.join('<br />'):'No message';
|
|
161
|
+
this.log(`<div class='log-success'>Passed: ${msg}</div>`);
|
|
162
|
+
this.status = 'Passed';
|
|
163
|
+
this.shadowRoot.getElementById('status').innerText = this.status;
|
|
164
|
+
this.dispatchEvent(new CustomEvent('testrun', {
|
|
165
|
+
detail: {
|
|
166
|
+
test: this,
|
|
167
|
+
status: this.status,
|
|
168
|
+
passed: true
|
|
169
|
+
},
|
|
170
|
+
bubbles: true
|
|
171
|
+
}));
|
|
172
|
+
}
|
|
173
|
+
const fail = (...messages) => {
|
|
174
|
+
const msg = messages.length?messages.join('<br />'):'No Message';
|
|
175
|
+
this.log(`<div class='log-error'>Failed: ${msg}</div>`);
|
|
176
|
+
this.status = 'Failed';
|
|
177
|
+
this.shadowRoot.getElementById('status').innerText = this.status;
|
|
178
|
+
this.dispatchEvent(new CustomEvent('testrun', {
|
|
179
|
+
detail: {
|
|
180
|
+
test: this,
|
|
181
|
+
status: this.status,
|
|
182
|
+
passed: false
|
|
183
|
+
},
|
|
184
|
+
bubbles: true
|
|
185
|
+
}));
|
|
186
|
+
}
|
|
187
|
+
await this.test({
|
|
188
|
+
pass,
|
|
189
|
+
fail,
|
|
190
|
+
log: this.log.bind(this),
|
|
191
|
+
logError: this.logError.bind(this),
|
|
192
|
+
logWarning: this.logWarning.bind(this),
|
|
193
|
+
logSuccess: this.logSuccess.bind(this)
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
get shadowTemplate(){
|
|
198
|
+
return /*html*/`
|
|
199
|
+
${super.shadowTemplate}
|
|
200
|
+
<h5>
|
|
201
|
+
<span id="name"></span>
|
|
202
|
+
<small>(
|
|
203
|
+
<span id="status">
|
|
204
|
+
${this.status}
|
|
205
|
+
</span>
|
|
206
|
+
)</small>
|
|
207
|
+
</h5>
|
|
208
|
+
<p id="description"></p>
|
|
209
|
+
<button
|
|
210
|
+
id="run"
|
|
211
|
+
class="d-b mb"
|
|
212
|
+
>Run Test</button>
|
|
213
|
+
<button
|
|
214
|
+
id="toggleLogs"
|
|
215
|
+
class="link"
|
|
216
|
+
>
|
|
217
|
+
<span class="show-logs-true">Hide</span>
|
|
218
|
+
<span class="show-logs-false">Show</span>
|
|
219
|
+
Logs
|
|
220
|
+
</button>
|
|
221
|
+
<pre class="show-logs-true"><code id="logs"></code></pre>
|
|
222
|
+
`;
|
|
223
|
+
}
|
|
224
|
+
get shadowStyles(){
|
|
225
|
+
return /*css*/`
|
|
226
|
+
${super.shadowStyles}
|
|
227
|
+
:host {
|
|
228
|
+
display: block;
|
|
229
|
+
border: 1px solid var(--c_border);
|
|
230
|
+
border-radius: var(--radius);
|
|
231
|
+
margin-bottom: var(--spacer);
|
|
232
|
+
padding: var(--spacer);
|
|
233
|
+
}
|
|
234
|
+
:host(:not([show-logs="true"])) .show-logs-true,
|
|
235
|
+
:host([show-logs="true"]) .show-logs-false {
|
|
236
|
+
display: none;
|
|
237
|
+
}
|
|
238
|
+
#logs {
|
|
239
|
+
min-height: 6rem;
|
|
240
|
+
max-height: 36rem;
|
|
241
|
+
resize: vertical;
|
|
242
|
+
}
|
|
243
|
+
:host([status="Passed"]) h5,
|
|
244
|
+
.log-success {
|
|
245
|
+
color: var(--tc_success);
|
|
246
|
+
}
|
|
247
|
+
:host([status="Failed"]) h5,
|
|
248
|
+
.log-error {
|
|
249
|
+
color: var(--tc_danger);
|
|
250
|
+
}
|
|
251
|
+
.log-warning {
|
|
252
|
+
color: var(--tc_warning);
|
|
253
|
+
}
|
|
254
|
+
.log-error .log-message::before {
|
|
255
|
+
content: 'Error: ';
|
|
256
|
+
}
|
|
257
|
+
.log-warning .log-message::before {
|
|
258
|
+
content: 'Warning: ';
|
|
259
|
+
}
|
|
260
|
+
`;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
window.customElements.define('k-test', Test);
|
|
264
|
+
|
|
265
|
+
class TestSummary extends Component {
|
|
266
|
+
constructor(){
|
|
267
|
+
super();
|
|
268
|
+
|
|
269
|
+
this[testUpdatedHandler] = () => {
|
|
270
|
+
this.update();
|
|
271
|
+
}
|
|
272
|
+
this[runClickHandler] = () => {
|
|
273
|
+
this.runAll();
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
this.registerAttributes({
|
|
277
|
+
passed: 0,
|
|
278
|
+
failed: 0,
|
|
279
|
+
notRan: 0
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
connectedCallback(){
|
|
283
|
+
super.connectedCallback();
|
|
284
|
+
this.update();
|
|
285
|
+
window.addEventListener('testadded', this[testUpdatedHandler]);
|
|
286
|
+
window.addEventListener('testrun', this[testUpdatedHandler]);
|
|
287
|
+
}
|
|
288
|
+
disconnectedCallback(){
|
|
289
|
+
window.removeEventListener('testadded', this[testUpdatedHandler]);
|
|
290
|
+
window.removeEventListener('testrun', this[testUpdatedHandler]);
|
|
291
|
+
if(this.rendered){
|
|
292
|
+
this.shadowRoot.getElementById('runAll').removeEventListener('click', this[runClickHandler]);
|
|
293
|
+
}
|
|
294
|
+
super.disconnectedCallback();
|
|
295
|
+
}
|
|
296
|
+
async render(force){
|
|
297
|
+
if(super.render(force)){
|
|
298
|
+
this.shadowRoot.getElementById('runAll').addEventListener('click', this[runClickHandler]);
|
|
299
|
+
return true;
|
|
300
|
+
}
|
|
301
|
+
return false;
|
|
302
|
+
}
|
|
303
|
+
update(){
|
|
304
|
+
let notRan = 0,
|
|
305
|
+
failed = 0,
|
|
306
|
+
passed = 0;
|
|
307
|
+
const $tests = [...document.querySelectorAll('k-test')];
|
|
308
|
+
$tests.forEach( $test => {
|
|
309
|
+
if($test.status === 'Passed'){
|
|
310
|
+
passed++;
|
|
311
|
+
} else if($test.status === 'Failed'){
|
|
312
|
+
failed++;
|
|
313
|
+
} else {
|
|
314
|
+
notRan++;
|
|
315
|
+
}
|
|
316
|
+
});
|
|
317
|
+
this.passed = passed;
|
|
318
|
+
this.failed = failed;
|
|
319
|
+
this.notRan = notRan;
|
|
320
|
+
if(this.rendered){
|
|
321
|
+
this.shadowRoot.getElementById('notRan').innerText = this.notRan;
|
|
322
|
+
this.shadowRoot.getElementById('passed').innerText = this.passed;
|
|
323
|
+
this.shadowRoot.getElementById('failed').innerText = this.failed;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
async runAll(){
|
|
327
|
+
const $tests = [...document.querySelectorAll('k-test')];
|
|
328
|
+
for(const $test of $tests){
|
|
329
|
+
await $test.run();
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
get shadowTemplate(){
|
|
333
|
+
return /*html*/`
|
|
334
|
+
<h3>Test Summary</h3>
|
|
335
|
+
<button
|
|
336
|
+
id="runAll"
|
|
337
|
+
class="primary mb"
|
|
338
|
+
>Run All Tests</button>
|
|
339
|
+
<p>Not Ran: <span id="notRan"></span></p>
|
|
340
|
+
<p>Passed: <span id="passed"></span></p>
|
|
341
|
+
<p>Failed: <span id="failed"></span></p>
|
|
342
|
+
`;
|
|
343
|
+
}
|
|
344
|
+
get shadowStyles(){
|
|
345
|
+
return /*css*/`
|
|
346
|
+
${super.shadowStyles}
|
|
347
|
+
:host {
|
|
348
|
+
display: block;
|
|
349
|
+
border: 1px solid var(--c_border);
|
|
350
|
+
border-radius: var(--radius);
|
|
351
|
+
padding: var(--spacer) var(--spacer) 0;
|
|
352
|
+
margin-bottom: var(--spacer);
|
|
353
|
+
}
|
|
354
|
+
`;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
window.customElements.define('k-test-summary', TestSummary);
|
package/test/index.html
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Tests</title>
|
|
7
|
+
<link rel="stylesheet" href="../kempo/kempo-vars.css" /><link rel="stylesheet" href="../kempo/kempo-styles.css" />
|
|
8
|
+
<style>
|
|
9
|
+
#test {
|
|
10
|
+
position: fixed;
|
|
11
|
+
top: 0;
|
|
12
|
+
right: 0;
|
|
13
|
+
min-width: 16px;
|
|
14
|
+
max-width: 640px;
|
|
15
|
+
min-height: 16px;
|
|
16
|
+
max-height: 640px;
|
|
17
|
+
opacity: 0.05;
|
|
18
|
+
pointer-events: none;
|
|
19
|
+
}
|
|
20
|
+
:root {
|
|
21
|
+
--container_width: 130rem;
|
|
22
|
+
}
|
|
23
|
+
</style>
|
|
24
|
+
</head>
|
|
25
|
+
<body>
|
|
26
|
+
<main>
|
|
27
|
+
<div class="row -mx">
|
|
28
|
+
<div class="col d-span-3 t-span-4 m-span-12 p">
|
|
29
|
+
<k-import src="/suites.inc.html"></k-import>
|
|
30
|
+
</div>
|
|
31
|
+
<div class="col d-span-9 t-span-8 m-span-12 p">
|
|
32
|
+
<div id="test"></div>
|
|
33
|
+
<h1>Kempo Tests</h1>
|
|
34
|
+
<k-test-summary></k-test-summary>
|
|
35
|
+
|
|
36
|
+
<h3>Components</h3>
|
|
37
|
+
<k-test-suite name="components/Component"></k-test-suite>
|
|
38
|
+
|
|
39
|
+
<h3>Utilities</h3>
|
|
40
|
+
<k-test-suite name="utils/cookie"></k-test-suite>
|
|
41
|
+
<k-test-suite name="utils/debounce"></k-test-suite>
|
|
42
|
+
</div>
|
|
43
|
+
</div>
|
|
44
|
+
</main>
|
|
45
|
+
<script src="/kempo/kempo.js" type="module"></script>
|
|
46
|
+
<script src="/components/Test.js" type="module"></script>
|
|
47
|
+
<script src="/components/SuiteList.js" type="module"></script>
|
|
48
|
+
</body>
|
|
49
|
+
</html>
|
package/test/index.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import express from 'express';
|
|
2
|
+
import fs from 'fs/promises';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import cli from '../kempo/utils/cli.js';
|
|
5
|
+
|
|
6
|
+
const {
|
|
7
|
+
port = 8084
|
|
8
|
+
} = cli();
|
|
9
|
+
|
|
10
|
+
const app = express();
|
|
11
|
+
|
|
12
|
+
app.use(express.static('test'));
|
|
13
|
+
app.use('/kempo', express.static('kempo'));
|
|
14
|
+
app.get('/api/tests', async (_, res) => {
|
|
15
|
+
const tests = {};
|
|
16
|
+
const categories = await fs.readdir('./test/tests/');
|
|
17
|
+
for(let i = 0; i < categories.length; i++){
|
|
18
|
+
tests[categories[i]] = (await fs.readdir(`./test/tests/${categories[i]}/`)).map( t => t.slice(0, t.length - 8));
|
|
19
|
+
}
|
|
20
|
+
res.json(tests);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
app.listen(port, () => {
|
|
24
|
+
console.log(`Tests Running on: http://localhost:${port}`);
|
|
25
|
+
});
|
package/test/suite.html
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Tests</title>
|
|
7
|
+
<link rel="stylesheet" href="../kempo/kempo-vars.css" /><link rel="stylesheet" href="../kempo/kempo-styles.css" />
|
|
8
|
+
<style>
|
|
9
|
+
#test {
|
|
10
|
+
position: fixed;
|
|
11
|
+
top: 0;
|
|
12
|
+
right: 0;
|
|
13
|
+
min-width: 16px;
|
|
14
|
+
max-width: 640px;
|
|
15
|
+
min-height: 16px;
|
|
16
|
+
max-height: 640px;
|
|
17
|
+
opacity: 0.05;
|
|
18
|
+
pointer-events: none;
|
|
19
|
+
}
|
|
20
|
+
:root {
|
|
21
|
+
--container_width: 130rem;
|
|
22
|
+
}
|
|
23
|
+
</style>
|
|
24
|
+
</head>
|
|
25
|
+
<body>
|
|
26
|
+
<main>
|
|
27
|
+
<div class="row -mx">
|
|
28
|
+
<div class="col d-span-3 t-span-4 m-span-12 p">
|
|
29
|
+
<a href="/"><h3>Tests Home</h3></a>
|
|
30
|
+
<k-import src="/suites.inc.html"></k-import>
|
|
31
|
+
</div>
|
|
32
|
+
<div class="col d-span-9 t-span-8 m-span-12 p">
|
|
33
|
+
<div id="test"></div>
|
|
34
|
+
<div id="suite"></div>
|
|
35
|
+
</div>
|
|
36
|
+
</div>
|
|
37
|
+
</main>
|
|
38
|
+
<script src="/kempo/kempo.js" type="module"></script>
|
|
39
|
+
<script src="/components/Test.js" type="module"></script>
|
|
40
|
+
<script src="/components/SuiteList.js" type="module"></script>
|
|
41
|
+
<script>
|
|
42
|
+
document.getElementById('suite').innerHTML = `<k-test-suite name="${new URLSearchParams(location.search).get('name')}"></k-test-suite>`;
|
|
43
|
+
</script>
|
|
44
|
+
</body>
|
|
45
|
+
</html>
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import Component from '../../../kempo/components/Component.js';
|
|
2
|
+
|
|
3
|
+
const raf = async () => new Promise(r=>requestAnimationFrame(r));
|
|
4
|
+
|
|
5
|
+
export const name = 'Component Test';
|
|
6
|
+
export const description = 'A set of tests for the core Component class';
|
|
7
|
+
export const tests = [
|
|
8
|
+
{
|
|
9
|
+
name: 'Can be instatiated',
|
|
10
|
+
description: 'An instance of the class can be created',
|
|
11
|
+
test: ({
|
|
12
|
+
pass,
|
|
13
|
+
fail,
|
|
14
|
+
log
|
|
15
|
+
}) => {
|
|
16
|
+
log('Creating an instance of Component');
|
|
17
|
+
try {
|
|
18
|
+
new Component();
|
|
19
|
+
pass('An instance of Component was created');
|
|
20
|
+
} catch (error) {
|
|
21
|
+
fail(error.message);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
name: 'Is Initiated when created via the tag',
|
|
27
|
+
description: 'When a <code><k-component></code> created, is it an instance of <code>Component</code>?',
|
|
28
|
+
test: ({
|
|
29
|
+
pass,
|
|
30
|
+
fail,
|
|
31
|
+
log
|
|
32
|
+
}) => {
|
|
33
|
+
log('Creating k-component');
|
|
34
|
+
const $comp = document.createElement('k-component');
|
|
35
|
+
log('Testing if result is an instanceof of Component');
|
|
36
|
+
if($comp instanceof Component){
|
|
37
|
+
pass('The result is an instance of Component');
|
|
38
|
+
} else {
|
|
39
|
+
fail('The result is not an instance of Component');
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
name: "Has all required properties",
|
|
45
|
+
description: "Has all required properties and they are the correct type",
|
|
46
|
+
test: ({
|
|
47
|
+
pass,
|
|
48
|
+
fail,
|
|
49
|
+
log
|
|
50
|
+
}) => {
|
|
51
|
+
log('Creating an instance of Component');
|
|
52
|
+
const $comp = new Component();
|
|
53
|
+
const requiredProps = {
|
|
54
|
+
shadowTemplate: 'string',
|
|
55
|
+
shadowStyles: 'string',
|
|
56
|
+
rendered: 'boolean',
|
|
57
|
+
render: 'function'
|
|
58
|
+
};
|
|
59
|
+
if(
|
|
60
|
+
Object.keys(requiredProps).every( propName => {
|
|
61
|
+
log(`Testing that ${propName} is a ${requiredProps[propName]}`);
|
|
62
|
+
return typeof($comp[propName]) === requiredProps[propName];
|
|
63
|
+
})
|
|
64
|
+
){
|
|
65
|
+
pass('The component contains all required properties and they are of the correct type');
|
|
66
|
+
} else {
|
|
67
|
+
fail('The component does not have all properties, or they are not of the correc type', JSON.stringify(requiredProps));
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
name: 'Is rendered when connected to a DOM',
|
|
73
|
+
description: 'The element should have it\'s rendered attribute set to true when it is connected to the DOM',
|
|
74
|
+
test: async ({
|
|
75
|
+
pass,
|
|
76
|
+
fail,
|
|
77
|
+
log
|
|
78
|
+
}) => {
|
|
79
|
+
log('Creating an instance of Component');
|
|
80
|
+
const $comp = new Component();
|
|
81
|
+
log('Attaching the component to the DOM');
|
|
82
|
+
document.getElementById('test').appendChild($comp);
|
|
83
|
+
log('Waiting 1 frame for render');
|
|
84
|
+
await raf();
|
|
85
|
+
log('Checking if the component is rendered');
|
|
86
|
+
if($comp.rendered){
|
|
87
|
+
pass('The component was rendered');
|
|
88
|
+
} else {
|
|
89
|
+
fail('The component was not rendered');
|
|
90
|
+
}
|
|
91
|
+
log('Cleanup: Removing the component from the DOM');
|
|
92
|
+
$comp.remove();
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
name: 'Contains a Shadow DOM',
|
|
97
|
+
description: 'The element should contain a Shadow DOM that contains the <code>shadowTemplate</code> and the <code>shadowStyles</code>.',
|
|
98
|
+
test: async ({
|
|
99
|
+
pass,
|
|
100
|
+
fail,
|
|
101
|
+
log
|
|
102
|
+
}) => {
|
|
103
|
+
log('Creating an instance of Component');
|
|
104
|
+
const $comp = new Component();
|
|
105
|
+
|
|
106
|
+
const cleanup = () => {
|
|
107
|
+
log('Cleanup: Removing the component from the DOM');
|
|
108
|
+
$comp.remove();
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
log('Attaching the component to the DOM');
|
|
112
|
+
document.getElementById('test').appendChild($comp);
|
|
113
|
+
log('Waiting 1 frame for render');
|
|
114
|
+
await raf();
|
|
115
|
+
|
|
116
|
+
log('Verifing if it contains a shadowRoot');
|
|
117
|
+
if(!$comp.shadowRoot){
|
|
118
|
+
fail('The component does not have a shadowRoot');
|
|
119
|
+
cleanup();
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
log('Verifing that the shadowRoot contains the shadowTemplate');
|
|
123
|
+
if(!$comp.shadowRoot.innerHTML.includes($comp.shadowTemplate)){
|
|
124
|
+
fail('The component\'s shadowRoot does not contain the shadowTemplate');
|
|
125
|
+
cleanup();
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
log('Verifing that the shadowRoot contains the shadowStyles');
|
|
129
|
+
if(!$comp.shadowRoot.innerHTML.includes($comp.shadowStyles)){
|
|
130
|
+
fail('The component\'s shadowRoot does not contain the shadowStyles');
|
|
131
|
+
cleanup();
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
pass('The elemnet contains a proper Shadow DOM');
|
|
135
|
+
cleanup();
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
];
|