-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
no breaking changes use childprocess to collect CLI stdout missing limit case tests fix #395
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -65,5 +65,9 @@ json/ | |
reports/ | ||
preview/ | ||
dist/ | ||
.nodesecurerc | ||
/.nodesecurerc | ||
.DS_Store | ||
|
||
# IDE | ||
.vscode | ||
jsconfig.json |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
import dotenv from "dotenv"; | ||
dotenv.config(); | ||
|
||
// Import Node.js Dependencies | ||
import { fileURLToPath } from "node:url"; | ||
import path from "node:path"; | ||
import fs from "node:fs/promises"; | ||
import { afterEach, describe, it } from "node:test"; | ||
import assert from "node:assert"; | ||
|
||
// Import Third-party Dependencies | ||
import stripAnsi from "strip-ansi"; | ||
|
||
// Import Internal Dependencies | ||
import { filterProcessStdout } from "../helpers/reportCommandRunner.js"; | ||
import * as CONSTANTS from "../../src/constants.js"; | ||
|
||
// CONSTANTS | ||
const __dirname = path.dirname(fileURLToPath(import.meta.url)); | ||
const processDir = path.join(__dirname, "../.."); | ||
|
||
describe("Report execute command", async () => { | ||
Check failure on line 22 in test/commands/execute.spec.ts GitHub Actions / test (20.x, ubuntu-latest)
|
||
afterEach(async() => await fs.rm(CONSTANTS.DIRS.CLONES, { | ||
recursive: true, force: true | ||
})); | ||
|
||
it("should execute command on fixture '.nodesecurerc'", async() => { | ||
const options = { | ||
cmd: "node", | ||
args: ["dist/bin/index.js", "execute"], | ||
cwd: processDir | ||
}; | ||
|
||
function byMessage(buffer) { | ||
const message = `.*`; | ||
const afterNonAlphaNum = String.raw`?<=[^a-zA-Z\d\s:]\s`; | ||
const beforeTime = String.raw`?=\s\d{1,5}.\d{1,4}ms`; | ||
const withoutDuplicates = String.raw`(?![\s\S]*\1)`; | ||
|
||
const matchMessage = `(${afterNonAlphaNum})(${message})(${beforeTime})|(${afterNonAlphaNum})(${message})`; | ||
const reg = new RegExp(`(${matchMessage})${withoutDuplicates}`, "g"); | ||
|
||
const matchedMessages = stripAnsi(buffer.toString()).match(reg); | ||
|
||
return matchedMessages ?? [""]; | ||
} | ||
|
||
const expectedLines = [ | ||
"Executing nreport at: C:\\PERSO\\dev\\report", | ||
"title: Default report title", | ||
"reporters: html,pdf", | ||
"[Fetcher: NPM] - Fetching NPM packages metadata on the NPM Registry", | ||
"", | ||
"[Fetcher: NPM] - successfully executed in", | ||
"[Fetcher: GIT] - Cloning GIT repositories", | ||
"[Fetcher: GIT] - Fetching repositories metadata on the NPM Registry", | ||
"[Fetcher: GIT] - successfully executed in", | ||
"[Reporter: HTML] - Building template and assets", | ||
"[Reporter: HTML] - successfully executed in", | ||
"[Reporter: PDF] - Using puppeteer to convert HTML content to PDF", | ||
"[Reporter: PDF] - successfully executed in", | ||
"Security report successfully generated! Enjoy 🚀." | ||
]; | ||
|
||
let actualLines: string[]= []; | ||
Check failure on line 65 in test/commands/execute.spec.ts GitHub Actions / test (20.x, ubuntu-latest)
|
||
|
||
try { | ||
actualLines = await filterProcessStdout(options, byMessage); | ||
} | ||
catch (error) { | ||
console.log(error); | ||
|
||
assert.fail("Execute command should not throw"); | ||
} | ||
|
||
assert.deepEqual(actualLines, expectedLines, "we are expecting these lines"); | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import dotenv from "dotenv"; | ||
dotenv.config(); | ||
|
||
// Import Node.js Dependencies | ||
import { fileURLToPath } from "node:url"; | ||
import fs from "node:fs/promises"; | ||
import path from "node:path"; | ||
import { beforeEach, describe, it } from "node:test"; | ||
import assert from "node:assert"; | ||
|
||
// Import Third-party Dependencies | ||
import stripAnsi from "strip-ansi"; | ||
|
||
// Import Internal Dependencies | ||
import { runProcess } from "../helpers/reportCommandRunner.ts"; | ||
|
||
// CONSTANTS | ||
const __dirname = path.dirname(fileURLToPath(import.meta.url)); | ||
const processDir = path.join(__dirname, "..", "fixtures"); | ||
const configFilePath = path.join(processDir, ".nodesecurerc"); | ||
|
||
describe("Report init command", async() => { | ||
beforeEach(async () => await fs.unlink(configFilePath)); | ||
Check failure on line 23 in test/commands/initialize.spec.ts GitHub Actions / test (20.x, ubuntu-latest)
|
||
it("should create config if not exists", async() => { | ||
const lines = [ | ||
/.*/, | ||
/ > Executing nreport at: .*$/, | ||
/.*/, | ||
/Successfully generated NodeSecure runtime configuration at current location/, | ||
/.*/ | ||
]; | ||
|
||
const processOptions = { | ||
cmd: "node", | ||
args: ["dist/bin/index.js", "initialize"], | ||
cwd: processDir | ||
}; | ||
|
||
for await (const line of runProcess(processOptions)) { | ||
const regexp = lines.shift(); | ||
assert.ok(regexp, "we are expecting this line"); | ||
assert.ok(regexp.test(stripAnsi(line)), `line (${line}) matches ${regexp}`); | ||
} | ||
|
||
// to avoid false positive if no lines have been emitted from process | ||
assert.equal(lines.length, 0); | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
{ | ||
"version": "1.0.0", | ||
"i18n": "english", | ||
"strategy": "github-advisory", | ||
"registry": "https://registry.npmjs.org", | ||
"report": { | ||
"theme": "light", | ||
"includeTransitiveInternal": false, | ||
"reporters": [ | ||
"html", | ||
"pdf" | ||
], | ||
"charts": [ | ||
{ | ||
"name": "Extensions", | ||
"display": true, | ||
"interpolation": "d3.interpolateRainbow", | ||
"type": "bar" | ||
}, | ||
{ | ||
"name": "Licenses", | ||
"display": true, | ||
"interpolation": "d3.interpolateCool", | ||
"type": "bar" | ||
}, | ||
{ | ||
"name": "Warnings", | ||
"display": true, | ||
"type": "horizontalBar", | ||
"interpolation": "d3.interpolateInferno" | ||
}, | ||
{ | ||
"name": "Flags", | ||
"display": true, | ||
"type": "horizontalBar", | ||
"interpolation": "d3.interpolateSinebow" | ||
} | ||
], | ||
"title": "Default report title", | ||
"showFlags": true | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
// Import Node.js Dependencies | ||
import { ChildProcess, spawn } from "node:child_process"; | ||
import { createInterface } from "node:readline"; | ||
|
||
// Import Third-party Dependencies | ||
import stripAnsi from "strip-ansi"; | ||
|
||
export async function* runProcess(options) { | ||
const childProcess = spawnedProcess(options); | ||
try { | ||
if(!childProcess.stdout){ | ||
Check failure on line 11 in test/helpers/reportCommandRunner.ts GitHub Actions / test (20.x, ubuntu-latest)
Check failure on line 11 in test/helpers/reportCommandRunner.ts GitHub Actions / test (20.x, ubuntu-latest)
Check failure on line 11 in test/helpers/reportCommandRunner.ts GitHub Actions / test (22.x, ubuntu-latest)
|
||
return | ||
Check failure on line 12 in test/helpers/reportCommandRunner.ts GitHub Actions / test (20.x, ubuntu-latest)
|
||
} | ||
|
||
const rStream = createInterface(childProcess.stdout); | ||
|
||
for await (const line of rStream) { | ||
yield stripAnsi(line); | ||
} | ||
} | ||
finally { | ||
childProcess.kill(); | ||
} | ||
} | ||
|
||
export function filterProcessStdout(options, filter): Promise<string[]> { | ||
return new Promise((resolve, reject) => { | ||
const childProcess = spawnedProcess(options); | ||
const output = new Set<string>(); | ||
|
||
childProcess.stdout?.on("data", (buffer) => { | ||
filter(buffer).forEach((filteredData) => { | ||
output.add(filteredData); | ||
}); | ||
}); | ||
|
||
childProcess.on("close", (code) => { | ||
resolve(Array.from(output)); | ||
}); | ||
|
||
childProcess.on("error", (err) => { | ||
reject(err); | ||
}); | ||
}); | ||
} | ||
|
||
function spawnedProcess(options): ChildProcess { | ||
const { cmd, args = [], cwd = process.cwd() } = options; | ||
|
||
return spawn(cmd, args, { | ||
stdio: ["ignore", "pipe", "pipe", "ipc"], | ||
cwd | ||
}); | ||
} |