aberdeen 0.2.1 → 0.2.3
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/dist/aberdeen.d.ts +573 -0
- package/dist/aberdeen.js +1756 -0
- package/dist/aberdeen.js.map +1 -0
- package/dist/prediction.d.ts +29 -0
- package/dist/prediction.js +110 -0
- package/dist/prediction.js.map +1 -0
- package/dist/route.d.ts +16 -0
- package/dist/route.js +119 -0
- package/dist/route.js.map +1 -0
- package/dist/transitions.d.ts +18 -0
- package/dist/transitions.js +67 -0
- package/dist/transitions.js.map +1 -0
- package/package.json +5 -2
- package/.github/workflows/deploy.yml +0 -43
- package/.vscode/launch.json +0 -23
- package/examples/input/index.html +0 -8
- package/examples/input/input.css +0 -56
- package/examples/input/input.js +0 -66
- package/examples/list/index.html +0 -7
- package/examples/list/list.js +0 -47
- package/examples/router/index.html +0 -8
- package/examples/router/page-home.js +0 -12
- package/examples/router/page-list.js +0 -35
- package/examples/router/page-settings.js +0 -6
- package/examples/router/router.js +0 -76
- package/examples/router/style.css +0 -88
- package/examples/tic-tac-toe/index.html +0 -8
- package/examples/tic-tac-toe/tic-tac-toe.css +0 -50
- package/examples/tic-tac-toe/tic-tac-toe.js +0 -90
- package/tests/_fakedom.js +0 -255
- package/tests/_init.js +0 -81
- package/tests/array.js +0 -109
- package/tests/binding.js +0 -106
- package/tests/browsers.js +0 -22
- package/tests/clean.js +0 -26
- package/tests/count.js +0 -105
- package/tests/create.js +0 -92
- package/tests/destroy.js +0 -270
- package/tests/dom.js +0 -219
- package/tests/errors.js +0 -114
- package/tests/immediate.js +0 -87
- package/tests/map.js +0 -76
- package/tests/objmap.js +0 -40
- package/tests/onEach.js +0 -392
- package/tests/prediction.js +0 -97
- package/tests/props.js +0 -49
- package/tests/schedule.js +0 -44
- package/tests/scope.js +0 -277
- package/tests/sort.js +0 -105
- package/tests/store.js +0 -254
- package/tsconfig.json +0 -67
package/tests/_fakedom.js
DELETED
|
@@ -1,255 +0,0 @@
|
|
|
1
|
-
let insertedCss = '';
|
|
2
|
-
|
|
3
|
-
global.document = {
|
|
4
|
-
createElement: tag => new Element(tag),
|
|
5
|
-
createTextNode: text => new TextNode(text),
|
|
6
|
-
head: {
|
|
7
|
-
appendChild: function(el) {
|
|
8
|
-
if (el.tag!=='style') {
|
|
9
|
-
throw new Error("only <style> inserts in head can be emulated");
|
|
10
|
-
}
|
|
11
|
-
insertedCss += el.innerText;
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
};
|
|
15
|
-
global.window = {};
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
let newCount = 0, changeCount = 0;
|
|
19
|
-
global.resetCounts = function() { newCount = changeCount = 0; };
|
|
20
|
-
global.getCounts = function() { return {new: newCount, change: changeCount}; };
|
|
21
|
-
|
|
22
|
-
let timeouts = [];
|
|
23
|
-
let currentTime = 0;
|
|
24
|
-
|
|
25
|
-
global.setTimeout = function(func,time) {
|
|
26
|
-
timeouts.push({func, time: time+currentTime});
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
global.passTime = function(ms) {
|
|
30
|
-
let targetTime = ms==null ? undefined : currentTime + ms;
|
|
31
|
-
while(timeouts.length) {
|
|
32
|
-
// Find the timeout that should occur first
|
|
33
|
-
let smallestIdx = 0;
|
|
34
|
-
for(let idx=1; idx<timeouts.length; idx++) {
|
|
35
|
-
if (timeouts[idx].time < timeouts[smallestIdx].time) smallestIdx = idx;
|
|
36
|
-
}
|
|
37
|
-
let timeout = timeouts[smallestIdx];
|
|
38
|
-
// If this timeout is not due yet, we're done
|
|
39
|
-
if (targetTime!=null && timeout.time > targetTime) break;
|
|
40
|
-
// Timeout is due! Remove it from the list, update the currentTime, and fire the callback!
|
|
41
|
-
timeouts.splice(smallestIdx, 1);
|
|
42
|
-
currentTime = timeout.time;
|
|
43
|
-
timeout.func();
|
|
44
|
-
}
|
|
45
|
-
currentTime = targetTime==null ? 0 : targetTime
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
class Node {
|
|
50
|
-
get nextSibling() {
|
|
51
|
-
return this.getSibling(+1);
|
|
52
|
-
}
|
|
53
|
-
get previousSibling() {
|
|
54
|
-
return this.getSibling(-1);
|
|
55
|
-
}
|
|
56
|
-
getSibling(delta) {
|
|
57
|
-
if (!this.parentNode) return;
|
|
58
|
-
let siblings = this.parentNode.childNodes;
|
|
59
|
-
let idx = siblings.indexOf(this);
|
|
60
|
-
if (idx < 0) throw new Error("not part of siblings!?");
|
|
61
|
-
return siblings[idx+delta];
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
class Element extends Node {
|
|
66
|
-
constructor(tag) {
|
|
67
|
-
super();
|
|
68
|
-
this.tag = tag;
|
|
69
|
-
this.childNodes = [];
|
|
70
|
-
this._style = {};
|
|
71
|
-
this.attrs = {};
|
|
72
|
-
this.events = {};
|
|
73
|
-
newCount++;
|
|
74
|
-
}
|
|
75
|
-
appendChild(node) {
|
|
76
|
-
this.insertBefore(node, null);
|
|
77
|
-
}
|
|
78
|
-
insertBefore(node, ref) {
|
|
79
|
-
if (node.parentNode) node.parentNode.removeChild(node);
|
|
80
|
-
else changeCount++;
|
|
81
|
-
node.parentNode = this;
|
|
82
|
-
if (ref) {
|
|
83
|
-
let idx = this.childNodes.indexOf(ref);
|
|
84
|
-
if (idx<0) throw new Error("non-existing ref node");
|
|
85
|
-
this.childNodes.splice(idx, 0, node);
|
|
86
|
-
} else {
|
|
87
|
-
this.childNodes.push(node);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
removeChild(node) {
|
|
91
|
-
let idx = this.childNodes.indexOf(node);
|
|
92
|
-
if (idx<0) throw new Error("no such child");
|
|
93
|
-
this.childNodes.splice(idx, 1);
|
|
94
|
-
node.parentNode = null;
|
|
95
|
-
changeCount++;
|
|
96
|
-
}
|
|
97
|
-
remove() {
|
|
98
|
-
this.parentNode.removeChild(this);
|
|
99
|
-
}
|
|
100
|
-
replaceChild(newNode, oldNode) {
|
|
101
|
-
this.insertBefore(newNode, oldNode);
|
|
102
|
-
this.removeChild(oldNode);
|
|
103
|
-
}
|
|
104
|
-
setAttribute(k, v) {
|
|
105
|
-
this.attrs[k] = ''+v;
|
|
106
|
-
changeCount++;
|
|
107
|
-
}
|
|
108
|
-
getAttribute(k) {
|
|
109
|
-
return this.attrs[k]
|
|
110
|
-
}
|
|
111
|
-
removeAttribute(k) {
|
|
112
|
-
delete this.attrs[k];
|
|
113
|
-
changeCount++;
|
|
114
|
-
}
|
|
115
|
-
get classList() {
|
|
116
|
-
return {
|
|
117
|
-
add: name => {
|
|
118
|
-
let set = this._getClassSet();
|
|
119
|
-
set.add(name);
|
|
120
|
-
this._setClassSet(set);
|
|
121
|
-
changeCount++;
|
|
122
|
-
},
|
|
123
|
-
remove: name => {
|
|
124
|
-
let set = this._getClassSet();
|
|
125
|
-
set.delete(name);
|
|
126
|
-
this._setClassSet(set);
|
|
127
|
-
changeCount++;
|
|
128
|
-
},
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
get parentElement() {
|
|
132
|
-
if (this.parentNode instanceof Element) return this.parentNode;
|
|
133
|
-
}
|
|
134
|
-
_getClassSet() {
|
|
135
|
-
return new Set(this.attrs.class ? this.attrs.class.split(' ') : []);
|
|
136
|
-
}
|
|
137
|
-
_setClassSet(map) {
|
|
138
|
-
this.attrs.class = Array.from(map).sort().join(' ');
|
|
139
|
-
if (!this.attrs.class) delete this.attrs.class;
|
|
140
|
-
}
|
|
141
|
-
get firstChild() {
|
|
142
|
-
return this.childNodes[0];
|
|
143
|
-
}
|
|
144
|
-
get lastChild() {
|
|
145
|
-
return this.childNodes[this.childNodes.length-1];
|
|
146
|
-
}
|
|
147
|
-
set style(val) {
|
|
148
|
-
if (val !== '') throw new Error("non-empty style string cannot be emulated");
|
|
149
|
-
this._style = {};
|
|
150
|
-
changeCount++;
|
|
151
|
-
}
|
|
152
|
-
set textContent(text) {
|
|
153
|
-
this.childNodes = [new TextNode(text)];
|
|
154
|
-
}
|
|
155
|
-
set innerHTML(html) {
|
|
156
|
-
this.childNodes = [];
|
|
157
|
-
if (html) {
|
|
158
|
-
let n = new Element('fake-emulated-html');
|
|
159
|
-
n.textContent = html;
|
|
160
|
-
this.appendChild(n);
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
get style() {
|
|
164
|
-
for(let k in this._style) {
|
|
165
|
-
if (this._style[k] === '') delete this._style[k];
|
|
166
|
-
}
|
|
167
|
-
return this._style;
|
|
168
|
-
}
|
|
169
|
-
set className(v) {
|
|
170
|
-
this.attrs.class = v;
|
|
171
|
-
changeCount++;
|
|
172
|
-
}
|
|
173
|
-
get offsetHeight() {
|
|
174
|
-
return 20;
|
|
175
|
-
}
|
|
176
|
-
get offsetWidth() {
|
|
177
|
-
return 200;
|
|
178
|
-
}
|
|
179
|
-
toString() {
|
|
180
|
-
let props = Object.assign({}, this);
|
|
181
|
-
for(let k in this.attrs) props['@'+k] = this.attrs[k];
|
|
182
|
-
for(let k in this.style) props[':'+k] = this._style[k];
|
|
183
|
-
delete props.tag;
|
|
184
|
-
delete props.attrs;
|
|
185
|
-
delete props._style;
|
|
186
|
-
delete props.events;
|
|
187
|
-
delete props.childNodes;
|
|
188
|
-
delete props.parentNode;
|
|
189
|
-
|
|
190
|
-
let arr = [];
|
|
191
|
-
for(let k in props) arr.push(k+'='+JSON.stringify(props[k]));
|
|
192
|
-
arr.sort();
|
|
193
|
-
for(let child of this.childNodes) arr.push(child.toString());
|
|
194
|
-
|
|
195
|
-
return this.tag + `{${arr.join(' ')}}`;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
addEventListener(name, func) {
|
|
199
|
-
this.events[name] = this.events[name] || new Set();
|
|
200
|
-
this.events[name].add(func);
|
|
201
|
-
changeCount++;
|
|
202
|
-
}
|
|
203
|
-
removeEventListener(name, func) {
|
|
204
|
-
if (this.events[name]) {
|
|
205
|
-
if (this.events[name].delete(func)) {
|
|
206
|
-
changeCount++
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
event(info) {
|
|
211
|
-
if (typeof info === 'string') info = {type: info};
|
|
212
|
-
let type = info.type;
|
|
213
|
-
info.target = this;
|
|
214
|
-
info.preventDefault = function(){};
|
|
215
|
-
info.stopPropagation = function(){ info.stopped = true; };
|
|
216
|
-
let node = this;
|
|
217
|
-
while(node && !info.stopped) {
|
|
218
|
-
let funcs = node.events[type];
|
|
219
|
-
if (funcs) {
|
|
220
|
-
for(let func of funcs) {
|
|
221
|
-
func.call(node, info);
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
node = node.parentNode;
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
getElementById(id) {
|
|
228
|
-
if (this.attrs.id === id) return this;
|
|
229
|
-
for(let child of this.childNodes) {
|
|
230
|
-
let el = child.getElementById(id);
|
|
231
|
-
if (el) return el;
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
class TextNode extends Node {
|
|
237
|
-
constructor(textContent) {
|
|
238
|
-
super();
|
|
239
|
-
this.textContent = '' + textContent;
|
|
240
|
-
newCount++;
|
|
241
|
-
}
|
|
242
|
-
toString() {
|
|
243
|
-
return JSON.stringify(this.textContent);
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
function getComputedStyle(el) {
|
|
248
|
-
return el._style;
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
global.Node = Node;
|
|
253
|
-
global.TextNode = TextNode;
|
|
254
|
-
global.Element = Element;
|
|
255
|
-
global.getComputedStyle = getComputedStyle;
|
package/tests/_init.js
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import * as _ from './_fakedom.js';
|
|
2
|
-
import mocha from 'mocha'
|
|
3
|
-
import {deepEqual as equal} from 'fast-equals'
|
|
4
|
-
|
|
5
|
-
import * as aberdeen from '../dist-min/aberdeen.js'
|
|
6
|
-
import * as transitions from '../dist-min/transitions.js'
|
|
7
|
-
import * as prediction from '../dist-min/prediction.js'
|
|
8
|
-
Object.assign(global, aberdeen, transitions, prediction)
|
|
9
|
-
|
|
10
|
-
let currentMountSeq = new Store(0)
|
|
11
|
-
mocha.beforeEach(() => {
|
|
12
|
-
document.body = document.createElement('body')
|
|
13
|
-
resetCounts()
|
|
14
|
-
})
|
|
15
|
-
|
|
16
|
-
mocha.afterEach(() => {
|
|
17
|
-
unmount()
|
|
18
|
-
passTime(2001) // wait for deletion transitions
|
|
19
|
-
assertBody(``)
|
|
20
|
-
})
|
|
21
|
-
|
|
22
|
-
function toDisplay(value) {
|
|
23
|
-
if (value instanceof Map) {
|
|
24
|
-
let results = []
|
|
25
|
-
value.forEach((value,key) => results.push(JSON.stringify(key)+": "+JSON.stringify(value)))
|
|
26
|
-
return "map{" + results.join(", ") + "}"
|
|
27
|
-
} else {
|
|
28
|
-
return JSON.stringify(value)
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
global.AssertError = class extends Error {
|
|
33
|
-
constructor(text, actual, expected, expectLiteral) {
|
|
34
|
-
text += `
|
|
35
|
-
Actual: ${toDisplay(actual)}
|
|
36
|
-
Expected: ${expectLiteral ? expected : toDisplay(expected)}`
|
|
37
|
-
super(text)
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
global.assert = function(bool, msg) {
|
|
42
|
-
if (!bool) throw new AssertError(`assert failed${msg ? ": "+msg : ""}`, bool, "something trueish", true)
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
global.assertEqual = function(actual, expected, msg) {
|
|
46
|
-
if (!equal(actual,expected)) throw new AssertError(`equal failed${msg ? ": "+msg : ""}`, actual, expected)
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
global.getBody = function() {
|
|
50
|
-
return document.body.toString().replace(/^body{/,'').replace(/}$/,'')
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
global.assertBody = function(expected) {
|
|
54
|
-
let actual = getBody()
|
|
55
|
-
if (actual !== expected) throw new AssertError(`assertBody failed`, actual, expected)
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
global.assertThrow = function(what, func) {
|
|
59
|
-
if (typeof what == 'function') {
|
|
60
|
-
func = what
|
|
61
|
-
what = undefined
|
|
62
|
-
}
|
|
63
|
-
try {
|
|
64
|
-
func()
|
|
65
|
-
} catch(e) {
|
|
66
|
-
if (what && e.toString().indexOf(what)<0) throw new AssertError(`wrong exception`, e.toString(), `something containing "${what}"`, true)
|
|
67
|
-
return
|
|
68
|
-
}
|
|
69
|
-
throw new AssertError(`exception expected`, undefined, `something containing "${what}"`, true)
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
global.objToMap = function(obj) {
|
|
73
|
-
if (typeof obj === 'object' && obj && obj.constructor===Object) {
|
|
74
|
-
let map = new Map()
|
|
75
|
-
for(let k in obj) {
|
|
76
|
-
map.set(k, objToMap(obj[k]))
|
|
77
|
-
}
|
|
78
|
-
return map
|
|
79
|
-
}
|
|
80
|
-
return obj
|
|
81
|
-
}
|
package/tests/array.js
DELETED
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
describe('Array', () => {
|
|
2
|
-
it('fires higher-scope isEmpty before getting to content', () => {
|
|
3
|
-
let store = new Store(['a'])
|
|
4
|
-
let cnt1 = 0, cnt2 = 0
|
|
5
|
-
mount(document.body, () => {
|
|
6
|
-
cnt1++
|
|
7
|
-
if (!store.isEmpty()) {
|
|
8
|
-
node('div', () => {
|
|
9
|
-
cnt2++;
|
|
10
|
-
text(store.get(0))
|
|
11
|
-
})
|
|
12
|
-
}
|
|
13
|
-
})
|
|
14
|
-
assertBody(`div{"a"}`)
|
|
15
|
-
|
|
16
|
-
store.set(0, 'b')
|
|
17
|
-
passTime();
|
|
18
|
-
assertBody(`div{"b"}`)
|
|
19
|
-
assertEqual([cnt1,cnt2], [1,2])
|
|
20
|
-
|
|
21
|
-
store.delete(0);
|
|
22
|
-
passTime()
|
|
23
|
-
assertBody(``)
|
|
24
|
-
assertEqual([cnt1,cnt2], [2,2])
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
it('reactively get() full array', () => {
|
|
28
|
-
let store = new Store([3, 4, new Store([5, 6])])
|
|
29
|
-
mount(document.body, () => {
|
|
30
|
-
text(JSON.stringify(store.get()))
|
|
31
|
-
text(JSON.stringify(store.query({depth: 1})[2].get()))
|
|
32
|
-
})
|
|
33
|
-
passTime()
|
|
34
|
-
assertBody(`"[3,4,[5,6]]" "[5,6]"`)
|
|
35
|
-
|
|
36
|
-
store.push(7)
|
|
37
|
-
store.ref(2).push(8)
|
|
38
|
-
passTime()
|
|
39
|
-
assertBody(`"[3,4,[5,6,8],7]" "[5,6,8]"`)
|
|
40
|
-
|
|
41
|
-
assertEqual(store.get(6), undefined)
|
|
42
|
-
assertEqual(store.get(6, 'a'), undefined)
|
|
43
|
-
})
|
|
44
|
-
|
|
45
|
-
it('handles invalid indexes', () => {
|
|
46
|
-
let store = new Store(["a","b","c"])
|
|
47
|
-
for(let index in [-1, 1000000, "1", 0.5]) {
|
|
48
|
-
assertThrow('Invalid array index', () => store.set(index, "test"))
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
assertEqual(store.get("1"), "b")
|
|
52
|
-
assertThrow("Invalid array index", () => store.get('a'))
|
|
53
|
-
assertThrow("Invalid array index", () => store.get(true))
|
|
54
|
-
})
|
|
55
|
-
|
|
56
|
-
it('merges', () => {
|
|
57
|
-
let cnt1 = 0, cnt2 = 0
|
|
58
|
-
let store = new Store([1,undefined,3])
|
|
59
|
-
mount(document.body, () => {
|
|
60
|
-
cnt1++
|
|
61
|
-
store.onEach(item => {
|
|
62
|
-
cnt2++
|
|
63
|
-
node('div', item.get())
|
|
64
|
-
})
|
|
65
|
-
})
|
|
66
|
-
|
|
67
|
-
assertBody(`div{"1"} div{"3"}`)
|
|
68
|
-
assertEqual([cnt1, cnt2], [1,2])
|
|
69
|
-
|
|
70
|
-
store.set(1, 2)
|
|
71
|
-
passTime()
|
|
72
|
-
assertBody(`div{"1"} div{"2"} div{"3"}`)
|
|
73
|
-
assertEqual([cnt1, cnt2], [1,3])
|
|
74
|
-
|
|
75
|
-
// Merging just replace the entire array
|
|
76
|
-
store.merge([1,"two"])
|
|
77
|
-
passTime()
|
|
78
|
-
assertBody(`div{"1"} div{"two"}`)
|
|
79
|
-
assertEqual([cnt1, cnt2], [1,4])
|
|
80
|
-
|
|
81
|
-
store.set(9,'ten')
|
|
82
|
-
passTime()
|
|
83
|
-
assertBody(`div{"1"} div{"two"} div{"ten"}`)
|
|
84
|
-
assertEqual([cnt1, cnt2], [1,5])
|
|
85
|
-
|
|
86
|
-
store.set(4, 'five')
|
|
87
|
-
passTime()
|
|
88
|
-
assertBody(`div{"1"} div{"two"} div{"five"} div{"ten"}`)
|
|
89
|
-
assertEqual([cnt1, cnt2], [1,6])
|
|
90
|
-
|
|
91
|
-
store.delete(1)
|
|
92
|
-
passTime()
|
|
93
|
-
assertBody(`div{"1"} div{"five"} div{"ten"}`)
|
|
94
|
-
assertEqual([cnt1, cnt2], [1,6])
|
|
95
|
-
|
|
96
|
-
store.delete(9)
|
|
97
|
-
store.push("six")
|
|
98
|
-
assertEqual(store.get(5), "six")
|
|
99
|
-
passTime()
|
|
100
|
-
assertBody(`div{"1"} div{"five"} div{"six"}`)
|
|
101
|
-
assertEqual([cnt1, cnt2], [1,7])
|
|
102
|
-
|
|
103
|
-
store.set([1, undefined, 3])
|
|
104
|
-
passTime()
|
|
105
|
-
assertBody(`div{"1"} div{"3"}`)
|
|
106
|
-
assertEqual([cnt1, cnt2], [1,8])
|
|
107
|
-
|
|
108
|
-
})
|
|
109
|
-
})
|
package/tests/binding.js
DELETED
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
describe('Value binding', function() {
|
|
2
|
-
it('binds input values', () => {
|
|
3
|
-
let store = new Store('test')
|
|
4
|
-
let inputElement;
|
|
5
|
-
mount(document.body, () => {
|
|
6
|
-
node('input', store, () => {
|
|
7
|
-
inputElement = getParentElement()
|
|
8
|
-
prop('class', {correct: store.get().length >= 5})
|
|
9
|
-
})
|
|
10
|
-
})
|
|
11
|
-
assertBody(`input{value="test"}`)
|
|
12
|
-
|
|
13
|
-
inputElement.value = "testx"
|
|
14
|
-
inputElement.event("input")
|
|
15
|
-
passTime()
|
|
16
|
-
|
|
17
|
-
assertBody(`input{@class="correct" value="testx"}`)
|
|
18
|
-
})
|
|
19
|
-
|
|
20
|
-
it('binds checkboxes', () => {
|
|
21
|
-
let store = new Store(true)
|
|
22
|
-
let inputElement;
|
|
23
|
-
mount(document.body, () => {
|
|
24
|
-
node('input', {type: 'checkbox'}, store, () => {
|
|
25
|
-
inputElement = getParentElement()
|
|
26
|
-
})
|
|
27
|
-
})
|
|
28
|
-
assertBody(`input{@type="checkbox" checked=true}`)
|
|
29
|
-
|
|
30
|
-
inputElement.checked = false
|
|
31
|
-
inputElement.event("input")
|
|
32
|
-
passTime()
|
|
33
|
-
|
|
34
|
-
assertBody(`input{@type="checkbox" checked=false}`)
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
it('binds radio buttons', () => {
|
|
38
|
-
let store = new Store('woman')
|
|
39
|
-
let inputElement1, inputElement2;
|
|
40
|
-
mount(document.body, () => {
|
|
41
|
-
node('input', {type: 'radio', name: 'gender', value: 'man'}, store, () => {
|
|
42
|
-
inputElement1 = getParentElement()
|
|
43
|
-
})
|
|
44
|
-
node('input', {type: 'radio', name: 'gender', value: 'woman'}, store, () => {
|
|
45
|
-
inputElement2 = getParentElement()
|
|
46
|
-
})
|
|
47
|
-
})
|
|
48
|
-
assertBody(`input{@name="gender" @type="radio" checked=false value="man"} input{@name="gender" @type="radio" checked=true value="woman"}`)
|
|
49
|
-
|
|
50
|
-
inputElement1.checked = true
|
|
51
|
-
inputElement1.event("input")
|
|
52
|
-
inputElement2.checked = false
|
|
53
|
-
inputElement2.event("input")
|
|
54
|
-
passTime()
|
|
55
|
-
|
|
56
|
-
assertEqual(store.get(), 'man')
|
|
57
|
-
})
|
|
58
|
-
|
|
59
|
-
it('reads initial value when Store is undefined', () => {
|
|
60
|
-
let store = new Store({})
|
|
61
|
-
mount(document.body, () => {
|
|
62
|
-
node('input', {value: 'a'}, store.ref('input'))
|
|
63
|
-
node('input', {type: 'checkbox', checked: true}, store.ref('checkbox'))
|
|
64
|
-
node('input', {type: 'radio', name: 'abc', value: 'x', checked: false}, store.ref('radio'))
|
|
65
|
-
node('input', {type: 'radio', name: 'abc', value: 'y', checked: true}, store.ref('radio'))
|
|
66
|
-
node('input', {type: 'radio', name: 'abc', value: 'z', checked: false}, store.ref('radio'))
|
|
67
|
-
})
|
|
68
|
-
assertEqual(store.get(), {input: 'a', checkbox: true, radio: 'y'})
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
it('changes DOM when Store value is updated', () => {
|
|
72
|
-
let store = new Store("test")
|
|
73
|
-
let toggle = new Store(true)
|
|
74
|
-
mount(document.body, () => {
|
|
75
|
-
node('input', store)
|
|
76
|
-
node('input', {type: 'checkbox'}, toggle)
|
|
77
|
-
})
|
|
78
|
-
assertBody(`input{value="test"} input{@type="checkbox" checked=true}`)
|
|
79
|
-
|
|
80
|
-
store.set("changed")
|
|
81
|
-
toggle.set(false)
|
|
82
|
-
passTime()
|
|
83
|
-
assertBody(`input{value="changed"} input{@type="checkbox" checked=false}`)
|
|
84
|
-
})
|
|
85
|
-
|
|
86
|
-
it('returns numbers for number/range typed inputs', () => {
|
|
87
|
-
let store = new Store("")
|
|
88
|
-
let inputElement;
|
|
89
|
-
mount(document.body, () => {
|
|
90
|
-
node('input', {type: 'number'}, store, () => {
|
|
91
|
-
inputElement = getParentElement()
|
|
92
|
-
})
|
|
93
|
-
})
|
|
94
|
-
assertBody(`input{@type="number" value=""}`)
|
|
95
|
-
|
|
96
|
-
inputElement.value = "123"
|
|
97
|
-
inputElement.event("input")
|
|
98
|
-
passTime()
|
|
99
|
-
assertEqual(store.get(), 123)
|
|
100
|
-
|
|
101
|
-
inputElement.value = ""
|
|
102
|
-
inputElement.event("input")
|
|
103
|
-
passTime()
|
|
104
|
-
assertEqual(store.get(), null)
|
|
105
|
-
})
|
|
106
|
-
})
|
package/tests/browsers.js
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
describe('Browsers', () => {
|
|
2
|
-
it('works without Array.from', () => {
|
|
3
|
-
let oldFrom = Array.from
|
|
4
|
-
Array.from = undefined
|
|
5
|
-
|
|
6
|
-
let store = new Store(false)
|
|
7
|
-
let cnt = 0
|
|
8
|
-
mount(document.body, () => {
|
|
9
|
-
cnt++
|
|
10
|
-
if (store.get()) node('a')
|
|
11
|
-
})
|
|
12
|
-
assertBody(``)
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
store.set(true)
|
|
16
|
-
passTime()
|
|
17
|
-
assertBody(`a{}`)
|
|
18
|
-
assertEqual(cnt, 2)
|
|
19
|
-
|
|
20
|
-
Array.from = oldFrom
|
|
21
|
-
})
|
|
22
|
-
})
|
package/tests/clean.js
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
describe('Clean', function() {
|
|
2
|
-
it('triggers once when redrawing', () => {
|
|
3
|
-
|
|
4
|
-
let cnt1 = 0, cnt2 = 0
|
|
5
|
-
let store = new Store(1)
|
|
6
|
-
mount(document.body, () => {
|
|
7
|
-
cnt1++
|
|
8
|
-
text(store.get())
|
|
9
|
-
clean(() => {
|
|
10
|
-
cnt2++
|
|
11
|
-
})
|
|
12
|
-
})
|
|
13
|
-
|
|
14
|
-
passTime()
|
|
15
|
-
assertBody(`"1"`)
|
|
16
|
-
assertEqual([cnt1, cnt2], [1, 0])
|
|
17
|
-
|
|
18
|
-
store.set(2)
|
|
19
|
-
passTime()
|
|
20
|
-
assertBody(`"2"`)
|
|
21
|
-
assertEqual([cnt1, cnt2], [2, 1])
|
|
22
|
-
|
|
23
|
-
unmount()
|
|
24
|
-
assertEqual([cnt1, cnt2], [2, 2])
|
|
25
|
-
})
|
|
26
|
-
})
|
package/tests/count.js
DELETED
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
describe('Count', () => {
|
|
2
|
-
it('reactively counts object keys', () => {
|
|
3
|
-
let store = new Store()
|
|
4
|
-
let cnt = 0
|
|
5
|
-
mount(document.body, () => {
|
|
6
|
-
text(store.count())
|
|
7
|
-
cnt++
|
|
8
|
-
})
|
|
9
|
-
passTime()
|
|
10
|
-
assertBody(`"0"`)
|
|
11
|
-
assertEqual(cnt, 1)
|
|
12
|
-
|
|
13
|
-
store.set('a', 1)
|
|
14
|
-
passTime()
|
|
15
|
-
assertBody(`"1"`)
|
|
16
|
-
assertEqual(cnt, 2)
|
|
17
|
-
|
|
18
|
-
store.set('a', 2)
|
|
19
|
-
passTime()
|
|
20
|
-
assertBody(`"1"`)
|
|
21
|
-
assertEqual(cnt, 2)
|
|
22
|
-
|
|
23
|
-
store.set('b', 1)
|
|
24
|
-
passTime()
|
|
25
|
-
assertBody(`"2"`)
|
|
26
|
-
assertEqual(cnt, 3)
|
|
27
|
-
|
|
28
|
-
store.delete('a')
|
|
29
|
-
passTime()
|
|
30
|
-
assertBody(`"1"`)
|
|
31
|
-
assertEqual(cnt, 4)
|
|
32
|
-
|
|
33
|
-
store.delete('b')
|
|
34
|
-
passTime()
|
|
35
|
-
assertBody(`"0"`)
|
|
36
|
-
assertEqual(cnt, 5)
|
|
37
|
-
})
|
|
38
|
-
|
|
39
|
-
it('counts non-reflectively', () => {
|
|
40
|
-
let cases = [
|
|
41
|
-
{data: [], count: 0},
|
|
42
|
-
{data: [1,2], count: 2},
|
|
43
|
-
{data: {}, count: 0},
|
|
44
|
-
{data: {a:1, b:2}, count: 2},
|
|
45
|
-
{data: objToMap({}), count: 0},
|
|
46
|
-
{data: objToMap({a:1, b:2}), count: 2},
|
|
47
|
-
]
|
|
48
|
-
for(let c of cases) {
|
|
49
|
-
let store = new Store(c.data)
|
|
50
|
-
assertEqual(store.count(), c.count)
|
|
51
|
-
assertEqual(store.isEmpty(), c.count==0)
|
|
52
|
-
}
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
it('throws when counting uncountable things', () => {
|
|
56
|
-
let store = new Store({a: 3})
|
|
57
|
-
assertThrow(() => {
|
|
58
|
-
store.count('a')
|
|
59
|
-
})
|
|
60
|
-
assertThrow(() => {
|
|
61
|
-
store.isEmpty('a')
|
|
62
|
-
})
|
|
63
|
-
assertEqual(store.count('b'), 0)
|
|
64
|
-
assertEqual(store.count('b', 'c', 'd'), 0)
|
|
65
|
-
assertEqual(store.isEmpty('b'), true)
|
|
66
|
-
assertEqual(store.isEmpty('b', 'c', 'd'), true)
|
|
67
|
-
})
|
|
68
|
-
|
|
69
|
-
it('reactively handles isEmpty', () => {
|
|
70
|
-
let store = new Store()
|
|
71
|
-
let cnt = 0
|
|
72
|
-
mount(document.body, () => {
|
|
73
|
-
text(store.isEmpty())
|
|
74
|
-
cnt++
|
|
75
|
-
})
|
|
76
|
-
passTime()
|
|
77
|
-
assertBody(`"true"`)
|
|
78
|
-
assertEqual(cnt, 1)
|
|
79
|
-
|
|
80
|
-
store.set('a', 1)
|
|
81
|
-
passTime()
|
|
82
|
-
assertBody(`"false"`)
|
|
83
|
-
assertEqual(cnt, 2)
|
|
84
|
-
|
|
85
|
-
store.set('a', 2)
|
|
86
|
-
passTime()
|
|
87
|
-
assertBody(`"false"`)
|
|
88
|
-
assertEqual(cnt, 2)
|
|
89
|
-
|
|
90
|
-
store.set('b', 1)
|
|
91
|
-
passTime()
|
|
92
|
-
assertBody(`"false"`)
|
|
93
|
-
assertEqual(cnt, 2)
|
|
94
|
-
|
|
95
|
-
store.delete('a')
|
|
96
|
-
passTime()
|
|
97
|
-
assertBody(`"false"`)
|
|
98
|
-
assertEqual(cnt, 2)
|
|
99
|
-
|
|
100
|
-
store.delete('b')
|
|
101
|
-
passTime()
|
|
102
|
-
assertBody(`"true"`)
|
|
103
|
-
assertEqual(cnt, 3)
|
|
104
|
-
})
|
|
105
|
-
})
|