diff --git a/deno.jsonc b/deno.jsonc index eb5a82b..a91cd79 100644 --- a/deno.jsonc +++ b/deno.jsonc @@ -7,7 +7,8 @@ "coverage-pretty": "deno task coverage && deno coverage coverage/profile", "coverage-html": "deno task coverage && deno coverage coverage/profile --lcov > coverage/coverage.lcov && genhtml -o coverage/html coverage/coverage.lcov", "test-sites": "deno test --allow-net --import-map=import_map.json all-sites", - "compile": "deno compile --output=sherlock -q --allow-net --import-map=import_map.json cli.ts" + "compile": "deno compile --output=sherlock -q --allow-net --import-map=import_map.json cli.ts", + "bundle": "deno bundle --import-map=import_map.json cli.ts" }, "lint": { "files": { diff --git a/import_map.json b/import_map.json index 8c49751..eff5221 100644 --- a/import_map.json +++ b/import_map.json @@ -1,5 +1,5 @@ { "imports": { - "std/": "https://deno.land/std@0.136.0/" + "std/": "https://deno.land/std@0.155.0/" } } diff --git a/mod.ts b/mod.ts index e6deae9..8d4c333 100644 --- a/mod.ts +++ b/mod.ts @@ -1,3 +1,3 @@ -export const SHERLOCK_VERSION = "2.2.0"; +export const SHERLOCK_VERSION = "2.3.0"; export { SherlockScanner } from "./src/sherlock-scanner.ts"; diff --git a/sites.ts b/sites.ts index 4ed4f2e..d7c7c30 100644 --- a/sites.ts +++ b/sites.ts @@ -159,14 +159,6 @@ export const sites: SiteList = { "username_claimed": "blue", "username_unclaimed": "noonewouldeverusethis7", }, - "Atom Discussions": { - "errorMsg": "Oops! That page doesn’t exist or is private.", - "errorType": "message", - "url": "https://discuss.atom.io/u/{}/summary", - "urlMain": "https://discuss.atom.io", - "username_claimed": "blue", - "username_unclaimed": "noonewouldeverusethis", - }, "Audiojungle": { "errorType": "status_code", "regexCheck": "^[a-zA-Z0-9_]+$", @@ -382,7 +374,7 @@ export const sites: SiteList = { "username_unclaimed": "noonewouldeverusethis77777", }, "Chess": { - "errorMsg": '"valid": false', + "errorMsg": "Username is valid", "errorType": "message", "regexCheck": "^[a-z1-9]{3,25}$", "url": "https://www.chess.com/member/{}", @@ -429,14 +421,6 @@ export const sites: SiteList = { "username_claimed": "blue", "username_unclaimed": "noonewouldeverusethis7", }, - "Codeforces": { - "errorType": "response_url", - "errorUrl": "https://codeforces.com/", - "url": "https://codeforces.com/profile/{}", - "urlMain": "https://www.codeforces.com/", - "username_claimed": "tourist", - "username_unclaimed": "noonewouldeverusethis789", - }, "Codepen": { "errorType": "status_code", "url": "https://codepen.io/{}", @@ -592,14 +576,6 @@ export const sites: SiteList = { "username_claimed": "blue", "username_unclaimed": "noonewouldeverusethis7", }, - "Ello": { - "errorMsg": "We couldn't find the page you're looking for", - "errorType": "message", - "url": "https://ello.co/{}", - "urlMain": "https://ello.co/", - "username_claimed": "blue", - "username_unclaimed": "noonewouldeverusethis7", - }, "Envato Forum": { "errorType": "status_code", "url": "https://forums.envato.com/u/{}", @@ -644,14 +620,6 @@ export const sites: SiteList = { "username_claimed": "fameswap", "username_unclaimed": "noonewouldeverusethis7", }, - "FanCentro": { - "errorMsg": "var environment", - "errorType": "message", - "url": "https://fancentro.com/{}", - "urlMain": "https://fancentro.com/", - "username_claimed": "nielsrosanna", - "username_unclaimed": "noonewouldeverusethis7", - }, "Fandom": { "errorType": "status_code", "url": "https://www.fandom.com/u/{}", @@ -761,14 +729,6 @@ export const sites: SiteList = { "username_claimed": "adam", "username_unclaimed": "noonewouldeverusethis7", }, - "Gab": { - "errorMsg": "The page you are looking for isn't here.", - "errorType": "message", - "url": "https://gab.com/{}", - "urlMain": "https://gab.com", - "username_claimed": "a", - "username_unclaimed": "noonewouldeverusethis", - }, "GaiaOnline": { "errorMsg": "No user ID specified or user does not exist", "errorType": "message", @@ -777,13 +737,6 @@ export const sites: SiteList = { "username_claimed": "adam", "username_unclaimed": "noonewouldeverusethis77777", }, - "Gam1ng": { - "errorType": "status_code", - "url": "https://gam1ng.com.br/user/{}", - "urlMain": "https://gam1ng.com.br", - "username_claimed": "PinKgirl", - "username_unclaimed": "noonewouldeverusethis77777", - }, "Gamespot": { "errorType": "status_code", "url": "https://www.gamespot.com/profile/{}/", @@ -819,14 +772,6 @@ export const sites: SiteList = { "username_claimed": "Upneet.Grover17", "username_unclaimed": "noonewouldeverusethis7", }, - "Ghost": { - "errorMsg": "Domain Error", - "errorType": "message", - "url": "https://{}.ghost.io/", - "urlMain": "https://ghost.org/", - "username_claimed": "troyhunt", - "username_unclaimed": "noonewouldeverusethis7", - }, "Giphy": { "errorType": "status_code", "url": "https://giphy.com/{}", @@ -849,14 +794,6 @@ export const sites: SiteList = { "username_claimed": "blue", "username_unclaimed": "noonewouldeverusethis7", }, - "GitHub Support Community": { - "errorMsg": "Oops! That page doesn’t exist or is private.", - "errorType": "message", - "url": "https://github.community/u/{}/summary", - "urlMain": "https://github.community", - "username_claimed": "jperl", - "username_unclaimed": "noonewouldusethis298", - }, "GitLab": { "errorMsg": "[]", "errorType": "message", @@ -880,6 +817,14 @@ export const sites: SiteList = { "username_claimed": "blue", "username_unclaimed": "noonewouldeverusethis7", }, + "Google Play": { + "errorMsg": "the requested URL was not found on this server", + "errorType": "message", + "url": "https://play.google.com/store/apps/developer?id={}", + "urlMain": "https://play.google.com", + "username_claimed": "GitHub", + "username_unclaimed": "noonewouldeverusethis7", + }, "Gradle": { "errorType": "status_code", "regexCheck": "^(?!-)[a-zA-Z0-9-]{3,}(?", "errorType": "message", "url": "https://quizlet.com/{}", "urlMain": "https://quizlet.com", @@ -1700,10 +1617,12 @@ export const sites: SiteList = { "RuneScape": { "errorMsg": '{"error":"NO_PROFILE","loggedIn":"false"}', "errorType": "message", - "regexCheck": "(?! )^[a-zA-Z0-9- ]{,12}(? { - assertEquals(parseArguments(["--help"]), { - _: [], - all: false, - a: false, - help: true, - h: true, +describe("CLI", () => { + let consoleStub: Stub; + + beforeEach(() => { + consoleStub = createConsoleStub(); }); - assertEquals(parseArguments(["-a", "-f=json"]), { - _: [], - all: true, - a: true, - f: "json", - format: "json", + + afterEach(() => { + consoleStub.restore(); }); - assertEquals(parseArguments(["-a", "-f=csv", "checkerschaf"]), { - _: ["checkerschaf"], - all: true, - a: true, - f: "csv", - format: "csv", + + it("parseArguments() parses all arguments correctly", () => { + assertEquals(parseArguments(["--help"]), { + _: [], + all: false, + help: true, + h: true, + }); + + assertEquals(parseArguments(["-a", "-f=json"]), { + _: [], + a: true, + all: true, + f: "json", + format: "json", + }); + + assertEquals(parseArguments(["-a", "-f=csv", "checkerschaf"]), { + _: ["checkerschaf"], + a: true, + all: true, + f: "csv", + format: "csv", + }); }); -}); -Deno.test( - "cli.ts: readCliArguments() parses default arguments correctly", - () => { - const consoleStub = createConsoleStub(); - try { + describe("readCliArguments", () => { + it("parses default arguments correctly", () => { assertEquals(readCliArguments(["checkerschaf"]), { formatter: new ConsoleFormatter(), timeout: 30, username: "checkerschaf", }); - } finally { - consoleStub.restore(); - } - }, -); + }); -Deno.test( - "cli.ts: readCliArguments() parses show all argument correctly", - () => { - const consoleStub = createConsoleStub(); - try { + it("parses show all argument correctly", () => { assertEquals(readCliArguments(["-a", "checkerschaf"]), { formatter: new ConsoleFormatter({ showAll: true }), timeout: 30, username: "checkerschaf", }); - } finally { - consoleStub.restore(); - } - }, -); - -Deno.test( - "cli.ts: showVersionMessage() contains the project version and the amount of active sites", - () => { - const consoleStub = createConsoleStub(); - - try { - showVersionMessage(); + }); + }); - assertEquals(consoleStub.calls.length, 1); + it("showVersionMessage() contains the project version and the amount of active sites", () => { + showVersionMessage(); - const versionStr = consoleStub.calls[0].args[0]; - assertStringIncludes(versionStr, `version`); - assertStringIncludes(versionStr, `${SHERLOCK_VERSION}`); - assertStringIncludes(versionStr, `sites`); - assertStringIncludes(versionStr, `${sitesCount}`); - } finally { - consoleStub.restore(); - } - }, -); + assertEquals(consoleStub.calls.length, 1); -Deno.test( - "cli.ts: showHelpMessage() contains the project version and the amount of active sites", - () => { - const consoleStub = createConsoleStub(); + const versionStr = consoleStub.calls[0].args[0]; + assertStringIncludes(versionStr, `version`); + assertStringIncludes(versionStr, `${SHERLOCK_VERSION}`); + assertStringIncludes(versionStr, `sites`); + assertStringIncludes(versionStr, `${sitesCount}`); + }); - try { - showHelpMessage(); + it("showHelpMessage() contains the project version and the amount of active sites", () => { + showHelpMessage(); - assertEquals(consoleStub.calls.length, 1); + assertEquals(consoleStub.calls.length, 1); - const helpStr = consoleStub.calls[0].args[0]; - assertStringIncludes(helpStr, `--help`); - assertStringIncludes(helpStr, `--version`); - assertStringIncludes(helpStr, `--all`); - assertStringIncludes(helpStr, `--timeout`); - assertStringIncludes(helpStr, `--format`); - assertStringIncludes(helpStr, `Examples`); - } finally { - consoleStub.restore(); - } - }, -); + const helpStr = consoleStub.calls[0].args[0]; + assertStringIncludes(helpStr, `--help`); + assertStringIncludes(helpStr, `--version`); + assertStringIncludes(helpStr, `--all`); + assertStringIncludes(helpStr, `--timeout`); + assertStringIncludes(helpStr, `--format`); + assertStringIncludes(helpStr, `Examples`); + }); +}); diff --git a/src/formatters/console-formatter.test.ts b/src/formatters/console-formatter.test.ts index eecaf19..f4dc1f4 100644 --- a/src/formatters/console-formatter.test.ts +++ b/src/formatters/console-formatter.test.ts @@ -1,3 +1,4 @@ +import { afterEach, beforeEach, describe, it } from "std/testing/bdd.ts"; import { createConsoleStub, siteStatusCode, @@ -7,63 +8,63 @@ import { ConsoleFormatter } from "./console-formatter.ts"; import { ScannerResult } from "../enums.ts"; import { assertStringIncludes } from "std/testing/asserts.ts"; import { gray, green, red } from "std/fmt/colors.ts"; +import type { Stub } from "std/testing/mock.ts"; -Deno.test("console-formatter.ts: onResult() prints a SUCCESS result", () => { - const consoleStub = createConsoleStub(); - try { - const formatter = new ConsoleFormatter(); - formatter.onResult({ - result: ScannerResult.SUCCESS, - site: siteStatusCode, - url: siteStatusCode.url, - siteName: "Demo Site", - username: testUsername, - }); - const consoleCallArgs = consoleStub.calls[0]?.args[0]; - assertStringIncludes(consoleCallArgs, `+`); - assertStringIncludes(consoleCallArgs, green("Demo Site")); - assertStringIncludes(consoleCallArgs, siteStatusCode.url); - } finally { +describe("Console Formatter", () => { + let consoleStub: Stub; + + beforeEach(() => { + consoleStub = createConsoleStub(); + }); + + afterEach(() => { consoleStub.restore(); - } -}); + }); -Deno.test("console-formatter.ts: onResult() prints a NOT_FOUND result", () => { - const consoleStub = createConsoleStub(); - try { - const formatter = new ConsoleFormatter({ showAll: true }); - formatter.onResult({ - result: ScannerResult.NOT_FOUND, - site: siteStatusCode, - url: siteStatusCode.url, - siteName: "Demo Site", - username: testUsername, + describe("onResult", () => { + it("prints a SUCCESS result", () => { + const formatter = new ConsoleFormatter(); + formatter.onResult({ + result: ScannerResult.SUCCESS, + site: siteStatusCode, + url: siteStatusCode.url, + siteName: "Demo Site", + username: testUsername, + }); + const consoleCallArgs = consoleStub.calls[0]?.args[0]; + assertStringIncludes(consoleCallArgs, `+`); + assertStringIncludes(consoleCallArgs, green("Demo Site")); + assertStringIncludes(consoleCallArgs, siteStatusCode.url); }); - const consoleCallArgs = consoleStub.calls[0]?.args[0]; - assertStringIncludes(consoleCallArgs, red("-")); - assertStringIncludes(consoleCallArgs, gray("Demo Site")); - } finally { - consoleStub.restore(); - } -}); -Deno.test("console-formatter.ts: onResult() prints an ERROR result", () => { - const consoleStub = createConsoleStub(); - try { - const formatter = new ConsoleFormatter({ showAll: true }); - formatter.onResult({ - result: ScannerResult.ERROR, - site: siteStatusCode, - url: siteStatusCode.url, - error: "Example Error", - siteName: "Demo Site", - username: testUsername, + it("prints a NOT_FOUND result", () => { + const formatter = new ConsoleFormatter({ showAll: true }); + formatter.onResult({ + result: ScannerResult.NOT_FOUND, + site: siteStatusCode, + url: siteStatusCode.url, + siteName: "Demo Site", + username: testUsername, + }); + const consoleCallArgs = consoleStub.calls[0]?.args[0]; + assertStringIncludes(consoleCallArgs, red("-")); + assertStringIncludes(consoleCallArgs, gray("Demo Site")); }); - const consoleCallArgs = consoleStub.calls[0]?.args[0]; - assertStringIncludes(consoleCallArgs, red("-")); - assertStringIncludes(consoleCallArgs, red("Demo Site")); - assertStringIncludes(consoleCallArgs, "Example Error"); - } finally { - consoleStub.restore(); - } + + it("prints an ERROR result", () => { + const formatter = new ConsoleFormatter({ showAll: true }); + formatter.onResult({ + result: ScannerResult.ERROR, + site: siteStatusCode, + url: siteStatusCode.url, + error: "Example Error", + siteName: "Demo Site", + username: testUsername, + }); + const consoleCallArgs = consoleStub.calls[0]?.args[0]; + assertStringIncludes(consoleCallArgs, red("-")); + assertStringIncludes(consoleCallArgs, red("Demo Site")); + assertStringIncludes(consoleCallArgs, "Example Error"); + }); + }); }); diff --git a/src/lib/fetcher.test.ts b/src/lib/fetcher.test.ts index 58c055f..bcde8f4 100644 --- a/src/lib/fetcher.test.ts +++ b/src/lib/fetcher.test.ts @@ -1,16 +1,13 @@ -import { - fetchSite, - fetchWithTimeout, - getSiteUserUrl, - replaceUsernameInUrl, -} from "./fetcher.ts"; +import { afterEach, beforeEach, describe, it } from "std/testing/bdd.ts"; +import { fetchSite, getSiteUserUrl, replaceUsernameInUrl } from "./fetcher.ts"; import { sites } from "../../sites.ts"; -import { assertEquals, assertStringIncludes } from "std/testing/asserts.ts"; +import { assertEquals } from "std/testing/asserts.ts"; import { returnsNext, stub } from "std/testing/mock.ts"; +import type { Stub } from "std/testing/mock.ts"; import { siteStatusCode, testUsername } from "../testing-helpers.ts"; import { ScannerResult } from "../enums.ts"; -const githubPromise = () => +const githubPromise = (): Promise => new Promise((resolve) => resolve( new Response("This is the sherlock-deno GitHub page from checkerschaf!", { @@ -19,152 +16,117 @@ const githubPromise = () => ) ); -Deno.test( - "fetcher.ts: replaceUsernameInUrl() - replaces an url placeholder with the username", - () => { - assertEquals( - replaceUsernameInUrl(siteStatusCode.url, testUsername), - "http://localhost/users/checkerschaf/hello", - ); - }, -); - -Deno.test( - "fetcher.ts: getSiteUserUrl() - replaces a site url placeholder with the username", - () => { - assertEquals( - getSiteUserUrl(siteStatusCode, testUsername), - "http://localhost/users/checkerschaf/hello", - ); - }, -); - -Deno.test( - "fetcher.ts: fetchWithTimeout() can get the response of a site", - async () => { - const fetchStub = stub(self, "fetch", returnsNext([githubPromise()])); - - try { - const response = await fetchWithTimeout( - "https://github.com/checkerschaf/sherlock-deno", - { headers: {}, timeout: 10 }, +describe({ + name: "Fetcher", + // TODO: review in future Deno versions + // This is needed because Deno currently doesn't clear internal resources and timers + // for the helper function AbortSignal.timeout() used in fetcher.ts + sanitizeOps: false, + sanitizeResources: false, + fn: () => { + it("replaces an url placeholder with the username", () => { + assertEquals( + replaceUsernameInUrl(siteStatusCode.url, testUsername), + "http://localhost/users/checkerschaf/hello", ); - assertEquals(response.status, 200); - - const content = await response.text(); - assertStringIncludes(content, "sherlock-deno"); - } finally { - fetchStub.restore(); - } - }, -); - -Deno.test( - "fetcher.ts: fetchSite() does NOT prepend a proxy url by default", - async () => { - const fetchStub = stub(self, "fetch", returnsNext([githubPromise()])); - - try { - const site = sites["GitHub"]; - await fetchSite({ - site, - siteName: "GitHub", - username: testUsername, - }); - - const call = fetchStub.calls[0]; - - const actualUrl = call.args[0]; - const expectedUrl = site.url.replace("{}", testUsername); - assertEquals(actualUrl, expectedUrl); - } finally { - fetchStub.restore(); - } - }, -); - -Deno.test("fetcher.ts: fetchSite() can append proxy headers", async () => { - const fetchStub = stub(self, "fetch", returnsNext([githubPromise()])); - - try { - const site = sites["GitHub"]; - const expectedProxyHeaders = { - "x-show-me-please": "okay", - }; - await fetchSite({ - site, - siteName: "GitHub", - username: testUsername, - proxyConfig: { - url: "doesnt matter", - headers: expectedProxyHeaders, - }, }); - const call = fetchStub.calls[0]; - - const actualHeaders: Headers = call.args[1].headers; - const proxyHeaderIsPresent = actualHeaders.has("x-show-me-please"); + it("replaces a site url placeholder with the username", () => { + assertEquals( + getSiteUserUrl(siteStatusCode, testUsername), + "http://localhost/users/checkerschaf/hello", + ); + }); - assertEquals(proxyHeaderIsPresent, true); - } finally { - fetchStub.restore(); - } -}); + describe("Fetching", () => { + let fetchStub: Stub; -Deno.test( - "fetcher.ts: fetchSite() prepends a proxy url if provided", - async () => { - const fetchStub = stub(self, "fetch", returnsNext([githubPromise()])); - - try { - const site = sites["GitHub"]; - const proxyUrl = "INCLUDE ME PLEASE"; - const siteResult = await fetchSite({ - site, - siteName: "GitHub", - username: testUsername, - proxyConfig: { - url: proxyUrl, - }, + beforeEach(() => { + fetchStub = stub(self, "fetch", returnsNext([githubPromise()])); }); - const call = fetchStub.calls[0]; - - const actualUrl = call.args[0]; - const expectedUrl = proxyUrl + site.url.replace("{}", testUsername); - assertEquals(actualUrl, expectedUrl); - - assertEquals(siteResult.site.url.includes(proxyUrl), false); - } finally { - fetchStub.restore(); - } - }, -); + afterEach(() => { + fetchStub.restore(); + }); -Deno.test( - "fetcher.ts: getSiteResult() - gets the scanner result of a site (GitHub)", - async () => { - const fetchStub = stub(self, "fetch", returnsNext([githubPromise()])); + it("getSiteResult() - gets the scanner result of a site (GitHub)", async () => { + const site = sites["GitHub"]; + assertEquals( + await fetchSite({ + site, + siteName: "GitHub", + username: testUsername, + }), + { + result: ScannerResult.SUCCESS, + site, + siteName: "GitHub", + url: getSiteUserUrl(site, testUsername), + username: testUsername, + }, + ); + }); - try { - const site = sites["GitHub"]; - assertEquals( - await fetchSite({ - site, - siteName: "GitHub", - username: testUsername, - }), - { - result: ScannerResult.SUCCESS, - site, - siteName: "GitHub", - url: getSiteUserUrl(site, testUsername), - username: testUsername, - }, - ); - } finally { - fetchStub.restore(); - } + describe("Proxy", () => { + it("fetchSite() does NOT prepend a proxy url by default", async () => { + const site = sites["GitHub"]; + await fetchSite({ + site, + siteName: "GitHub", + username: testUsername, + }); + + const call = fetchStub.calls[0]; + + const actualUrl = call.args[0]; + const expectedUrl = site.url.replace("{}", testUsername); + assertEquals(actualUrl, expectedUrl); + }); + + it("fetchSite() can append proxy headers", async () => { + const site = sites["GitHub"]; + const expectedProxyHeaders = { + "x-show-me-please": "okay", + }; + await fetchSite({ + site, + siteName: "GitHub", + username: testUsername, + proxyConfig: { + url: "doesnt matter", + headers: expectedProxyHeaders, + }, + }); + + const call = fetchStub.calls[0]; + + const actualHeaders: Headers = call.args[1].headers; + const proxyHeaderIsPresent = actualHeaders.has("x-show-me-please"); + + assertEquals(proxyHeaderIsPresent, true); + }); + + it("fetchSite() prepends a proxy url if provided", async () => { + const site = sites["GitHub"]; + const proxyUrl = "INCLUDE ME PLEASE"; + const siteResult = await fetchSite({ + site, + siteName: "GitHub", + username: testUsername, + proxyConfig: { + url: proxyUrl, + }, + }); + + const call = fetchStub.calls[0]; + + const actualUrl = call.args[0]; + const expectedUrl = proxyUrl + site.url.replace("{}", testUsername); + assertEquals(actualUrl, expectedUrl); + + assertEquals(siteResult.site.url.includes(proxyUrl), false); + }); + }); + }); }, -); +}); diff --git a/src/lib/fetcher.ts b/src/lib/fetcher.ts index 710b5dc..848ae6c 100644 --- a/src/lib/fetcher.ts +++ b/src/lib/fetcher.ts @@ -20,8 +20,8 @@ export const fetchSite = async ({ try { const urlToFetch = (proxyConfig?.url || "") + userPageUrl; - const response = await fetchWithTimeout(urlToFetch, { - timeout, + const response = await fetch(urlToFetch, { + signal: AbortSignal.timeout(timeout), headers: new Headers({ "Accept-Language": "en-US,en", "User-Agent": @@ -45,7 +45,7 @@ export const fetchSite = async ({ // Request was aborted by the timeout if ( error instanceof DOMException && - error.message === "Ongoing fetch was aborted." + error.name === "TimeoutError" ) { return { ...siteResult, @@ -63,26 +63,6 @@ export const fetchSite = async ({ } }; -export const fetchWithTimeout = async ( - resource: string | Request | URL, - options: { headers: HeadersInit; timeout: number }, -) => { - const { timeout } = options; - - const controller = new AbortController(); - const id = setTimeout(() => { - controller.abort(); - }, timeout); - - const response = await fetch(resource, { - headers: options.headers, - signal: controller.signal, - }); - - clearTimeout(id); - return response; -}; - export const getSiteUserUrl = (site: Site, username: string): string => { return replaceUsernameInUrl(site.urlProbe || site.url, username); }; diff --git a/src/lib/timer.test.ts b/src/lib/timer.test.ts index 64f5d78..e6c0dc5 100644 --- a/src/lib/timer.test.ts +++ b/src/lib/timer.test.ts @@ -1,11 +1,20 @@ +import { afterEach, beforeEach, describe, it } from "std/testing/bdd.ts"; import { assertEquals } from "std/testing/asserts.ts"; import { FakeTime } from "std/testing/time.ts"; import Timer from "./timer.ts"; -Deno.test("timer.ts: calculate time between start and end", () => { - const time: FakeTime = new FakeTime(); +describe("Timer", () => { + let time: FakeTime; - try { + beforeEach(() => { + time = new FakeTime(); + }); + + afterEach(() => { + time.restore(); + }); + + it("calculate time between start and end", () => { const timer = new Timer(); timer.start(); time.tick(1000); @@ -15,7 +24,5 @@ Deno.test("timer.ts: calculate time between start and end", () => { assertEquals(timer.elapsedTime(), 1500); time.tick(500); assertEquals(timer.elapsedTime(), 1500); - } finally { - time.restore(); - } + }); }); diff --git a/src/response-checker.test.ts b/src/response-checker.test.ts index db82a79..ec8176e 100644 --- a/src/response-checker.test.ts +++ b/src/response-checker.test.ts @@ -1,3 +1,4 @@ +import { describe, it } from "std/testing/bdd.ts"; import { checkResponseUrl, checkStatusCode, @@ -15,109 +16,93 @@ import { testUsername, } from "./testing-helpers.ts"; -Deno.test( - "response-checker.ts: checkStatusCode() - success if status is 200", - async () => { - assertEquals( - await checkStatusCode(successResponse()), - ScannerResult.SUCCESS, - ); - }, -); +describe("Response Checker", () => { + describe("Status Code", () => { + it("success if status is 200", async () => { + assertEquals( + await checkStatusCode(successResponse()), + ScannerResult.SUCCESS, + ); + }); -Deno.test( - "response-checker.ts: checkStatusCode() - error if status is 500-599", - async () => { - assertEquals( - await checkStatusCode( - new Response("This is a successful test", { - status: 502, - }), - ), - ScannerResult.ERROR, - ); - }, -); + it("error if status is 500-599", async () => { + assertEquals( + await checkStatusCode( + new Response("This is a successful test", { + status: 502, + }), + ), + ScannerResult.ERROR, + ); + }); -Deno.test( - "response-checker.ts: checkStatusCode() - not found if status is not 200 and not 500", - async () => { - assertEquals( - await checkStatusCode( - new Response("This is a successful test", { - status: 404, - }), - ), - ScannerResult.NOT_FOUND, - ); - }, -); + it("not found if status is not 200 and not 500", async () => { + assertEquals( + await checkStatusCode( + new Response("This is a successful test", { + status: 404, + }), + ), + ScannerResult.NOT_FOUND, + ); + }); + }); -Deno.test( - "response-checker.ts: checkStatusMessage() - success if body does not contain an error message", - async () => { - assertEquals( - await checkStatusMessage({ - response: successResponse(), - site: siteStatusMessage, - username: testUsername, - }), - ScannerResult.SUCCESS, - ); - }, -); + describe("Status Message", () => { + it("success if body does not contain an error message", async () => { + assertEquals( + await checkStatusMessage({ + response: successResponse(), + site: siteStatusMessage, + username: testUsername, + }), + ScannerResult.SUCCESS, + ); + }); -Deno.test( - "response-checker.ts: checkStatusMessage() - not found if body contains an error message", - async () => { - assertEquals( - await checkStatusMessage({ - response: new Response( - "This is an error test. User not found text included", - { - status: 200, - }, - ), - site: siteStatusMessage, - username: testUsername, - }), - ScannerResult.NOT_FOUND, - ); - }, -); + it("not found if body contains an error message", async () => { + assertEquals( + await checkStatusMessage({ + response: new Response( + "This is an error test. User not found text included", + { + status: 200, + }, + ), + site: siteStatusMessage, + username: testUsername, + }), + ScannerResult.NOT_FOUND, + ); + }); + }); -Deno.test( - "response-checker.ts: checkResponseUrl() - success if url is not the error url", - async () => { - assertEquals( - await checkResponseUrl({ - response: successResponse(), - site: siteRedirect, - username: testUsername, - url: getSiteUserUrl(siteRedirect, testUsername), - }), - ScannerResult.SUCCESS, - ); - }, -); + describe("Response URL", () => { + it("success if url is not the error url", async () => { + assertEquals( + await checkResponseUrl({ + response: successResponse(), + site: siteRedirect, + username: testUsername, + url: getSiteUserUrl(siteRedirect, testUsername), + }), + ScannerResult.SUCCESS, + ); + }); -Deno.test( - "response-checker.ts: checkResponseUrl() - not found if url is the error url", - async () => { - assertEquals( - await checkResponseUrl({ - response: successResponse(), - site: siteRedirect, - username: testUsername, - }), - ScannerResult.NOT_FOUND, - ); - }, -); + it("not found if url is the error url", async () => { + assertEquals( + await checkResponseUrl({ + response: successResponse(), + site: siteRedirect, + username: testUsername, + }), + ScannerResult.NOT_FOUND, + ); + }); + }); -Deno.test( - "response-checker.ts: responseIsUserPage() - can select the check method based on the site", - async () => { + it("can select the check method based on the site", async () => { // Status Code assertEquals( await responseIsUserPage({ @@ -148,5 +133,5 @@ Deno.test( }), ScannerResult.SUCCESS, ); - }, -); + }); +}); diff --git a/src/scanner.test.ts b/src/scanner.test.ts index 6f751f5..f1daeb6 100644 --- a/src/scanner.test.ts +++ b/src/scanner.test.ts @@ -1,33 +1,59 @@ +import { describe, it } from "std/testing/bdd.ts"; import { SherlockScanner } from "./sherlock-scanner.ts"; -import { assertThrows } from "std/testing/asserts.ts"; +import { assertEquals, assertThrows } from "std/testing/asserts.ts"; +import { spy } from "std/testing/mock.ts"; import { ConsoleFormatter } from "./formatters/console-formatter.ts"; +import { testUsername } from "./testing-helpers.ts"; +import { sites } from "../sites.ts"; +import { ScannerResult } from "./enums.ts"; -Deno.test("scanner.ts: an invalid username throws an exception", () => { - assertThrows( - () => { - new SherlockScanner({ - username: "checkerschaf?", // The question mark is the invalid character - timeout: 10, - formatter: new ConsoleFormatter(), - }); - }, - Error, - "Username contains invalid characters. Stopping.", - ); - assertThrows( - () => { - new SherlockScanner({ - username: "checkerschaf&", // The ampersand is the invalid character - timeout: 10, - formatter: new ConsoleFormatter(), - }); - }, - Error, - "Username contains invalid characters. Stopping.", - ); -}); +describe("Sherlock Scanner", () => { + it("an invalid username throws an exception", () => { + assertThrows( + () => { + new SherlockScanner({ + username: "checkerschaf?", // The question mark is the invalid character + timeout: 10, + formatter: new ConsoleFormatter(), + }); + }, + Error, + "Username contains invalid characters. Stopping.", + ); + assertThrows( + () => { + new SherlockScanner({ + username: "checkerschaf&", // The ampersand is the invalid character + timeout: 10, + formatter: new ConsoleFormatter(), + }); + }, + Error, + "Username contains invalid characters. Stopping.", + ); + }); + + it("onSiteProcessed() method can be overwritten", () => { + const scanner = new SherlockScanner({ + username: "checkerschaf", + timeout: 1, + formatter: new ConsoleFormatter(), + }); + const spyOnSiteProcessed = spy(); + scanner.onSiteProcessed = spyOnSiteProcessed; + + assertEquals(spyOnSiteProcessed.calls.length, 0); -Deno.test( - "scanner.ts: the onSiteProcessed() method can be overwritten", - () => {}, -); + const siteResult = { + result: ScannerResult.SUCCESS, + site: sites["GitHub"], + siteName: "GitHub", + url: "https://github.com/checkerschaf", + username: testUsername, + }; + scanner.onSiteProcessed(siteResult); + + assertEquals(spyOnSiteProcessed.calls.length, 1); + assertEquals(spyOnSiteProcessed.calls.at(0)?.args, [siteResult]); + }); +}); diff --git a/src/testing-helpers.ts b/src/testing-helpers.ts index e2223df..d26526d 100644 --- a/src/testing-helpers.ts +++ b/src/testing-helpers.ts @@ -1,11 +1,11 @@ import type { Site } from "../src/types.ts"; import { SiteErrorType } from "../src/enums.ts"; -import type { Stub } from "std/testing/mock.ts"; +import { Stub } from "std/testing/mock.ts"; import { stub } from "std/testing/mock.ts"; export const createConsoleStub = ( method: keyof Console = "log", -): Stub => { +): Stub => { return stub(console, method); };