|
3 | 3 | // ../test/van.test.js
|
4 | 4 | window.numTests = 0;
|
5 | 5 | var runTests = async (van2, msgDom2, { debug }) => {
|
6 |
| - const { a, b, button, div: div2, h2: h22, input, li, option, p, pre, select, span, sup, table, tbody, td, th, thead, tr, ul } = van2.tags; |
| 6 | + const { a, b, button, div: div2, h2: h22, i, input, li, option, p, pre, select, span, sup, table, tbody, td, th, thead, tr, ul } = van2.tags; |
7 | 7 | const assert = (cond) => {
|
8 | 8 | if (!cond)
|
9 | 9 | throw new Error("Assertion failed");
|
|
447 | 447 | },
|
448 | 448 | derive_derivedState: () => {
|
449 | 449 | const numItems = van2.state(0);
|
450 |
| - const items = van2.derive(() => [...Array(numItems.val).keys()].map((i) => `Item ${i + 1}`)); |
| 450 | + const items = van2.derive(() => [...Array(numItems.val).keys()].map((i2) => `Item ${i2 + 1}`)); |
451 | 451 | const selectedIndex = van2.derive(() => (items.val, 0));
|
452 | 452 | const selectedItem = van2.derive(() => items.val[selectedIndex.val]);
|
453 | 453 | numItems.val = 3;
|
|
610 | 610 | }),
|
611 | 611 | stateDerivedChild_statefulDynamicDom: withHiddenDom(async (hiddenDom) => {
|
612 | 612 | const numItems = van2.state(0);
|
613 |
| - const items = van2.derive(() => [...Array(numItems.val).keys()].map((i) => `Item ${i + 1}`)); |
| 613 | + const items = van2.derive(() => [...Array(numItems.val).keys()].map((i2) => `Item ${i2 + 1}`)); |
614 | 614 | const selectedIndex = van2.derive(() => (items.val, 0));
|
615 | 615 | const domFunc = (dom) => {
|
616 | 616 | if (dom && items.val === items.oldVal) {
|
|
619 | 619 | itemDoms[selectedIndex.val].classList.add("selected");
|
620 | 620 | return dom;
|
621 | 621 | }
|
622 |
| - return ul(items.val.map((item, i) => li({ class: i === selectedIndex.val ? "selected" : "" }, item))); |
| 622 | + return ul(items.val.map((item, i2) => li({ class: i2 === selectedIndex.val ? "selected" : "" }, item))); |
623 | 623 | };
|
624 | 624 | van2.add(hiddenDom, domFunc);
|
625 | 625 | numItems.val = 3;
|
|
978 | 978 | hiddenDom.innerHTML = div2(h22("Basic Counter"), Counter2({ van: van2, init: counterInit }), h22("Styled Counter"), p("Select the button style: ", selectDom), Counter2({ van: van2, init: counterInit, buttonStyle })).innerHTML;
|
979 | 979 | const clickBtns = async (dom, numUp, numDown) => {
|
980 | 980 | const [upBtn, downBtn] = [...dom.querySelectorAll("button")];
|
981 |
| - for (let i = 0; i < numUp; ++i) { |
| 981 | + for (let i2 = 0; i2 < numUp; ++i2) { |
982 | 982 | upBtn.click();
|
983 | 983 | await sleep(waitMsOnDomUpdates);
|
984 | 984 | }
|
985 |
| - for (let i = 0; i < numDown; ++i) { |
| 985 | + for (let i2 = 0; i2 < numDown; ++i2) { |
986 | 986 | downBtn.click();
|
987 | 987 | await sleep(waitMsOnDomUpdates);
|
988 | 988 | }
|
|
1186 | 1186 | " ",
|
1187 | 1187 | select({ oninput: (e) => sortedBy.val = e.target.value, value: sortedBy }, option({ value: "Ascending" }, "Ascending"), option({ value: "Descending" }, "Descending")),
|
1188 | 1188 | // A State-derived child node
|
1189 |
| - () => sortedBy.val === "Ascending" ? ul(items.val.split(",").sort().map((i) => li(i))) : ul(items.val.split(",").sort().reverse().map((i) => li(i))) |
| 1189 | + () => sortedBy.val === "Ascending" ? ul(items.val.split(",").sort().map((i2) => li(i2))) : ul(items.val.split(",").sort().reverse().map((i2) => li(i2))) |
1190 | 1190 | );
|
1191 | 1191 | };
|
1192 | 1192 | van2.add(hiddenDom, SortedList());
|
|
1286 | 1286 | await sleep(waitMsOnDomUpdates);
|
1287 | 1287 | assertEq(hiddenDom.innerHTML, '<span><button style="background-color: yellow;">Click Me</button> <button style="background-color: green;">Turn Red</button> <button style="background-color: rgb(235, 235, 235);">Get Darker</button></span>');
|
1288 | 1288 | }),
|
| 1289 | + hydrate: hydrateExample(Counter), |
| 1290 | + hydrateOptimized: hydrateExample(OptimizedCounter), |
1289 | 1291 | domValuedState_excludeDebug: withHiddenDom(async (hiddenDom) => {
|
1290 | 1292 | const TurnBold = () => {
|
1291 | 1293 | const vanJS = van2.state("VanJS");
|
1292 | 1294 | return span(button({ onclick: () => vanJS.val = b("VanJS") }, "Turn Bold"), " Welcome to ", vanJS, ". ", vanJS, " is awesome!");
|
1293 | 1295 | };
|
1294 | 1296 | van2.add(hiddenDom, TurnBold());
|
1295 | 1297 | const dom = hiddenDom.firstChild;
|
1296 |
| - assertEq(dom.outerHTML, "<span><button>Turn Bold</button> Welcome to VanJS. VanJS is awesome!</span>"); |
| 1298 | + assertEq(dom.outerHTML, "<span><button>Turn Bold</button> Welcome to VanJS. VanJS is awesome!</span>"); |
1297 | 1299 | dom.querySelector("button").click();
|
1298 | 1300 | await sleep(waitMsOnDomUpdates);
|
1299 |
| - assertEq(dom.outerHTML, "<span><button>Turn Bold</button> Welcome to . <b>VanJS</b> is awesome!</span>"); |
| 1301 | + assertEq(dom.outerHTML, "<span><button>Turn Bold</button> Welcome to . <b>VanJS</b> is awesome!</span>"); |
1300 | 1302 | }),
|
1301 |
| - hydrate: hydrateExample(Counter), |
1302 |
| - hydrateOptimized: hydrateExample(OptimizedCounter) |
| 1303 | + minimizeDomUpdates: withHiddenDom(async (hiddenDom) => { |
| 1304 | + const name = van2.state(""); |
| 1305 | + const Name1 = () => { |
| 1306 | + const numRendered = van2.state(0); |
| 1307 | + return div2(() => { |
| 1308 | + ++numRendered.val; |
| 1309 | + return name.val.trim().length === 0 ? p("Please enter your name") : p("Hello ", b(name)); |
| 1310 | + }, p(i("The <p> element has been rendered ", numRendered, " time(s)."))); |
| 1311 | + }; |
| 1312 | + const Name2 = () => { |
| 1313 | + const numRendered = van2.state(0); |
| 1314 | + const isNameEmpty = van2.derive(() => name.val.trim().length === 0); |
| 1315 | + return div2(() => { |
| 1316 | + ++numRendered.val; |
| 1317 | + return isNameEmpty.val ? p("Please enter your name") : p("Hello ", b(name)); |
| 1318 | + }, p(i("The <p> element has been rendered ", numRendered, " time(s)."))); |
| 1319 | + }; |
| 1320 | + van2.add(hiddenDom, p("Your name is: ", input({ type: "text", value: name, oninput: (e) => name.val = e.target.value })), Name1(), Name2()); |
| 1321 | + await sleep(waitMsOnDomUpdates); |
| 1322 | + assertEq(hiddenDom.innerHTML, '<p>Your name is: <input type="text"></p><div><p>Please enter your name</p><p><i>The <p> element has been rendered 1 time(s).</i></p></div><div><p>Please enter your name</p><p><i>The <p> element has been rendered 1 time(s).</i></p></div>'); |
| 1323 | + hiddenDom.querySelector("input").value = "T"; |
| 1324 | + hiddenDom.querySelector("input").dispatchEvent(new Event("input")); |
| 1325 | + await sleep(waitMsOnDomUpdates); |
| 1326 | + hiddenDom.querySelector("input").value = "Ta"; |
| 1327 | + hiddenDom.querySelector("input").dispatchEvent(new Event("input")); |
| 1328 | + await sleep(waitMsOnDomUpdates); |
| 1329 | + hiddenDom.querySelector("input").value = "Tao"; |
| 1330 | + hiddenDom.querySelector("input").dispatchEvent(new Event("input")); |
| 1331 | + await sleep(waitMsOnDomUpdates); |
| 1332 | + await sleep(waitMsOnDomUpdates); |
| 1333 | + assertEq(hiddenDom.innerHTML, '<p>Your name is: <input type="text"></p><div><p>Hello <b>Tao</b></p><p><i>The <p> element has been rendered 4 time(s).</i></p></div><div><p>Hello <b>Tao</b></p><p><i>The <p> element has been rendered 2 time(s).</i></p></div>'); |
| 1334 | + hiddenDom.querySelector("input").value = ""; |
| 1335 | + hiddenDom.querySelector("input").dispatchEvent(new Event("input")); |
| 1336 | + await sleep(waitMsOnDomUpdates * 2); |
| 1337 | + assertEq(hiddenDom.innerHTML, '<p>Your name is: <input type="text"></p><div><p>Please enter your name</p><p><i>The <p> element has been rendered 5 time(s).</i></p></div><div><p>Please enter your name</p><p><i>The <p> element has been rendered 3 time(s).</i></p></div>'); |
| 1338 | + hiddenDom.querySelector("input").value = "X"; |
| 1339 | + hiddenDom.querySelector("input").dispatchEvent(new Event("input")); |
| 1340 | + await sleep(waitMsOnDomUpdates); |
| 1341 | + hiddenDom.querySelector("input").value = "Xi"; |
| 1342 | + hiddenDom.querySelector("input").dispatchEvent(new Event("input")); |
| 1343 | + await sleep(waitMsOnDomUpdates); |
| 1344 | + hiddenDom.querySelector("input").value = "Xin"; |
| 1345 | + hiddenDom.querySelector("input").dispatchEvent(new Event("input")); |
| 1346 | + await sleep(waitMsOnDomUpdates); |
| 1347 | + await sleep(waitMsOnDomUpdates); |
| 1348 | + assertEq(hiddenDom.innerHTML, '<p>Your name is: <input type="text"></p><div><p>Hello <b>Xin</b></p><p><i>The <p> element has been rendered 8 time(s).</i></p></div><div><p>Hello <b>Xin</b></p><p><i>The <p> element has been rendered 4 time(s).</i></p></div>'); |
| 1349 | + }) |
1303 | 1350 | };
|
1304 | 1351 | const gcTests = {
|
1305 | 1352 | bindingBasic: withHiddenDom(async (hiddenDom) => {
|
1306 | 1353 | const counter = van2.state(0);
|
1307 | 1354 | const bindingsPropKey = Object.entries(counter).find(([_, v]) => Array.isArray(v))[0];
|
1308 | 1355 | van2.add(hiddenDom, () => span(`Counter: ${counter.val}`));
|
1309 |
| - for (let i = 0; i < 100; ++i) |
| 1356 | + for (let i2 = 0; i2 < 100; ++i2) |
1310 | 1357 | ++counter.val;
|
1311 | 1358 | await sleep(waitMsOnDomUpdates);
|
1312 | 1359 | assertEq(hiddenDom.innerHTML, "<span>Counter: 100</span>");
|
|
1317 | 1364 | const bindingsPropKey = Object.entries(renderPre).find(([_, v]) => Array.isArray(v))[0];
|
1318 | 1365 | const dom = div2(() => (renderPre.val ? pre : div2)(() => `--${text.val}--`));
|
1319 | 1366 | van2.add(hiddenDom, dom);
|
1320 |
| - for (let i = 0; i < 20; ++i) { |
| 1367 | + for (let i2 = 0; i2 < 20; ++i2) { |
1321 | 1368 | renderPre.val = !renderPre.val;
|
1322 | 1369 | await sleep(waitMsOnDomUpdates);
|
1323 | 1370 | }
|
|
1332 | 1379 | const dom = div2(() => cond.val ? a2.val + b2.val : c.val + d.val);
|
1333 | 1380 | van2.add(hiddenDom, dom);
|
1334 | 1381 | const allStates = [cond, a2, b2, c, d];
|
1335 |
| - for (let i = 0; i < 100; ++i) { |
| 1382 | + for (let i2 = 0; i2 < 100; ++i2) { |
1336 | 1383 | const randomState = allStates[Math.floor(Math.random() * allStates.length)];
|
1337 | 1384 | if (randomState === cond)
|
1338 | 1385 | randomState.val = !randomState.val;
|
|
1349 | 1396 | const a2 = van2.state(0);
|
1350 | 1397 | const listenersPropKey = Object.entries(a2).filter(([_, v]) => Array.isArray(v))[1][0];
|
1351 | 1398 | van2.derive(() => history.push(a2.val));
|
1352 |
| - for (let i = 0; i < 100; ++i) |
| 1399 | + for (let i2 = 0; i2 < 100; ++i2) |
1353 | 1400 | ++a2.val;
|
1354 | 1401 | assertEq(history.length, 101);
|
1355 | 1402 | assertBetween(a2[listenersPropKey].length, 1, 3);
|
|
1363 | 1410 | return (renderPre.val ? pre : div2)(() => `--${text.val}--`);
|
1364 | 1411 | });
|
1365 | 1412 | van2.add(hiddenDom, dom);
|
1366 |
| - for (let i = 0; i < 20; ++i) { |
| 1413 | + for (let i2 = 0; i2 < 20; ++i2) { |
1367 | 1414 | renderPre.val = !renderPre.val;
|
1368 | 1415 | await sleep(waitMsOnDomUpdates);
|
1369 | 1416 | }
|
|
1377 | 1424 | const listenersPropKey = Object.entries(renderPre).filter(([_, v]) => Array.isArray(v))[1][0];
|
1378 | 1425 | const dom = div2(() => (renderPre.val ? pre : div2)({ class: () => class1.val ? "class1" : "class2" }, "Text"));
|
1379 | 1426 | van2.add(hiddenDom, dom);
|
1380 |
| - for (let i = 0; i < 20; ++i) { |
| 1427 | + for (let i2 = 0; i2 < 20; ++i2) { |
1381 | 1428 | renderPre.val = !renderPre.val;
|
1382 | 1429 | await sleep(waitMsOnDomUpdates);
|
1383 | 1430 | }
|
|
1393 | 1440 | oncustom: van2.derive(() => handlerType.val === 1 ? () => van2.add(hiddenDom, p("Handler 1 triggered!")) : () => van2.add(hiddenDom, p("Handler 2 triggered!")))
|
1394 | 1441 | })));
|
1395 | 1442 | van2.add(hiddenDom, dom);
|
1396 |
| - for (let i = 0; i < 20; ++i) { |
| 1443 | + for (let i2 = 0; i2 < 20; ++i2) { |
1397 | 1444 | renderPre.val = !renderPre.val;
|
1398 | 1445 | await sleep(waitMsOnDomUpdates);
|
1399 | 1446 | }
|
|
1407 | 1454 | const listenersPropKey = Object.entries(a2).filter(([_, v]) => Array.isArray(v))[1][0];
|
1408 | 1455 | van2.derive(() => cond.val ? a2.val + b2.val : c.val + d.val);
|
1409 | 1456 | const allStates = [cond, a2, b2, c, d];
|
1410 |
| - for (let i = 0; i < 100; ++i) { |
| 1457 | + for (let i2 = 0; i2 < 100; ++i2) { |
1411 | 1458 | const randomState = allStates[Math.floor(Math.random() * allStates.length)];
|
1412 | 1459 | if (randomState === cond)
|
1413 | 1460 | randomState.val = !randomState.val;
|
|
0 commit comments