test-sequence.js 35 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163
  1. /* This Source Code Form is subject to the terms of the Mozilla Public
  2. * License, v. 2.0. If a copy of the MPL was not distributed with this
  3. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  4. "use strict";
  5. let { seq, iterate, filter, map, reductions, reduce, count,
  6. isEmpty, every, isEvery, some, take, takeWhile, drop,
  7. dropWhile, concat, first, rest, nth, last, dropLast,
  8. distinct, remove, mapcat, fromEnumerator, string,
  9. object, pairs, keys, values, each
  10. } = require("sdk/util/sequence");
  11. const boom = () => { throw new Error("Boom!"); };
  12. const broken = seq(function*() {
  13. yield 1;
  14. throw new Error("Boom!");
  15. });
  16. exports["test seq"] = assert => {
  17. let xs = seq(function*() {
  18. yield 1;
  19. yield 2;
  20. yield 3;
  21. });
  22. assert.deepEqual([...seq(null)], [], "seq of null is empty");
  23. assert.deepEqual([...seq(void(0))], [], "seq of void is empty");
  24. assert.deepEqual([...xs], [1, 2, 3], "seq of 1 2 3");
  25. assert.deepEqual([...seq(xs)], [1, 2, 3], "seq of seq is seq");
  26. assert.deepEqual([...seq([])], [], "seq of emtpy array is empty");
  27. assert.deepEqual([...seq([1])], [1], "seq of lonly array is single element");
  28. assert.deepEqual([...seq([1, 2, 3])], [1, 2, 3], "seq of array is it's elements");
  29. assert.deepEqual([...seq("")], [], "seq of emtpy string is empty");
  30. assert.deepEqual([...seq("o")], ["o"], "seq of char is single char seq");
  31. assert.deepEqual([...seq("hello")], ["h", "e", "l", "l", "o"],
  32. "seq of string are chars");
  33. assert.deepEqual([...seq(new Set())], [], "seq of emtpy set is empty");
  34. assert.deepEqual([...seq(new Set([1]))], [1], "seq of lonely set is single");
  35. assert.deepEqual([...seq(new Set([1, 2, 3]))], [1, 2, 3], "seq of lonely set is single");
  36. assert.deepEqual([...seq(new Map())], [], "seq of emtpy map is empty");
  37. assert.deepEqual([...seq(new Map([[1, 2]]))], [[1, 2]], "seq single mapping is that mapping");
  38. assert.deepEqual([...seq(new Map([[1, 2], [3, 4], [5, 6]]))],
  39. [[1, 2], [3, 4], [5, 6]],
  40. "seq of map is key value mappings");
  41. [function(){}, 1, /foo/, true].forEach(x => {
  42. assert.throws(() => seq(x), "Type is not seq-able");
  43. });
  44. assert.throws(() => [...broken],
  45. /Boom/,
  46. "broken sequence errors propagate");
  47. };
  48. exports["test seq casting"] = assert => {
  49. const xs = seq(function*() { yield 1; yield 2; yield 3; });
  50. const ys = seq(function*() { yield 1; });
  51. const zs = seq(function*() {});
  52. const kvs = seq(function*() { yield ["a", 1]; yield ["b", 2]; });
  53. const kv = seq(function*() { yield ["a", 1]; });
  54. assert.deepEqual([...xs], [1, 2, 3], "cast to array");
  55. assert.deepEqual([...ys], [1], "cast to of one element");
  56. assert.deepEqual([...zs], [], "cast empty array");
  57. assert.deepEqual(string(...xs), "123", "cast to string");
  58. assert.deepEqual(string(...ys), "1", "cast to char");
  59. assert.deepEqual(string(...zs), "", "cast to empty string");
  60. assert.deepEqual(new Set(xs), new Set([1, 2, 3]),
  61. "cast to set of items");
  62. assert.deepEqual(new Set(ys), new Set([1]),
  63. "cast to set of one item");
  64. assert.deepEqual(new Set(zs), new Set(),
  65. "cast to set of one item");
  66. assert.deepEqual(new Map(kvs), new Map([["a", 1], ["b", 2]]),
  67. "cast to map");
  68. assert.deepEqual(new Map(kv), new Map([["a", 1]]),
  69. "cast to single mapping");
  70. assert.deepEqual(new Map(zs), new Map(),
  71. "cast to empty map");
  72. assert.deepEqual(object(...kvs), {a: 1, b: 2},
  73. "cast to object");
  74. assert.deepEqual(object(...kv), {a: 1},
  75. "cast to single pair");
  76. assert.deepEqual(object(...zs), {},
  77. "cast to empty object");
  78. };
  79. exports["test pairs"] = assert => {
  80. assert.deepEqual([...pairs(null)], [], "pairs on null is empty");
  81. assert.deepEqual([...pairs(void(0))], [], "pairs on void is empty");
  82. assert.deepEqual([...pairs({})], [], "empty sequence");
  83. assert.deepEqual([...pairs({a: 1})], [["a", 1]], "single pair");
  84. assert.deepEqual([...pairs({a: 1, b: 2, c: 3})].sort(),
  85. [["a", 1], ["b", 2], ["c", 3]],
  86. "creates pairs");
  87. let items = [];
  88. for (let [key, value] of pairs({a: 1, b: 2, c: 3}))
  89. items.push([key, value]);
  90. assert.deepEqual(items.sort(),
  91. [["a", 1], ["b", 2], ["c", 3]],
  92. "for of works on pairs");
  93. assert.deepEqual([...pairs([])], [], "pairs on empty array is empty");
  94. assert.deepEqual([...pairs([1])], [[0, 1]], "pairs on array is [index, element]");
  95. assert.deepEqual([...pairs([1, 2, 3])],
  96. [[0, 1], [1, 2], [2, 3]],
  97. "for arrays it pair of [index, element]");
  98. assert.deepEqual([...pairs("")], [], "pairs on empty string is empty");
  99. assert.deepEqual([...pairs("a")], [[0, "a"]], "pairs on char is [0, char]");
  100. assert.deepEqual([...pairs("hello")],
  101. [[0, "h"], [1, "e"], [2, "l"], [3, "l"], [4, "o"]],
  102. "for strings it's pair of [index, char]");
  103. assert.deepEqual([...pairs(new Map())],
  104. [],
  105. "pairs on empty map is empty");
  106. assert.deepEqual([...pairs(new Map([[1, 3]]))],
  107. [[1, 3]],
  108. "pairs on single mapping single mapping");
  109. assert.deepEqual([...pairs(new Map([[1, 2], [3, 4]]))],
  110. [[1, 2], [3, 4]],
  111. "pairs on map returs key vaule pairs");
  112. assert.throws(() => pairs(new Set()),
  113. "can't pair set");
  114. assert.throws(() => pairs(4),
  115. "can't pair number");
  116. assert.throws(() => pairs(true),
  117. "can't pair boolean");
  118. };
  119. exports["test keys"] = assert => {
  120. assert.deepEqual([...keys(null)], [], "keys on null is empty");
  121. assert.deepEqual([...keys(void(0))], [], "keys on void is empty");
  122. assert.deepEqual([...keys({})], [], "empty sequence");
  123. assert.deepEqual([...keys({a: 1})], ["a"], "single key");
  124. assert.deepEqual([...keys({a: 1, b: 2, c: 3})].sort(),
  125. ["a", "b", "c"],
  126. "all keys");
  127. let items = [];
  128. for (let key of keys({a: 1, b: 2, c: 3}))
  129. items.push(key);
  130. assert.deepEqual(items.sort(),
  131. ["a", "b", "c"],
  132. "for of works on keys");
  133. assert.deepEqual([...keys([])], [], "keys on empty array is empty");
  134. assert.deepEqual([...keys([1])], [0], "keys on array is indexes");
  135. assert.deepEqual([...keys([1, 2, 3])],
  136. [0, 1, 2],
  137. "keys on arrays returns indexes");
  138. assert.deepEqual([...keys("")], [], "keys on empty string is empty");
  139. assert.deepEqual([...keys("a")], [0], "keys on char is 0");
  140. assert.deepEqual([...keys("hello")],
  141. [0, 1, 2, 3, 4],
  142. "keys on strings is char indexes");
  143. assert.deepEqual([...keys(new Map())],
  144. [],
  145. "keys on empty map is empty");
  146. assert.deepEqual([...keys(new Map([[1, 3]]))],
  147. [1],
  148. "keys on single mapping single mapping is single key");
  149. assert.deepEqual([...keys(new Map([[1, 2], [3, 4]]))],
  150. [1, 3],
  151. "keys on map is keys from map");
  152. assert.throws(() => keys(new Set()),
  153. "can't keys set");
  154. assert.throws(() => keys(4),
  155. "can't keys number");
  156. assert.throws(() => keys(true),
  157. "can't keys boolean");
  158. };
  159. exports["test values"] = assert => {
  160. assert.deepEqual([...values({})], [], "empty sequence");
  161. assert.deepEqual([...values({a: 1})], [1], "single value");
  162. assert.deepEqual([...values({a: 1, b: 2, c: 3})].sort(),
  163. [1, 2, 3],
  164. "all values");
  165. let items = [];
  166. for (let value of values({a: 1, b: 2, c: 3}))
  167. items.push(value);
  168. assert.deepEqual(items.sort(),
  169. [1, 2, 3],
  170. "for of works on values");
  171. assert.deepEqual([...values([])], [], "values on empty array is empty");
  172. assert.deepEqual([...values([1])], [1], "values on array elements");
  173. assert.deepEqual([...values([1, 2, 3])],
  174. [1, 2, 3],
  175. "values on arrays returns elements");
  176. assert.deepEqual([...values("")], [], "values on empty string is empty");
  177. assert.deepEqual([...values("a")], ["a"], "values on char is char");
  178. assert.deepEqual([...values("hello")],
  179. ["h", "e", "l", "l", "o"],
  180. "values on strings is chars");
  181. assert.deepEqual([...values(new Map())],
  182. [],
  183. "values on empty map is empty");
  184. assert.deepEqual([...values(new Map([[1, 3]]))],
  185. [3],
  186. "keys on single mapping single mapping is single key");
  187. assert.deepEqual([...values(new Map([[1, 2], [3, 4]]))],
  188. [2, 4],
  189. "values on map is values from map");
  190. assert.deepEqual([...values(new Set())], [], "values on empty set is empty");
  191. assert.deepEqual([...values(new Set([1]))], [1], "values on set is it's items");
  192. assert.deepEqual([...values(new Set([1, 2, 3]))],
  193. [1, 2, 3],
  194. "values on set is it's items");
  195. assert.throws(() => values(4),
  196. "can't values number");
  197. assert.throws(() => values(true),
  198. "can't values boolean");
  199. };
  200. exports["test fromEnumerator"] = assert => {
  201. const { Cc, Ci } = require("chrome");
  202. const { enumerateObservers,
  203. addObserver,
  204. removeObserver } = Cc["@mozilla.org/observer-service;1"].
  205. getService(Ci.nsIObserverService);
  206. const topic = "sec:" + Math.random().toString(32).substr(2);
  207. const [a, b, c] = [{wrappedJSObject: {}},
  208. {wrappedJSObject: {}},
  209. {wrappedJSObject: {}}];
  210. const unwrap = x => x.wrappedJSObject;
  211. [a, b, c].forEach(x => addObserver(x, topic, false));
  212. const xs = fromEnumerator(() => enumerateObservers(topic));
  213. const ys = map(unwrap, xs);
  214. assert.deepEqual([...ys], [a, b, c].map(unwrap),
  215. "all observers are there");
  216. removeObserver(b, topic);
  217. assert.deepEqual([...ys], [a, c].map(unwrap),
  218. "b was removed");
  219. removeObserver(a, topic);
  220. assert.deepEqual([...ys], [c].map(unwrap),
  221. "a was removed");
  222. removeObserver(c, topic);
  223. assert.deepEqual([...ys], [],
  224. "c was removed, now empty");
  225. addObserver(a, topic, false);
  226. assert.deepEqual([...ys], [a].map(unwrap),
  227. "a was added");
  228. removeObserver(a, topic);
  229. assert.deepEqual([...ys], [].map(unwrap),
  230. "a was removed, now empty");
  231. };
  232. exports["test filter"] = assert => {
  233. const isOdd = x => x % 2;
  234. const odds = seq(function*() { yield 1; yield 3; yield 5; });
  235. const evens = seq(function*() { yield 2; yield 4; yield 6; });
  236. const mixed = seq(function*() {
  237. yield 1;
  238. yield 2;
  239. yield 3;
  240. yield 4;
  241. });
  242. assert.deepEqual([...filter(isOdd, mixed)], [1, 3],
  243. "filtered odds");
  244. assert.deepEqual([...filter(isOdd, odds)], [1, 3, 5],
  245. "kept all");
  246. assert.deepEqual([...filter(isOdd, evens)], [],
  247. "kept none");
  248. let xs = filter(boom, mixed);
  249. assert.throws(() => [...xs], /Boom/, "errors propagate");
  250. assert.throws(() => [...filter(isOdd, broken)], /Boom/,
  251. "sequence errors propagate");
  252. };
  253. exports["test filter array"] = assert => {
  254. let isOdd = x => x % 2;
  255. let xs = filter(isOdd, [1, 2, 3, 4]);
  256. let ys = filter(isOdd, [1, 3, 5]);
  257. let zs = filter(isOdd, [2, 4, 6]);
  258. assert.deepEqual([...xs], [1, 3], "filteres odds");
  259. assert.deepEqual([...ys], [1, 3, 5], "kept all");
  260. assert.deepEqual([...zs], [], "kept none");
  261. assert.ok(!Array.isArray(xs));
  262. };
  263. exports["test filter set"] = assert => {
  264. let isOdd = x => x % 2;
  265. let xs = filter(isOdd, new Set([1, 2, 3, 4]));
  266. let ys = filter(isOdd, new Set([1, 3, 5]));
  267. let zs = filter(isOdd, new Set([2, 4, 6]));
  268. assert.deepEqual([...xs], [1, 3], "filteres odds");
  269. assert.deepEqual([...ys], [1, 3, 5], "kept all");
  270. assert.deepEqual([...zs], [], "kept none");
  271. };
  272. exports["test filter string"] = assert => {
  273. let isUpperCase = x => x.toUpperCase() === x;
  274. let xs = filter(isUpperCase, "aBcDe");
  275. let ys = filter(isUpperCase, "ABC");
  276. let zs = filter(isUpperCase, "abcd");
  277. assert.deepEqual([...xs], ["B", "D"], "filteres odds");
  278. assert.deepEqual([...ys], ["A", "B", "C"], "kept all");
  279. assert.deepEqual([...zs], [], "kept none");
  280. };
  281. exports["test filter lazy"] = assert => {
  282. const x = 1;
  283. let y = 2;
  284. const xy = seq(function*() { yield x; yield y; });
  285. const isOdd = x => x % 2;
  286. const actual = filter(isOdd, xy);
  287. assert.deepEqual([...actual], [1], "only one odd number");
  288. y = 3;
  289. assert.deepEqual([...actual], [1, 3], "filter is lazy");
  290. };
  291. exports["test filter non sequences"] = assert => {
  292. const False = _ => false;
  293. assert.throws(() => [...filter(False, 1)],
  294. "can't iterate number");
  295. assert.throws(() => [...filter(False, {a: 1, b:2})],
  296. "can't iterate object");
  297. };
  298. exports["test map"] = assert => {
  299. let inc = x => x + 1;
  300. let xs = seq(function*() { yield 1; yield 2; yield 3; });
  301. let ys = map(inc, xs);
  302. assert.deepEqual([...ys], [2, 3, 4], "incremented each item");
  303. assert.deepEqual([...map(inc, null)], [], "mapping null is empty");
  304. assert.deepEqual([...map(inc, void(0))], [], "mapping void is empty");
  305. assert.deepEqual([...map(inc, new Set([1, 2, 3]))], [2, 3, 4], "maps set items");
  306. };
  307. exports["test map two inputs"] = assert => {
  308. let sum = (x, y) => x + y;
  309. let xs = seq(function*() { yield 1; yield 2; yield 3; });
  310. let ys = seq(function*() { yield 4; yield 5; yield 6; });
  311. let zs = map(sum, xs, ys);
  312. assert.deepEqual([...zs], [5, 7, 9], "summed numbers");
  313. };
  314. exports["test map diff sized inputs"] = assert => {
  315. let sum = (x, y) => x + y;
  316. let xs = seq(function*() { yield 1; yield 2; yield 3; });
  317. let ys = seq(function*() { yield 4; yield 5; yield 6; yield 7; yield 8; });
  318. let zs = map(sum, xs, ys);
  319. assert.deepEqual([...zs], [5, 7, 9], "summed numbers");
  320. assert.deepEqual([...map(sum, ys, xs)], [5, 7, 9],
  321. "index of exhasting input is irrelevant");
  322. };
  323. exports["test map multi"] = assert => {
  324. let sum = (x, y, z, w) => x + y + z + w;
  325. let xs = seq(function*() { yield 1; yield 2; yield 3; yield 4; });
  326. let ys = seq(function*() { yield 4; yield 5; yield 6; yield 7; yield 8; });
  327. let zs = seq(function*() { yield 10; yield 11; yield 12; });
  328. let ws = seq(function*() { yield 0; yield 20; yield 40; yield 60; });
  329. let actual = map(sum, xs, ys, zs, ws);
  330. assert.deepEqual([...actual], [15, 38, 61], "summed numbers");
  331. };
  332. exports["test map errors"] = assert => {
  333. assert.deepEqual([...map(boom, [])], [],
  334. "won't throw if empty");
  335. const xs = map(boom, [1, 2, 4]);
  336. assert.throws(() => [...xs], /Boom/, "propagates errors");
  337. assert.throws(() => [...map(x => x, broken)], /Boom/,
  338. "sequence errors propagate");
  339. };
  340. exports["test reductions"] = assert => {
  341. let sum = (...xs) => xs.reduce((x, y) => x + y, 0);
  342. assert.deepEqual([...reductions(sum, [1, 1, 1, 1])],
  343. [1, 2, 3, 4],
  344. "works with arrays");
  345. assert.deepEqual([...reductions(sum, 5, [1, 1, 1, 1])],
  346. [5, 6, 7, 8, 9],
  347. "array with initial");
  348. assert.deepEqual([...reductions(sum, seq(function*() {
  349. yield 1;
  350. yield 2;
  351. yield 3;
  352. }))],
  353. [1, 3, 6],
  354. "works with sequences");
  355. assert.deepEqual([...reductions(sum, 10, seq(function*() {
  356. yield 1;
  357. yield 2;
  358. yield 3;
  359. }))],
  360. [10, 11, 13, 16],
  361. "works with sequences");
  362. assert.deepEqual([...reductions(sum, [])], [0],
  363. "invokes accumulator with no args");
  364. assert.throws(() => [...reductions(boom, 1, [1])],
  365. /Boom/,
  366. "arg errors errors propagate");
  367. assert.throws(() => [...reductions(sum, 1, broken)],
  368. /Boom/,
  369. "sequence errors propagate");
  370. };
  371. exports["test reduce"] = assert => {
  372. let sum = (...xs) => xs.reduce((x, y) => x + y, 0);
  373. assert.deepEqual(reduce(sum, [1, 2, 3, 4, 5]),
  374. 15,
  375. "works with arrays");
  376. assert.deepEqual(reduce(sum, seq(function*() {
  377. yield 1;
  378. yield 2;
  379. yield 3;
  380. })),
  381. 6,
  382. "works with sequences");
  383. assert.deepEqual(reduce(sum, 10, [1, 2, 3, 4, 5]),
  384. 25,
  385. "works with array & initial");
  386. assert.deepEqual(reduce(sum, 5, seq(function*() {
  387. yield 1;
  388. yield 2;
  389. yield 3;
  390. })),
  391. 11,
  392. "works with sequences & initial");
  393. assert.deepEqual(reduce(sum, []), 0, "reduce with no args");
  394. assert.deepEqual(reduce(sum, "a", []), "a", "reduce with initial");
  395. assert.deepEqual(reduce(sum, 1, [1]), 2, "reduce with single & initial");
  396. assert.throws(() => [...reduce(boom, 1, [1])],
  397. /Boom/,
  398. "arg errors errors propagate");
  399. assert.throws(() => [...reduce(sum, 1, broken)],
  400. /Boom/,
  401. "sequence errors propagate");
  402. };
  403. exports["test each"] = assert => {
  404. const collect = xs => {
  405. let result = [];
  406. each((...etc) => result.push(...etc), xs);
  407. return result;
  408. };
  409. assert.deepEqual(collect(null), [], "each ignores null");
  410. assert.deepEqual(collect(void(0)), [], "each ignores void");
  411. assert.deepEqual(collect([]), [], "each ignores empty");
  412. assert.deepEqual(collect([1]), [1], "each works on single item arrays");
  413. assert.deepEqual(collect([1, 2, 3, 4, 5]),
  414. [1, 2, 3, 4, 5],
  415. "works with arrays");
  416. assert.deepEqual(collect(seq(function*() {
  417. yield 1;
  418. yield 2;
  419. yield 3;
  420. })),
  421. [1, 2, 3],
  422. "works with sequences");
  423. assert.deepEqual(collect(""), [], "ignores empty strings");
  424. assert.deepEqual(collect("a"), ["a"], "works on chars");
  425. assert.deepEqual(collect("hello"), ["h", "e", "l", "l", "o"],
  426. "works on strings");
  427. assert.deepEqual(collect(new Set()), [], "ignores empty sets");
  428. assert.deepEqual(collect(new Set(["a"])), ["a"],
  429. "works on single item sets");
  430. assert.deepEqual(collect(new Set([1, 2, 3])), [1, 2, 3],
  431. "works on muti item tests");
  432. assert.deepEqual(collect(new Map()), [], "ignores empty maps");
  433. assert.deepEqual(collect(new Map([["a", 1]])), [["a", 1]],
  434. "works on single mapping maps");
  435. assert.deepEqual(collect(new Map([[1, 2], [3, 4], [5, 6]])),
  436. [[1, 2], [3, 4], [5, 6]],
  437. "works on muti mapping maps");
  438. assert.throws(() => collect({}), "objects arn't supported");
  439. assert.throws(() => collect(1), "numbers arn't supported");
  440. assert.throws(() => collect(true), "booleas arn't supported");
  441. };
  442. exports["test count"] = assert => {
  443. assert.equal(count(null), 0, "null counts to 0");
  444. assert.equal(count(), 0, "undefined counts to 0");
  445. assert.equal(count([]), 0, "empty array");
  446. assert.equal(count([1, 2, 3]), 3, "non-empty array");
  447. assert.equal(count(""), 0, "empty string");
  448. assert.equal(count("hello"), 5, "non-empty string");
  449. assert.equal(count(new Map()), 0, "empty map");
  450. assert.equal(count(new Map([[1, 2], [2, 3]])), 2, "non-empty map");
  451. assert.equal(count(new Set()), 0, "empty set");
  452. assert.equal(count(new Set([1, 2, 3, 4])), 4, "non-empty set");
  453. assert.equal(count(seq(function*() {})), 0, "empty sequence");
  454. assert.equal(count(seq(function*() { yield 1; yield 2; })), 2,
  455. "non-empty sequence");
  456. assert.throws(() => count(broken),
  457. /Boom/,
  458. "sequence errors propagate");
  459. };
  460. exports["test isEmpty"] = assert => {
  461. assert.equal(isEmpty(null), true, "null is empty");
  462. assert.equal(isEmpty(), true, "undefined is empty");
  463. assert.equal(isEmpty([]), true, "array is array");
  464. assert.equal(isEmpty([1, 2, 3]), false, "array isn't empty");
  465. assert.equal(isEmpty(""), true, "string is empty");
  466. assert.equal(isEmpty("hello"), false, "non-empty string");
  467. assert.equal(isEmpty(new Map()), true, "empty map");
  468. assert.equal(isEmpty(new Map([[1, 2], [2, 3]])), false, "non-empty map");
  469. assert.equal(isEmpty(new Set()), true, "empty set");
  470. assert.equal(isEmpty(new Set([1, 2, 3, 4])), false , "non-empty set");
  471. assert.equal(isEmpty(seq(function*() {})), true, "empty sequence");
  472. assert.equal(isEmpty(seq(function*() { yield 1; yield 2; })), false,
  473. "non-empty sequence");
  474. assert.equal(isEmpty(broken), false, "hasn't reached error");
  475. };
  476. exports["test isEvery"] = assert => {
  477. let isOdd = x => x % 2;
  478. let isTrue = x => x === true;
  479. let isFalse = x => x === false;
  480. assert.equal(isEvery(isOdd, seq(function*() {
  481. yield 1;
  482. yield 3;
  483. yield 5;
  484. })), true, "all are odds");
  485. assert.equal(isEvery(isOdd, seq(function*() {
  486. yield 1;
  487. yield 2;
  488. yield 3;
  489. })), false, "contains even");
  490. assert.equal(isEvery(isTrue, seq(function*() {})), true, "true if empty");
  491. assert.equal(isEvery(isFalse, seq(function*() {})), true, "true if empty");
  492. assert.equal(isEvery(isTrue, null), true, "true for null");
  493. assert.equal(isEvery(isTrue, undefined), true, "true for undefined");
  494. assert.throws(() => isEvery(boom, [1, 2]),
  495. /Boom/,
  496. "arg errors errors propagate");
  497. assert.throws(() => isEvery(x => true, broken),
  498. /Boom/,
  499. "sequence errors propagate");
  500. assert.equal(isEvery(x => false, broken), false,
  501. "hasn't reached error");
  502. };
  503. exports["test some"] = assert => {
  504. let isOdd = x => x % 2;
  505. let isTrue = x => x === true;
  506. let isFalse = x => x === false;
  507. assert.equal(some(isOdd, seq(function*() {
  508. yield 2;
  509. yield 4;
  510. yield 6;
  511. })), null, "all are even");
  512. assert.equal(some(isOdd, seq(function*() {
  513. yield 2;
  514. yield 3;
  515. yield 4;
  516. })), true, "contains odd");
  517. assert.equal(some(isTrue, seq(function*() {})), null,
  518. "null if empty")
  519. assert.equal(some(isFalse, seq(function*() {})), null,
  520. "null if empty")
  521. assert.equal(some(isTrue, null), null, "null for null");
  522. assert.equal(some(isTrue, undefined), null, "null for undefined");
  523. assert.throws(() => some(boom, [1, 2]),
  524. /Boom/,
  525. "arg errors errors propagate");
  526. assert.throws(() => some(x => false, broken),
  527. /Boom/,
  528. "sequence errors propagate");
  529. assert.equal(some(x => true, broken), true,
  530. "hasn't reached error");
  531. };
  532. exports["test take"] = assert => {
  533. let xs = seq(function*() {
  534. yield 1;
  535. yield 2;
  536. yield 3;
  537. yield 4;
  538. yield 5;
  539. yield 6;
  540. });
  541. assert.deepEqual([...take(3, xs)], [1, 2, 3], "took 3 items");
  542. assert.deepEqual([...take(3, [1, 2, 3, 4, 5])], [1, 2, 3],
  543. "took 3 from array");
  544. let ys = seq(function*() { yield 1; yield 2; });
  545. assert.deepEqual([...take(3, ys)], [1, 2], "takes at max n");
  546. assert.deepEqual([...take(3, [1, 2])], [1, 2],
  547. "takes at max n from arary");
  548. let empty = seq(function*() {});
  549. assert.deepEqual([...take(5, empty)], [], "nothing to take");
  550. assert.throws(() => [...take(3, broken)],
  551. /Boom/,
  552. "sequence errors propagate");
  553. assert.deepEqual([...take(1, broken)], [1],
  554. "hasn't reached error");
  555. };
  556. exports["test iterate"] = assert => {
  557. let inc = x => x + 1;
  558. let nums = iterate(inc, 0);
  559. assert.deepEqual([...take(5, nums)], [0, 1, 2, 3, 4], "took 5");
  560. assert.deepEqual([...take(10, nums)], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], "took 10");
  561. let xs = iterate(x => x * 3, 2);
  562. assert.deepEqual([...take(4, xs)], [2, 6, 18, 54], "took 4");
  563. assert.throws(() => [...iterate(boom, 0)],
  564. /Boom/,
  565. "function exceptions propagate");
  566. };
  567. exports["test takeWhile"] = assert => {
  568. let isNegative = x => x < 0;
  569. let xs = seq(function*() {
  570. yield -2;
  571. yield -1;
  572. yield 0;
  573. yield 1;
  574. yield 2;
  575. yield 3;
  576. });
  577. assert.deepEqual([...takeWhile(isNegative, xs)], [-2, -1],
  578. "took until 0");
  579. let ys = seq(function*() {});
  580. assert.deepEqual([...takeWhile(isNegative, ys)], [],
  581. "took none");
  582. let zs = seq(function*() {
  583. yield 0;
  584. yield 1;
  585. yield 2;
  586. yield 3;
  587. });
  588. assert.deepEqual([...takeWhile(isNegative, zs)], [],
  589. "took none");
  590. assert.throws(() => [...takeWhile(boom, zs)],
  591. /Boom/,
  592. "function errors errors propagate");
  593. assert.throws(() => [...takeWhile(x => true, broken)],
  594. /Boom/,
  595. "sequence errors propagate");
  596. assert.deepEqual([...takeWhile(x => false, broken)],
  597. [],
  598. "hasn't reached error");
  599. };
  600. exports["test drop"] = assert => {
  601. let testDrop = xs => {
  602. assert.deepEqual([...drop(2, xs)],
  603. [3, 4],
  604. "dropped two elements");
  605. assert.deepEqual([...drop(1, xs)],
  606. [2, 3, 4],
  607. "dropped one");
  608. assert.deepEqual([...drop(0, xs)],
  609. [1, 2, 3, 4],
  610. "dropped 0");
  611. assert.deepEqual([...drop(-2, xs)],
  612. [1, 2, 3, 4],
  613. "dropped 0 on negative `n`");
  614. assert.deepEqual([...drop(5, xs)],
  615. [],
  616. "dropped all items");
  617. };
  618. testDrop([1, 2, 3, 4]);
  619. testDrop(seq(function*() {
  620. yield 1;
  621. yield 2;
  622. yield 3;
  623. yield 4;
  624. }));
  625. assert.throws(() => [...drop(1, broken)],
  626. /Boom/,
  627. "sequence errors propagate");
  628. };
  629. exports["test dropWhile"] = assert => {
  630. let isNegative = x => x < 0;
  631. let True = _ => true;
  632. let False = _ => false;
  633. let test = xs => {
  634. assert.deepEqual([...dropWhile(isNegative, xs)],
  635. [0, 1, 2],
  636. "dropped negative");
  637. assert.deepEqual([...dropWhile(True, xs)],
  638. [],
  639. "drop all");
  640. assert.deepEqual([...dropWhile(False, xs)],
  641. [-2, -1, 0, 1, 2],
  642. "keep all");
  643. };
  644. test([-2, -1, 0, 1, 2]);
  645. test(seq(function*() {
  646. yield -2;
  647. yield -1;
  648. yield 0;
  649. yield 1;
  650. yield 2;
  651. }));
  652. assert.throws(() => [...dropWhile(boom, [1, 2, 3])],
  653. /Boom/,
  654. "function errors errors propagate");
  655. assert.throws(() => [...dropWhile(x => true, broken)],
  656. /Boom/,
  657. "sequence errors propagate");
  658. };
  659. exports["test concat"] = assert => {
  660. let test = (a, b, c, d) => {
  661. assert.deepEqual([...concat()],
  662. [],
  663. "nothing to concat");
  664. assert.deepEqual([...concat(a)],
  665. [1, 2, 3],
  666. "concat with nothing returns same as first");
  667. assert.deepEqual([...concat(a, b)],
  668. [1, 2, 3, 4, 5],
  669. "concat items from both");
  670. assert.deepEqual([...concat(a, b, a)],
  671. [1, 2, 3, 4, 5, 1, 2, 3],
  672. "concat itself");
  673. assert.deepEqual([...concat(c)],
  674. [],
  675. "concat of empty is empty");
  676. assert.deepEqual([...concat(a, c)],
  677. [1, 2, 3],
  678. "concat with empty");
  679. assert.deepEqual([...concat(c, c, c)],
  680. [],
  681. "concat of empties is empty");
  682. assert.deepEqual([...concat(c, b)],
  683. [4, 5],
  684. "empty can be in front");
  685. assert.deepEqual([...concat(d)],
  686. [7],
  687. "concat singular");
  688. assert.deepEqual([...concat(d, d)],
  689. [7, 7],
  690. "concat singulars");
  691. assert.deepEqual([...concat(a, a, b, c, d, c, d, d)],
  692. [1, 2, 3, 1, 2, 3, 4, 5, 7, 7, 7],
  693. "many concats");
  694. let ab = concat(a, b);
  695. let abcd = concat(ab, concat(c, d));
  696. let cdabcd = concat(c, d, abcd);
  697. assert.deepEqual([...cdabcd],
  698. [7, 1, 2, 3, 4, 5, 7],
  699. "nested concats");
  700. };
  701. test([1, 2, 3],
  702. [4, 5],
  703. [],
  704. [7]);
  705. test(seq(function*() { yield 1; yield 2; yield 3; }),
  706. seq(function*() { yield 4; yield 5; }),
  707. seq(function*() { }),
  708. seq(function*() { yield 7; }));
  709. assert.throws(() => [...concat(broken, [1, 2, 3])],
  710. /Boom/,
  711. "function errors errors propagate");
  712. };
  713. exports["test first"] = assert => {
  714. let test = (xs, empty) => {
  715. assert.equal(first(xs), 1, "returns first");
  716. assert.equal(first(empty), null, "returns null empty");
  717. };
  718. test("1234", "");
  719. test([1, 2, 3], []);
  720. test([1, 2, 3], null);
  721. test([1, 2, 3], undefined);
  722. test(seq(function*() { yield 1; yield 2; yield 3; }),
  723. seq(function*() { }));
  724. assert.equal(first(broken), 1, "did not reached error");
  725. };
  726. exports["test rest"] = assert => {
  727. let test = (xs, x, nil) => {
  728. assert.deepEqual([...rest(xs)], ["b", "c"],
  729. "rest items");
  730. assert.deepEqual([...rest(x)], [],
  731. "empty when singular");
  732. assert.deepEqual([...rest(nil)], [],
  733. "empty when empty");
  734. };
  735. test("abc", "a", "");
  736. test(["a", "b", "c"], ["d"], []);
  737. test(seq(function*() { yield "a"; yield "b"; yield "c"; }),
  738. seq(function*() { yield "d"; }),
  739. seq(function*() {}));
  740. test(["a", "b", "c"], ["d"], null);
  741. test(["a", "b", "c"], ["d"], undefined);
  742. assert.throws(() => [...rest(broken)],
  743. /Boom/,
  744. "sequence errors propagate");
  745. };
  746. exports["test nth"] = assert => {
  747. let notFound = {};
  748. let test = xs => {
  749. assert.equal(nth(xs, 0), "h", "first");
  750. assert.equal(nth(xs, 1), "e", "second");
  751. assert.equal(nth(xs, 5), void(0), "out of bound");
  752. assert.equal(nth(xs, 5, notFound), notFound, "out of bound");
  753. assert.equal(nth(xs, -1), void(0), "out of bound");
  754. assert.equal(nth(xs, -1, notFound), notFound, "out of bound");
  755. assert.equal(nth(xs, 4), "o", "5th");
  756. };
  757. let testEmpty = xs => {
  758. assert.equal(nth(xs, 0), void(0), "no first in empty");
  759. assert.equal(nth(xs, 5), void(0), "no 5th in empty");
  760. assert.equal(nth(xs, 0, notFound), notFound, "notFound on out of bound");
  761. };
  762. test("hello");
  763. test(["h", "e", "l", "l", "o"]);
  764. test(seq(function*() {
  765. yield "h";
  766. yield "e";
  767. yield "l";
  768. yield "l";
  769. yield "o";
  770. }));
  771. testEmpty(null);
  772. testEmpty(undefined);
  773. testEmpty([]);
  774. testEmpty("");
  775. testEmpty(seq(function*() {}));
  776. assert.throws(() => nth(broken, 1),
  777. /Boom/,
  778. "sequence errors propagate");
  779. assert.equal(nth(broken, 0), 1, "have not reached error");
  780. };
  781. exports["test last"] = assert => {
  782. assert.equal(last(null), null, "no last in null");
  783. assert.equal(last(void(0)), null, "no last in undefined");
  784. assert.equal(last([]), null, "no last in []");
  785. assert.equal(last(""), null, "no last in ''");
  786. assert.equal(last(seq(function*() { })), null, "no last in empty");
  787. assert.equal(last("hello"), "o", "last from string");
  788. assert.equal(last([1, 2, 3]), 3, "last from array");
  789. assert.equal(last([1]), 1, "last from singular");
  790. assert.equal(last(seq(function*() {
  791. yield 1;
  792. yield 2;
  793. yield 3;
  794. })), 3, "last from sequence");
  795. assert.throws(() => last(broken),
  796. /Boom/,
  797. "sequence errors propagate");
  798. };
  799. exports["test dropLast"] = assert => {
  800. let test = xs => {
  801. assert.deepEqual([...dropLast(xs)],
  802. [1, 2, 3, 4],
  803. "dropped last");
  804. assert.deepEqual([...dropLast(0, xs)],
  805. [1, 2, 3, 4, 5],
  806. "dropped none on 0");
  807. assert.deepEqual([...dropLast(-3, xs)],
  808. [1, 2, 3, 4, 5],
  809. "drop none on negative");
  810. assert.deepEqual([...dropLast(3, xs)],
  811. [1, 2],
  812. "dropped given number");
  813. assert.deepEqual([...dropLast(5, xs)],
  814. [],
  815. "dropped all");
  816. };
  817. let testEmpty = xs => {
  818. assert.deepEqual([...dropLast(xs)],
  819. [],
  820. "nothing to drop");
  821. assert.deepEqual([...dropLast(0, xs)],
  822. [],
  823. "dropped none on 0");
  824. assert.deepEqual([...dropLast(-3, xs)],
  825. [],
  826. "drop none on negative");
  827. assert.deepEqual([...dropLast(3, xs)],
  828. [],
  829. "nothing to drop");
  830. };
  831. test([1, 2, 3, 4, 5]);
  832. test(seq(function*() {
  833. yield 1;
  834. yield 2;
  835. yield 3;
  836. yield 4;
  837. yield 5;
  838. }));
  839. testEmpty([]);
  840. testEmpty("");
  841. testEmpty(seq(function*() {}));
  842. assert.throws(() => [...dropLast(broken)],
  843. /Boom/,
  844. "sequence errors propagate");
  845. };
  846. exports["test distinct"] = assert => {
  847. let test = (xs, message) => {
  848. assert.deepEqual([...distinct(xs)],
  849. [1, 2, 3, 4, 5],
  850. message);
  851. };
  852. test([1, 2, 1, 3, 1, 4, 1, 5], "works with arrays");
  853. test(seq(function*() {
  854. yield 1;
  855. yield 2;
  856. yield 1;
  857. yield 3;
  858. yield 1;
  859. yield 4;
  860. yield 1;
  861. yield 5;
  862. }), "works with sequences");
  863. test(new Set([1, 2, 1, 3, 1, 4, 1, 5]),
  864. "works with sets");
  865. test(seq(function*() {
  866. yield 1;
  867. yield 2;
  868. yield 2;
  869. yield 2;
  870. yield 1;
  871. yield 3;
  872. yield 1;
  873. yield 4;
  874. yield 4;
  875. yield 4;
  876. yield 1;
  877. yield 5;
  878. }), "works with multiple repeatitions");
  879. test([1, 2, 3, 4, 5], "work with distinct arrays");
  880. test(seq(function*() {
  881. yield 1;
  882. yield 2;
  883. yield 3;
  884. yield 4;
  885. yield 5;
  886. }), "works with distinct seqs");
  887. };
  888. exports["test remove"] = assert => {
  889. let isPositive = x => x > 0;
  890. let test = xs => {
  891. assert.deepEqual([...remove(isPositive, xs)],
  892. [-2, -1, 0],
  893. "removed positives");
  894. };
  895. test([1, -2, 2, -1, 3, 7, 0]);
  896. test(seq(function*() {
  897. yield 1;
  898. yield -2;
  899. yield 2;
  900. yield -1;
  901. yield 3;
  902. yield 7;
  903. yield 0;
  904. }));
  905. assert.throws(() => [...distinct(broken)],
  906. /Boom/,
  907. "sequence errors propagate");
  908. };
  909. exports["test mapcat"] = assert => {
  910. let upto = n => seq(function* () {
  911. let index = 0;
  912. while (index < n) {
  913. yield index;
  914. index = index + 1;
  915. }
  916. });
  917. assert.deepEqual([...mapcat(upto, [1, 2, 3, 4])],
  918. [0, 0, 1, 0, 1, 2, 0, 1, 2, 3],
  919. "expands given sequence");
  920. assert.deepEqual([...mapcat(upto, [0, 1, 2, 0])],
  921. [0, 0, 1],
  922. "expands given sequence");
  923. assert.deepEqual([...mapcat(upto, [0, 0, 0])],
  924. [],
  925. "expands given sequence");
  926. assert.deepEqual([...mapcat(upto, [])],
  927. [],
  928. "nothing to expand");
  929. assert.deepEqual([...mapcat(upto, null)],
  930. [],
  931. "nothing to expand");
  932. assert.deepEqual([...mapcat(upto, void(0))],
  933. [],
  934. "nothing to expand");
  935. let xs = seq(function*() {
  936. yield 0;
  937. yield 1;
  938. yield 0;
  939. yield 2;
  940. yield 0;
  941. });
  942. assert.deepEqual([...mapcat(upto, xs)],
  943. [0, 0, 1],
  944. "expands given sequence");
  945. assert.throws(() => [...mapcat(boom, xs)],
  946. /Boom/,
  947. "function errors errors propagate");
  948. assert.throws(() => [...mapcat(upto, broken)],
  949. /Boom/,
  950. "sequence errors propagate");
  951. };
  952. require("sdk/test").run(exports);