style.ts 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. import { assert } from "chai";
  2. import { init, styleModule, h, toVNode } from "../../src/index";
  3. const patch = init([styleModule]);
  4. const featureDiscoveryElm = document.createElement("div");
  5. featureDiscoveryElm.style.setProperty("--foo", "foo");
  6. const hasCssVariables =
  7. featureDiscoveryElm.style.getPropertyValue("--foo") === "foo";
  8. describe("style", function () {
  9. let elm: any, vnode0: any;
  10. beforeEach(function () {
  11. elm = document.createElement("div");
  12. vnode0 = elm;
  13. });
  14. it("is being styled", function () {
  15. elm = patch(vnode0, h("div", { style: { fontSize: "12px" } })).elm;
  16. assert.strictEqual(elm.style.fontSize, "12px");
  17. });
  18. it("can be memoized", function () {
  19. const cachedStyles = { fontSize: "14px", display: "inline" };
  20. const vnode1 = h("i", { style: cachedStyles });
  21. const vnode2 = h("i", { style: cachedStyles });
  22. elm = patch(vnode0, vnode1).elm;
  23. assert.strictEqual(elm.style.fontSize, "14px");
  24. assert.strictEqual(elm.style.display, "inline");
  25. elm = patch(vnode1, vnode2).elm;
  26. assert.strictEqual(elm.style.fontSize, "14px");
  27. assert.strictEqual(elm.style.display, "inline");
  28. });
  29. it("updates styles", function () {
  30. const vnode1 = h("i", { style: { fontSize: "14px", display: "inline" } });
  31. const vnode2 = h("i", { style: { fontSize: "12px", display: "block" } });
  32. const vnode3 = h("i", { style: { fontSize: "10px", display: "block" } });
  33. elm = patch(vnode0, vnode1).elm;
  34. assert.strictEqual(elm.style.fontSize, "14px");
  35. assert.strictEqual(elm.style.display, "inline");
  36. elm = patch(vnode1, vnode2).elm;
  37. assert.strictEqual(elm.style.fontSize, "12px");
  38. assert.strictEqual(elm.style.display, "block");
  39. elm = patch(vnode2, vnode3).elm;
  40. assert.strictEqual(elm.style.fontSize, "10px");
  41. assert.strictEqual(elm.style.display, "block");
  42. });
  43. it("explicialy removes styles", function () {
  44. const vnode1 = h("i", { style: { fontSize: "14px" } });
  45. const vnode2 = h("i", { style: { fontSize: "" } });
  46. const vnode3 = h("i", { style: { fontSize: "10px" } });
  47. elm = patch(vnode0, vnode1).elm;
  48. assert.strictEqual(elm.style.fontSize, "14px");
  49. patch(vnode1, vnode2);
  50. assert.strictEqual(elm.style.fontSize, "");
  51. patch(vnode2, vnode3);
  52. assert.strictEqual(elm.style.fontSize, "10px");
  53. });
  54. it("implicially removes styles from element", function () {
  55. const vnode1 = h("div", [h("i", { style: { fontSize: "14px" } })]);
  56. const vnode2 = h("div", [h("i")]);
  57. const vnode3 = h("div", [h("i", { style: { fontSize: "10px" } })]);
  58. patch(vnode0, vnode1);
  59. assert.strictEqual(elm.firstChild.style.fontSize, "14px");
  60. patch(vnode1, vnode2);
  61. assert.strictEqual(elm.firstChild.style.fontSize, "");
  62. patch(vnode2, vnode3);
  63. assert.strictEqual(elm.firstChild.style.fontSize, "10px");
  64. });
  65. it("updates css variables", function () {
  66. if (!hasCssVariables) {
  67. this.skip();
  68. } else {
  69. const vnode1 = h("div", { style: { "--myVar": 1 as any } });
  70. const vnode2 = h("div", { style: { "--myVar": 2 as any } });
  71. const vnode3 = h("div", { style: { "--myVar": 3 as any } });
  72. elm = patch(vnode0, vnode1).elm;
  73. assert.strictEqual(elm.style.getPropertyValue("--myVar"), "1");
  74. elm = patch(vnode1, vnode2).elm;
  75. assert.strictEqual(elm.style.getPropertyValue("--myVar"), "2");
  76. elm = patch(vnode2, vnode3).elm;
  77. assert.strictEqual(elm.style.getPropertyValue("--myVar"), "3");
  78. }
  79. });
  80. it("explicialy removes css variables", function () {
  81. if (!hasCssVariables) {
  82. this.skip();
  83. } else {
  84. const vnode1 = h("i", { style: { "--myVar": 1 as any } });
  85. const vnode2 = h("i", { style: { "--myVar": "" } });
  86. const vnode3 = h("i", { style: { "--myVar": 2 as any } });
  87. elm = patch(vnode0, vnode1).elm;
  88. assert.strictEqual(elm.style.getPropertyValue("--myVar"), "1");
  89. patch(vnode1, vnode2);
  90. assert.strictEqual(elm.style.getPropertyValue("--myVar"), "");
  91. patch(vnode2, vnode3);
  92. assert.strictEqual(elm.style.getPropertyValue("--myVar"), "2");
  93. }
  94. });
  95. it("implicially removes css variables from element", function () {
  96. if (!hasCssVariables) {
  97. this.skip();
  98. } else {
  99. const vnode1 = h("div", [h("i", { style: { "--myVar": 1 as any } })]);
  100. const vnode2 = h("div", [h("i")]);
  101. const vnode3 = h("div", [h("i", { style: { "--myVar": 2 as any } })]);
  102. patch(vnode0, vnode1);
  103. assert.strictEqual(elm.firstChild.style.getPropertyValue("--myVar"), "1");
  104. patch(vnode1, vnode2);
  105. assert.strictEqual(elm.firstChild.style.getPropertyValue("--myVar"), "");
  106. patch(vnode2, vnode3);
  107. assert.strictEqual(elm.firstChild.style.getPropertyValue("--myVar"), "2");
  108. }
  109. });
  110. it("updates delayed styles in next frame", function (done) {
  111. const vnode1 = h("i", {
  112. style: { fontSize: "14px", delayed: { fontSize: "16px" } as any },
  113. });
  114. const vnode2 = h("i", {
  115. style: { fontSize: "18px", delayed: { fontSize: "20px" } as any },
  116. });
  117. elm = patch(vnode0, vnode1).elm;
  118. assert.strictEqual(elm.style.fontSize, "14px");
  119. requestAnimationFrame(() => {
  120. requestAnimationFrame(() => {
  121. assert.strictEqual(elm.style.fontSize, "16px");
  122. elm = patch(vnode1, vnode2).elm;
  123. assert.strictEqual(elm.style.fontSize, "18px");
  124. requestAnimationFrame(() => {
  125. requestAnimationFrame(() => {
  126. assert.strictEqual(elm.style.fontSize, "20px");
  127. done();
  128. });
  129. });
  130. });
  131. });
  132. });
  133. it("applies tranform as transition on remove", function (done) {
  134. const btn = h(
  135. "button",
  136. {
  137. style: {
  138. transition: "transform 0.1s",
  139. remove: { transform: "translateY(100%)" } as any,
  140. },
  141. },
  142. ["A button"]
  143. );
  144. const vnode1 = h("div.parent", {}, [btn]);
  145. const vnode2 = h("div.parent", {}, [null]);
  146. document.body.appendChild(vnode0);
  147. patch(vnode0, vnode1);
  148. patch(vnode1, vnode2);
  149. const button = document.querySelector("button") as HTMLButtonElement;
  150. assert.notStrictEqual(button, null);
  151. button.addEventListener("transitionend", function () {
  152. assert.strictEqual(document.querySelector("button"), null);
  153. done();
  154. });
  155. });
  156. describe("using toVNode()", function () {
  157. it("handles (ignoring) comment nodes", function () {
  158. const comment = document.createComment("yolo");
  159. const prevElm = document.createElement("div");
  160. prevElm.appendChild(comment);
  161. const nextVNode = h("div", [h("span", "Hi")]);
  162. elm = patch(toVNode(prevElm), nextVNode).elm;
  163. assert.strictEqual(elm, prevElm);
  164. assert.strictEqual(elm.tagName, "DIV");
  165. assert.strictEqual(elm.childNodes.length, 1);
  166. assert.strictEqual(elm.childNodes[0].tagName, "SPAN");
  167. assert.strictEqual(elm.childNodes[0].textContent, "Hi");
  168. });
  169. });
  170. });