caching-api.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. import { makeStrongCache } from "../lib/config/caching";
  2. describe("caching API", () => {
  3. it("should allow permacaching with .forever()", () => {
  4. let count = 0;
  5. const fn = makeStrongCache((arg, cache) => {
  6. cache.forever();
  7. return { arg, count: count++ };
  8. });
  9. expect(fn("one")).toEqual({ arg: "one", count: 0 });
  10. expect(fn("one")).toBe(fn("one"));
  11. expect(fn("two")).toEqual({ arg: "two", count: 1 });
  12. expect(fn("two")).toBe(fn("two"));
  13. expect(fn("one")).not.toEqual(fn("two"));
  14. });
  15. it("should allow disabling caching with .never()", () => {
  16. let count = 0;
  17. const fn = makeStrongCache((arg, cache) => {
  18. cache.never();
  19. return { arg, count: count++ };
  20. });
  21. expect(fn("one")).toEqual({ arg: "one", count: 0 });
  22. expect(fn("one")).toEqual({ arg: "one", count: 1 });
  23. expect(fn("one")).not.toEqual(fn("one"));
  24. expect(fn("two")).toEqual({ arg: "two", count: 4 });
  25. expect(fn("two")).toEqual({ arg: "two", count: 5 });
  26. expect(fn("two")).not.toEqual(fn("two"));
  27. expect(fn("one")).not.toEqual(fn("two"));
  28. });
  29. it("should allow caching based on a value with .using(fn)", () => {
  30. let count = 0;
  31. let other = "default";
  32. const fn = makeStrongCache((arg, cache) => {
  33. const val = cache.using(() => other);
  34. return { arg, val, count: count++ };
  35. });
  36. expect(fn("one")).toEqual({ arg: "one", val: "default", count: 0 });
  37. expect(fn("one")).toBe(fn("one"));
  38. expect(fn("two")).toEqual({ arg: "two", val: "default", count: 1 });
  39. expect(fn("two")).toBe(fn("two"));
  40. other = "new";
  41. expect(fn("one")).toEqual({ arg: "one", val: "new", count: 2 });
  42. expect(fn("one")).toBe(fn("one"));
  43. expect(fn("two")).toEqual({ arg: "two", val: "new", count: 3 });
  44. expect(fn("two")).toBe(fn("two"));
  45. other = "default";
  46. expect(fn("one")).toEqual({ arg: "one", val: "default", count: 0 });
  47. expect(fn("one")).toBe(fn("one"));
  48. expect(fn("two")).toEqual({ arg: "two", val: "default", count: 1 });
  49. expect(fn("two")).toBe(fn("two"));
  50. other = "new";
  51. expect(fn("one")).toEqual({ arg: "one", val: "new", count: 2 });
  52. expect(fn("one")).toBe(fn("one"));
  53. expect(fn("two")).toEqual({ arg: "two", val: "new", count: 3 });
  54. expect(fn("two")).toBe(fn("two"));
  55. });
  56. it("should allow invalidation based on a value with .invalidate(fn)", () => {
  57. let count = 0;
  58. let other = "default";
  59. const fn = makeStrongCache((arg, cache) => {
  60. const val = cache.invalidate(() => other);
  61. return { arg, val, count: count++ };
  62. });
  63. expect(fn("one")).toEqual({ arg: "one", val: "default", count: 0 });
  64. expect(fn("one")).toBe(fn("one"));
  65. expect(fn("two")).toEqual({ arg: "two", val: "default", count: 1 });
  66. expect(fn("two")).toBe(fn("two"));
  67. other = "new";
  68. expect(fn("one")).toEqual({ arg: "one", val: "new", count: 2 });
  69. expect(fn("one")).toBe(fn("one"));
  70. expect(fn("two")).toEqual({ arg: "two", val: "new", count: 3 });
  71. expect(fn("two")).toBe(fn("two"));
  72. other = "default";
  73. expect(fn("one")).toEqual({ arg: "one", val: "default", count: 4 });
  74. expect(fn("one")).toBe(fn("one"));
  75. expect(fn("two")).toEqual({ arg: "two", val: "default", count: 5 });
  76. expect(fn("two")).toBe(fn("two"));
  77. other = "new";
  78. expect(fn("one")).toEqual({ arg: "one", val: "new", count: 6 });
  79. expect(fn("one")).toBe(fn("one"));
  80. expect(fn("two")).toEqual({ arg: "two", val: "new", count: 7 });
  81. expect(fn("two")).toBe(fn("two"));
  82. });
  83. it("should allow invalidation with .using and .invalidate", () => {
  84. let count = 0;
  85. let other = "default";
  86. let another = "another";
  87. const fn = makeStrongCache((arg, cache) => {
  88. const val = cache.using(() => other);
  89. const val2 = cache.invalidate(() => another);
  90. return { arg, val, val2, count: count++ };
  91. });
  92. expect(fn("one")).toEqual({
  93. arg: "one",
  94. val: "default",
  95. val2: "another",
  96. count: 0,
  97. });
  98. expect(fn("one")).toBe(fn("one"));
  99. expect(fn("two")).toEqual({
  100. arg: "two",
  101. val: "default",
  102. val2: "another",
  103. count: 1,
  104. });
  105. expect(fn("two")).toBe(fn("two"));
  106. other = "new";
  107. expect(fn("one")).toEqual({
  108. arg: "one",
  109. val: "new",
  110. val2: "another",
  111. count: 2,
  112. });
  113. expect(fn("one")).toBe(fn("one"));
  114. expect(fn("two")).toEqual({
  115. arg: "two",
  116. val: "new",
  117. val2: "another",
  118. count: 3,
  119. });
  120. expect(fn("two")).toBe(fn("two"));
  121. other = "default";
  122. expect(fn("one")).toEqual({
  123. arg: "one",
  124. val: "default",
  125. val2: "another",
  126. count: 4,
  127. });
  128. expect(fn("one")).toBe(fn("one"));
  129. expect(fn("two")).toEqual({
  130. arg: "two",
  131. val: "default",
  132. val2: "another",
  133. count: 5,
  134. });
  135. expect(fn("two")).toBe(fn("two"));
  136. other = "new";
  137. expect(fn("one")).toEqual({
  138. arg: "one",
  139. val: "new",
  140. val2: "another",
  141. count: 6,
  142. });
  143. expect(fn("one")).toBe(fn("one"));
  144. expect(fn("two")).toEqual({
  145. arg: "two",
  146. val: "new",
  147. val2: "another",
  148. count: 7,
  149. });
  150. expect(fn("two")).toBe(fn("two"));
  151. another = "second";
  152. expect(fn("one")).toEqual({
  153. arg: "one",
  154. val: "new",
  155. val2: "second",
  156. count: 8,
  157. });
  158. expect(fn("one")).toBe(fn("one"));
  159. expect(fn("two")).toEqual({
  160. arg: "two",
  161. val: "new",
  162. val2: "second",
  163. count: 9,
  164. });
  165. expect(fn("two")).toBe(fn("two"));
  166. });
  167. it("should auto-permacache by default", () => {
  168. let count = 0;
  169. const fn = makeStrongCache(arg => ({ arg, count: count++ }));
  170. expect(fn("one")).toEqual({ arg: "one", count: 0 });
  171. expect(fn("one")).toBe(fn("one"));
  172. expect(fn("two")).toEqual({ arg: "two", count: 1 });
  173. expect(fn("two")).toBe(fn("two"));
  174. expect(fn("one")).not.toEqual(fn("two"));
  175. });
  176. it("should throw if you set permacaching and use .using", () => {
  177. const fn = makeStrongCache((arg, cache) => {
  178. cache.forever();
  179. cache.using(() => null);
  180. });
  181. expect(() => fn()).toThrow(/Caching has already been configured/);
  182. });
  183. it("should throw if you set permacaching and use .invalidate", () => {
  184. const fn = makeStrongCache((arg, cache) => {
  185. cache.forever();
  186. cache.invalidate(() => null);
  187. });
  188. expect(() => fn()).toThrow(/Caching has already been configured/);
  189. });
  190. it("should throw if you set permacaching and use .never", () => {
  191. const fn = makeStrongCache((arg, cache) => {
  192. cache.forever();
  193. cache.never();
  194. });
  195. expect(() => fn()).toThrow(/Caching has already been configured/);
  196. });
  197. it("should throw if you set no caching and use .using", () => {
  198. const fn = makeStrongCache((arg, cache) => {
  199. cache.never();
  200. cache.using(() => null);
  201. });
  202. expect(() => fn()).toThrow(/Caching has already been configured/);
  203. });
  204. it("should throw if you set no caching and use .invalidate", () => {
  205. const fn = makeStrongCache((arg, cache) => {
  206. cache.never();
  207. cache.invalidate(() => null);
  208. });
  209. expect(() => fn()).toThrow(/Caching has already been configured/);
  210. });
  211. it("should throw if you set no caching and use .never", () => {
  212. const fn = makeStrongCache((arg, cache) => {
  213. cache.never();
  214. cache.using(() => null);
  215. });
  216. expect(() => fn()).toThrow(/Caching has already been configured/);
  217. });
  218. it("should throw if you configure .forever after exiting", () => {
  219. const fn = makeStrongCache((arg, cache) => cache);
  220. expect(() => fn().forever()).toThrow(
  221. /Cannot change caching after evaluation/,
  222. );
  223. });
  224. it("should throw if you configure .never after exiting", () => {
  225. const fn = makeStrongCache((arg, cache) => cache);
  226. expect(() => fn().never()).toThrow(
  227. /Cannot change caching after evaluation/,
  228. );
  229. });
  230. it("should throw if you configure .using after exiting", () => {
  231. const fn = makeStrongCache((arg, cache) => cache);
  232. expect(() => fn().using(() => null)).toThrow(
  233. /Cannot change caching after evaluation/,
  234. );
  235. });
  236. it("should throw if you configure .invalidate after exiting", () => {
  237. const fn = makeStrongCache((arg, cache) => cache);
  238. expect(() => fn().invalidate(() => null)).toThrow(
  239. /Cannot change caching after evaluation/,
  240. );
  241. });
  242. describe("simple", () => {
  243. it("should allow permacaching with cache(true)", () => {
  244. let count = 0;
  245. const fn = makeStrongCache((arg, cache) => {
  246. cache = cache.simple();
  247. cache(true);
  248. return { arg, count: count++ };
  249. });
  250. expect(fn("one")).toEqual({ arg: "one", count: 0 });
  251. expect(fn("one")).toBe(fn("one"));
  252. expect(fn("two")).toEqual({ arg: "two", count: 1 });
  253. expect(fn("two")).toBe(fn("two"));
  254. expect(fn("one")).not.toEqual(fn("two"));
  255. });
  256. it("should allow disabling caching with cache(false)", () => {
  257. let count = 0;
  258. const fn = makeStrongCache((arg, cache) => {
  259. cache = cache.simple();
  260. cache(false);
  261. return { arg, count: count++ };
  262. });
  263. expect(fn("one")).toEqual({ arg: "one", count: 0 });
  264. expect(fn("one")).toEqual({ arg: "one", count: 1 });
  265. expect(fn("one")).not.toEqual(fn("one"));
  266. expect(fn("two")).toEqual({ arg: "two", count: 4 });
  267. expect(fn("two")).toEqual({ arg: "two", count: 5 });
  268. expect(fn("two")).not.toEqual(fn("two"));
  269. expect(fn("one")).not.toEqual(fn("two"));
  270. });
  271. it("should allow caching based on a value with cache(fn)", () => {
  272. let count = 0;
  273. let other = "default";
  274. const fn = makeStrongCache((arg, cache) => {
  275. cache = cache.simple();
  276. const val = cache(() => other);
  277. return { arg, val, count: count++ };
  278. });
  279. expect(fn("one")).toEqual({ arg: "one", val: "default", count: 0 });
  280. expect(fn("one")).toBe(fn("one"));
  281. expect(fn("two")).toEqual({ arg: "two", val: "default", count: 1 });
  282. expect(fn("two")).toBe(fn("two"));
  283. other = "new";
  284. expect(fn("one")).toEqual({ arg: "one", val: "new", count: 2 });
  285. expect(fn("one")).toBe(fn("one"));
  286. expect(fn("two")).toEqual({ arg: "two", val: "new", count: 3 });
  287. expect(fn("two")).toBe(fn("two"));
  288. other = "default";
  289. expect(fn("one")).toEqual({ arg: "one", val: "default", count: 0 });
  290. expect(fn("one")).toBe(fn("one"));
  291. expect(fn("two")).toEqual({ arg: "two", val: "default", count: 1 });
  292. expect(fn("two")).toBe(fn("two"));
  293. other = "new";
  294. expect(fn("one")).toEqual({ arg: "one", val: "new", count: 2 });
  295. expect(fn("one")).toBe(fn("one"));
  296. expect(fn("two")).toEqual({ arg: "two", val: "new", count: 3 });
  297. expect(fn("two")).toBe(fn("two"));
  298. });
  299. });
  300. });