UNPKG

inlineresources

Version:

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

502 lines (379 loc) 18.9 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 { font-size: 14px; }"); done(); }); }); it("should fail correctly", function (done) { util.ajax("non_existing_url.html", {}) .catch(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"); } }); }); });