From 7d8b30a9bb3b4864425e61f9fc7afa810c7e0260 Mon Sep 17 00:00:00 2001 From: Masafumi Koba Date: Sun, 17 Jun 2018 15:00:26 +0900 Subject: [PATCH] feat(init): add new options (`cwd`, `logger`) to `init()` (#203) --- README.md | 8 ++++++-- lib/init.js | 31 ++++++++++++++++++------------- package.json | 2 +- test/helpers/exec.js | 4 ++++ test/init.test.js | 36 +++++++++++++++++++++--------------- 5 files changed, 50 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index 07abaa06..0fe9d757 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,11 @@ ybiq init ### Programmatic API ```js -const ybiq = require('ybiq') +const ybiq = require("ybiq"); -ybiq.init() +ybiq.init({ + // Default options + // cwd: process.cwd(), + // logger: msg => process.stdout.write(msg), +}); ``` diff --git a/lib/init.js b/lib/init.js index 70d36136..be8aafea 100644 --- a/lib/init.js +++ b/lib/init.js @@ -1,22 +1,22 @@ const path = require('path') +const { EOL } = require('os') const fs = require('fs-extra') const originalPackage = require('../package.json') -const stdout = str => process.stdout.write(`${str}\n`) - const packagePath = (...pathElements) => path.join(...[__dirname, '..', ...pathElements]) -const copyFile = async (src, dest) => { - await fs.copy(src, dest) - stdout(`${dest} was updated.`) -} - const template = name => path.join(__dirname, '..', 'templates', name) class Init { - constructor(baseDir) { + constructor(baseDir, logger) { this.baseDir = baseDir + this.logger = logger + } + + async copyFile(src, dest) { + await fs.copy(src, dest) + this.logger(`${dest} was updated.`) } currentPath(...pathElements) { @@ -26,7 +26,7 @@ class Init { async writeFile(fileName, fileContent) { const file = this.currentPath(fileName) await fs.writeFile(file, `${fileContent}\n`) - stdout(`${file} was updated.`) + this.logger(`${file} was updated.`) } async readFile(fileName) { @@ -65,16 +65,21 @@ class Init { } async writeTemplateFile(name) { - await copyFile(template(name), this.currentPath(name)) + await this.copyFile(template(name), this.currentPath(name)) } async writePackageFile(name) { - await copyFile(packagePath(name), this.currentPath(name)) + await this.copyFile(packagePath(name), this.currentPath(name)) } } -module.exports = async function init() { - const cmd = new Init(process.cwd()) +const defaultLogger = msg => process.stdout.write(`${msg}${EOL}`) + +module.exports = async function init({ + cwd = process.cwd(), + logger = defaultLogger, +} = {}) { + const cmd = new Init(cwd, logger) await cmd.updatePackageFile() await cmd.writePackageFile('.editorconfig') await cmd.writePackageFile('.prettierignore') diff --git a/package.json b/package.json index b56ae938..41ecf8ed 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "eslint-config-ybiquitous": "^4.2.1" }, "scripts": { - "test": "nyc --check-coverage tape \"test/**/*.test.js\"", + "test": "nyc --check-coverage --lines 100 --branches 90 tape \"test/**/*.test.js\"", "test:watch": "nodemon --ext js --watch . --exec \"tape test/**/*.test.js\"", "test:coverage": "nyc report --reporter=text-lcov > coverage.lcov", "lint:js": "eslint --ignore-path .gitignore --ext .js,.jsx,.mjs .", diff --git a/test/helpers/exec.js b/test/helpers/exec.js index c64ef840..149af740 100644 --- a/test/helpers/exec.js +++ b/test/helpers/exec.js @@ -7,6 +7,10 @@ module.exports = function exec(...args) { const options = { env: { ...process.env, LANG: 'C' }, } + const lastArg = args[args.length - 1] + if (lastArg && typeof lastArg === 'object') { + options.cwd = lastArg.cwd + } return new Promise((resolve, reject) => { cp.execFile(tested, args, options, (error, stdout, stderr) => { if (error) { diff --git a/test/init.test.js b/test/init.test.js index c96a2b57..992b68f7 100644 --- a/test/init.test.js +++ b/test/init.test.js @@ -2,6 +2,7 @@ const path = require('path') const os = require('os') const fs = require('fs-extra') const test = require('tape') +const exec = require('./helpers/exec') const pkg = require('../package.json') const init = require('../lib/init') @@ -10,15 +11,13 @@ const readFile = file => fs.readFile(file, 'utf8') const sandbox = async (fn, t) => { const workDir = path.join(os.tmpdir(), `${pkg.name}${Date.now()}`) await fs.mkdirs(workDir) - const origDir = process.cwd() - process.chdir(workDir) - const origLogger = process.stdout.write const logMsgs = [] - process.stdout.write = msg => logMsgs.push(msg) + const logger = msg => logMsgs.push(msg) try { - const fixturePath = name => path.join(__dirname, 'fixtures', name) + const cwd = process.cwd() + const fixturePath = name => path.join(cwd, 'test', 'fixtures', name) const fixture = async name => { const src = fixturePath(name) const dest = path.join(workDir, 'package.json') @@ -30,13 +29,12 @@ const sandbox = async (fn, t) => { fixturePath, fixture, readFixture: name => readFile(fixturePath(name)), - readOrigFile: name => readFile(path.join(origDir, name)), + readOrigFile: name => readFile(path.join(cwd, name)), readWorkFile: name => readFile(path.join(workDir, name)), logMessage: () => logMsgs.join(''), + initArgs: { cwd: workDir, logger }, }) } finally { - process.stdout.write = origLogger - process.chdir(origDir) await fs.remove(workDir) } } @@ -48,7 +46,7 @@ test('init', t => { testInSandbox('update "package.json"', async (t, ctx) => { const src = await ctx.fixture('package-normal.json') - await init() + await init(ctx.initArgs) const actual = await readFile(src) const expected = await ctx.readFixture('package-normal_expected.json') t.is(actual, expected) @@ -57,7 +55,7 @@ test('init', t => { testInSandbox('update "package.json" without fields', async (t, ctx) => { const src = await ctx.fixture('package-empty.json') - await init() + await init(ctx.initArgs) const actual = await readFile(src) const expected = await ctx.readFixture('package-empty_expected.json') t.is(actual, expected) @@ -66,7 +64,7 @@ test('init', t => { ;['.editorconfig', '.prettierignore', '.markdownlint.json'].forEach(file => { testInSandbox(`write "${file}"`, async (t, ctx) => { await ctx.fixture('package-normal.json') - await init() + await init(ctx.initArgs) t.ok(ctx.logMessage().includes('package.json was updated.')) const original = await ctx.readOrigFile(file) @@ -78,7 +76,7 @@ test('init', t => { testInSandbox('write ".eslintrc.js"', async (t, ctx) => { await ctx.fixture('package-normal.json') - await init() + await init(ctx.initArgs) t.ok(ctx.logMessage().includes('.eslintrc.js was updated.')) const actual = await ctx.readWorkFile('.eslintrc.js') @@ -89,7 +87,7 @@ test('init', t => { testInSandbox('write ".commitlintrc.js"', async (t, ctx) => { await ctx.fixture('package-normal.json') - await init() + await init(ctx.initArgs) t.ok(ctx.logMessage().includes('.commitlintrc.js was updated.')) const actual = await ctx.readWorkFile('.commitlintrc.js') @@ -98,10 +96,18 @@ test('init', t => { t.end() }) - testInSandbox('throw error if no package.json', async t => { - const error = await init().catch(err => err) + testInSandbox('throw error if no package.json', async (t, ctx) => { + const error = await init(ctx.initArgs).catch(err => err) t.ok(error instanceof Error) t.is(error.code, 'ENOENT') t.end() }) + + testInSandbox('End-to-End via CLI', async (t, ctx) => { + await ctx.fixture('package-normal.json') + const { stdout, stderr } = await exec('init', { cwd: ctx.initArgs.cwd }) + t.ok(stdout.includes('package.json was updated.')) + t.is(stderr, '') + t.end() + }) })