UNPKG

rx-player

Version:
305 lines (276 loc) 11.8 kB
import { describe, it, expect } from "vitest"; import { getFilenameIndexInUrl, getRelativeUrl, resolveURL } from "../url-utils"; describe(`utils - resolveURL ${resolveURL.name}`, () => { it("should return an empty string if no argument is given", () => { expect(resolveURL()).toBe(""); }); it("should concatenate multiple URLs", () => { expect(resolveURL("http://toto.com/a")).toBe("http://toto.com/a"); expect( resolveURL("http://toto.com/a" /** Trailling slash missing */, "b/c/d/", "g.a"), ).toBe("http://toto.com/b/c/d/g.a"); expect( resolveURL("http://toto.com/a/" /** With a trailling slash */, "b/c/d/", "g.a"), ).toBe("http://toto.com/a/b/c/d/g.a"); }); it("should ignore empty strings when concatenating multiple URLs", () => { expect(resolveURL("", "http://toto.com/a", "")).toBe("http://toto.com/a"); expect(resolveURL("http://toto.com/a/", "b/c/d/", "", "g.a")).toBe( "http://toto.com/a/b/c/d/g.a", ); }); it("should handle absolute path and keep the last one only", () => { expect(resolveURL("http://toto.com/a", "/b/c/d/", "/", "/g.a")).toBe( "http://toto.com/g.a", ); }); it("should reset the concatenation if a given string contains a scheme", () => { expect(resolveURL("http://toto.com/a", "b/c/d/", "torrent://g.a", "b")).toBe( "torrent://g.a/b", ); }); it("should have a - fairly simple - algorithm to simplify parent directories", () => { expect( resolveURL("http://toto.com/a/", "b/c/d/", "torrent://g.a/b/c/d/", "../a"), ).toBe("torrent://g.a/b/c/a"); expect( resolveURL("http://toto.com/a/", "b/c/d/", "torrent://g.a/b/c/d/", "../c/../../a"), ).toBe("torrent://g.a/b/a"); }); it("should have a - fairly simple - algorithm to simplify the current directory", () => { expect( resolveURL("http://toto.com/a/", "b/c/d/", "torrent://g.a/b/c/d/", "./a"), ).toBe("torrent://g.a/b/c/d/a"); expect( resolveURL("http://toto.com/a/", "b/c/d/", "torrent://g.a/b/c/d/", "../c/.././a"), ).toBe("torrent://g.a/b/c/a"); }); it("should resolve absolute urls with overriding baseURL path", () => { expect(resolveURL("http://a/b/c/d;p?q", "/g")).toBe("http://a/g"); }); const normalExamples = [ { input: "g:h", output: "g:h" }, { input: "g", output: "http://a/b/c/g" }, { input: "./g", output: "http://a/b/c/g" }, { input: "g/", output: "http://a/b/c/g/" }, { input: "/g", output: "http://a/g" }, { input: "//g", output: "http://g" }, { input: "?y", output: "http://a/b/c/d;p?y" }, { input: "g?y", output: "http://a/b/c/g?y" }, { input: "#s", output: "http://a/b/c/d;p?q#s" }, { input: "g#s", output: "http://a/b/c/g#s" }, { input: "g?y#s", output: "http://a/b/c/g?y#s" }, { input: ";x", output: "http://a/b/c/;x" }, { input: "g;x", output: "http://a/b/c/g;x" }, { input: "g;x?y#s", output: "http://a/b/c/g;x?y#s" }, { input: "", output: "http://a/b/c/d;p?q" }, { input: ".", output: "http://a/b/c/" }, { input: "./", output: "http://a/b/c/" }, { input: "..", output: "http://a/b/" }, { input: "../", output: "http://a/b/" }, { input: "../g", output: "http://a/b/g" }, { input: "../..", output: "http://a/" }, { input: "../../", output: "http://a/" }, { input: "../../g", output: "http://a/g" }, ]; normalExamples.forEach((example) => { it("should conform to RFC 3986 normal examples - case: " + example.input, () => { const baseURL: string = "http://a/b/c/d;p?q"; // https://datatracker.ietf.org/doc/html/rfc3986#section-5.4.1 expect(resolveURL(baseURL, example.input)).toBe(example.output); }); }); const abnormalExamples = [ { input: "../../../g", output: "http://a/g" }, { input: "../../../../g", output: "http://a/g" }, { input: "/./g", output: "http://a/g" }, { input: "/../g", output: "http://a/g" }, { input: "g.", output: "http://a/b/c/g." }, { input: ".g", output: "http://a/b/c/.g" }, { input: "g..", output: "http://a/b/c/g.." }, { input: "..g", output: "http://a/b/c/..g" }, { input: "./../g", output: "http://a/b/g" }, { input: "./g/.", output: "http://a/b/c/g/" }, { input: "g/./h", output: "http://a/b/c/g/h" }, { input: "g/../h", output: "http://a/b/c/h" }, { input: "g;x=1/./y", output: "http://a/b/c/g;x=1/y" }, { input: "g;x=1/../y", output: "http://a/b/c/y" }, { input: "g?y/./x", output: "http://a/b/c/g?y/./x" }, { input: "g?y/../x", output: "http://a/b/c/g?y/../x" }, { input: "g#s/./x", output: "http://a/b/c/g#s/./x" }, { input: "g#s/../x", output: "http://a/b/c/g#s/../x" }, ]; abnormalExamples.forEach((example) => { it("should conform to RFC 3986 abnormal examples - case: " + example.input, () => { // https://datatracker.ietf.org/doc/html/rfc3986#section-5.4.2 const baseURL: string = "http://a/b/c/d;p?q"; expect(resolveURL(baseURL, example.input)).toBe(example.output); }); }); it("should work with URL with a port number in the URL", () => { const baseURL = "http://example.com:8090/foo/"; const relative = "bar"; expect(resolveURL(baseURL, relative)).toBe("http://example.com:8090/foo/bar"); }); it("should work with credentials in the URL", () => { const baseURL = "http://username:password@example.com/"; const relative = "bar"; expect(resolveURL(baseURL, relative)).toBe( "http://username:password@example.com/bar", ); }); }); describe("utils - getFilenameIndexInUrl", () => { it("should return the length for a string without slash", () => { const str = ";.<;L'dl'02984lirsahg;oliwr"; expect(getFilenameIndexInUrl(str)).toEqual(str.length); }); it("should return the index after the last / if one in URL", () => { expect(getFilenameIndexInUrl(";ojdsfgje/eprowig/tohjroj/9ohyjwoij/s")).toEqual(36); }); it("should return length if the only slash are part of the protocol", () => { const url1 = "http://www.example.com"; expect(getFilenameIndexInUrl(url1)).toEqual(url1.length); const url2 = "https://a.t"; expect(getFilenameIndexInUrl(url2)).toEqual(url2.length); const url3 = "ftp://s"; expect(getFilenameIndexInUrl(url3)).toEqual(url3.length); }); it("should not include slash coming in query parameters", () => { expect(getFilenameIndexInUrl("http://www.example.com?test/toto")).toEqual(22); expect(getFilenameIndexInUrl("https://ww/ddd?test/toto/efewf/ffe/")).toEqual(11); expect(getFilenameIndexInUrl("https://ww/rr/d?test/toto/efewf/ffe/")).toEqual(14); expect(getFilenameIndexInUrl("https://ww/rr/d/?test/toto/efewf/ffe/")).toEqual(16); }); }); describe("utils - getRelativeUrl", () => { it("should succeed on two absolute URLs on the same domain", () => { expect( getRelativeUrl("https://foo.com/foo/bar/cil/", "https://foo.com/foo/bar/cil/diub"), ).toEqual("diub"); expect( getRelativeUrl( "https://foo.com/foo/bar/cil/", "https://foo.com/foo/bar/cil/diub/emp", ), ).toEqual("diub/emp"); expect( getRelativeUrl( "https://foo.com/foo/bar/cil/diub/emp/", "https://foo.com/foo/bar/cil/f/g/h/i", ), ).toEqual("../../f/g/h/i"); expect( getRelativeUrl( "https://foo.com/foo/bar/cil/emp", "https://foo.com/foo/bar/cil/emp", ), ).toEqual(""); }); it("should handle it right when one of the input is just a domain name without a path", () => { expect( getRelativeUrl( "http://github.com" /** Without a starting slash */, "http://github.com/rx-player", ), ).toBe("/rx-player"); expect( getRelativeUrl( "http://github.com/rx-player/", "http://github.com" /** Without a starting slash */, ), ).toBe(".."); }); it("should handle it right when one of the input has a path of length 0", () => { expect(getRelativeUrl("http://github.com/", "http://github.com/rx-player")).toBe( "rx-player", ); expect( getRelativeUrl( "http://github.com/rx-player/", "http://github.com" /** Without a starting slash */, ), ).toBe(".."); }); it("should fail if scheme is different", () => { expect( getRelativeUrl("http://foo.com/foo/bar/cil/emp", "https://foo.com/foo/bar/cil/emp"), ).toEqual(null); expect( getRelativeUrl("https://foo.com/foo/bar/cil/emp", "http://foo.com/foo/bar/cil/emp"), ).toEqual(null); }); it("should fail if domain is different", () => { expect( getRelativeUrl( "https://bar.com/foo/bar/cil/emp", "https://foo.com/foo/bar/cil/emp", ), ).toEqual(null); }); it("should fail if one anounce a domain but not the other", () => { expect(getRelativeUrl("https://foo.com/foo/bar/cil/diub/emp", "/a")).toEqual(null); expect(getRelativeUrl("../url", "https://foo.com")).toEqual(null); }); it('should output "." if the URL points to the same file', () => { expect(getRelativeUrl("../url", "../url")).toEqual(""); expect( getRelativeUrl( "https://foo.com/foo/bar/cil/diub/emp", "https://foo.com/foo/bar/cil/diub/emp", ), ).toEqual(""); expect( getRelativeUrl( "https://foo.com/foo/bar/cil/diub/emp", "https://foo.com/foo/bar/../bar/cil/diub/emp", ), ).toEqual(""); }); it("should succeed on two relative URLs", () => { expect(getRelativeUrl("../url/a", "../url/a/b")).toEqual("a/b"); expect(getRelativeUrl("../url/a", "../url/b/c")).toEqual("b/c"); }); it("should fail if one seems to be relative to the domain's root, yet we don't know it", () => { expect(getRelativeUrl("/url/a", "../../../url/b/c")).toEqual(null); expect(getRelativeUrl("./url/a", "/url/b/c")).toEqual(null); expect(getRelativeUrl("http://foo.com/url/a", "../url/b/c")).toEqual(null); }); it("should succeed if both seem to be relative to the domain's root, even if we don't know it", () => { expect(getRelativeUrl("/url/a", "/url/b/c")).toEqual("b/c"); }); const normalExamples = [ { input: "http://a/b/c/g", output: "g" }, { input: "http://a/b/c/g/", output: "g/" }, { input: "http://a/g", output: "../../g" }, { input: "http://a/b/c/d;p?y", output: "?y" }, { input: "http://a/b/c/g?y", output: "g?y" }, { input: "http://a/b/c/d;p?q#s", output: "#s" }, { input: "http://a/b/c/g#s", output: "g#s" }, { input: "http://a/b/c/g?y#s", output: "g?y#s" }, { input: "http://a/b/c/;x", output: ";x" }, { input: "http://a/b/c/g;x", output: "g;x" }, { input: "http://a/b/c/g;x?y#s", output: "g;x?y#s" }, { input: "http://a/b/c/d;p?q", output: "" }, { input: "http://a/b/c/", output: "." }, { input: "http://a/b/", output: ".." }, { input: "http://a/b/g", output: "../g" }, { input: "http://a/", output: "../.." }, { input: "http://a/g", output: "../../g" }, ]; normalExamples.forEach((example) => { it("should conform to RFC 3986 normal examples - case: " + example.input, () => { const baseURL: string = "http://a/b/c/d;p?q"; // https://datatracker.ietf.org/doc/html/rfc3986#section-5.4.1 expect(getRelativeUrl(baseURL, example.input)).toBe(example.output); }); }); it("should succeed on two relative URLs", () => { expect(getRelativeUrl("../url/a", "../url/a/b")).toEqual("a/b"); expect(getRelativeUrl("../url/a", "../url/b/c")).toEqual("b/c"); }); it("should return null if the relation between the two URLs is unclear", () => { expect(getRelativeUrl("/url/a", "url/a/b")).toEqual(null); expect(getRelativeUrl("url/a", "/url/a/b")).toEqual(null); }); });