From 767026a6bbc62d116637d969a92b846ad8519088 Mon Sep 17 00:00:00 2001 From: carvilsi Date: Mon, 28 Aug 2023 14:25:53 +0200 Subject: [PATCH] big refactor, removing debug and adding failing tests --- index.js | 127 ++++++++++++++++++++++-------------------- package-lock.json | 10 +++- package.json | 1 + tests/snoopm.test.mjs | 125 ++++++++++++++++++++++++++++------------- 4 files changed, 162 insertions(+), 101 deletions(-) diff --git a/index.js b/index.js index 989787a..279fd5c 100755 --- a/index.js +++ b/index.js @@ -14,7 +14,11 @@ const Table = require('cli-table'); const Spinner = require('cli-spinner').Spinner; const semver = require('semver'); const logger = require('logplease').create('SnOOpm'); +const url = require('url'); +const isUrl = require('is-url'); +const packageName = 'package.json'; +const nodeModulesName = 'node_modules'; const npmView = 'npm view --json=true '; var urls = [], logOutputFormat = 'default', @@ -24,7 +28,6 @@ var urls = [], spinner, dep = {}, args; -const debug = false; var readPackage = (packageData) => { try { @@ -65,7 +68,6 @@ var readPackage = (packageData) => { } var getUrlOfPackage = (packageName) => { - if (debug) console.log(`🐞 package name: ${packageName}`); return new Promise((resolve, reject) => { exec(npmView.concat(packageName), (error, stdout, stderr) => { if (!error && !stderr) { @@ -81,47 +83,39 @@ var getUrlOfPackage = (packageName) => { } var parseCommandLine = () => { - if (this.options.verbose && this.options.color) { this.logOutputFormat = 'verbose-noColor'; table = new Table({ head:['name','Ver.','URL','Description'] }); - } else - if (this.options.verbose && !this.options.color) { + } else if (this.options.verbose && !this.options.color) { this.logOutputFormat = 'verbose'; table = new Table(); - } else - if (!this.options.verbose && this.options.color) { + } else if (!this.options.verbose && this.options.color) { this.logOutputFormat = 'default-noColor'; table = new Table({ head:['name','URL','Description'] }); - } else - if (this.options.verbose && this.options.dev) { + } else if (this.options.verbose && this.options.dev) { table = new Table(); - } else - if (this.options.verbose && this.options.dev && this.options.color) { + } else if (this.options.verbose && this.options.dev && this.options.color) { table = new Table({ head:['name','Ver.','URL','Description'] }); - } - else { + } else { table = new Table(); } - } -var requesting = (url) => { - axios.get(url).then((response)=>{ +var request = (url) => { + axios.get(url).then((response) => { try { readPackage(response.data); } catch (error) { - logger.error('Invalid package.json provided by url'); - process.exit(42); + throw new Error(`Invalid url provided: ${url}`); } }).catch((error)=>{ - logger.error('Error requesting package.json'); + return Error(`Error requesting ${url}`); }); } @@ -224,65 +218,76 @@ var writeDown = (depData) => { } } +function parseArgs(arg) { + const par = path.parse(arg); + var snooopmPath; + + if (par.base === '.' && par.name === '.' || + par.base === '' && par.name === '') { + snooopmPath = `${process.cwd()}/${packageName}`; + } + if (par.dir.indexOf(nodeModulesName) !== -1) { + if (par.root === '/') { + if (par.base === packageName) { + snooopmPath = `${par.dir}/${par.base}`; + } else { + snooopmPath = `${par.dir}/${par.base}/${packageName}`; + } + } + if (par.root === '') { + if (par.base === packageName) { + snooopmPath = `${process.cwd()}/${par.dir}/${par.base}`; + } else { + snooopmPath = `${process.cwd()}/${par.dir}/${par.base}/${packageName}`; + } + } + } + if (typeof snooopmPath !== 'undefined') { + return snooopmPath; + } else { + throw new Error(`Invalid provided path for: ${arg}`); + } +} + +function parseUrl(prl) { + const snoopmURL = new URL(prl); + if (snoopmURL.host === 'github.com' ) { + snoopmURL.host = 'raw.githubusercontent.com'; + if (snoopmURL.pathname.indexOf('package.json') === -1) { + snoopmURL.pathname = `${snoopmURL.pathname}/master/package.json`; + } + if (snoopmURL.pathname.indexOf('package.json') !== -1) { + snoopmURL.pathname = snoopmURL.pathname.replace('/blob',''); + } + } + return snoopmURL.toString(); +} + var snoopm = (args, options) => { try { spinner = new Spinner('SnOOping.. %s'); spinner.setSpinnerString('==^^^^==||__'); this.options = options; - if (typeof args === 'undefined') { - this.args = []; - } else { - this.args = args; - } - - //TODO: refactor this! + // we want a clean output for lines option without the spinner if (typeof this.options.lines === 'undefined') { spinner.start(); } - // we want to read the local package json file - if (!this.args.length || this.args[0] === '.') { - readPackage(require(process.cwd().concat('/package.json'))); + + const arg = !args.length ? '' : args[0]; + if (isUrl(arg)) { + request(parseUrl(arg)); } else { - if (path.basename(this.args[0]).trim() === 'package.json' - || this.args[0].indexOf('node_modules') !== -1) { - if (this.args[0].indexOf('.') === 0 || this.args[0].indexOf('/') === 0) { - var pathPackage = this.args[0]; - if (this.args[0].indexOf('package.json') === -1) { - pathPackage = `${pathPackage}/package.json`; - } - readPackage(require(pathPackage)); - } - // url to json raw provided - if (this.args[0].indexOf('http') === 0) { - var url = this.args[0]; - if (url.indexOf('github.com') > 0) { - url = url.replace('github.com','raw.githubusercontent.com'); - url = url.replace('blob/',''); - } - requesting(url); - } - } - // trying yo read package.json from git hub repository and master branch - else if (this.args[0].indexOf('http') === 0) { - var url = this.args[0]; - var urlArr = url.split('\/'); - if (url.indexOf('github.com') > 0 && urlArr.length === 5) { - url = url.replace('github.com','raw.githubusercontent.com'); - requesting(url.concat('/').concat('master').concat('/').concat('package.json')); - } - } else { - throw new Error('no valid path or no valid url provided'); - } + readPackage(require(parseArgs(arg))); } return snoopm; - } catch (e) { - logger.error('Error 42'); + console.log('WTFfffffffffffffffffffffffffff'); logger.error(e); process.exit(42); } } module.exports = snoopm; + diff --git a/package-lock.json b/package-lock.json index d391854..08f8c41 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "snoopm", - "version": "1.1.14", + "version": "1.1.15", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "snoopm", - "version": "1.1.14", + "version": "1.1.15", "license": "MIT", "dependencies": { "axios": "^1.5.0", @@ -14,6 +14,7 @@ "cli-table": "^0.3.11", "colors": "^1.4.0", "commander": "^11.0.0", + "is-url": "^1.2.4", "logplease": "^1.2.15", "semver": "^7.5.4" }, @@ -758,6 +759,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-url": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", + "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==" + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", diff --git a/package.json b/package.json index 377f1c8..16c7aa4 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "cli-table": "^0.3.11", "colors": "^1.4.0", "commander": "^11.0.0", + "is-url": "^1.2.4", "logplease": "^1.2.15", "semver": "^7.5.4" }, diff --git a/tests/snoopm.test.mjs b/tests/snoopm.test.mjs index aea32f1..d55b6e3 100644 --- a/tests/snoopm.test.mjs +++ b/tests/snoopm.test.mjs @@ -1,9 +1,11 @@ -import {execa} from 'execa'; -import {assert} from 'chai'; +import { execa } from 'execa'; +import { assert } from 'chai'; import { createRequire } from "module"; const require = createRequire(import.meta.url); const pckg = require("./../package.json"); +const snoopmBin = './bin/snoopm.js'; + const snoopmDependencies = ['axios','cli-spinner','cli-table','colors','commander','logplease','semver']; const snoopmDevDependencies = ['chai','mocha','execa']; @@ -22,12 +24,12 @@ function assertDependencies(stdout, dependencies) { describe('SnOOpm local', async ()=> { it('should retieve version', async () => { - const {stdout} = await execa('./bin/snoopm.js', ['--version']); + const {stdout} = await execa(snoopmBin, ['--version']); assert.equal(stdout, pckg.version, `version should be ${pckg.version}`); }); it('should retieve default table output for snooping on local package.json no arguments', async () => { - const {stdout} = await execa('./bin/snoopm.js'); + const {stdout} = await execa(snoopmBin); // only print the output once. console.log(stdout); // try to assert things like urls and descriptions is not safe, because could change. @@ -35,51 +37,51 @@ describe('SnOOpm local', async ()=> { }); it('should retieve default table output for snooping on local package.json argument "."', async () => { - const {stdout} = await execa('./bin/snoopm.js', ['.']); + const {stdout} = await execa(snoopmBin, ['.']); assertDependencies(stdout, snoopmDependencies); }); it('should retieve list output for snooping on local package.json argument "-l"', async () => { - const {stdout} = await execa('./bin/snoopm.js', ['-l']); + const {stdout} = await execa(snoopmBin, ['-l']); console.log(stdout); assert.equal(stdout.indexOf('┌────'), -1, 'should not contain table'); assertDependencies(stdout, snoopmDependencies); }); it('should retieve default table output with dev-dependencies for snooping on local package.json dev-dependencies argument "-d"', async () => { - const {stdout} = await execa('./bin/snoopm.js', ['-d']); + const {stdout} = await execa(snoopmBin, ['-d']); console.log(stdout); assertDependencies(stdout, snoopmDevDependencies); }); it('should retieve default table output with dev-dependencies for snooping on local package.json dev-dependencies argument "-d ."', async () => { - const {stdout} = await execa('./bin/snoopm.js', ['-d', '.']); + const {stdout} = await execa(snoopmBin, ['-d', '.']); assertDependencies(stdout, snoopmDevDependencies); }); it('should retieve list of dev-dependencies output for snooping on local package.json argument "-ld"', async () => { - const {stdout} = await execa('./bin/snoopm.js', ['-ld']); + const {stdout} = await execa(snoopmBin, ['-ld']); console.log(stdout); assert.equal(stdout.indexOf('┌────'), -1, 'should not contain table'); assertDependencies(stdout, snoopmDevDependencies); }); it('should retieve default table output verbose for snooping on local package.json argument "-v"', async () => { - var {stdout} = await execa('./bin/snoopm.js', ['-v']); + var {stdout} = await execa(snoopmBin, ['-v']); console.log(stdout); assertDependencies(stdout, snoopmDependencies); assert.notEqual(stdout.indexOf(pckg.dependencies[snoopmDependencies[0]].substring(1)), -1, 'should find the dependency version'); }); it('should retieve dev-dependencies table output verbose for snooping on local package.json argument "-dv"', async () => { - var {stdout} = await execa('./bin/snoopm.js', ['-dv']); + var {stdout} = await execa(snoopmBin, ['-dv']); console.log(stdout); assertDependencies(stdout, snoopmDevDependencies); assert.notEqual(stdout.indexOf(pckg.devDependencies[snoopmDevDependencies[0]].substring(1)), -1, 'should find the dev-dependency version'); }); it('should retieve list output verbose for snooping on local package.json argument "-lv"', async () => { - var {stdout} = await execa('./bin/snoopm.js', ['-lv']); + var {stdout} = await execa(snoopmBin, ['-lv']); console.log(stdout); assertDependencies(stdout, snoopmDependencies); assert.equal(stdout.indexOf('┌────'), -1, 'should not contain table'); @@ -87,7 +89,7 @@ describe('SnOOpm local', async ()=> { }); it('should retieve dev-dependencies list output verbose for snooping on local package.json argument "-dlv"', async () => { - var {stdout} = await execa('./bin/snoopm.js', ['-dlv']); + var {stdout} = await execa(snoopmBin, ['-dlv']); console.log(stdout); assertDependencies(stdout, snoopmDevDependencies); assert.equal(stdout.indexOf('┌────'), -1, 'should not contain table'); @@ -99,58 +101,70 @@ describe('SnOOpm local', async ()=> { describe('SnOOpm remote', async ()=> { it('should retieve default table output for snooping at remote package.json "[url]"', async () => { - const {stdout} = await execa('./bin/snoopm.js', [pckg.repository.url]); + const {stdout} = await execa(snoopmBin, [pckg.repository.url]); assertDependencies(stdout, snoopmDependencies); }); - + + it.only('should fail if non sense url is provided, e.g "http://lolandthefoobar.baz"', async () => { + const u = 'http://lolandthefoobar.baz'; + try { + const {stdout} = await execa(snoopmBin, [u]); + done(new Error('This test should fail')); + } catch (error) { + console.log(error) + assert.equal(error.exitCode, 42, 'should fail'); + //assert.notEqual(error.stdout.indexOf(`Error: Invalid provided path for: ${u}`), -1, 'should print an error'); + } + }); + it('should retieve default table output for snooping at remote package.json complete GitHub url "[url]"', async () => { - const {stdout} = await execa('./bin/snoopm.js', [urlGitHubPackageNode]); + const {stdout} = await execa(snoopmBin, [urlGitHubPackageNode]); assertDependencies(stdout, snoopmDependencies); }); it('should retieve default table output for snooping at remote package.json raw GitHub url "[url]"', async () => { - const {stdout} = await execa('./bin/snoopm.js', [urlGitHubRawPackageNode]); + const {stdout} = await execa(snoopmBin, [urlGitHubRawPackageNode]); assertDependencies(stdout, snoopmDependencies); }); it('should retieve dev-dependencies table output for snooping at remote package.json "[url] -d"', async () => { - const {stdout} = await execa('./bin/snoopm.js', [pckg.repository.url, '-d']); + const {stdout} = await execa(snoopmBin, [pckg.repository.url, '-d']); assertDependencies(stdout, snoopmDevDependencies); }); it('should retieve list output for snooping at remote package.json "[url] -l"', async () => { - const {stdout} = await execa('./bin/snoopm.js', [pckg.repository.url, '-l']); + const {stdout} = await execa(snoopmBin, [pckg.repository.url, '-l']); assert.equal(stdout.indexOf('┌────'), -1, 'should not contain table'); assertDependencies(stdout, snoopmDependencies); }); it('should retieve dev-dependencies able list output for snooping at remote package.json "[url] -ld"', async () => { - const {stdout} = await execa('./bin/snoopm.js', [pckg.repository.url, '-ld']); + const {stdout} = await execa(snoopmBin, [pckg.repository.url, '-ld']); assert.equal(stdout.indexOf('┌────'), -1, 'should not contain table'); assertDependencies(stdout, snoopmDevDependencies); }); it('should retieve default table verbose output for snooping at remote package.json "[url] -v"', async () => { - const {stdout} = await execa('./bin/snoopm.js', [pckg.repository.url, '-v']); + const {stdout} = await execa(snoopmBin, [pckg.repository.url, '-v']); assertDependencies(stdout, snoopmDependencies); assert.notEqual(stdout.indexOf(pckg.dependencies[snoopmDependencies[0]].substring(1)), -1, 'should find the dependency version'); }); it('should retieve dev-dependencies verbose table output for snooping at remote package.json "[url] -dv"', async () => { - const {stdout} = await execa('./bin/snoopm.js', [pckg.repository.url, '-dv']); + const {stdout} = await execa(snoopmBin, [pckg.repository.url, '-dv']); assertDependencies(stdout, snoopmDevDependencies); assert.notEqual(stdout.indexOf(pckg.devDependencies[snoopmDevDependencies[0]].substring(1)), -1, 'should find the dependency version'); }); it('should retieve list verbose output for snooping at remote package.json "[url] -vl"', async () => { - const {stdout} = await execa('./bin/snoopm.js', [pckg.repository.url, '-vl']); + const {stdout} = await execa(snoopmBin, [pckg.repository.url, '-vl']); assertDependencies(stdout, snoopmDependencies); assert.equal(stdout.indexOf('┌────'), -1, 'should not contain table'); assert.notEqual(stdout.indexOf(pckg.dependencies[snoopmDependencies[0]].substring(1)), -1, 'should find the dependency version'); }); it('should retieve dev-dependencies verbose table output for snooping at remote package.json "[url] -dlv"', async () => { - const {stdout} = await execa('./bin/snoopm.js', [pckg.repository.url, '-dlv']); + const {stdout} = await execa(snoopmBin, [pckg.repository.url, '-dlv']); assertDependencies(stdout, snoopmDevDependencies); assert.equal(stdout.indexOf('┌────'), -1, 'should not contain table'); assert.notEqual(stdout.indexOf(pckg.devDependencies[snoopmDevDependencies[0]].substring(1)), -1, 'should find the dependency version'); @@ -159,67 +173,102 @@ describe('SnOOpm remote', async ()=> { }); describe('SnOOpm at node_modules', async ()=> { + it('should retieve default table output for snooping at node_modules package.json "[node_modules_path]"', async () => { - const {stdout} = await execa('./bin/snoopm.js', [pathPackageNodeModule]); + const {stdout} = await execa(snoopmBin, [pathPackageNodeModule]); assertDependencies(stdout, snoopmDependencies); }); + it.only('should fail if non sense path is provided, e.g "./node_modules"', async () => { + const p = './node_modules'; + try { + const {stdout} = await execa(snoopmBin, [p]); + done(new Error('This test should fail')); + } catch (error) { + assert.equal(error.exitCode, 42, 'should fail'); + assert.notEqual(error.stdout.indexOf(`Error: Invalid provided path for: ${p}`), -1, 'should print an error'); + } + }); + + it.only('should fail if non sense path is provided, e.g "lol"', async () => { + const p = 'lol'; + try { + const {stdout} = await execa(snoopmBin, [p]); + done(new Error('This test should fail')); + } catch (error) { + assert.equal(error.exitCode, 42, 'should fail'); + assert.notEqual(error.stdout.indexOf(`Error: Invalid provided path for: ${p}`), -1, 'should print an error'); + } + }); + it('should retieve default table output for snooping at node_modules package.json "[node_modules_path]" only with directory', async () => { - const {stdout} = await execa('./bin/snoopm.js', [pathPackageNodeModuleDir]); + const {stdout} = await execa(snoopmBin, [pathPackageNodeModuleDir]); assertDependencies(stdout, snoopmDependencies); }); it('should retieve default table output for snooping at node_modules package.json "[node_modules_path]" with absolute path', async () => { const absolutePathPackageNodeModule = `${process.cwd()}${pathPackageNodeModule.substring(1)}`; - const {stdout} = await execa('./bin/snoopm.js', [absolutePathPackageNodeModule]); - console.log(stdout); + const {stdout} = await execa(snoopmBin, [absolutePathPackageNodeModule]); assertDependencies(stdout, snoopmDependencies); }); - - it('should retieve default table output for snooping at node_modules package.json "[node_modules_path]" only with directory and with absolute path', async () => { + + it('should retieve default table output for snooping at node_modules package.json "[node_modules_path]" without ./', async () => { + const noDotPathPackageNodeModule = pathPackageNodeModule.substring(2); + const {stdout} = await execa(snoopmBin, [noDotPathPackageNodeModule + ]); + assertDependencies(stdout, snoopmDependencies); + }); + + it('should retieve default table output for snooping at node_modules package.json "[node_modules_path]" only with directory and with absolute path', async () => { const absolutePathPackageNodeModuleDir = `${process.cwd()}${pathPackageNodeModuleDir.substring(1)}`; - const {stdout} = await execa('./bin/snoopm.js', [absolutePathPackageNodeModuleDir]); + const {stdout} = await execa(snoopmBin, [absolutePathPackageNodeModuleDir]); assertDependencies(stdout, snoopmDependencies); }); + it('should retieve default table output for snooping at node_modules package.json "[node_modules_path]" only with directory and without ./', async () => { + const noDotPathPackageNodeModuleDir = pathPackageNodeModuleDir.substring(2); + const {stdout} = await execa(snoopmBin, [noDotPathPackageNodeModuleDir]); + assertDependencies(stdout, snoopmDependencies); + }); + it('should retieve dev-dependencies table output for snooping at node_modules package.json "[node_modules_path] -d"', async () => { - const {stdout} = await execa('./bin/snoopm.js', [pathPackageNodeModule, '-d']); + const {stdout} = await execa(snoopmBin, [pathPackageNodeModule, '-d']); assertDependencies(stdout, snoopmDevDependencies); }); it('should retieve list output for snooping at node_modules package.json "[node_modules_path] -l"', async () => { - const {stdout} = await execa('./bin/snoopm.js', [pathPackageNodeModule, '-l']); + const {stdout} = await execa(snoopmBin, [pathPackageNodeModule, '-l']); assert.equal(stdout.indexOf('┌────'), -1, 'should not contain table'); assertDependencies(stdout, snoopmDependencies); }); it('should retieve dev-dependencies table output for snooping at node_modules package.json "[node_modules_path] -d"', async () => { - const {stdout} = await execa('./bin/snoopm.js', [pathPackageNodeModule, '-ld']); + const {stdout} = await execa(snoopmBin, [pathPackageNodeModule, '-ld']); assert.equal(stdout.indexOf('┌────'), -1, 'should not contain table'); assertDependencies(stdout, snoopmDevDependencies); }); it('should retieve default table verbose output for snooping at node_modules package.json "[node_modules_path] -v"', async () => { - const {stdout} = await execa('./bin/snoopm.js', [pathPackageNodeModule, '-v']); + const {stdout} = await execa(snoopmBin, [pathPackageNodeModule, '-v']); assertDependencies(stdout, snoopmDependencies); assert.notEqual(stdout.indexOf(pckg.dependencies[snoopmDependencies[0]].substring(1)), -1, 'should find the dependency version'); }); it('should retieve dev-dependencies verbose table output for snooping at node_modules package.json "[node_modules_path] -dv"', async () => { - const {stdout} = await execa('./bin/snoopm.js', [pathPackageNodeModule, '-dv']); + const {stdout} = await execa(snoopmBin, [pathPackageNodeModule, '-dv']); assertDependencies(stdout, snoopmDevDependencies); assert.notEqual(stdout.indexOf(pckg.devDependencies[snoopmDevDependencies[0]].substring(1)), -1, 'should find the dependency version'); }); it('should retieve list verbose output for snooping at node_modules package.json "[node_modules_path] -vl"', async () => { - const {stdout} = await execa('./bin/snoopm.js', [pathPackageNodeModule, '-vl']); + const {stdout} = await execa(snoopmBin, [pathPackageNodeModule, '-vl']); assertDependencies(stdout, snoopmDependencies); assert.equal(stdout.indexOf('┌────'), -1, 'should not contain table'); assert.notEqual(stdout.indexOf(pckg.dependencies[snoopmDependencies[0]].substring(1)), -1, 'should find the dependency version'); }); it('should retieve dev-dependencies verbose table output for snooping at node_modules package.json "[node_modules_path] -dlv"', async () => { - const {stdout} = await execa('./bin/snoopm.js', [pathPackageNodeModule, '-dlv']); + const {stdout} = await execa(snoopmBin, [pathPackageNodeModule, '-dlv']); assertDependencies(stdout, snoopmDevDependencies); assert.equal(stdout.indexOf('┌────'), -1, 'should not contain table'); assert.notEqual(stdout.indexOf(pckg.devDependencies[snoopmDevDependencies[0]].substring(1)), -1, 'should find the dependency version');