/** @odoo-module */ import { describe, expect, test } from "@odoo/hoot"; import { queryOne } from "@odoo/hoot-dom"; import { isInstanceOf, isIterable } from "@web/../lib/hoot-dom/hoot_dom_utils"; import { deepCopy, deepEqual, formatHumanReadable, formatTechnical, generateHash, levenshtein, lookup, match, parseQuery, S_CIRCULAR, title, toExplicitString, } from "../hoot_utils"; import { mountForTest, parseUrl } from "./local_helpers"; const recursive = {}; recursive.self = recursive; describe(parseUrl(import.meta.url), () => { test("deepCopy", () => { expect(deepCopy(true)).toEqual(true); expect(deepCopy(false)).toEqual(false); expect(deepCopy(null)).toEqual(null); expect(deepCopy(recursive)).toEqual({ self: S_CIRCULAR }); expect(deepCopy(new Date(0))).toEqual(new Date(0)); expect(deepCopy({ a: 1, b: 2 })).toEqual({ a: 1, b: 2 }); expect(deepCopy({ o: { a: [{ b: 1 }] } })).toEqual({ o: { a: [{ b: 1 }] } }); expect(deepCopy(Symbol.for("a"))).toEqual(Symbol.for("a")); expect(deepCopy(document.createElement("div"))).toEqual(document.createElement("div")); expect(deepCopy([1, 2, 3])).toEqual([1, 2, 3]); }); test("deepEqual", () => { const TRUTHY_CASES = [ [true, true], [false, false], [null, null], [recursive, recursive], [new Date(0), new Date(0)], [ { b: 2, a: 1 }, { a: 1, b: 2 }, ], [{ o: { a: [{ b: 1 }] } }, { o: { a: [{ b: 1 }] } }], [Symbol.for("a"), Symbol.for("a")], [document.createElement("div"), document.createElement("div")], [ [1, 2, 3], [1, 2, 3], ], ]; const FALSY_CASES = [ [true, false], [null, undefined], [recursive, { ...recursive, a: 1 }], [ [1, 2, 3], [3, 1, 2], ], [new Date(0), new Date(1_000)], [{ a: new Date(0) }, { a: 0 }], [document.createElement("a"), document.createElement("div")], [{ [Symbol("a")]: 1 }, { [Symbol("a")]: 1 }], ]; const TRUTHY_IF_UNORDERED_CASES = [ [ [1, "2", 3], ["2", 3, 1], ], [ [1, { a: [4, 2] }, "3"], [{ a: [2, 4] }, "3", 1], ], [ new Set([ "abc", new Map([ ["b", 2], ["a", 1], ]), ]), new Set([ new Map([ ["a", 1], ["b", 2], ]), "abc", ]), ], ]; expect.assertions( TRUTHY_CASES.length + FALSY_CASES.length + TRUTHY_IF_UNORDERED_CASES.length * 2 ); for (const [a, b] of TRUTHY_CASES) { expect(deepEqual(a, b)).toBe(true, { message: [a, `==`, b], }); } for (const [a, b] of FALSY_CASES) { expect(deepEqual(a, b)).toBe(false, { message: [a, `!=`, b], }); } for (const [a, b] of TRUTHY_IF_UNORDERED_CASES) { expect(deepEqual(a, b)).toBe(false, { message: [a, `!=`, b], }); expect(deepEqual(a, b, { ignoreOrder: true })).toBe(true, { message: [a, `==`, b, `(unordered))`], }); } }); test("formatHumanReadable", () => { // Strings expect(formatHumanReadable("abc")).toBe(`"abc"`); expect(formatHumanReadable("a".repeat(300))).toBe(`"${"a".repeat(80)}…"`); expect(formatHumanReadable(`with "double quotes"`)).toBe(`'with "double quotes"'`); expect(formatHumanReadable(`with "double quotes" and 'single quote'`)).toBe( `\`with "double quotes" and 'single quote'\`` ); // Numbers expect(formatHumanReadable(1)).toBe(`1`); // Other primitives expect(formatHumanReadable(true)).toBe(`true`); expect(formatHumanReadable(null)).toBe(`null`); // Functions & classes expect(formatHumanReadable(async function oui() {})).toBe(`async function oui() { … }`); expect(formatHumanReadable(class Oui {})).toBe(`class Oui { … }`); // Iterators expect(formatHumanReadable([1, 2, 3])).toBe(`[1, 2, 3]`); expect(formatHumanReadable(new Set([1, 2, 3]))).toBe(`Set [1, 2, 3]`); expect( formatHumanReadable( new Map([ ["a", 1], ["b", 2], ]) ) ).toBe(`Map [["a", 1], ["b", 2]]`); // Objects expect(formatHumanReadable(/ab(c)d/gi)).toBe(`/ab(c)d/gi`); expect(formatHumanReadable(new Date("1997-01-09T12:30:00.000Z"))).toBe( `1997-01-09T12:30:00.000Z` ); expect(formatHumanReadable({})).toBe(`{ }`); expect(formatHumanReadable({ a: { b: 1 } })).toBe(`{ a: { b: 1 } }`); expect( formatHumanReadable( new Proxy( { allowed: true, get forbidden() { throw new Error("Cannot access!"); }, }, {} ) ) ).toBe(`{ allowed: true }`); expect(formatHumanReadable(window)).toBe(`Window { }`); // Nodes expect(formatHumanReadable(document.createElement("div"))).toBe("
"); expect(formatHumanReadable(document.createTextNode("some text"))).toBe("#text"); expect(formatHumanReadable(document)).toBe("#document"); }); test("formatTechnical", () => { expect( formatTechnical({ b: 2, [Symbol("s")]: "value", a: true, }) ).toBe( `{ a: true, b: 2, Symbol(s): "value", }`.trim() ); expect(formatTechnical(["a", "b"])).toBe( `[ "a", "b", ]`.trim() ); class List extends Array {} expect(formatTechnical(new List("a", "b"))).toBe( `List [ "a", "b", ]`.trim() ); function toArguments() { return arguments; } expect(formatTechnical(toArguments("a", "b"))).toBe( `Arguments [ "a", "b", ]`.trim() ); }); test("generateHash", () => { expect(generateHash("abc")).toHaveLength(8); expect(generateHash("abcdef")).toHaveLength(8); expect(generateHash("abc")).toBe(generateHash("abc")); expect(generateHash("abc")).not.toBe(generateHash("def")); }); test("isInstanceOf", async () => { await mountForTest(/* xml */ `