diff --git a/package.json b/package.json index 05368e7a..90fccba8 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "prepublishOnly": "rimraf ./dist && npm run build && pkg-ok", "build": "node ./esbuild.config.js", "test": "npm run test-only && npm run lint", - "test-only": "glob -c \"node --loader=esmock --no-warnings --test-concurrency 1 --test\" \"test/**/*.test.js\"", + "test-only": "glob -c \"node --no-warnings --test-concurrency 1 --test\" \"test/**/*.test.js\"", "coverage": "c8 --reporter=lcov npm run test", "clear:cache": "node ./scripts/clear-cache.js" }, @@ -72,7 +72,6 @@ "cross-env": "^7.0.3", "esbuild": "^0.25.0", "eslint-plugin-jsdoc": "^50.6.2", - "esmock": "^2.6.7", "http-server": "^14.1.1", "pkg-ok": "^3.0.0", "pretty-bytes": "^7.0.0", diff --git a/src/http-server/endpoints/flags.js b/src/http-server/endpoints/flags.js index ab40a283..cbcf2bac 100644 --- a/src/http-server/endpoints/flags.js +++ b/src/http-server/endpoints/flags.js @@ -1,5 +1,5 @@ // Import Node.js Dependencies -import { pipeline } from "node:stream"; +import stream from "node:stream"; // Import Third-party Dependencies import send from "@polka/send-type"; @@ -19,7 +19,7 @@ export function get(req, res) { res.writeHead(200, { "Content-Type": "text/html" }); - return pipeline(lazyFetchFlagFile(req.params.title), res, (err) => { + return stream.pipeline(lazyFetchFlagFile(req.params.title), res, (err) => { if (err) { console.error(err); } diff --git a/src/http-server/index.js b/src/http-server/index.js index b832bd4d..2b907890 100644 --- a/src/http-server/index.js +++ b/src/http-server/index.js @@ -22,6 +22,11 @@ import * as middlewares from "./middlewares/index.js"; import { appCache } from "../cache.js"; import { WebSocketServerInstanciator } from "./websocket/index.js"; +// CONSTANTS +export const BROWSER = { + open +}; + export function buildServer(dataFilePath, options = {}) { const httpConfigPort = typeof options.port === "number" ? options.port : 0; const openLink = typeof options.openLink === "boolean" ? options.openLink : true; @@ -68,7 +73,7 @@ export function buildServer(dataFilePath, options = {}) { console.log(kleur.magenta().bold(await i18n.getToken("cli.http_server_started")), kleur.cyan().bold(link)); if (openLink) { - open(link); + BROWSER.open(link); } }); diff --git a/test/commands/scorecard.test.js b/test/commands/scorecard.test.js index 58ab6eef..b8f0d20c 100644 --- a/test/commands/scorecard.test.js +++ b/test/commands/scorecard.test.js @@ -3,15 +3,16 @@ import { fileURLToPath } from "node:url"; import path from "node:path"; import { test } from "node:test"; import assert from "node:assert"; +import fs from "node:fs"; // Import Third-party Dependencies -import esmock from "esmock"; import { API_URL } from "@nodesecure/ossf-scorecard-sdk"; import { Ok } from "@openally/result"; // Import Internal Dependencies import { runProcess } from "../helpers/cliCommandRunner.js"; import { arrayFromAsync, getExpectedScorecardLines } from "../helpers/utils.js"; +import { getCurrentRepository } from "../../src/commands/scorecard.js"; // CONSTANTS const __dirname = path.dirname(fileURLToPath(import.meta.url)); @@ -97,26 +98,19 @@ test("should not display scorecard for unknown repository", async() => { assert.deepEqual(givenLines, expectedLines, `lines should be ${expectedLines}`); }); -test("should retrieve repository whithin git config", async() => { - const testingModule = await esmock("../../src/commands/scorecard.js", { - fs: { - readFileSync: () => [ - "[remote \"origin\"]", - "\turl = git@github.com:myawesome/repository.git" - ].join("\n") - } - }); +test("should retrieve repository within git config", async(ctx) => { + const readFileResult = [ + "[remote \"origin\"]", + "\turl = git@github.com:myawesome/repository.git" + ].join("\n"); + ctx.mock.method(fs, "readFileSync", () => readFileResult); - assert.deepEqual(testingModule.getCurrentRepository(), Ok(["myawesome/repository", "github"])); + assert.deepEqual(getCurrentRepository(), Ok(["myawesome/repository", "github"])); }); -test("should not find origin remote", async() => { - const testingModule = await esmock("../../src/commands/scorecard.js", { - fs: { - readFileSync: () => "just one line" - } - }); - const result = testingModule.getCurrentRepository(); +test("should not find origin remote", async(ctx) => { + ctx.mock.method(fs, "readFileSync", () => "just one line"); + const result = getCurrentRepository(); assert.equal(result.err, true); assert.equal(result.val, "Cannot find origin remote."); diff --git a/test/httpServer.test.js b/test/httpServer.test.js index c3a1923e..fe5397e0 100644 --- a/test/httpServer.test.js +++ b/test/httpServer.test.js @@ -1,22 +1,24 @@ // Import Node.js Dependencies import fs from "node:fs"; import { fileURLToPath } from "node:url"; -import { after, before, describe, test } from "node:test"; +import { after, before, describe, test, mock } from "node:test"; import { once } from "node:events"; import path from "node:path"; import assert from "node:assert"; +import stream from "node:stream"; // Import Third-party Dependencies import { get, post, MockAgent, getGlobalDispatcher, setGlobalDispatcher } from "@myunisoft/httpie"; import * as i18n from "@nodesecure/i18n"; import * as flags from "@nodesecure/flags"; import enableDestroy from "server-destroy"; -import esmock from "esmock"; import cacache from "cacache"; // Import Internal Dependencies -import { buildServer } from "../src/http-server/index.js"; +import { buildServer, BROWSER } from "../src/http-server/index.js"; import { CACHE_PATH } from "../src/cache.js"; +import * as rootEndpoint from "../src/http-server/endpoints/root.js"; +import * as flagsEndpoint from "../src/http-server/endpoints/flags.js"; // CONSTANTS const kHttpPort = 17049; @@ -69,20 +71,35 @@ describe("httpServer", { concurrency: 1 }, () => { assert.equal(result.headers["content-type"], "text/html"); }); - test("'/' should fail", async() => { - const errors = []; - const module = await esmock("../src/http-server/endpoints/root.js", { - "@polka/send-type": { - default: (_res, _status, { error }) => errors.push(error) + test("'/' should fail", async(ctx) => { + class Response { + constructor() { + this.body = ""; + this.headers = {}; + this.statusCode = 200; } - }); - - await module.get({}, ({ - writeHead: () => { - throw new Error("fake error"); + end(str) { + this.body = str; + } + writeHead(int) { + this.statusCode = int; + } + getHeader(key) { + return this.headers[key]; } - })); - assert.deepEqual(errors, ["fake error"]); + } + + const fakeError = "fake error"; + function toThrow() { + throw new Error(fakeError); + } + ctx.mock.method(Response.prototype, "writeHead", toThrow, { times: 1 }); + + const response = new Response(); + await rootEndpoint.get({}, response); + + assert.strictEqual(response.body, JSON.stringify({ error: fakeError })); + assert.strictEqual(response.statusCode, 500); }); test("'/flags' should return the flags list as JSON", async() => { @@ -111,19 +128,12 @@ describe("httpServer", { concurrency: 1 }, () => { }); }); - test("'/flags/description/:title' should fail", async() => { - const module = await esmock("../src/http-server/endpoints/flags.js", { - stream: { - pipeline: (_stream, _res, err) => err("fake error") - }, - fs: { - createReadStream: () => "foo" - } - }); + test("'/flags/description/:title' should fail", async(ctx) => { + ctx.mock.method(stream, "pipeline", (_stream, _res, err) => err("fake error")); const logs = []; console.error = (data) => logs.push(data); - await module.get({ params: { title: "hasWarnings" } }, ({ writeHead: () => true })); + await flagsEndpoint.get({ params: { title: "hasWarnings" } }, ({ writeHead: () => true })); assert.deepEqual(logs, ["fake error"]); }); @@ -312,30 +322,25 @@ describe("httpServer", { concurrency: 1 }, () => { describe("httpServer without options", () => { let httpServer; - let opened = false; + let spawnOpen; // We want to disable WS process.env.NODE_ENV = "test"; before(async() => { - const module = await esmock("../src/http-server/index.js", { - open: () => (opened = true) - }); - - httpServer = module.buildServer(JSON_PATH); + spawnOpen = mock.method(BROWSER, "open", () => void 0); + httpServer = buildServer(JSON_PATH); await once(httpServer.server, "listening"); enableDestroy(httpServer.server); }); after(async() => { httpServer.server.destroy(); + spawnOpen.mock.restore(); }); - test("should listen on random port", () => { + test("should listen on random port and call childProcess.spawn method ('open' pkg) to open link", async() => { assert.ok(httpServer.server.address().port > 0); - }); - - test("should have openLink to true", () => { - assert.equal(opened, true); + assert.strictEqual(spawnOpen.mock.callCount(), 1); }); });