UNPKG

inlineresources

Version:

Inlines style sheets, images, fonts and scripts in HTML documents. Works in the browser.

572 lines (452 loc) 20.1 kB
"use strict"; var util = require("../../src/util"), testHelper = require("../testHelper"); describe("Inline utilities function", function () { describe("clone", function () { it("should create a copy of the given object", function () { var input = { anOption: "1", yetAnotherOption: "21" }, output; output = util.clone(input); expect(input).toEqual(output); expect(input).not.toBe(output); }); }); describe("cloneArray", function () { it("should create a copy of the given list", function () { var input = [1, 2, 3], output; output = util.cloneArray(input); expect(input).toEqual(output); expect(input).not.toBe(output); }); }); describe("getDocumentBaseUrl", function () { var endsWith = function (str, matchStr) { return str.substr(-matchStr.length) === matchStr; }; it("should return a document's base url", function (done) { var fixturePath = testHelper.fixturesPath + "image.html", url, nonQueryPart; testHelper .loadHTMLDocumentFixture("image.html") .then(function (doc) { url = util.getDocumentBaseUrl(doc); nonQueryPart = url.split("?")[0]; expect(endsWith(nonQueryPart, fixturePath)).toBeTruthy(); done(); }); }); }); describe("joinUrl", function () { it("should append the url to a directory-only base", function () { var url = util.joinUrl("rel/path/", "the_relative_url"); expect(url).toEqual("rel/path/the_relative_url"); }); it("should append the url to a file base", function () { var url = util.joinUrl("rel/path/something", "the_relative_url"); expect(url).toEqual("rel/path/the_relative_url"); }); it("should merge ../ with a directory-only base", function () { var url = util.joinUrl("rel/path/", "../the_relative_url"); expect(url).toEqual("rel/the_relative_url"); }); it("should just return the url if absolute", function () { var url = util.joinUrl("rel/path/", "/the_relative_url"); expect(url).toEqual("/the_relative_url"); }); it("should combine a url starting with '/' with the host of the base", function () { var url = util.joinUrl( "http://example.com/rel/path/", "/the_relative_url" ); expect(url).toEqual("http://example.com/the_relative_url"); }); it("should ignore base with an absolute url", function () { var url = util.joinUrl( "http://example.com/rel/path/", "http://github.com//the_relative_url" ); expect(url).toEqual("http://github.com//the_relative_url"); }); it("should ignore base without directories", function () { var url = util.joinUrl("aFile", "anotherFile"); expect(url).toEqual("anotherFile"); }); it("should ignore an undefined base", function () { var url = util.joinUrl(undefined, "aFile"); expect(url).toEqual("aFile"); }); it("should keep a relative base URL", function () { var url = util.joinUrl("../rel/path/", "the_relative_url"); expect(url).toEqual("../rel/path/the_relative_url"); }); }); describe("isDataUri", function () { it("should report data URI", function () { expect( util.isDataUri("data:image/png;base64,soMEfAkebASE64=") ).toBeTruthy(); }); it("should handle single quotes", function () { expect(util.isDataUri("path/file.png")).toBeFalsy(); }); }); describe("ajax", function () { it("should load content from a URL", function (done) { util.ajax(testHelper.fixturesPath + "some.css", {}).then(function ( loadedContent ) { expect(loadedContent).toEqual("p {\n font-size: 14px;\n}\n"); done(); }); }); it("should fail correctly", function (done) { util.ajax("non_existing_url.html", {}).catch(function () { done(); }); }); it("should include msg and url in error", function (done) { var url = "non_existing_url.html"; util.ajax(url, {}).catch(function (e) { expect(e.msg).toEqual("Unable to load url"); expect(e.url).toEqual(url); done(); }); }); describe("options", function () { var ajaxRequest; beforeEach(function () { ajaxRequest = jasmine.createSpyObj("ajaxRequest", [ "open", "addEventListener", "overrideMimeType", "send", ]); spyOn(window, "XMLHttpRequest").and.returnValue(ajaxRequest); spyOn(util, "joinUrl").and.callFake(function (baseUrl, url) { return baseUrl ? baseUrl + url : url; }); }); it("should attach an unique parameter to the given URL to circumvent caching if requested", function () { util.ajax("non_existing_url.html", { cache: "none" }); expect(ajaxRequest.open).toHaveBeenCalledWith( "GET", jasmine.any(String), true ); expect(ajaxRequest.open.calls.mostRecent().args[1]).toMatch( /^non_existing_url.html\?_=[0123456789]+$/ ); }); it("should attach an unique parameter to the given URL to circumvent caching if requested (legacy: 'false')", function () { util.ajax("non_existing_url.html", { cache: false }); expect(ajaxRequest.open).toHaveBeenCalledWith( "GET", jasmine.any(String), true ); expect(ajaxRequest.open.calls.mostRecent().args[1]).toMatch( /^non_existing_url.html\?_=[0123456789]+$/ ); }); it("should not attach an unique parameter to the given URL by default", function () { util.ajax("non_existing_url.html", {}); expect(ajaxRequest.open).toHaveBeenCalledWith( "GET", "non_existing_url.html", true ); }); it("should allow caching for repeated calls if requested", function () { var dateNowSpy = spyOn(window.Date, "now").and.returnValue(42); util.ajax("non_existing_url.html", { cache: "none" }); expect(ajaxRequest.open.calls.mostRecent().args[1]).toEqual( "non_existing_url.html?_=42" ); dateNowSpy.and.returnValue(43); util.ajax("non_existing_url.html", { cache: "repeated" }); expect(ajaxRequest.open.calls.mostRecent().args[1]).toEqual( "non_existing_url.html?_=42" ); expect(dateNowSpy.calls.count()).toEqual(1); }); it("should not cache repeated calls by default", function () { var dateNowSpy = spyOn(window.Date, "now").and.returnValue(42); util.ajax("non_existing_url.html", { cache: "none" }); expect(ajaxRequest.open.calls.mostRecent().args[1]).toEqual( "non_existing_url.html?_=42" ); dateNowSpy.and.returnValue(43); util.ajax("non_existing_url.html", { cache: "none" }); expect(ajaxRequest.open.calls.mostRecent().args[1]).toEqual( "non_existing_url.html?_=43" ); }); it("should force mime type if requested", function () { util.ajax("non_existing_url.html", { mimeType: "42" }); expect(ajaxRequest.overrideMimeType).toHaveBeenCalledWith("42"); }); it("should load URLs relative to baseUrl", function () { util.ajax("relative/url.png", { baseUrl: "http://example.com/", }); expect(ajaxRequest.open.calls.mostRecent().args[1]).toEqual( "http://example.com/relative/url.png" ); expect(util.joinUrl).toHaveBeenCalledWith( "http://example.com/", "relative/url.png" ); }); it("should report url relative to baseUrl in error", function (done) { var url = "non_existing_url.html", baseUrl = "http://example.com/"; ajaxRequest.open.and.throwError(new Error("a")); util.ajax(url, { baseUrl: baseUrl }).catch(function (e) { expect(util.joinUrl).toHaveBeenCalledWith(baseUrl, url); expect(e.msg).toEqual("Unable to load url"); expect(e.url).toEqual(baseUrl + url); done(); }); }); }); }); describe("binaryAjax", function () { var mockAjaxWith = function (promise) { return spyOn(util, "ajax").and.returnValue(promise); }; var rejectedPromise = function (e) { return Promise.reject(e); }; var resolvedPromise = function () { return Promise.resolve(""); }; beforeEach(function () { spyOn(util, "joinUrl").and.callFake(function (baseUrl, url) { return url; }); }); it("should load binary data", function (done) { util.binaryAjax(testHelper.fixturesPath + "green.png", {}).then( function (loadedContent) { expect(btoa(loadedContent)).toEqual( "iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAABFElEQVR4nO3OMQ0AAAjAMPybhnsKxrHUQGc2r+iBkB4I6YGQHgjpgZAeCOmBkB4I6YGQHgjpgZAeCOmBkB4I6YGQHgjpgZAeCOmBkB4I6YGQHgjpgZAeCOmBkB4I6YGQHgjpgZAeCOmBkB4I6YGQHgjpgZAeCOmBkB4I6YGQHgjpgZAeCOmBkB4I6YGQHgjpgZAeCOmBkB4I6YGQHgjpgZAeCOmBkB4I6YGQHgjpgZAeCOmBkB4I6YGQHgjpgZAeCOmBkB4I6YGQHgjpgZAeCOmBkB4I6YGQHgjpgZAeCOmBkB4I6YGQHgjpgZAeCOmBkB4I6YGQHgjpgZAeCOmBkB4I6YGQHgjpgZAeCOmBkB4I6YHAAV821mT1w27RAAAAAElFTkSuQmCC" ); done(); } ); }); it("should handle an error", function (done) { mockAjaxWith(rejectedPromise()); util.binaryAjax("url", {}).catch(done); }); it("should hand through the error object", function (done) { var e = new Error("oh my"); mockAjaxWith(rejectedPromise(e)); util.binaryAjax("url", {}).catch(function (error) { expect(error).toBe(e); done(); }); }); it("should circumvent caching if requested", function () { var ajaxSpy = mockAjaxWith(resolvedPromise()); util.binaryAjax("url", { cache: "none" }); expect(ajaxSpy).toHaveBeenCalledWith("url", { mimeType: jasmine.any(String), cache: "none", }); }); it("should cache by default", function () { var ajaxSpy = mockAjaxWith(resolvedPromise()); util.binaryAjax("url", {}); expect(ajaxSpy).toHaveBeenCalledWith("url", { mimeType: jasmine.any(String), }); }); }); describe("getDataURIForImageURL", function () { var binaryAjaxSpy; var mockBinaryAjax = function (targetUrl, content) { binaryAjaxSpy.and.callFake(function (url) { return new Promise(function (resolve) { if (url === targetUrl) { resolve(content); } }); }); }; beforeEach(function () { binaryAjaxSpy = spyOn(util, "binaryAjax"); }); it("should return an image as data: URI", function (done) { mockBinaryAjax("green.png", "fakeImageContent"); util.getDataURIForImageURL("green.png", {}).then(function ( returnedDataURI ) { expect(returnedDataURI).toEqual( "data:image/png;base64," + btoa("fakeImageContent") ); expect(binaryAjaxSpy).toHaveBeenCalledWith("green.png", {}); done(); }); }); it("should return a SVG as data: URI", function (done) { var svgImageHead = '<?xml version="1.0" encoding="utf-8"?>'; mockBinaryAjax("green.svg", svgImageHead); util.getDataURIForImageURL("green.svg", {}).then(function ( returnedDataURI ) { expect(returnedDataURI).toEqual( "data:image/svg+xml;base64," + btoa(svgImageHead) ); done(); }); }); it("should return a SVG as data: URI without XML head", function (done) { var svgImageHead = '<svg xmlns="http://www.w3.org/2000/svg">'; mockBinaryAjax("green.svg", svgImageHead); util.getDataURIForImageURL("green.svg", {}).then(function ( returnedDataURI ) { expect(returnedDataURI).toEqual( "data:image/svg+xml;base64," + btoa(svgImageHead) ); done(); }); }); it("should return an error if the image could not be located due to a REST error", function (done) { binaryAjaxSpy.and.callFake(function () { return Promise.reject(); }); util.getDataURIForImageURL("image_does_not_exist.png", {}).catch( done ); }); it("should hand through the error object", function (done) { var e = new Error("not good"); binaryAjaxSpy.and.callFake(function () { return Promise.reject(e); }); util.getDataURIForImageURL("image_does_not_exist.png", {}).catch( function (error) { expect(error).toBe(e); done(); } ); }); it("should circumvent caching if requested", function () { mockBinaryAjax("image.png", "content"); util.getDataURIForImageURL("image.png", { cache: "none" }); expect(binaryAjaxSpy).toHaveBeenCalledWith("image.png", { cache: "none", }); }); }); describe("memoize", function () { var func, aResult, memo, hasher; beforeEach(function () { memo = {}; aResult = "the function result"; func = jasmine.createSpy("func").and.callFake(function () { return aResult; }); hasher = function (x) { return x; }; }); it("should call the memoized function for the first time", function () { var memoized = util.memoize(func, hasher, memo); expect(func).not.toHaveBeenCalled(); memoized("a parameter", 1, "and a 3rd parameter"); expect(func).toHaveBeenCalledWith( "a parameter", 1, "and a 3rd parameter" ); }); it("should not call the memoized function for a second time with the same parameters", function () { var memoized = util.memoize(func, hasher, memo); memoized("a parameter", 1, "and a 3rd parameter"); func.calls.reset(); memoized("a parameter", 1, "and a 3rd parameter"); expect(func).not.toHaveBeenCalled(); }); it("should return the return value", function () { var memoized = util.memoize(func, hasher, memo); var ret = memoized("param1"); expect(ret).toBe(aResult); }); it("should memoize the return value", function () { var memoized = util.memoize(func, hasher, memo); memoized("param1"); var ret = memoized("param1"); expect(ret).toBe(aResult); }); it("should call the memoized function again with different parameters", function () { var memoized = util.memoize(func, hasher, memo); memoized("a parameter", 1, "and a 3rd parameter"); func.calls.reset(); memoized("another parameter", 1, 2); expect(func).toHaveBeenCalledWith("another parameter", 1, 2); }); it("should memoize different functions independently", function () { var yetAnotherResult = "yet another result", func2 = jasmine.createSpy("func2").and.callFake(function () { return yetAnotherResult; }), memoized = util.memoize(func, hasher, memo), memoized2 = util.memoize(func2, hasher, memo); memoized("a parameter", 1, "and a 3rd parameter"); var ret = memoized2("a parameter", 1, "and a 3rd parameter"); expect(func2).toHaveBeenCalled(); expect(ret).toBe(yetAnotherResult); }); it("should memoize across the same memo objects", function () { var memoized1 = util.memoize(func, hasher, memo), memoized2 = util.memoize(func, hasher, memo); memoized1("a parameter", 1, "and a 3rd parameter"); func.calls.reset(); memoized2("a parameter", 1, "and a 3rd parameter"); expect(func).not.toHaveBeenCalled(); }); it("should not memoize across different memo objects", function () { var memoized1 = util.memoize(func, hasher, memo), memoized2 = util.memoize(func, hasher, {}); memoized1("a parameter", 1, "and a 3rd parameter"); func.calls.reset(); memoized2("a parameter", 1, "and a 3rd parameter"); expect(func).toHaveBeenCalledWith( "a parameter", 1, "and a 3rd parameter" ); }); it("should use hash function result when comparing parameter keys with disjunct values", function () { var hasher = JSON.stringify, memoized = util.memoize(func, hasher, memo); memoized({ a: 1 }, 1, 2); func.calls.reset(); memoized({ b: 2 }, 1, 2); expect(func).toHaveBeenCalled(); }); it("should use hash function result when comparing parameter keys with same values", function () { var hasher = function (x) { return typeof x === "object" ? {} : x; }, memoized = util.memoize(func, hasher, memo); memoized({ a: 1 }, 1, 2); func.calls.reset(); memoized({ b: 2 }, 1, 2); expect(func).not.toHaveBeenCalled(); }); it("should throw an error if the memo is not an object", function () { try { util.memoize(func, hasher, 42); expect(true).toBe(false); } catch (e) { expect(e.message).toEqual("cacheBucket is not an object"); } }); }); });