1import {Test} from '../Test.js';
2import {REF, DOM, diff, FP, EventStream} from '../Ref.js';
3
4class DiffTest extends Test {
5 testArrayDiff() {
6 let removed = [];
7 let newArray = [];
8 diff([1, 2, 3], [4, 5, 6], item => removed.push(item), item => newArray.push(item));
9 this.expect(removed).equalToArray([1, 2, 3]);
10 this.expect(newArray).equalToArray([4, 5, 6]);
11
12 removed = [];
13 newArray = [];
14 diff([1, 2, 3], [2, 3, 4], item => removed.push(item), item => newArray.push(item));
15 this.expect(removed).equalToArray([1]);
16 this.expect(newArray).equalToArray([2, 3, 4]);
17
18 removed = [];
19 newArray = [];
20 diff([2], [2, 3, 4], item => removed.push(item), item => newArray.push(item));
21 this.expect(removed).equalToArray([]);
22 this.expect(newArray).equalToArray([2, 3, 4]);
23
24 removed = [];
25 newArray = [];
26 diff([], [2, 3, 4], item => removed.push(item), item => newArray.push(item));
27 this.expect(removed).equalToArray([]);
28 this.expect(newArray).equalToArray([2, 3, 4]);
29
30 removed = [];
31 newArray = [];
32 diff([4, 3, 2], [2, 3, 4], item => removed.push(item), item => newArray.push(item));
33 this.expect(removed).equalToArray([]);
34 this.expect(newArray).equalToArray([2, 3, 4]);
35
36 removed = [];
37 newArray = [];
38 diff([4, 3, 2, 5, 6], [2, 3, 4], item => removed.push(item), item => newArray.push(item));
39 this.expect(removed).equalToArray([5, 6]);
40 this.expect(newArray).equalToArray([2, 3, 4]);
41
42 removed = [];
43 newArray = [];
44 diff([], [], item => removed.push(item), item => newArray.push(item));
45 this.expect(removed).equalToArray([]);
46 this.expect(newArray).equalToArray([]);
47 }
48}
49
50class DomTest extends Test {
51 setup(rootElement) {
52 this.rootElement = rootElement;
53 }
54
55 testInject() {
56 this.rootElement.innerHTML = "";
57 const injector = `<div id="${Math.random()}"></div>`;
58 DOM.inject(this.rootElement, injector);
59 this.expect(this.rootElement.innerHTML).equalToValue(injector);
60 this.rootElement.innerHTML = "";
61 }
62
63 testBefore() {
64 let initial = '<div id="1"></div><div id="2"></div><div id="3"></div>';
65 this.rootElement.innerHTML = initial;
66 let injector = `<div id="${Math.random()}"></div>`;
67 DOM.before(this.rootElement.children[0], injector);
68 this.expect(this.rootElement.innerHTML).equalToValue(`${injector}${initial}`);
69 this.rootElement.innerHTML = initial;
70 DOM.before(this.rootElement.children[1], injector);
71 this.expect(this.rootElement.innerHTML).equalToValue(`<div id="1"></div>${injector}<div id="2"></div><div id="3"></div>`);
72 this.rootElement.innerHTML = initial;
73 DOM.before(this.rootElement.children[2], injector);
74 this.expect(this.rootElement.innerHTML).equalToValue(`<div id="1"></div><div id="2"></div>${injector}<div id="3"></div>`);
75 }
76
77 testAfter() {
78 let initial = '<div id="1"></div><div id="2"></div><div id="3"></div>';
79 this.rootElement.innerHTML = initial;
80 let injector = `<div id="${Math.random()}"></div>`;
81 DOM.after(this.rootElement.children[0], injector);
82 this.expect(this.rootElement.innerHTML).equalToValue(`<div id="1"></div>${injector}<div id="2"></div><div id="3"></div>`);
83 this.rootElement.innerHTML = initial;
84 DOM.after(this.rootElement.children[1], injector);
85 this.expect(this.rootElement.innerHTML).equalToValue(`<div id="1"></div><div id="2"></div>${injector}<div id="3"></div>`);
86 this.rootElement.innerHTML = initial;
87 DOM.after(this.rootElement.children[2], injector);
88 this.expect(this.rootElement.innerHTML).equalToValue(`${initial}${injector}`);
89 }
90
91 testPrepend() {
92 let initial = '<div id="1"></div><div id="2"></div><div id="3"></div>';
93 this.rootElement.innerHTML = initial;
94 let injector = `<div id="${Math.random()}"></div>`;
95 DOM.prepend(this.rootElement, injector);
96 this.expect(this.rootElement.innerHTML).equalToValue(`${injector}${initial}`);
97 }
98
99 testAppend() {
100 let initial = '<div id="1"></div><div id="2"></div><div id="3"></div>';
101 this.rootElement.innerHTML = initial;
102 let injector = `<div id="${Math.random()}"></div>`;
103 DOM.append(this.rootElement, injector);
104 this.expect(this.rootElement.innerHTML).equalToValue(`${initial}${injector}`);
105 }
106
107 testReplace() {
108 let initial = '<div id="1"></div><div id="2"></div><div id="3"></div>';
109 this.rootElement.innerHTML = initial;
110 let injector = `<div id="${Math.random()}"></div>`;
111 DOM.replace(this.rootElement.children[0], injector);
112 this.expect(this.rootElement.innerHTML).equalToValue(`${injector}<div id="2"></div><div id="3"></div>`);
113 }
114
115 testRemove() {
116 let initial = '<div id="1"></div><div id="2"></div><div id="3"></div>';
117 this.rootElement.innerHTML = initial;
118 DOM.remove(this.rootElement.children[0]);
119 this.expect(this.rootElement.innerHTML).equalToValue(`<div id="2"></div><div id="3"></div>`);
120 }
121}
122
123class RefTest extends Test {
124 setup(rootElement) {
125 this.rootElement = rootElement;
126 }
127
128 async testOnElementMount() {
129 let triggered = false;
130 let currentRef = null;
131 const creatAComponent = () => {
132 let ref = REF.createRef({
133 onElementMount: (element) => {
134 triggered = true;
135 }
136 });
137 currentRef = ref;
138 return `<div ref="${ref}"></div>`;
139 };
140
141 const firstComp = creatAComponent();
142 DOM.inject(this.rootElement, firstComp);
143 await this.waitForRefMounted(currentRef);
144 this.expect(triggered).equalToValue(true);
145 this.expect(currentRef.element.outerHTML).equalToValue(firstComp);
146
147 triggered = false;
148 const secondComp = creatAComponent();
149 DOM.replace(this.rootElement.children[0], secondComp);
150 await this.waitForRefMounted(currentRef);
151 this.expect(triggered).equalToValue(true);
152 this.expect(currentRef.element.outerHTML).equalToValue(secondComp);
153 }
154
155 async testOnElementUnmount() {
156 let triggered = false;
157 let currentRef = null;
158 const creatAComponent = () => {
159 let ref = REF.createRef({
160 onElementUnmount: (element) => {
161 triggered = true;
162 }
163 });
164 currentRef = ref;
165 return `<div ref="${ref}"></div>`;
166 };
167
168 const firstComp = creatAComponent();
169 DOM.inject(this.rootElement, firstComp);
170 DOM.replace(this.rootElement.children[0], "<div></div>");
171 await this.waitForRefUnmounted(currentRef);
172 this.expect(triggered).equalToValue(true);
173 this.expect(currentRef.element.parentElement).equalToValue(null);
174
175 triggered = false;
176 DOM.inject(this.rootElement, firstComp);
177 DOM.remove(this.rootElement.children[0]);
178 let expectedE = null;
179 try {
180 await this.waitForRefUnmounted(currentRef);
181 } catch (e) {
182 // destoried ref won't be triggered
183 this.expect(triggered).equalToValue(false);
184 expectedE = e;
185 }
186 this.expect(expectedE).notEqualToValue(null);
187
188 triggered = false;
189 const secondComp = creatAComponent();
190 DOM.inject(this.rootElement, secondComp);
191 DOM.remove(this.rootElement.children[0]);
192 await this.waitForRefUnmounted(currentRef);
193 this.expect(triggered).equalToValue(true);
194 this.expect(currentRef.element.parentElement).equalToValue(null);
195 }
196
197 async testOnComplexStateUpdate() {
198 let verifier = null;
199 let triggered = false;
200 let expectedE = null;
201 let initialState = {
202 initialState: Math.random()
203 };
204 let ref = REF.createRef({
205 onStateUpdate:(element, stateDiff, state) => {
206 if (verifier) verifier(element, stateDiff, state);
207 }
208 });
209 ref.setState(initialState);
210 try {
211 await this.waitForStateUpdated(ref);
212 } catch (e) {
213 expectedE = e;
214 }
215 // before element mount, we don't trigger state update callback, we just save the state
216 this.expect(triggered).equalToValue(false);
217 this.expect(expectedE).notEqualToValue(null);
218 this.expect(ref.state.initialState).equalToValue(initialState.initialState);
219 // Each time it will create a new state object
220 this.expect(ref.state).notEqualToValue(initialState);
221
222 DOM.inject(this.rootElement, `<div ref="${ref}"></div>`);
223 verifier = (element, stateDiff, state) => {
224 triggered = true;
225 this.expect(stateDiff.initialState).equalToValue(initialState.initialState);
226 this.expect(state.fakeState).equalToValue(undefined);
227 };
228 await this.waitForStateUpdated(ref);
229 this.expect(triggered).equalToValue(true);
230
231 triggered = false;
232 let fakeState = {
233 fakeState: Math.random()
234 };
235 verifier = (element, stateDiff, state) => {
236 triggered = true;
237 this.expect(stateDiff.fakeState).equalToValue(fakeState.fakeState);
238 this.expect(state.fakeState).equalToValue(undefined);
239
240 this.expect(state.initialState).equalToValue(initialState.initialState);
241 this.expect(stateDiff.initialState).equalToValue(undefined);
242 };
243 ref.setState(fakeState);
244 await this.waitForStateUpdated(ref);
245 this.expect(ref.state.fakeState).equalToValue(fakeState.fakeState);
246 this.expect(ref.state.initialState).equalToValue(initialState.initialState);
247 this.expect(triggered).equalToValue(true);
248 }
249
250 async testOnValueStateUpdate() {
251 let triggered = false;
252 let verifier = null;
253 const initialState = Math.random();
254 const ref = REF.createRef({
255 state: initialState,
256 onStateUpdate:(element, stateDiff, state) => {
257 if (verifier) verifier(element, stateDiff, state);
258 }
259 });
260 verifier = (element, stateDiff, state) => {
261 triggered = true;
262 this.expect(element).notEqualToValue(null);
263 this.expect(stateDiff).equalToValue(initialState);
264 }
265 DOM.inject(this.rootElement, `<div ref="${ref}"></div>`);
266 await this.waitForStateUpdated(ref);
267 this.expect(triggered).equalToValue(true);
268
269 const newState = null;
270 triggered = false;
271 verifier = (element, stateDiff, state) => {
272 triggered = true;
273 this.expect(stateDiff).equalToValue(newState);
274 this.expect(state).equalToValue(initialState);
275 }
276 ref.setState(newState);
277 await this.waitForStateUpdated(ref);
278 this.expect(triggered).equalToValue(true);
279
280 const newState1 = 0;
281 triggered = false;
282 verifier = (element, stateDiff, state) => {
283 triggered = true;
284 this.expect(stateDiff).equalToValue(newState1);
285 this.expect(state).equalToValue(newState);
286 }
287 ref.setState(newState1);
288 await this.waitForStateUpdated(ref);
289 this.expect(triggered).equalToValue(true);
290
291 const newState2 = undefined;
292 let expectedE = null;
293 ref.setState(newState1);
294 try {
295 await this.waitForStateUpdated(ref);
296 } catch(e) {
297 expectedE = e;
298 }
299 this.expect(expectedE).notEqualToValue(null);
300 }
301}
302export {DiffTest, DomTest, RefTest};