diff --git a/.gitignore b/.gitignore index fa59d6d..e519fab 100644 --- a/.gitignore +++ b/.gitignore @@ -1,56 +1,21 @@ # Logs logs *.log -npm-debug.log* yarn-debug.log* yarn-error.log* -# Runtime data -pids -*.pid -*.seed -*.pid.lock - # Es-5 compiled directory lib -# Directory for instrumented libs generated by jscoverage/JSCover -lib-cov - -# Coverage directory used by tools like istanbul -coverage - -# nyc test coverage -.nyc_output - -# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) -.grunt - -# Bower dependency directory (https://bower.io/) -bower_components - -# node-waf configuration -.lock-wscript - -# Compiled binary addons (https://nodejs.org/api/addons.html) -build/Release - # Dependency directories node_modules/ -jspm_packages/ # TypeScript v1 declaration files typings/ -# Optional npm cache directory -.npm - # Optional eslint cache .eslintcache -# Optional REPL history -.node_repl_history - # Output of 'npm pack' *.tgz @@ -60,5 +25,5 @@ typings/ # dotenv environment variables file .env -# next.js build output -.next +# Test artifacts +test-app diff --git a/__e2e__/commands/new.test.ts b/__e2e__/commands/new.test.ts index 236c0ee..5b1b37c 100644 --- a/__e2e__/commands/new.test.ts +++ b/__e2e__/commands/new.test.ts @@ -1,20 +1,18 @@ import fs from 'fs'; import path from 'path'; -import run from '../test-utils'; +import { rmTestDir, run } from '../test-utils'; jest.setTimeout(240000); const testDirPath = path.join(__dirname, 'test-app'); beforeEach(() => { - if (fs.existsSync(testDirPath)) { - fs.rmdirSync(testDirPath, { recursive: true }); - } + rmTestDir(testDirPath); }); afterAll(() => { - fs.rmdirSync(testDirPath, { recursive: true }); + rmTestDir(testDirPath); }); const generatedFiles = [ @@ -59,7 +57,7 @@ describe('new command', () => { // Assertion for the configured scripts expect(pkgJson.name).toBe('test-app'); expect(pkgJson.scripts['build']).toBe('webpack'); - expect(pkgJson.scripts['serve']).toBe('webpack-dev-server --open'); + expect(pkgJson.scripts['serve']).toBe('webpack serve'); }); it('uses npm on supplying --use-npm', async () => { @@ -90,6 +88,38 @@ describe('new command', () => { // Assertion for the configured scripts expect(pkgJson.name).toBe('test-app'); expect(pkgJson.scripts['build']).toBe('webpack'); - expect(pkgJson.scripts['serve']).toBe('webpack-dev-server --open'); + expect(pkgJson.scripts['serve']).toBe('webpack serve'); + + // Remove test-app directory + rmTestDir(testDirPath); + }); + + it('creates a project in the current directory', async () => { + // Create test-app directory + fs.mkdirSync(testDirPath); + + const { exitCode } = await run(['new', '.'], { + cwd: testDirPath, + input: '\n', + }); + + // Assertions + expect(exitCode).toBe(0); + generatedFiles.forEach(file => + expect(fs.existsSync(path.join(testDirPath, file))).toBeTruthy() + ); + + const pkgJson = JSON.parse( + fs.readFileSync(path.join(testDirPath, 'package.json')) + ); + + // Assertion for the installed dependencies + expect(pkgJson.dependencies).toBeFalsy(); + deps.forEach(dep => expect(pkgJson.devDependencies[dep]).toBeTruthy()); + + // Assertion for the configured scripts + expect(pkgJson.name).toBe('test-app'); + expect(pkgJson.scripts['build']).toBe('webpack'); + expect(pkgJson.scripts['serve']).toBe('webpack serve'); }); }); diff --git a/__e2e__/test-utils.ts b/__e2e__/test-utils.ts index cad8e5f..dfb9ca0 100644 --- a/__e2e__/test-utils.ts +++ b/__e2e__/test-utils.ts @@ -1,10 +1,17 @@ import execa from 'execa'; +import fs from 'fs'; import path from 'path'; const CLI_PATH = path.join(__dirname, '..', 'bin'); -export default ( +export const run = ( args: string[], options = {} ): execa.ExecaChildProcess => execa('node', [CLI_PATH].concat(args), options); + +export const rmTestDir = (testDirPath: string): void => { + if (fs.existsSync(testDirPath)) { + fs.rmdirSync(testDirPath, { recursive: true }); + } +}; diff --git a/bin/index.js b/bin/index.js index 1a8be11..cf048a2 100755 --- a/bin/index.js +++ b/bin/index.js @@ -14,14 +14,10 @@ program .description('Scaffolds a static site boilerplate template to work on.') .action(scaffoldProject); -program.arguments('').action(cmd => { +program.on('command:*', ([cmd]) => { program.outputHelp(); console.log(` ` + kleur.red(`\n Unknown command ${kleur.yellow(cmd)}.`)); console.log(); }); program.parse(process.argv); - -if (!program.args.length) { - program.help(); -} diff --git a/package.json b/package.json index 70aeab2..4b8c5af 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ }, "homepage": "https://github.com/jamesgeorge007/scaffold-static#readme", "dependencies": { - "commander": "^5.0.0", + "commander": "^6.2.1", "execa": "^4.0.0", "inquirer": "^6.2.1", "kleur": "^3.0.3", diff --git a/src/commands/scaffold.ts b/src/commands/scaffold.ts index 4e8f255..62831ef 100644 --- a/src/commands/scaffold.ts +++ b/src/commands/scaffold.ts @@ -29,7 +29,14 @@ export default async ( process.exit(1); } - if (fs.existsSync(projectName)) { + const isCurrentDir = projectName === '.'; + + if (isCurrentDir && fs.readdirSync('.').length) { + logger.error(` The current directory isn't empty`); + process.exit(1); + } + + if (!isCurrentDir && fs.existsSync(projectName)) { logger.error(` ${projectName} already exists in path`); process.exit(1); } @@ -52,7 +59,7 @@ export default async ( ]); // Create the project directory - fs.mkdirSync(projectName); + !isCurrentDir && fs.mkdirSync(projectName); // Create css and js directory const cssDirPath = path.join(projectName, 'css'); @@ -83,8 +90,8 @@ export default async ( // Dependencies to be installed const deps = [ - 'webpack@^4.44.2', - 'webpack-cli@^3.3.12', + 'webpack', + 'webpack-cli', 'webpack-dev-server', 'css-loader', 'style-loader', @@ -108,14 +115,16 @@ export default async ( // Add build and serve scripts pkgJson = { ...pkgJson, - name: projectName, scripts: { - ...pkgJson.scripts, build: 'webpack', - serve: 'webpack-dev-server --open', + serve: 'webpack serve', }, }; + if (!isCurrentDir) { + pkgJson.name = projectName; + } + fs.writeFileSync( path.join(projectName, 'package.json'), JSON.stringify(pkgJson, null, 2) @@ -132,6 +141,11 @@ export default async ( // Instructions to the user console.log(); - logger.success('Please follow these instructions:- '); - logger.info(`cd ${projectName} && ${pm} run serve`); + logger.success('Now, type in:'); + + let msg = `${pm} run serve`; + if (!isCurrentDir) { + msg = `cd ${projectName} && ${msg}`; + } + logger.info(msg); }; diff --git a/src/templates/webpack.config.js b/src/templates/webpack.config.js index ae486d7..772f9e5 100644 --- a/src/templates/webpack.config.js +++ b/src/templates/webpack.config.js @@ -11,6 +11,7 @@ module.exports = { }, devServer: { contentBase: './dist', + open: true, }, plugins: [ new HtmlWebpackPlugin({ diff --git a/yarn.lock b/yarn.lock index ef0afe5..add9b9c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2117,16 +2117,16 @@ combined-stream@^1.0.6, combined-stream@~1.0.6: dependencies: delayed-stream "~1.0.0" -commander@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae" - integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg== - commander@^6.2.0: version "6.2.0" resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.0.tgz#b990bfb8ac030aedc6d11bc04d1488ffef56db75" integrity sha512-zP4jEKbe8SHzKJYQmq8Y9gYjtO/POJLgIdKgV7B9qNmABVFVc+ctqSX6iXh4mCpJfRBOabiZ2YKPg8ciDw6C+Q== +commander@^6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c" + integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA== + component-emitter@^1.2.1: version "1.3.0" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0"