UNPKG

data-context-binding

Version:

Simple and lightweight solution for binding data to DOM elements.

426 lines (368 loc) 18.8 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>DB - Tests</title> <!--<script async src="https://cdn.jsdelivr.net/npm/data-context"></script>--> <!--<script async src="https://cdn.jsdelivr.net/npm/data-context-binding"></script>--> <script async src="./datacontext.js"></script> <script async type="text/javascript" src="./browser.js"></script> <script id="data" type="application/json"> [{"nr":123},{"nr":456},{"nr":789}] </script> <script> importModules( ["data-context", "data-context-binding"], function tests(DC, DB) { testRunner("DB - Tests ", { skip: false }, (test) => { test("Startup ", { skip: false }, (check, done) => { var datacontext = DB(); document.body.innerHTML = ""; check(typeof document.body.parentElement.datacontext).mustBe("object"); check(document.body.parentElement.datacontext._isDataContext).mustBe(true); check(document.body.parentElement.datacontext.stringifyChanges()).mustBe(undefined); check(DC.stringify(document.body.parentElement.datacontext)).mustBe('[{"nr":123},{"nr":456},{"nr":789}]'); done(); }); test("Default innerHTMLBind ", { skip: false }, (check) => { var datacontext = DB(); var testDiv = document.createElement('div'); var div = document.createElement('div'); div.setAttribute('path', '[0].nr'); div.setAttribute('bind', ''); testDiv.appendChild(div); document.body.appendChild(testDiv); DB.bindAllElements(testDiv); check(div.innerHTML).mustBe('123'); datacontext[0].nr = 111; check(div.innerHTML).mustBe('111') datacontext[0].nr = 123; check(div.innerHTML).mustBe('123') testDiv.remove(); check(datacontext[0].emit("nr")).mustBe(false); check(datacontext[0]._events["nr"]).mustBe(undefined); return true; }); test("Default valueBind ", { skip: false }, (check) => { //debugger; var datacontext = DB(); var testDiv = document.createElement('div'); var input = document.createElement('input'); input.setAttribute('path', '[0].nr'); input.setAttribute('bind', ''); testDiv.appendChild(input); document.body.appendChild(testDiv); DB.bindAllElements(testDiv); check(input.value).mustBe('123'); input.value = 'abc'; //input.onchange(); input.dispatchEvent(new Event('change', {})); check(datacontext[0].nr).mustBe('abc'); datacontext[0].nr = 123; check(datacontext[0].nr).mustBe(123); check(input.value).mustBe('123'); testDiv.remove(); check(datacontext[0].emit("nr")).mustBe(false); check(datacontext[0]._events["nr"]).mustBe(undefined); return true; }); test("Default checkBind ", { skip: false }, (check) => { //debugger; var datacontext = DB(); datacontext.unshift({ is: true }); var testDiv = document.createElement('div'); var input = document.createElement('input'); input.setAttribute('type', 'checkbox'); input.setAttribute('path', '[0].is'); input.setAttribute('bind', ''); testDiv.appendChild(input); document.body.appendChild(testDiv); DB.bindAllElements(testDiv); check(input.checked).mustBe(true); input.checked = false; //input.onchange(); input.dispatchEvent(new Event('change', {})); check(datacontext[0].is).mustBe(false); datacontext[0].is = true; check(datacontext[0].is).mustBe(true); check(input.checked).mustBe(true); check(Boolean(input.attributes.checked)).mustBe(true); testDiv.remove(); check(datacontext[0].emit("is")).mustBe(false); check(datacontext[0]._events["is"]).mustBe(undefined); datacontext.shift(); check(datacontext.length).mustBe(3); return true; }); test("Default hiddenBind ", { skip: false }, (check) => { //debugger; var datacontext = DB(); datacontext.unshift({ hidden: true }); var testDiv = document.createElement('div'); var div = document.createElement('div'); div.setAttribute('path', '[0].hidden'); div.setAttribute('bind', 'hidden'); div.innerHTML = 'visible text'; testDiv.appendChild(div); document.body.appendChild(testDiv); DB.bindAllElements(testDiv); check(isVisible(div)).mustBe(false); datacontext[0].hidden = false; check(datacontext[0].hidden).mustBe(false); check(isVisible(div)).mustBe(true); testDiv.remove(); check(datacontext[0].emit("hidden")).mustBe(false); check(datacontext[0]._events["hidden"]).mustBe(undefined); datacontext.shift(); check(datacontext.length).mustBe(3); return true; function isVisible(e) { return !!(e.offsetWidth || e.offsetHeight || e.getClientRects().length); } }); test("Default rebinding ", { skip: false }, (check) => { //debugger; var datacontext = DB(); var testDiv = document.createElement('div'); var div = document.createElement('div'); div.setAttribute('path', '[0].nr'); div.setAttribute('bind', ''); testDiv.appendChild(div); document.body.appendChild(testDiv); DB.bindAllElements(testDiv); check(div.innerHTML).mustBe('123'); datacontext[0] = { "nr": 'abc' }; check(div.innerHTML).mustBe('abc'); datacontext[0] = { "nr": 123 }; testDiv.remove(); check(datacontext[0].emit("nr")).mustBe(false); check(datacontext[0]._events["nr"]).mustBe(undefined); return true; }); test("Template ", { skip: false }, (check) => { //debugger; var datacontext = DB(); var testDiv = document.createElement('div'); document.body.appendChild(testDiv); testDiv.setAttribute('template', '#temp'); var template = document.createElement('template'); testDiv.appendChild(template); template.setAttribute('id', 'temp'); template.innerHTML = '<div path="[0].nr" bind></div>' var div = template.content.lastElementChild; DB.bindAllElements(testDiv); check(div.innerHTML).mustBe(''); var newDiv = testDiv.lastElementChild; check(newDiv instanceof HTMLTemplateElement).mustBe(false); check(newDiv.innerHTML).mustBe('123'); datacontext[0] = { "nr": 'abc' }; check(newDiv.innerHTML).mustBe('abc'); datacontext[0] = { "nr": 123 }; testDiv.remove(); check(datacontext[0].emit("nr")).mustBe(false); check(datacontext[0]._events["nr"]).mustBe(undefined); return true; }); test("Template fetch ", { skip: location.protocol === "file:" }, (check, done) => { //debugger; var testDiv = document.createElement('div'); document.body.appendChild(testDiv); testDiv.setAttribute('path', '[0]'); testDiv.setAttribute('template', './template.html'); DB.bindAllElements(testDiv); setTimeout(function () { var datacontext = DB(); var newDiv = testDiv.firstElementChild; check(newDiv instanceof HTMLTemplateElement).mustBe(false); check(newDiv.innerHTML).mustBe('123'); datacontext[0] = { "nr": 'abc' }; check(newDiv.innerHTML).mustBe('abc'); datacontext[0] = { "nr": 123 }; testDiv.remove(); check(datacontext[0].emit("nr")).mustBe(false); check(datacontext[0]._events["nr"]).mustBe(undefined); done(); }, 200); }); test("Templates ", { skip: false }, (check) => { //debugger; var datacontext = DB(); var testDiv = document.createElement('div'); document.body.appendChild(testDiv); testDiv.setAttribute('templates', '#temp'); var template = document.createElement('template'); testDiv.appendChild(template); template.setAttribute('id', 'temp'); template.innerHTML = '<div path="nr" bind></div>' var div = template.content.lastElementChild; DB.bindAllElements(testDiv); check(div.innerHTML).mustBe(''); var lastDiv = testDiv.lastElementChild; check(lastDiv instanceof HTMLTemplateElement).mustBe(false); check(lastDiv.innerHTML).mustBe('789'); datacontext[2] = { "nr": 'abc' }; check(lastDiv.innerHTML).mustBe('abc'); datacontext[2] = { "nr": 789 }; testDiv.remove(); check(datacontext[2].emit("nr")).mustBe(false); check(datacontext[2]._events["nr"]).mustBe(undefined); return true; }); test("Templates fetch ", { skip: location.protocol === "file:" }, (check, done) => { //debugger; var testDiv = document.createElement('div'); document.body.appendChild(testDiv); testDiv.setAttribute('templates', './template.html'); DB.bindAllElements(testDiv); setTimeout(function () { var datacontext = DB(); var newDiv = testDiv.firstElementChild; check(newDiv instanceof HTMLTemplateElement).mustBe(false); check(newDiv.innerHTML).mustBe('123'); datacontext[0] = { "nr": 'abc' }; check(newDiv.innerHTML).mustBe('abc'); datacontext[0] = { "nr": 123 }; testDiv.remove(); check(datacontext[0].emit("nr")).mustBe(false); check(datacontext[0]._events["nr"]).mustBe(undefined); done(); }, 200); }); }); }); function testRunner(runnerName, options, cb) { var stdout = "", timeouts = {}, countStarted = 0, countCompleted = 0, testsStarted = false, testOK = true, strSKIP = '[<span style="background-color:gray;"> SKIP </span>]', strTestsERR = '[<span style="background-color:red;"> The tests failed! </span>]', strTestsDONE = '[<span style="background-color:green;"> The tests are done! </span>]'; //skip if (options?.skip) { testsStarted = "SKIP"; if (runnerName) { log("SKIP > ", spaces(runnerName), " > ", strSKIP); } testCompleted(); return testOK; } if (runnerName) { log("START > ", spaces(runnerName)); } cb(test); testsStarted = true; testCompleted(); return testOK; function log() { for (let i = 0; i < arguments.length; i++) { stdout += arguments[i]; } stdout += "<br>"; } function test(testName, options, fn) { var startTime, endTime, id = ++countStarted, label = '<span style="min-width:50px;color:initial;justify-content:right;">' + id + ".</span> TEST > " + spaces(testName), strOK = '[<span style="background-color:green;">OK</span>]', strERR = '[<span style="background-color:red;">FAILED</span>]<span>-></span>'; wait(function () { //skip if (options?.skip) { log(label, "<span></span>", strSKIP); testCompleted(); return; } //timeout timeouts[id] = setTimeout(function () { done("timeout"); }, options?.timeout || 5000); startTime = performance.now(); try { if (fn(check, done)) { done(); } } catch (err) { done(err); } }); function done(err = '') { endTime = performance.now(); if (err) { testOK = false; } log(label, '<span style="color:initial;justify-content:left;"> : ', (endTime - startTime).toFixed(2), "ms </span>", err ? strERR : strOK, err || ""); if (timeouts[id]) { testCompleted(); } clearTimeout(timeouts[id]); delete timeouts[id]; } function check(value) { return { mustBe: function mustBe(mustBe) { if (value !== mustBe) { throw ' returned: <span style="background-color:blue;"> ' + value + ' </span><span></span> must be: <span style="background-color:blue;" > ' + mustBe + ' </span>'; } return this; }, mustNotBe: function mustNotBe(mustNotBe) { if (value === mustNotBe) { throw ' returned: <span style="background-color:blue;"> ' + value + ' </span><span></span> must not be: <span style="background-color:blue;" > ' + mustNotBe + ' </span>'; } return this; }, done }; } function wait(cb) { if (Object.keys(timeouts).length) { setTimeout(wait, 10, cb); } else { cb(); } } } function testCompleted() { countCompleted++; if (!testsStarted || countStarted >= countCompleted) { return; } if (runnerName) { if (testsStarted === "SKIP") { document.body.innerHTML += "<hr>" + stdout + "<hr>"; } else if (!testOK) { log("END > ", runnerName, " > ", strTestsERR); document.body.innerHTML += "<hr>" + stdout + "<hr>"; } else { log("END > ", runnerName, " > ", strTestsDONE); document.body.innerHTML += "<hr>" + stdout + "<hr>"; } } } function spaces(s) { return '<span style="color:initial;justify-content:left;min-width:200px;">' + s + '</span>'; } } /** * Module import function - step 2. * @param {string[]} importIdentifierArray Modules to import. * @param {(...importModules:any[]) => void} callback Callback function. */ function importModules(importIdentifierArray, callback) { var thisScope = "undefined" != typeof globalThis ? globalThis : "undefined" != typeof window ? window : "undefined" != typeof global ? global : "undefined" != typeof self ? self : {}; if (!thisScope.modules) { thisScope.modules = {}; } waitModules(); function waitModules() { if (importIdentifierArray.length) { for (let i = 0; i < importIdentifierArray.length; i++) { if (!thisScope.modules[importIdentifierArray[i]]) { return setTimeout(waitModules, 10); } } } callback.call(thisScope, ...importIdentifierArray.map(function (id) { return thisScope.modules[id]; })); } } </script> <style type="text/css"> span { display: inline-flex; min-width: 140px; color: white; justify-content: center; margin: 2px; } </style> </head> <body></body> </html>