Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 6 additions & 9 deletions bin/dev.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
#!/usr/bin/env node

import { execute } from '@oclif/core';

// Localhost
// process.env.GRAPHQL_HOST = 'http://localhost:3000';

Expand All @@ -11,11 +9,10 @@ process.env.GRAPHQL_HOST = 'https://api.dev.nes.herodevs.com';
// Prod
// process.env.GRAPHQL_HOST = 'https://api.nes.herodevs.com';

// If no command is provided, default to scan:eol -t
// See https://github.com/oclif/oclif/issues/277#issuecomment-657352674 for more info
if (process.argv.length === 2) {
process.argv[2] = 'scan:eol';
process.argv[3] = '-t';
}
import main from './main.js';

await execute({ development: true, dir: import.meta.url });
try {
await main(false);
} catch (error) {
process.exit(1);
}
29 changes: 29 additions & 0 deletions bin/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { parseArgs } from 'node:util';
import { execute } from '@oclif/core';

async function main(isProduction = false) {
const { positionals } = parseArgs({
allowPositionals: true,
strict: false, // Don't validate flags
});

// If no arguments at all, default to scan:eol -t
if (positionals.length === 0) {
process.argv.splice(2, 0, 'scan:eol', '-t');
}
// If only flags are provided, set scan:eol as the command for those flags
else if (positionals.length === 1 && positionals[0].startsWith('-')) {
process.argv.splice(2, 0, 'scan:eol');
}

try {
await execute({
development: !isProduction,
dir: new URL('./dev.js', import.meta.url),
});
} catch (error) {
process.exit(1);
}
}

export default main;
13 changes: 5 additions & 8 deletions bin/run.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
#!/usr/bin/env node

import { execute } from '@oclif/core';
import main from './main.js';

// If no command is provided, default to scan:eol -t
// See https://github.com/oclif/oclif/issues/277#issuecomment-657352674 for more info
if (process.argv.length === 2) {
process.argv[2] = 'scan:eol';
process.argv[3] = '-t';
try {
await main(true);
} catch (error) {
process.exit(1);
}

await execute({ dir: import.meta.url });
87 changes: 65 additions & 22 deletions e2e/scan/eol.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,71 @@ const execAsync = promisify(exec);

const GRAPHQL_HOST = 'https://api.dev.nes.herodevs.com';

describe('default arguments', () => {
it('defaults to scan:eol -t when no arguments are provided', async () => {
// Run the CLI directly with no arguments
const { stdout } = await execAsync('node bin/run.js', {
env: { ...process.env, GRAPHQL_HOST },
});

// Match table header
match(stdout, /┌.*┬.*┬.*┬.*┬.*┐/, 'Should show table top border');
match(stdout, /│ NAME\s*│ VERSION\s*│ EOL\s*│ DAYS EOL\s*│ TYPE\s*│ # OF VULNS*|/, 'Should show table headers');
match(stdout, /├.*┼.*┼.*┼.*┼.*┤/, 'Should show table header separator');

// Match table content
match(
stdout,
/│ bootstrap\s*│ 3\.1\.1\s*│ 2019-07-24\s*│ \d+\s*│ npm\s*│/,
'Should show bootstrap package in table',
);

// Match table footer
match(stdout, /└.*┴.*┴.*┴.*┴.*┘/, 'Should show table bottom border');
});

it('runs scan:eol -a -t when -a -t is passed in', async () => {
const { stdout, stderr } = await execAsync('node bin/run.js -a -t', {
env: { ...process.env, GRAPHQL_HOST },
});

// Verify command executed successfully
match(stdout, /components scanned/, 'Should show components scanned message');
});

it('runs scan:eol --json when --json is passed in', async () => {
// Run the CLI with --json flag
const { stdout } = await execAsync('node bin/run.js --json', {
env: { ...process.env, GRAPHQL_HOST },
});

// Verify JSON output
doesNotMatch(stdout, /Here are the results of the scan:/, 'Should not show results header');
doesNotThrow(() => JSON.parse(stdout), 'Output should be valid JSON');
});

it('shows help for scan:eol when --help is passed in', async () => {
const { stdout } = await execAsync('node bin/run.js --help', {
env: { ...process.env, GRAPHQL_HOST },
});

// Verify help output
match(stdout, /USAGE/, 'Should show usage section');
match(stdout, /FLAGS/, 'Should show flags section');
match(stdout, /EXAMPLES/, 'Should show examples section');
});

it('shows global help when help is passed in', async () => {
const { stdout } = await execAsync('node bin/run.js help', {
env: { ...process.env, GRAPHQL_HOST },
});

// Verify help output
match(stdout, /USAGE/, 'Should show usage section');
match(stdout, /TOPICS/, 'Should show topics section');
match(stdout, /COMMANDS/, 'Should show commands section');
});
});
describe('scan:eol e2e', () => {
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const fixturesDir = path.resolve(__dirname, '../fixtures');
Expand Down Expand Up @@ -46,28 +111,6 @@ describe('scan:eol e2e', () => {
return output;
}

it('defaults to scan:eol -t when no arguments are provided', async () => {
// Run the CLI directly with no arguments
const { stdout } = await execAsync('node bin/run.js', {
env: { ...process.env, GRAPHQL_HOST },
});

// Match table header
match(stdout, /┌.*┬.*┬.*┬.*┬.*┐/, 'Should show table top border');
match(stdout, /│ NAME\s*│ VERSION\s*│ EOL\s*│ DAYS EOL\s*│ TYPE\s*│ # OF VULNS*|/, 'Should show table headers');
match(stdout, /├.*┼.*┼.*┼.*┼.*┤/, 'Should show table header separator');

// Match table content
match(
stdout,
/│ bootstrap\s*│ 3\.1\.1\s*│ 2019-07-24\s*│ \d+\s*│ npm\s*│/,
'Should show bootstrap package in table',
);

// Match table footer
match(stdout, /└.*┴.*┴.*┴.*┴.*┘/, 'Should show table bottom border');
});

it('scans existing SBOM for EOL components', async () => {
const cmd = `scan:eol --file ${simpleSbom}`;
const { stdout } = await run(cmd);
Expand Down