From 40b93c86cc9faee48a8315ad97d8e81099e63897 Mon Sep 17 00:00:00 2001 From: fabnguess Date: Fri, 1 Dec 2023 00:26:37 +0000 Subject: [PATCH] refactor (test) : Migration de la bande vers le lanceur de test Node.js --- .github/workflows/node.js.yml | 2 +- README.md | 2 +- index.js | 12 ++- package.json | 10 +- test/index.test.js | 177 ++++++++++++++++++++++++++++++++ test/test.js | 185 ---------------------------------- 6 files changed, 189 insertions(+), 199 deletions(-) create mode 100644 test/index.test.js delete mode 100644 test/test.js diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index 9aabcb3..b68dfb5 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node-version: [16.x, 18.x] + node-version: [18.x, 20.x] fail-fast: false steps: - name: Harden Runner diff --git a/README.md b/README.md index 9900c72..749e22f 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Download and (optionaly) extract github repository archive. ## Requirements -- [Node.js](https://nodejs.org/en/) v16 or higher +- [Node.js](https://nodejs.org/en/) v18 or higher ## Getting Started diff --git a/index.js b/index.js index da0387d..50ef001 100644 --- a/index.js +++ b/index.js @@ -1,13 +1,15 @@ // Import Node.js Dependencies -import { createWriteStream, createReadStream } from "fs"; -import fs from "fs/promises"; -import path from "path"; -import { createGunzip } from "zlib"; -import { pipeline } from "stream/promises"; +import { createWriteStream, createReadStream } from "node:fs"; +import fs from "node:fs/promises"; +import path from "node:path"; +import { createGunzip } from "node:zlib"; +import { pipeline } from "node:stream/promises"; // Import Third-party Dependencies import tar from "tar-fs"; import httpie from "@myunisoft/httpie"; +import * as dotenv from "dotenv"; +dotenv.config(); // CONSTANTS const kGithubURL = new URL("https://github.com/"); diff --git a/package.json b/package.json index 18b3eea..18d58d3 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "exports": "./index.js", "scripts": { "prepublishOnly": "pkg-ok", - "test": "cross-env esm-tape-runner 'test/**/*.js' | tap-monkey", + "test": "node -r dotenv --test", "coverage": "c8 -r html npm test" }, "repository": { @@ -36,16 +36,12 @@ "devDependencies": { "@nodesecure/eslint-config": "^1.5.0", "@slimio/is": "^2.0.0", - "@small-tech/esm-tape-runner": "^2.0.0", - "@small-tech/tap-monkey": "^1.4.0", "c8": "^7.12.0", - "cross-env": "^7.0.3", "dotenv": "^16.0.2", "eslint": "^8.23.0", - "pkg-ok": "^3.0.0", - "tape": "^5.6.0" + "pkg-ok": "^3.0.0" }, "engines": { - "node": ">=16" + "node": ">=18" } } diff --git a/test/index.test.js b/test/index.test.js new file mode 100644 index 0000000..c6e2146 --- /dev/null +++ b/test/index.test.js @@ -0,0 +1,177 @@ +// Import Node.js Dependencies +import { join, dirname } from "node:path"; +import { fileURLToPath } from "node:url"; +import fs from "node:fs/promises"; +import { describe, before, test } from "node:test"; +import assert from "node:assert"; + +// Import Third-party Dependencies +import is from "@slimio/is"; +import { MockAgent } from "@myunisoft/httpie"; + +// Import Internal Dependencies +import * as github from "../index.js"; + +// CONSTANTS +const __dirname = dirname(fileURLToPath(import.meta.url)); + +test("github.download should be an asyncFunction", () => { + assert.equal(is.func(github.download), true); + assert.equal(is.asyncFunction(github.download), true); +}); + +test("github.downloadAndExtract should be an asyncFunction", () => { + assert.equal(is.func(github.downloadAndExtract), true); + assert.equal(is.asyncFunction(github.downloadAndExtract), true); +}); + +test("download must throw: repository must be a string!", () => { + assert.rejects( + async() => await github.download(10), + { + name: "TypeError", + message: "repository must be a string!" + } + ); +}); + +test("download public repository (without extraction)", async() => { + const { location, repository, organization } = await github.download("SlimIO.Config", { + dest: __dirname, + branch: "master" + }); + assert.equal(repository, "Config"); + assert.equal(organization, "SlimIO"); + assert.equal(location, join(__dirname, "Config-master.tar.gz")); + + await fs.access(location); + await fs.unlink(location); +}); + +test("download public repository (at current working dir)", async() => { + const { location } = await github.download("NodeSecure.utils"); + assert.equal(location, join(process.cwd(), "utils-main.tar.gz")); + + await fs.access(location); + await fs.unlink(location); +}); + +test("download private repository (without extraction)", async() => { + const { location } = await github.download("SlimIO.Core", { + dest: __dirname, + branch: "master" + }); + assert.equal(location, join(__dirname, "Core-master.tar.gz")); + + await fs.access(location); + await fs.unlink(location); +}); + +describe("download public repository (with extraction)", () => { + let location; + + before(async() => { + const result = await github.downloadAndExtract("SlimIO.is", { + dest: __dirname, + branch: "master" + }); + location = result.location; + }); + + test("should have the correct download location", async() => { + assert.equal(location, join(__dirname, "is-master")); + }); + + test("should be a directory", async() => { + const st = await fs.stat(location); + assert.ok(st.isDirectory()); + }); + + test("should not have the tar.gz file", async() => { + const filePath = join(__dirname, "is-master.tar.gz"); + assert.rejects( + async() => await fs.access(filePath), + { + name: "Error", + code: "ENOENT", + message: /no such file or directory/ + } + ); + }); +}); + +test("download public repository (with extraction and removeArchive disabled)", async() => { + const { location } = await github.downloadAndExtract("SlimIO.Safe-emitter", { + dest: __dirname, + branch: "master", + removeArchive: false + }); + + await fs.access(join(__dirname, "Safe-emitter-master.tar.gz")); + assert.equal(location, join(__dirname, "Safe-emitter-master")); + assert.equal((await fs.stat(location)).isDirectory(), true); +}); + +test("teardown", async() => { + await new Promise((resolve) => setTimeout(resolve, 50)); + + const dirents = await fs.readdir(__dirname, { withFileTypes: true }); + for (const dirent of dirents) { + if (dirent.name === "index.test.js") { + continue; + } + + const fullPath = join(__dirname, dirent.name); + if (dirent.isDirectory()) { + await fs.rm(fullPath, { recursive: true, force: true }); + } + else { + await fs.unlink(fullPath); + } + } +}); + +test("get contributors last activites for NodeSecure/scanner", async() => { + const expectedData = new Set(["fraxken", "PierreDemailly"]); + + const agent = new MockAgent(); + agent.disableNetConnect(); + + const client = agent.get("https://api.github.com"); + + client.intercept({ method: "GET", path: "/repos/NodeSecure/scanner/contributors" }) + .reply(200, expectedData); + + assert.equal(expectedData.has("fraxken"), true); +}); + + +test("getContributorsLastActivities must throw: repository must be a string, but got `repository`", async() => { + const repository = 1; + + assert.rejects( + async() => await github.getContributorsLastActivities("My-fake-owner", repository), + { + name: "TypeError", + message: `repository must be a string, but got ${repository}` + } + ); +}); + +test("getContributorsLastActivities must throw: owner must be a string, but got `owner`", async() => { + const owner = 1; + + assert.rejects( + async() => await github.getContributorsLastActivities(owner, "my-fake-repository"), + { + name: "TypeError", + message: `owner must be a string, but got ${owner}` + } + ); +}); + +test("getContributorsLastActivities must not throw & return null when he can't find a repository", async() => { + const contributors = await github.getContributorsLastActivities("my-fake-owner", "my-fake-repository"); + + assert.equal(contributors, null); +}); diff --git a/test/test.js b/test/test.js deleted file mode 100644 index cc0a961..0000000 --- a/test/test.js +++ /dev/null @@ -1,185 +0,0 @@ -import dotenv from "dotenv"; -dotenv.config(); - -// Import Node.js Dependencies -import { join, dirname } from "path"; -import { fileURLToPath } from "url"; -import fs from "fs/promises"; - -// Import Third-party Dependencies -import test from "tape"; -import is from "@slimio/is"; - -// Import Internal Dependencies -import * as github from "../index.js"; - -// CONSTANTS -const __dirname = dirname(fileURLToPath(import.meta.url)); - -test("github.download should be an asyncFunction", (tape) => { - tape.true(is.func(github.download)); - tape.true(is.asyncFunction(github.download)); - - tape.end(); -}); - -test("github.downloadAndExtract should be an asyncFunction", (tape) => { - tape.true(is.func(github.downloadAndExtract)); - tape.true(is.asyncFunction(github.downloadAndExtract)); - - tape.end(); -}); - -test("download must throw: repository must be a string!", async(tape) => { - tape.plan(2); - - try { - await github.download(10); - } - catch (error) { - tape.strictEqual(error.name, "TypeError"); - tape.strictEqual(error.message, "repository must be a string!"); - } - - tape.end(); -}); - -test("download public repository (without extraction)", async(tape) => { - const { location, repository, organization } = await github.download("SlimIO.Config", { - dest: __dirname, - branch: "master" - }); - tape.is(repository, "Config"); - tape.is(organization, "SlimIO"); - tape.is(location, join(__dirname, "Config-master.tar.gz")); - - await fs.access(location); - await fs.unlink(location); - - tape.end(); -}); - -test("download public repository (at current working dir)", async(tape) => { - const { location } = await github.download("NodeSecure.utils"); - tape.is(location, join(process.cwd(), "utils-main.tar.gz")); - - await fs.access(location); - await fs.unlink(location); - - tape.end(); -}); - -test("download private repository (without extraction)", async(tape) => { - const { location } = await github.download("SlimIO.Core", { - dest: __dirname, - branch: "master" - }); - tape.is(location, join(__dirname, "Core-master.tar.gz")); - - await fs.access(location); - await fs.unlink(location); - - tape.end(); -}); - -test("download public repository (with extraction)", async(tape) => { - tape.plan(3); - - const { location } = await github.downloadAndExtract("SlimIO.is", { - dest: __dirname, - branch: "master" - }); - tape.is(location, join(__dirname, "is-master")); - - const st = await fs.stat(location); - tape.true(st.isDirectory()); - - try { - await fs.access(join(__dirname, "is-master.tar.gz")); - } - catch { - tape.pass(); - } - - tape.end(); -}); - -test("download public repository (with extraction and removeArchive disabled)", async(tape) => { - tape.plan(2); - - const { location } = await github.downloadAndExtract("SlimIO.Safe-emitter", { - dest: __dirname, - branch: "master", - removeArchive: false - }); - - await fs.access(join(__dirname, "Safe-emitter-master.tar.gz")); - tape.is(location, join(__dirname, "Safe-emitter-master")); - tape.true((await fs.stat(location)).isDirectory()); - - tape.end(); -}); - -test("teardown", async() => { - await new Promise((resolve) => setTimeout(resolve, 50)); - - const dirents = await fs.readdir(__dirname, { withFileTypes: true }); - for (const dirent of dirents) { - if (dirent.name === "test.js") { - continue; - } - - const fullPath = join(__dirname, dirent.name); - if (dirent.isDirectory()) { - await fs.rm(fullPath, { recursive: true, force: true }); - } - else { - await fs.unlink(fullPath); - } - } -}); - -test("get contributors last activites for NodeSecure/scanner", async(tape) => { - const contributors = await github.getContributorsLastActivities("NodeSecure", "scanner"); - - tape.true(contributors.has("fraxken")); -}); - -test("getContributorsLastActivities must throw: repository must be a string, but got `repository`", async(tape) => { - tape.plan(2); - - const repository = 1; - - try { - await github.getContributorsLastActivities("My-fake-owner", repository); - } - catch (error) { - tape.strictEqual(error.name, "TypeError"); - tape.strictEqual(error.message, `repository must be a string, but got ${repository}`); - } - - tape.end(); -}); - -test("getContributorsLastActivities must throw: owner must be a string, but got `owner`", async(tape) => { - tape.plan(2); - - const owner = 1; - - try { - await github.getContributorsLastActivities(owner, "my-fake-repository"); - } - catch (error) { - tape.strictEqual(error.name, "TypeError"); - tape.strictEqual(error.message, `owner must be a string, but got ${owner}`); - } - - tape.end(); -}); - -test("getContributorsLastActivities must not throw & return null when he can't find a repository", async(tape) => { - const contributors = await github.getContributorsLastActivities("my-fake-owner", "my-fake-repository"); - - tape.is(contributors, null); - tape.end(); -});