/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at . */
// @flow
import {
getFilename,
getTruncatedFileName,
getFileURL,
getDisplayPath,
getMode,
getSourceLineCount,
isThirdParty,
isJavaScript,
underRoot,
isUrlExtension,
isExtensionDirectoryPath,
getLineText,
} from "../source.js";
import {
makeMockSource,
makeMockSourceWithContent,
makeMockSourceAndContent,
makeMockWasmSourceWithContent,
makeMockThread,
makeFullfilledMockSourceContent,
} from "../test-mockup";
import { isFulfilled } from "../async-value.js";
import type { Source } from "../../types";
const defaultSymbolDeclarations = {
classes: [],
functions: [],
memberExpressions: [],
callExpressions: [],
objectProperties: [],
identifiers: [],
imports: [],
comments: [],
literals: [],
hasJsx: false,
hasTypes: false,
loading: false,
framework: undefined,
};
describe("sources", () => {
const unicode = "\u6e2c";
const encodedUnicode = encodeURIComponent(unicode);
describe("getFilename", () => {
it("should give us a default of (index)", () => {
expect(
getFilename(makeMockSource("http://localhost.com:7999/increment/"))
).toBe("(index)");
});
it("should give us the filename", () => {
expect(
getFilename(
makeMockSource("http://localhost.com:7999/increment/hello.html")
)
).toBe("hello.html");
});
it("should give us the readable Unicode filename if encoded", () => {
expect(
getFilename(
makeMockSource(
`http://localhost.com:7999/increment/${encodedUnicode}.html`
)
)
).toBe(`${unicode}.html`);
});
it("should give us the filename excluding the query strings", () => {
expect(
getFilename(
makeMockSource(
"http://localhost.com:7999/increment/hello.html?query_strings"
)
)
).toBe("hello.html");
});
it("should give us the proper filename for pretty files", () => {
expect(
getFilename(
makeMockSource(
"http://localhost.com:7999/increment/hello.html:formatted"
)
)
).toBe("hello.html");
});
});
describe("getTruncatedFileName", () => {
it("should truncate the file name when it is more than 30 chars", () => {
expect(
getTruncatedFileName(
makeMockSource(
"really-really-really-really-really-really-long-name.html"
),
"",
30
)
).toBe("really-really…long-name.html");
});
it("should first decode the filename and then truncate it", () => {
expect(
getTruncatedFileName(
makeMockSource(`${encodedUnicode.repeat(30)}.html`),
"",
30
)
).toBe("測測測測測測測測測測測測測…測測測測測測測測測.html");
});
});
describe("getDisplayPath", () => {
it("should give us the path for files with same name", () => {
const sources: Source[] = [
makeMockSource("http://localhost.com:7999/increment/xyz/hello.html"),
makeMockSource("http://localhost.com:7999/increment/abc/hello.html"),
makeMockSource("http://localhost.com:7999/increment/hello.html"),
];
expect(
getDisplayPath(
makeMockSource("http://localhost.com:7999/increment/abc/hello.html"),
sources
)
).toBe("abc");
});
it(`should give us the path for files with same name
in directories with same name`, () => {
const sources: Source[] = [
makeMockSource(
"http://localhost.com:7999/increment/xyz/web/hello.html"
),
makeMockSource(
"http://localhost.com:7999/increment/abc/web/hello.html"
),
makeMockSource("http://localhost.com:7999/increment/hello.html"),
];
expect(
getDisplayPath(
makeMockSource(
"http://localhost.com:7999/increment/abc/web/hello.html"
),
sources
)
).toBe("abc/web");
});
it("should give no path for files with unique name", () => {
const sources: Source[] = [
makeMockSource("http://localhost.com:7999/increment/xyz.html"),
makeMockSource("http://localhost.com:7999/increment/abc.html"),
makeMockSource("http://localhost.com:7999/increment/hello.html"),
];
expect(
getDisplayPath(
makeMockSource("http://localhost.com:7999/increment/abc/web.html"),
sources
)
).toBe(undefined);
});
it("should not show display path for pretty file", () => {
const sources: Source[] = [
makeMockSource("http://localhost.com:7999/increment/abc/web/hell.html"),
makeMockSource(
"http://localhost.com:7999/increment/abc/web/hello.html"
),
makeMockSource(
"http://localhost.com:7999/increment/xyz.html:formatted"
),
];
expect(
getDisplayPath(
makeMockSource(
"http://localhost.com:7999/increment/abc/web/hello.html:formatted"
),
sources
)
).toBe(undefined);
});
it(`should give us the path for files with same name when both
are pretty and different path`, () => {
const sources: Source[] = [
makeMockSource(
"http://localhost.com:7999/increment/xyz/web/hello.html:formatted"
),
makeMockSource(
"http://localhost.com:7999/increment/abc/web/hello.html:formatted"
),
makeMockSource(
"http://localhost.com:7999/increment/hello.html:formatted"
),
];
expect(
getDisplayPath(
makeMockSource(
"http://localhost.com:7999/increment/abc/web/hello.html:formatted"
),
sources
)
).toBe("abc/web");
});
});
describe("getFileURL", () => {
it("should give us the file url", () => {
expect(
getFileURL(
makeMockSource("http://localhost.com:7999/increment/hello.html")
)
).toBe("http://localhost.com:7999/increment/hello.html");
});
it("should truncate the file url when it is more than 50 chars", () => {
expect(
getFileURL(
makeMockSource("http://localhost-long.com:7999/increment/hello.html")
)
).toBe("…ttp://localhost-long.com:7999/increment/hello.html");
});
it("should first decode the file URL and then truncate it", () => {
expect(
getFileURL(makeMockSource(`http://${encodedUnicode.repeat(39)}.html`))
).toBe(`…ttp://${unicode.repeat(39)}.html`);
});
});
describe("isJavaScript", () => {
it("is not JavaScript", () => {
{
const source = makeMockSourceAndContent("foo.html", undefined, "");
expect(isJavaScript(source, source.content)).toBe(false);
}
{
const source = makeMockSourceAndContent(
undefined,
undefined,
"text/html"
);
expect(isJavaScript(source, source.content)).toBe(false);
}
});
it("is JavaScript", () => {
{
const source = makeMockSourceAndContent("foo.js");
expect(isJavaScript(source, source.content)).toBe(true);
}
{
const source = makeMockSourceAndContent("bar.jsm");
expect(isJavaScript(source, source.content)).toBe(true);
}
{
const source = makeMockSourceAndContent(
undefined,
undefined,
"text/javascript"
);
expect(isJavaScript(source, source.content)).toBe(true);
}
{
const source = makeMockSourceAndContent(
undefined,
undefined,
"application/javascript"
);
expect(isJavaScript(source, source.content)).toBe(true);
}
});
});
describe("isThirdParty", () => {
it("node_modules", () => {
expect(isThirdParty(makeMockSource("/node_modules/foo.js"))).toBe(true);
});
it("bower_components", () => {
expect(isThirdParty(makeMockSource("/bower_components/foo.js"))).toBe(
true
);
});
it("not third party", () => {
expect(isThirdParty(makeMockSource("/bar/foo.js"))).toBe(false);
});
});
describe("getMode", () => {
it("//@flow", () => {
const source = makeMockSourceAndContent(
undefined,
undefined,
"text/javascript",
"// @flow"
);
expect(getMode(source, source.content)).toEqual({
name: "javascript",
typescript: true,
});
});
it("/* @flow */", () => {
const source = makeMockSourceAndContent(
undefined,
undefined,
"text/javascript",
" /* @flow */"
);
expect(getMode(source, source.content)).toEqual({
name: "javascript",
typescript: true,
});
});
it("mixed html", () => {
const source = makeMockSourceAndContent(
undefined,
undefined,
"",
" {
const source = makeMockSourceAndContent(
undefined,
undefined,
"text/x-elm",
'main = text "Hello, World!"'
);
expect(getMode(source, source.content)).toEqual({ name: "elm" });
});
it("returns jsx if contentType jsx is given", () => {
const source = makeMockSourceAndContent(
undefined,
undefined,
"text/jsx",
"
"
);
expect(getMode(source, source.content)).toEqual({ name: "jsx" });
});
it("returns jsx if sourceMetaData says it's a react component", () => {
const source = makeMockSourceAndContent(
undefined,
undefined,
"",
""
);
expect(
getMode(source, source.content, {
...defaultSymbolDeclarations,
hasJsx: true,
})
).toEqual({ name: "jsx" });
});
it("returns jsx if the fileExtension is .jsx", () => {
const source = makeMockSourceAndContent(
"myComponent.jsx",
undefined,
"",
""
);
expect(getMode(source, source.content)).toEqual({ name: "jsx" });
});
it("returns text/x-haxe if the file extension is .hx", () => {
const source = makeMockSourceAndContent(
"myComponent.hx",
undefined,
"",
"function foo(){}"
);
expect(getMode(source, source.content)).toEqual({ name: "text/x-haxe" });
});
it("typescript", () => {
const source = makeMockSourceAndContent(
undefined,
undefined,
"text/typescript",
"function foo(){}"
);
expect(getMode(source, source.content)).toEqual({
name: "javascript",
typescript: true,
});
});
it("typescript-jsx", () => {
const source = makeMockSourceAndContent(
undefined,
undefined,
"text/typescript-jsx",
""
);
expect(getMode(source, source.content).base).toEqual({
name: "javascript",
typescript: true,
});
});
it("cross-platform clojure(script) with reader conditionals", () => {
const source = makeMockSourceAndContent(
"my-clojurescript-source-with-reader-conditionals.cljc",
undefined,
"text/x-clojure",
"(defn str->int [s] " +
" #?(:clj (java.lang.Integer/parseInt s) " +
" :cljs (js/parseInt s)))"
);
expect(getMode(source, source.content)).toEqual({ name: "clojure" });
});
it("clojurescript", () => {
const source = makeMockSourceAndContent(
"my-clojurescript-source.cljs",
undefined,
"text/x-clojurescript",
"(+ 1 2 3)"
);
expect(getMode(source, source.content)).toEqual({ name: "clojure" });
});
it("coffeescript", () => {
const source = makeMockSourceAndContent(
undefined,
undefined,
"text/coffeescript",
"x = (a) -> 3"
);
expect(getMode(source, source.content)).toEqual({ name: "coffeescript" });
});
it("wasm", () => {
const source = makeMockWasmSourceWithContent({
binary: "\x00asm\x01\x00\x00\x00",
});
expect(getMode(source, source.content.value)).toEqual({ name: "text" });
});
it("marko", () => {
const source = makeMockSourceAndContent(
"http://localhost.com:7999/increment/sometestfile.marko",
undefined,
"does not matter",
"function foo(){}"
);
expect(getMode(source, source.content)).toEqual({ name: "javascript" });
});
it("es6", () => {
const source = makeMockSourceAndContent(
"http://localhost.com:7999/increment/sometestfile.es6",
undefined,
"does not matter",
"function foo(){}"
);
expect(getMode(source, source.content)).toEqual({ name: "javascript" });
});
it("vue", () => {
const source = makeMockSourceAndContent(
"http://localhost.com:7999/increment/sometestfile.vue?query=string",
undefined,
"does not matter",
"function foo(){}"
);
expect(getMode(source, source.content)).toEqual({ name: "javascript" });
});
});
describe("getSourceLineCount", () => {
it("should give us the amount bytes for wasm source", () => {
const { content } = makeMockWasmSourceWithContent({
binary: "\x00asm\x01\x00\x00\x00",
});
expect(getSourceLineCount(content.value)).toEqual(8);
});
it("should give us the amout of lines for js source", () => {
const { content } = makeMockSourceWithContent(
undefined,
undefined,
"text/javascript",
"function foo(){\n}"
);
if (!content || !isFulfilled(content)) {
throw new Error("Unexpected content value");
}
expect(getSourceLineCount(content.value)).toEqual(2);
});
});
describe("underRoot", () => {
const threads = [
makeMockThread({ actor: "server0.conn1.child1/thread19" }),
];
it("should detect normal source urls", () => {
const source = makeMockSource(
"resource://activity-stream/vendor/react.js"
);
expect(underRoot(source, "resource://activity-stream", threads)).toBe(
true
);
});
it("should detect source urls under chrome:// as root", () => {
const source = makeMockSource(
"chrome://browser/content/contentSearchUI.js"
);
expect(underRoot(source, "chrome://", threads)).toBe(true);
});
it("should detect source urls if root is a thread actor Id", () => {
const source = makeMockSource(
"resource://activity-stream/vendor/react-dom.js"
);
expect(underRoot(source, "server0.conn1.child1/thread19", threads)).toBe(
true
);
});
});
describe("isUrlExtension", () => {
it("should detect mozilla extension", () => {
expect(isUrlExtension("moz-extension://id/js/content.js")).toBe(true);
});
it("should detect chrome extension", () => {
expect(isUrlExtension("chrome-extension://id/js/content.js")).toBe(true);
});
it("should return false for non-extension assets", () => {
expect(isUrlExtension("https://example.org/init.js")).toBe(false);
});
});
describe("isExtensionDirectoryPath", () => {
it("should detect mozilla extension directory", () => {
expect(isExtensionDirectoryPath("moz-extension://id")).toBe(true);
});
it("should detect chrome extension directory", () => {
expect(isExtensionDirectoryPath("chrome-extension://id")).toBe(true);
});
it("should return false for child file within the extension directory", () => {
expect(isExtensionDirectoryPath("moz-extension://id/js/content.js")).toBe(
false
);
});
});
describe("getLineText", () => {
it("first line", () => {
const text = getLineText(
"fake-source",
makeFullfilledMockSourceContent("aaa\nbbb\nccc"),
1
);
expect(text).toEqual("aaa");
});
it("last line", () => {
const text = getLineText(
"fake-source",
makeFullfilledMockSourceContent("aaa\nbbb\nccc"),
3
);
expect(text).toEqual("ccc");
});
it("one line", () => {
const text = getLineText(
"fake-source",
makeFullfilledMockSourceContent("aaa"),
1
);
expect(text).toEqual("aaa");
});
it("bad line", () => {
const text = getLineText(
"fake-source",
makeFullfilledMockSourceContent("aaa\nbbb\nccc"),
5
);
expect(text).toEqual("");
});
});
});