From 10544f8ab7fdf751a2f82eef17bc23d7739e05a7 Mon Sep 17 00:00:00 2001 From: Damien Cassou Date: Wed, 10 Apr 2024 09:38:04 +0200 Subject: [PATCH] 32129139: Convert tests from jasmine to jest --- src/test/htmlCanvasTest.js | 105 ++++++++++++++++++++---- src/test/router/hashLocationTest.js | 26 ++++-- src/test/router/routeTest.js | 89 +++++++++++---------- src/test/router/routerTest.js | 120 ++++++++++++++++++---------- src/test/widgetTest.js | 72 ++++++++++++----- 5 files changed, 284 insertions(+), 128 deletions(-) diff --git a/src/test/htmlCanvasTest.js b/src/test/htmlCanvasTest.js index 7f181671..ee453e55 100644 --- a/src/test/htmlCanvasTest.js +++ b/src/test/htmlCanvasTest.js @@ -1,5 +1,6 @@ import htmlCanvas from "../htmlCanvas.js"; import jQuery from "jquery"; +import { describe, it, expect } from "@jest/globals"; function withCanvas(callback) { jQuery("BODY").append('
'); @@ -30,10 +31,12 @@ describe("htmlCanvas", () => { it("throws exception if jQuery dont match element", () => { expect(() => { htmlCanvas("#notfound"); - }).toThrowError("htmlTagBrush requires an element"); + }).toThrow("htmlTagBrush requires an element"); }); it("can render HTML tags", () => { + expect.assertions(2); + withCanvas((html) => { // Arrange: a Hello World! H1 html.h1("Hello World!"); @@ -49,6 +52,8 @@ describe("htmlCanvas", () => { }); it("standard attributes are supported", () => { + expect.assertions(2); + withCanvas((html) => { // Arrange: a Google link html.a("Google").id("test_id").href("http://www.google.se"); @@ -64,6 +69,8 @@ describe("htmlCanvas", () => { }); it("render object literal attributes", () => { + expect.assertions(3); + withCanvas((html) => { // Arrange: a div with attributes html.div( @@ -90,6 +97,8 @@ describe("htmlCanvas", () => { describe("should omit an attribute", () => { it("when value is html.omit()", () => { + expect.assertions(2); + withCanvas((html) => { // Arrange: a div with attributes html.div( @@ -111,6 +120,8 @@ describe("htmlCanvas", () => { }); it("when value is undefined", () => { + expect.assertions(1); + withCanvas((html) => { let attributeName = "data-test"; @@ -121,6 +132,8 @@ describe("htmlCanvas", () => { }); it("when value is null", () => { + expect.assertions(1); + withCanvas((html) => { let attributeName = "data-test"; @@ -131,6 +144,8 @@ describe("htmlCanvas", () => { }); it("when value if false", () => { + expect.assertions(1); + withCanvas((html) => { let attributeName = "data-test"; @@ -141,6 +156,8 @@ describe("htmlCanvas", () => { }); it("when value is the empty string", () => { + expect.assertions(1); + withCanvas((html) => { let attributeName = "data-test"; @@ -152,6 +169,8 @@ describe("htmlCanvas", () => { }); it("callbacks can be attached to events", () => { + expect.assertions(2); + withCanvas((html) => { let clicked = false; @@ -174,11 +193,13 @@ describe("htmlCanvas", () => { // and click triggers callback linkEl.click(); - expect(clicked).toBe(true); + expect(clicked).toBeTrue(); }); }); it("callbacks can be attached using attributes", () => { + expect.assertions(2); + withCanvas((html) => { let clicked = false; @@ -197,11 +218,13 @@ describe("htmlCanvas", () => { // and click triggers callback linkEl.click(); - expect(clicked).toBe(true); + expect(clicked).toBeTrue(); }); }); it("tags can be nested", () => { + expect.assertions(3); + withCanvas((html) => { // Arrange: a inner and outer div with a span as inner child html.div( @@ -217,6 +240,8 @@ describe("htmlCanvas", () => { }); it("can omit nested tags", () => { + expect.assertions(3); + withCanvas((html) => { // Arrange: a inner and outer div with a span as inner child // where the child is omitted @@ -233,6 +258,8 @@ describe("htmlCanvas", () => { }); it("parts can be assigned to variables", () => { + expect.assertions(2); + withCanvas((html) => { // Arrange a button, assign to variable and then set class let button = html.a("Home").id("test_button").href("/"); @@ -245,6 +272,8 @@ describe("htmlCanvas", () => { }); it("render() can append objects to brush", () => { + expect.assertions(1); + withCanvas((html) => { // Arrange: a DIV let div = html.div().id("aDiv"); @@ -258,6 +287,8 @@ describe("htmlCanvas", () => { }); it("can render arrays", () => { + expect.assertions(1); + withCanvas((html) => { // Arrange a div with10 sub span supplied to DIV as an array html.div( @@ -267,11 +298,13 @@ describe("htmlCanvas", () => { ).id("test_div"); // Assert: - expect(jQuery("#test_div > SPAN").length).toBe(10); + expect(jQuery("#test_div > SPAN")).toHaveLength(10); }); }); it("can render several objects using html.render", () => { + expect.assertions(1); + withCanvas((html) => { // Arrange html.div((html) => { @@ -279,27 +312,31 @@ describe("htmlCanvas", () => { }).id("test_div"); // Assert: - expect(jQuery("#test_div > SPAN").length).toBe(2); + expect(jQuery("#test_div > SPAN")).toHaveLength(2); }); }); it("throws error if object to append is null or undefined", () => { + expect.assertions(2); + withCanvas((html) => { expect(() => { html.render(null); - }).toThrowError( + }).toThrow( "Cannot read properties of null (reading 'appendToBrush')", ); expect(() => { html.render(undefined); - }).toThrowError( + }).toThrow( "Cannot read properties of undefined (reading 'appendToBrush')", ); }); }); it("can render with html function", () => { + expect.assertions(2); + withCanvas((html) => { // Arrange a function that take a canvas as argument. function htmlFn(html2) { @@ -316,6 +353,8 @@ describe("htmlCanvas", () => { }); it("delegates rendering to objects implementing appendToBrush()", () => { + expect.assertions(1); + withCanvas((html) => { function appendableObject() { let that = {}; @@ -336,6 +375,8 @@ describe("htmlCanvas", () => { }); it("rendering html strings not allowed by default", () => { + expect.assertions(1); + withCanvas((html) => { // Arrange: let htmlString = '
foo
'; @@ -348,7 +389,9 @@ describe("htmlCanvas", () => { }); }); - it("rendering of strings is escaped ", () => { + it("rendering of strings is escaped", () => { + expect.assertions(1); + withCanvas((html) => { // Arrange: let htmlString = "<>&foo"; @@ -361,7 +404,9 @@ describe("htmlCanvas", () => { }); }); - it("rendering using `html()` does not escape ", () => { + it("rendering using `html()` does not escape", () => { + expect.assertions(1); + withCanvas((html) => { // Arrange: let htmlString = "
hello
"; @@ -375,6 +420,8 @@ describe("htmlCanvas", () => { }); it("element() returns brush element", () => { + expect.assertions(1); + withCanvas((html) => { // Arrange: a heading let h1 = html.h1().id("aHeading"); @@ -385,6 +432,8 @@ describe("htmlCanvas", () => { }); it("setAttribute() get/set style using key/value", () => { + expect.assertions(1); + withCanvas((html) => { // Arrange: a heading with id let h1 = html.h1().setAttribute("id", "aHeading"); @@ -395,6 +444,8 @@ describe("htmlCanvas", () => { }); it("css() get/set style", () => { + expect.assertions(1); + withCanvas((html) => { // Arrange: a div let div = html.div(); @@ -406,6 +457,8 @@ describe("htmlCanvas", () => { }); it("attr() get/set style", () => { + expect.assertions(1); + withCanvas((html) => { // Arrange: a heading with id (set using map) let h1 = html.h1().attr({ id: "aHeading" }); @@ -416,6 +469,8 @@ describe("htmlCanvas", () => { }); it("addClass()/removeClass() add/remove class", () => { + expect.assertions(2); + withCanvas((html) => { // Arrange: a heading let h1 = html.h1().id("aHeading"); @@ -433,26 +488,32 @@ describe("htmlCanvas", () => { }); it("addClass() with a complex argument", () => { + expect.assertions(1); + withCanvas((html) => { let h1 = html.h1(); h1.addClass(["foo", { disabled: () => false }, ["bar"]]); - expect(h1.element.className).toEqual("foo disabled bar"); + expect(h1.element.className).toBe("foo disabled bar"); }); }); it("removeClass() with a complex argument", () => { + expect.assertions(1); + withCanvas((html) => { let h1 = html.h1({ class: "foo baz disabled bar" }); h1.removeClass(["foo", { disabled: () => false }, ["bar"]]); - expect(h1.element.className).toEqual("baz"); + expect(h1.element.className).toBe("baz"); }); }); it("asJQuery() returns jQuery that match brush element", () => { + expect.assertions(1); + withCanvas((html) => { // Arrange: a heading let h1 = html.h1().id("aHeading"); @@ -464,6 +525,8 @@ describe("htmlCanvas", () => { // TODO: allow or throw exception? it("can render almost everything", () => { + expect.assertions(1); + withCanvas((html) => { html.render(0); // toString() html.render(3.141_592_653_59); // toString() @@ -477,26 +540,30 @@ describe("htmlCanvas", () => { describe("svg tags", () => { it("can render an SVG element with svgTag", () => { + expect.assertions(1); + withCanvas((html) => { let tag = html.svgTag("svg"); - expect(tag.element.namespaceURI).toEqual( + expect(tag.element.namespaceURI).toBe( "http://www.w3.org/2000/svg", ); }); }); it("can render the svg-specific tags", () => { + expect.assertions(12); + withCanvas((html) => { ["svg", "circle", "path", "polygon", "rect", "text"].forEach( (tagName) => { let tag = html[tagName](); - expect(tag.element.namespaceURI).toEqual( + expect(tag.element.namespaceURI).toBe( "http://www.w3.org/2000/svg", ); - expect(tag.element.tagName.toLowerCase()).toEqual( + expect(tag.element.tagName.toLowerCase()).toStrictEqual( tagName, ); }, @@ -565,28 +632,32 @@ describe("htmlCanvas", () => { withCanvas((html) => { let tag = html.div({ class: input }); - expect(tag.element.className).toEqual(expectedOutput); + expect(tag.element.className).toStrictEqual(expectedOutput); }); } }); it("render() accepts a ref attribute to retrieve the DOM element", () => { + expect.assertions(1); + withCanvas((html) => { let rootRef = {}; html.render({ ref: rootRef }, (html) => html.p("foo")); - expect(rootRef.current.innerHTML).toEqual("

foo

"); + expect(rootRef.current.innerHTML).toBe("

foo

"); }); }); it("div() accepts a ref attribute to retrieve the DOM element", () => { + expect.assertions(1); + withCanvas((html) => { let rootRef = {}; html.div({ ref: rootRef }, (html) => html.p("foo")); - expect(rootRef.current.outerHTML).toEqual("

foo

"); + expect(rootRef.current.outerHTML).toBe("

foo

"); }); }); }); diff --git a/src/test/router/hashLocationTest.js b/src/test/router/hashLocationTest.js index 54642072..32c90afd 100644 --- a/src/test/router/hashLocationTest.js +++ b/src/test/router/hashLocationTest.js @@ -1,5 +1,13 @@ import jQuery from "jquery"; import hashLocationModel from "../../router/hashLocation.js"; +import { + afterEach, + beforeEach, + describe, + expect, + it, + jest, +} from "@jest/globals"; // Helpers @@ -34,7 +42,7 @@ describe("hashLocation", () => { my = {}; hashLocation = hashLocationModel({}, my); - jasmine.clock().install(); + jest.useFakeTimers(); }); afterEach(() => { @@ -42,13 +50,13 @@ describe("hashLocation", () => { hashLocation.stop(); } window.location.hash = ""; - jasmine.clock().uninstall(); + jest.useRealTimers(); }); it("hash defaults", () => { // Assert that defaults are correct - expect(my.currentHash).toBe(undefined); - expect(my.history.length).toBe(0); + expect(my.currentHash).toBeUndefined(); + expect(my.history).toHaveLength(0); }); it("start() initilize hash", () => { @@ -60,7 +68,7 @@ describe("hashLocation", () => { // Assert that hash is current location and history is set expect(my.currentHash).toBe("#!/test"); - expect(my.history.length).toBe(1); + expect(my.history).toHaveLength(1); expect(my.history[0]).toBe(my.currentHash); }); @@ -74,7 +82,7 @@ describe("hashLocation", () => { hashLocation.start(); // Assert that hash was reset, - expect(my.history.length).toBe(1); + expect(my.history).toHaveLength(1); expect(my.history[0]).toBe(my.currentHash); }); @@ -109,7 +117,7 @@ describe("hashLocation", () => { it("setUrl() triggers change", () => { let anotherHashLocation = hashLocationModel(); - let spy = jasmine.createSpy("changed event"); + let spy = jest.fn(); // Arrange: listen for url changes anotherHashLocation.changed.register(spy); @@ -129,6 +137,8 @@ describe("hashLocation", () => { }); it("back()", (callback) => { + expect.assertions(5); + delayedSteps( () => { hashLocation.stop(); @@ -173,6 +183,6 @@ describe("hashLocation", () => { }, ); - jasmine.clock().tick(131); + jest.advanceTimersByTime(131); }); }); diff --git a/src/test/router/routeTest.js b/src/test/router/routeTest.js index d3dfe02b..77c59c89 100644 --- a/src/test/router/routeTest.js +++ b/src/test/router/routeTest.js @@ -1,4 +1,5 @@ import router from "../../router.js"; +import { describe, it, expect } from "@jest/globals"; function assertMatch(url, route, _message) { expect( @@ -21,7 +22,7 @@ function assertNoMatch(url, route, _message) { describe("route", () => { // MATCH tests - it("Empty route", () => { + it("empty route", () => { let route = ""; assertMatch("", route, "Match empty"); @@ -32,7 +33,7 @@ describe("route", () => { assertNoMatch("value", route, "Don't match values"); }); - it("Slash route", () => { + it("slash route", () => { let route = "/"; assertMatch("", route, "Match empty"); @@ -43,7 +44,7 @@ describe("route", () => { assertNoMatch("value", route, "Don't match values"); }); - it("Static route", () => { + it("static route", () => { let route = "a/static/path"; assertMatch("/a/static/path", route, "Match if all segments are equal"); @@ -61,7 +62,7 @@ describe("route", () => { ); }); - it("Route ignore trailing slash on pattern", () => { + it("route ignore trailing slash on pattern", () => { let route = "a/static/path/"; // <-- ends with a slash assertMatch("/a/static/path", route, "Match if all segments are equal"); @@ -79,7 +80,7 @@ describe("route", () => { ); }); - it("Parameter route", () => { + it("parameter route", () => { let route = "a/#parameter/path"; // assertMatch("/a/foo/path", route, "Match any segment value"); @@ -99,7 +100,7 @@ describe("route", () => { assertNoMatch("b/foo/path", route, "B does not match static a"); }); - it("Multiple parameters route", () => { + it("multiple parameters route", () => { let route = "#parameter/#parameter2"; // assertMatch("foo/bar", route, "Match any segment values"); @@ -118,7 +119,7 @@ describe("route", () => { ); }); - it("Optional Parameter route", () => { + it("optional Parameter route", () => { let route = "a/?parameter/path"; // assertMatch("/a/foo/path", route, "Match any segment value"); @@ -140,7 +141,7 @@ describe("route", () => { assertNoMatch("b/foo/path", route, "B does not match static a"); }); - it("Multiple Optional Parameter route", () => { + it("multiple Optional Parameter route", () => { let route = "?foo/world/?bar/hello"; assertMatch("/foo/world/bar/hello", route, "Match if all segments"); @@ -168,7 +169,7 @@ describe("route", () => { ); }); - it("Mixed Optional and Mandatory Parameter route", () => { + it("mixed Optional and Mandatory Parameter route", () => { let route = "?foo/#bar/?bro"; assertMatch("/foo/bar/bro", route, "Match if all segments"); @@ -192,21 +193,21 @@ describe("route", () => { // Parameter binding tests - it("Route match result", () => { + it("route match result", () => { let route = router.route({ pattern: "#a/#b" }); let url = router.url({ rawUrl: "hello/world" }); let result = url.matchRoute(route); expect(result.isMatch()).toBeTruthy(); - expect(result.getRoute()).toEqual(route); - expect(result.getUrl()).toEqual(url); + expect(result.getRoute()).toStrictEqual(route); + expect(result.getUrl()).toStrictEqual(url); expect(result.getRouteParameters()).toBeTruthy(); expect(result.getRouteParameters().a).toBe("hello"); }); - it("Route match capture parameters", () => { + it("route match capture parameters", () => { let result = router .url({ rawUrl: "/hello/world" }) .matchRoute(router.route({ pattern: "#foo/#bar" })); @@ -217,7 +218,7 @@ describe("route", () => { expect(props.bar).toBe("world"); }); - it("Route match capture parameters mixed with statics", () => { + it("route match capture parameters mixed with statics", () => { let result = router .url({ rawUrl: "/hello/static/world" }) .matchRoute(router.route({ pattern: "#foo/static/#bar" })); @@ -228,7 +229,7 @@ describe("route", () => { expect(props.bar).toBe("world"); }); - it("Route parameter capture optional parameters", () => { + it("route parameter capture optional parameters", () => { let result = router .url({ rawUrl: "/hello/world" }) .matchRoute(router.route({ pattern: "?foo/?bar" })); @@ -239,27 +240,33 @@ describe("route", () => { expect(props.bar).toBe("world"); }); - it("Route parameter capture optional parameters mixed with parameters", () => { + it("route parameter capture optional parameters mixed with parameters", () => { let firstOptionalBothMatch = router .url({ rawUrl: "hello/world" }) .matchRoute(router.route({ pattern: "?foo/#bar" })) .getRouteParameters(); - expect(firstOptionalBothMatch).toEqual({ foo: "hello", bar: "world" }); + expect(firstOptionalBothMatch).toStrictEqual({ + foo: "hello", + bar: "world", + }); let firstOptionalOneMatch = router .url({ rawUrl: "/world" }) .matchRoute(router.route({ pattern: "?foo/#bar" })) .getRouteParameters(); - expect(firstOptionalOneMatch).toEqual({ foo: undefined, bar: "world" }); + expect(firstOptionalOneMatch).toStrictEqual({ + foo: undefined, + bar: "world", + }); let optionalInPath = router .url({ rawUrl: "hello/world" }) .matchRoute(router.route({ pattern: "#foo/?bar/#bro" })) .getRouteParameters(); - expect(optionalInPath).toEqual({ + expect(optionalInPath).toStrictEqual({ foo: "hello", bar: undefined, bro: "world", @@ -270,14 +277,14 @@ describe("route", () => { .matchRoute(router.route({ pattern: "#foo/?bar/?bro" })) .getRouteParameters(); - expect(trailingOptionals).toEqual({ + expect(trailingOptionals).toStrictEqual({ foo: "hello", bar: "world", bro: undefined, }); }); - it("Route parameter can have defaults", () => { + it("route parameter can have defaults", () => { let route = router.route({ pattern: "?foo/?bar", options: { @@ -297,17 +304,17 @@ describe("route", () => { // Query - it("Query", () => { + it("query", () => { let query = router .url({ rawUrl: "hello/world?a=1&b=2&c=3" }) .getQuery(); - expect(query).toEqual({ a: "1", b: "2", c: "3" }); + expect(query).toStrictEqual({ a: "1", b: "2", c: "3" }); }); // Expand - it("Expand parameters", () => { + it("expand parameters", () => { let route = router.route({ pattern: "#a/test/#b" }); let url = route.expand({ a: "hello", b: "world" }); @@ -315,7 +322,7 @@ describe("route", () => { expect(url).toBe("hello/test/world"); }); - it("Route parameter expansion can handle arrays", () => { + it("route parameter expansion can handle arrays", () => { let route = router.route({ pattern: "foo/#bar", }); @@ -325,7 +332,7 @@ describe("route", () => { expect(url).toBe("foo/a,b"); }); - it("Route optional parameter expansion can handle arrays", () => { + it("route optional parameter expansion can handle arrays", () => { let route = router.route({ pattern: "foo", }); @@ -334,7 +341,7 @@ describe("route", () => { expect(url).toBe("foo?bar=a,b"); }); - it("Expand optionals", () => { + it("expand optionals", () => { let route = router.route({ pattern: "#a/?c/#b/?d" }); expect(route.expand({ a: "hello", b: "world", d: "d" })).toBe( @@ -348,7 +355,7 @@ describe("route", () => { ); }); - it("Expand extra parameters to the query string", () => { + it("expand extra parameters to the query string", () => { let route = router.route({ pattern: "#a/#b" }); expect(route.expand({ a: "hello", b: "world", c: "foo" })).toBe( @@ -360,17 +367,17 @@ describe("route", () => { ).toBe("hello/world?c=foo&d=bar"); }); - it("Expand throws not valid URL error", () => { + it("expand throws not valid URL error", () => { let route = router.route({ pattern: "#a/#b" }); expect(() => { route.expand({ a: "hello" }); - }).toThrowError("Could not generate a valid URL"); + }).toThrow("Could not generate a valid URL"); }); // Constraints - it("Route with function constraint", () => { + it("route with function constraint", () => { let aRoute = router.route({ pattern: "/hello/#foo/", options: { @@ -391,7 +398,7 @@ describe("route", () => { ).toBeTruthy(); }); - it("Route with array constraint", () => { + it("route with array constraint", () => { let aRoute = router.route({ pattern: "hello/#foo", options: { @@ -410,7 +417,7 @@ describe("route", () => { ).toBeTruthy(); }); - it("Route with RegExp constraint", () => { + it("route with RegExp constraint", () => { let aRoute = router.route({ pattern: "hello/#foo", options: { @@ -429,7 +436,7 @@ describe("route", () => { ).toBeTruthy(); }); - it("Route with mixed constraints", () => { + it("route with mixed constraints", () => { let aRoute = router.route({ pattern: "#a/#b/#c", options: { @@ -466,7 +473,7 @@ describe("route", () => { ).toBeTruthy(); }); - it("Route constraints on optional parameters", () => { + it("route constraints on optional parameters", () => { let aRoute = router.route({ pattern: "?a/?b/?c", options: { @@ -496,7 +503,7 @@ describe("route", () => { aRoute .matchUrl(router.url({ rawUrl: "henrik/micke/h" })) .getRouteParameters(), - ).toEqual({ a: "henrik", b: "micke", c: "h" }); + ).toStrictEqual({ a: "henrik", b: "micke", c: "h" }); expect( aRoute.matchUrl(router.url({ rawUrl: "henrik/micke" })).isMatch(), @@ -506,7 +513,7 @@ describe("route", () => { aRoute .matchUrl(router.url({ rawUrl: "henrik/micke" })) .getRouteParameters(), - ).toEqual({ a: "henrik", b: "micke", c: undefined }); + ).toStrictEqual({ a: "henrik", b: "micke", c: undefined }); expect( aRoute.matchUrl(router.url({ rawUrl: "henrik" })).isMatch(), @@ -516,7 +523,7 @@ describe("route", () => { aRoute .matchUrl(router.url({ rawUrl: "henrik" })) .getRouteParameters(), - ).toEqual({ a: "henrik", b: undefined, c: undefined }); + ).toStrictEqual({ a: "henrik", b: undefined, c: undefined }); expect( aRoute.matchUrl(router.url({ rawUrl: "micke" })).isMatch(), @@ -526,7 +533,7 @@ describe("route", () => { aRoute .matchUrl(router.url({ rawUrl: "micke" })) .getRouteParameters(), - ).toEqual({ a: undefined, b: "micke", c: undefined }); + ).toStrictEqual({ a: undefined, b: "micke", c: undefined }); expect( aRoute.matchUrl(router.url({ rawUrl: "h" })).isMatch(), @@ -534,10 +541,10 @@ describe("route", () => { expect( aRoute.matchUrl(router.url({ rawUrl: "h" })).getRouteParameters(), - ).toEqual({ a: undefined, b: undefined, c: "h" }); + ).toStrictEqual({ a: undefined, b: undefined, c: "h" }); }); - it("Ignore trailing segments route option", () => { + it("ignore trailing segments route option", () => { let aRoute = router.route({ pattern: "hello/#foo", options: { diff --git a/src/test/router/routerTest.js b/src/test/router/routerTest.js index 69db6721..a0409f14 100644 --- a/src/test/router/routerTest.js +++ b/src/test/router/routerTest.js @@ -1,4 +1,12 @@ import router from "../../router/router.js"; +import { + afterEach, + beforeEach, + describe, + expect, + it, + jest, +} from "@jest/globals"; function delayedSteps() { let steps = Array.prototype.slice.call(arguments); @@ -26,23 +34,23 @@ describe("router", () => { my = {}; aRouter = router({}, my); - jasmine.clock().install(); + jest.useFakeTimers(); }); afterEach(() => { aRouter.stop(); aRouter.clear(); aRouter = null; - jasmine.clock().uninstall(); + jest.useRealTimers(); }); - it("Router defaults", () => { + it("router defaults", () => { // Assert that defaults are correct - expect(my.routeTable.length).toBe(0); - expect(my.lastMatch).toBe(undefined); + expect(my.routeTable).toHaveLength(0); + expect(my.lastMatch).toBeUndefined(); }); - it("Router options", () => { + it("router options", () => { // Arrange a router with options set let anotherMy = {}; @@ -60,25 +68,25 @@ describe("router", () => { expect(anotherMy.location.isFake).toBeTruthy(); }); - it("Add route", () => { + it("add route", () => { // Act: add a route let route = aRouter.addRoute({ pattern: "/users/" }); // Assert that route was added to route table - expect(my.routeTable.length).toBe(1); + expect(my.routeTable).toHaveLength(1); expect(my.routeTable[0]).toBe(route); }); - it("Remove route", () => { + it("remove route", () => { // Act: add and remove route let route = aRouter.addRoute({ pattern: "/users/" }); aRouter.removeRoute(route); // Assert that route was removed from route table - expect(my.routeTable.length).toBe(0); + expect(my.routeTable).toHaveLength(0); }); - it("Named routes", () => { + it("named routes", () => { // Arrange: a named route let route = aRouter.addRoute({ name: "users", pattern: "/users/" }); @@ -89,7 +97,7 @@ describe("router", () => { expect(namedRoute).toBe(route); }); - it("Add routes with priority", () => { + it("add routes with priority", () => { // Act: add routes with different priorities let invoiceRoute = aRouter.addRoute({ pattern: "/invoice/" }); let ticketRoute = aRouter.addRoute({ pattern: "/ticket/" }); @@ -101,7 +109,7 @@ describe("router", () => { let userRoute = aRouter.addRoute({ pattern: "/user/", priority: 1 }); // Assert that route was added to route table in correct order - expect(my.routeTable.length).toBe(5); + expect(my.routeTable).toHaveLength(5); expect(my.routeTable[0]).toBe(userRoute); expect(my.routeTable[2]).toBe(orderRoute); expect(my.routeTable[3]).toBe(invoiceRoute); @@ -111,7 +119,7 @@ describe("router", () => { it("resolveUrl executes route callback on match", () => { // Arrange: setup a route let userRoute = aRouter.addRoute({ pattern: "/user/" }); - let spy = jasmine.createSpy("matched event"); + let spy = jest.fn(); userRoute.on("matched", spy); @@ -120,11 +128,11 @@ describe("router", () => { aRouter.resolveUrl("/order/"); // Assert that callback was executed - expect(spy).toHaveBeenCalledTimes(1); + expect(spy).toHaveBeenCalledOnce(); }); it("resolveUrl triggers resolveUrl event", () => { - let spy = jasmine.createSpy("resolveUrl event"); + let spy = jest.fn(); // listen for "resolveUrl event" on router aRouter.on("resolveUrl", spy); @@ -133,10 +141,12 @@ describe("router", () => { aRouter.resolveUrl("/user/"); // Assert that callback was executed - expect(spy).toHaveBeenCalledWith(jasmine.anything()); + expect(spy).toHaveBeenCalledWith(expect.anything()); }); it("resolveUrl triggers routeMatched event", (done) => { + expect.assertions(2); + // Arrange: setup a route let userRoute = aRouter.addRoute({ pattern: "/user/" }); @@ -144,7 +154,7 @@ describe("router", () => { aRouter.on("routeMatched", function (result) { // Assert that callback was executed expect(result).toBeTruthy(); - expect(result.getRoute()).toEqual(userRoute); + expect(result.getRoute()).toStrictEqual(userRoute); this.unbind(); // clean-up done(); // execute asserts @@ -155,12 +165,14 @@ describe("router", () => { }); it("resolveUrl triggers routeNotFound event", (done) => { + expect.assertions(2); + // Arrange: setup no routes but // a lister for "notFound event" aRouter.on("routeNotFound", function (url) { // Assert that callback was executed expect(url).toBeTruthy(); - expect(url.toString()).toEqual("/user/"); + expect(url.toString()).toBe("/user/"); this.unbind(); // clean-up done(); // execute asserts @@ -171,7 +183,7 @@ describe("router", () => { }); it("resolveUrl executes action on match", () => { - let spy = jasmine.createSpy("action"); + let spy = jest.fn(); // Arrange: setup a route aRouter.addRoute({ @@ -183,16 +195,18 @@ describe("router", () => { aRouter.resolveUrl("/user/"); // Assert that callback was executed - expect(spy).toHaveBeenCalledWith(jasmine.anything()); + expect(spy).toHaveBeenCalledWith({}); }); it("resolveUrl pass values to action", (done) => { + expect.assertions(2); + // Arrange a route that have two mandatory parameters aRouter.addRoute({ pattern: "/user/#userid/order/#orderid", action: function (userid, orderid) { - expect(userid).toEqual("john"); - expect(orderid).toEqual("1"); + expect(userid).toBe("john"); + expect(orderid).toBe("1"); this.unbind(); // clean-up done(); // execute asserts @@ -204,12 +218,15 @@ describe("router", () => { }); it("resolveUrl pass optional values to action", (done) => { + expect.assertions(2); + // Arrange a route that have two mandatory parameters aRouter.addRoute({ pattern: "/user/?userid/order/?orderid", action: function (userid, orderid) { - expect(userid).toBe(undefined); + expect(userid).toBeUndefined(); expect(orderid).toBe("1"); + this.unbind(); // clean-up done(); // execute asserts }, @@ -220,6 +237,8 @@ describe("router", () => { }); it("resolveUrl pass optional value defaults to action", (done) => { + expect.assertions(2); + // Arrange a route that have two optional parameters // with defaukts aRouter.addRoute({ @@ -231,6 +250,7 @@ describe("router", () => { action: function (userid, orderid) { expect(userid).toBe("bengan"); expect(orderid).toBe("1"); + this.unbind(); // clean-up done(); // execute asserts }, @@ -241,6 +261,8 @@ describe("router", () => { }); it("resolveUrl pass query as last argument to action", (done) => { + expect.assertions(3); + // Arrange a route that have one parameter aRouter.addRoute({ pattern: "/user/#userid/order", @@ -249,6 +271,7 @@ describe("router", () => { expect(userid).toBe("john"); expect(query.filter).toBe("open"); expect(query.orderBy).toBe("date"); + this.unbind(); // clean-up done(); // execute asserts }, @@ -259,6 +282,8 @@ describe("router", () => { }); it("resolveUrl continues if fallThrough", (done) => { + expect.assertions(2); + // Arrange a 3 routes, where first have fallThrough // set and the two other have not @@ -267,6 +292,7 @@ describe("router", () => { pattern: "/user/", action: function () { expect(true).toBeTruthy(); + this.unbind(); // clean-up }, }); @@ -275,6 +301,7 @@ describe("router", () => { pattern: "/user/", action: function () { expect(true).toBeTruthy(); + this.unbind(); // clean-up done(); // execute asserts }, @@ -284,6 +311,7 @@ describe("router", () => { pattern: "/user/", action: function () { expect(true).toBeTruthy(); + this.unbind(); // clean-up }, }); @@ -292,8 +320,8 @@ describe("router", () => { aRouter.resolveUrl("/user/"); }); - it("Add route with constraints", () => { - let action = jasmine.createSpy("action"); + it("add route with constraints", () => { + let action = jest.fn(); aRouter.addRoute({ pattern: "/user/#name/", @@ -305,14 +333,14 @@ describe("router", () => { aRouter.resolveUrl("/user/nicolas"); - expect(action).toHaveBeenCalledWith("nicolas", jasmine.anything()); - expect(action).toHaveBeenCalledTimes(1); + expect(action).toHaveBeenCalledWith("nicolas", expect.anything()); + expect(action).toHaveBeenCalledOnce(); // resolve two URLs that do *not* match constraint aRouter.resolveUrl("/user/john"); aRouter.resolveUrl("/user/james"); - expect(action).toHaveBeenCalledTimes(1); + expect(action).toHaveBeenCalledOnce(); }); it("getUrl returns current location", () => { @@ -339,10 +367,10 @@ describe("router", () => { expect(window.location.hash).toBe("#!/"); }); - it("Pipe notfound to another router", () => { + it("pipe notfound to another router", () => { // Arrange another router with a route handler let anotherRouter = router(); - let spy = jasmine.createSpy("action"); + let spy = jest.fn(); anotherRouter.addRoute({ pattern: "APathNotInDefaultRouterButInPipedRouter", @@ -355,13 +383,14 @@ describe("router", () => { // Assert that second router matched the route expect(spy).toHaveBeenCalledWith({}); + anotherRouter.stop(); }); - it("Pipe route to another router", () => { + it("pipe route to another router", () => { // Arrange another router with a route handler let anotherRouter = router(); - let spy = jasmine.createSpy("action"); + let spy = jest.fn(); anotherRouter.addRoute({ pattern: "/a/b/#c", @@ -373,11 +402,14 @@ describe("router", () => { aRouter.resolveUrl("/a/b/c"); // Assert that second router matched the route - expect(spy).toHaveBeenCalledTimes(1); + expect(spy).toHaveBeenCalledOnce(); + anotherRouter.stop(); }); it("back()", (done) => { + expect.assertions(5); + aRouter.stop(); window.location.hash = ""; // start path aRouter.start(); @@ -419,10 +451,10 @@ describe("router", () => { done, ); - jasmine.clock().tick(131); + jest.advanceTimersByTime(131); }); - it("Expand parameters for named route", () => { + it("expand parameters for named route", () => { // Arrange: a named route aRouter.addRoute({ name: "user", pattern: "/user/#userId" }); @@ -437,7 +469,7 @@ describe("router", () => { expect(url.toString()).toBe("user/john?includeDetails=true"); }); - it("Expand parameters for empty route", () => { + it("expand parameters for empty route", () => { // Arrange: empty hash route window.location.hash = ""; // start path @@ -450,7 +482,7 @@ describe("router", () => { expect(url.toString()).toBe("?userId=john&includeDetails=true"); }); - it("Expand parameters for current route", () => { + it("expand parameters for current route", () => { // Arrange: a named route aRouter.addRoute({ name: "user", @@ -472,7 +504,7 @@ describe("router", () => { ); }); - it("LinkTo with default parameters", () => { + it("linkTo with default parameters", () => { // Arrange: a route with non optional parameter #foo aRouter.addRoute({ name: "bar", @@ -489,7 +521,7 @@ describe("router", () => { expect(url.toString()).toBe("#!/default/bar"); }); - it("GetParameters from current URL", () => { + it("getParameters from current URL", () => { // Arrange: a named route aRouter.addRoute({ name: "user", pattern: "/user/#userId" }); @@ -500,13 +532,13 @@ describe("router", () => { let parameters = aRouter.getParameters(); // Assert that parameters contains both query and URL parameters - expect(parameters).toEqual({ + expect(parameters).toStrictEqual({ userId: "john", includeCompanies: "true", }); }); - it("GetParameter", () => { + it("getParameter", () => { // Arrange: a named route aRouter.addRoute({ name: "user", pattern: "/user/#userId" }); @@ -526,6 +558,8 @@ describe("router", () => { }); it("setParameters()", (done) => { + expect.assertions(4); + aRouter.stop(); window.location.hash = ""; // start path aRouter.start(); @@ -562,6 +596,6 @@ describe("router", () => { done, ); - jasmine.clock().tick(131); + jest.advanceTimersByTime(131); }); }); diff --git a/src/test/widgetTest.js b/src/test/widgetTest.js index 916cfd80..1d586f3b 100644 --- a/src/test/widgetTest.js +++ b/src/test/widgetTest.js @@ -1,8 +1,9 @@ import widget from "../widget.js"; import htmlCanvas from "../htmlCanvas.js"; import jQuery from "jquery"; +import { jest, describe, it, expect } from "@jest/globals"; -let widgetSubclass = widget.subclass((that) => { +const widgetSubclass = widget.subclass((that) => { that.renderContentOn = function (html) { html.h1("Hello world"); }; @@ -37,9 +38,11 @@ function withCanvas(callback) { describe("function", () => { it("widgets are assigned unique identifiers", () => { + expect.assertions(1000); + withWidget((aWidget) => { for (let i = 0; i < 1000; i++) { - expect(widgetSubclass().id()).not.toEqual(aWidget.id()); + expect(widgetSubclass().id()).not.toStrictEqual(aWidget.id()); } }); }); @@ -51,6 +54,8 @@ describe("function", () => { }); it("widgets supports events", () => { + expect.assertions(1); + // Arrange: a widget with a public method // that triggers an event when executed. let aWidget = (function () { @@ -89,7 +94,7 @@ describe("function", () => { return that; })(); - let spy = jasmine.createSpy("callback"); + let spy = jest.fn(); // Assert: that callback is executed when aWidget.anEvent.register(spy); @@ -97,7 +102,7 @@ describe("function", () => { // event is triggered aWidget.aMethod(); - expect(spy).toHaveBeenCalled(); + expect(spy).toHaveBeenCalledWith(); }); it("linkTo() creates links to paths in app", () => { @@ -116,13 +121,17 @@ describe("function", () => { expect(window.location.hash).toBe(my.linkTo("foo/bar")); }); - it("Render", () => { + it("render", () => { + expect.assertions(1); + withWidget((aWidget) => { expect(jQuery(`#${aWidget.id()}`).get(0)).toBeTruthy(); }); }); - it("Update", () => { + it("update", () => { + expect.assertions(1); + withWidget((aWidget) => { aWidget.renderContentOn = function (html) { html.div().id("foo"); @@ -134,7 +143,9 @@ describe("function", () => { }); }); - it("Remove", () => { + it("remove", () => { + expect.assertions(2); + withWidget((aWidget) => { let id = `#${aWidget.id()}`; @@ -146,7 +157,9 @@ describe("function", () => { }); }); - it("Widgets can be appended a jQuery", () => { + it("widgets can be appended a jQuery", () => { + expect.assertions(1); + withCanvas((html) => { // Arrange: a widget let aWidget = (function () { @@ -170,7 +183,9 @@ describe("function", () => { }); }); - it("Widgets can replace content of a jQuery", () => { + it("widgets can replace content of a jQuery", () => { + expect.assertions(2); + withCanvas((html) => { // Arrange: a widget let aWidget = (function () { @@ -190,12 +205,14 @@ describe("function", () => { aWidget.replace(divQuery); // Assert: that widget was appended to DIV - expect(divQuery.children().length).toBe(1); + expect(divQuery.children()).toHaveLength(1); expect(divQuery.children().get(0).id).toBe(aWidget.id()); }); }); - it("Widgets can be appended to a HTML canvas", () => { + it("widgets can be appended to a HTML canvas", () => { + expect.assertions(1); + withCanvas((html) => { // Arrange: a widget let aWidget = (function () { @@ -217,6 +234,8 @@ describe("function", () => { }); it("isRendered()", () => { + expect.assertions(2); + withCanvas((html) => { // Arrange: a widget let aWidget = (function () { @@ -241,6 +260,8 @@ describe("function", () => { }); it("renderRoot() can be overridden in widget", () => { + expect.assertions(1); + withCanvas((html) => { // Arrange: a widget that renders it"s root as // form instead of DIV @@ -266,6 +287,8 @@ describe("function", () => { }); it("willAttach() and didAttach() are called upon rendering", () => { + expect.assertions(2); + withCanvas((html) => { let aWidget = (function () { let my = {}; @@ -295,6 +318,8 @@ describe("function", () => { }); it("willUpdate() is not called when rendering", () => { + expect.assertions(1); + withCanvas((html) => { let aWidget = (function () { let my = {}; @@ -316,6 +341,8 @@ describe("function", () => { }); it("willUpdate() is called when updating", () => { + expect.assertions(1); + withCanvas((html) => { let aWidget = (function () { let my = {}; @@ -338,39 +365,43 @@ describe("function", () => { }); it("widgets initialize their subwidgets", () => { - let spy = jasmine.createSpy("init"); + let spy = jest.fn(); let mySubclass = widget.subclass((that, my) => { my.initializeSubwidgets = spy; }); mySubclass(); - expect(spy).toHaveBeenCalled(); + expect(spy).toHaveBeenCalledWith({}); }); it("widgets initialize their subwidgets after themselves", () => { - // TODO: refactor when - // https://github.com/jasmine/jasmine/pull/1242 is merged - let init = jasmine.createSpy("init"); - let initSub = jasmine.createSpy("init sub"); + expect.assertions(2); + + let init = jest.fn(); + let initSub = jest.fn(); let mySubclass = widget.subclass((that, my) => { my.initialize = init; my.initializeSubwidgets = function () { - expect(init).toHaveBeenCalled(); + expect(init).toHaveBeenCalledWith(expect.anything()); + initSub(); }; }); mySubclass(); - expect(initSub).toHaveBeenCalled(); + expect(initSub).toHaveBeenCalledWith(); }); it("widgets can create an event", () => { + expect.assertions(2); + // eslint-disable-next-line no-shadow -- we should fix that later withWidget((widget, my) => { expect(widget.foo).toBeUndefined(); + my.createEvent("foo"); expect(widget.foo).toBeTruthy(); @@ -378,10 +409,13 @@ describe("function", () => { }); it("widgets can create events", () => { + expect.assertions(4); + // eslint-disable-next-line no-shadow -- we should fix that later withWidget((widget, my) => { expect(widget.foo).toBeUndefined(); expect(widget.bar).toBeUndefined(); + my.createEvents("foo", "bar"); expect(widget.foo).toBeTruthy();