No known key found for this signature in database
GPG Key ID: 51D5A407BFCE64A9
22 changed files with 4600 additions and 111 deletions
-
3.circleci/config.yml
-
1.gitignore
-
2.prettierrc
-
6babel.config.js
-
5jest.config.js
-
12package.json
-
31src/commands/add/prettier.ts
-
19src/commands/add/tailwind.ts
-
81src/commands/wall/index.ts
-
68src/tests/__snapshots__/wall.spec.ts.snap
-
68src/tests/add/__snapshots__/prettier.spec.ts.snap
-
50src/tests/add/__snapshots__/tailwind.spec.ts.snap
-
153src/tests/add/prettier.spec.ts
-
267src/tests/add/tailwind.spec.ts
-
96src/tests/wall.spec.ts
-
85src/utls/__snapshots__/base-add-command.spec.ts.snap
-
113src/utls/__snapshots__/base-command.spec.ts.snap
-
353src/utls/base-add-command.spec.ts
-
48src/utls/base-add-command.ts
-
255src/utls/base-command.spec.ts
-
58src/utls/base-command.ts
-
2935yarn.lock
@ -1,7 +1,7 @@ |
|||||
{ |
{ |
||||
"semi": true, |
"semi": true, |
||||
"singleQuote": true, |
"singleQuote": true, |
||||
"printWidth": 120, |
|
||||
|
"printWidth": 100, |
||||
"quoteProps": "consistent", |
"quoteProps": "consistent", |
||||
"trailingComma": "all" |
"trailingComma": "all" |
||||
} |
} |
||||
@ -0,0 +1,6 @@ |
|||||
|
module.exports = { |
||||
|
presets: [ |
||||
|
['@babel/preset-env', {targets: {node: 'current'}}], |
||||
|
'@babel/preset-typescript', |
||||
|
], |
||||
|
}; |
||||
@ -0,0 +1,5 @@ |
|||||
|
module.exports = { |
||||
|
preset: 'ts-jest', |
||||
|
testEnvironment: 'node', |
||||
|
collectCoverage: true, |
||||
|
}; |
||||
@ -0,0 +1,68 @@ |
|||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP |
||||
|
|
||||
|
exports[`wall command should download wallpaper and console output 1`] = ` |
||||
|
Array [ |
||||
|
"Searching wallpapers", |
||||
|
"The step was done without any error.", |
||||
|
"Downloading wallpaper", |
||||
|
"Successfully wrote wallhaven-thing.jpg.", |
||||
|
] |
||||
|
`; |
||||
|
|
||||
|
exports[`wall command should download wallpaper and console output to specific file 1`] = ` |
||||
|
Array [ |
||||
|
"Searching wallpapers", |
||||
|
"The step was done without any error.", |
||||
|
"Downloading wallpaper", |
||||
|
"Successfully wrote wall.jpg.", |
||||
|
] |
||||
|
`; |
||||
|
|
||||
|
exports[`wall command should print a warning when output exists 1`] = ` |
||||
|
Array [ |
||||
|
"Searching wallpapers", |
||||
|
"The step was done without any error.", |
||||
|
"Downloading wallpaper", |
||||
|
"The file wall.jpg already exist", |
||||
|
"The flag force was not set, aborting", |
||||
|
] |
||||
|
`; |
||||
|
|
||||
|
exports[`wall command should print a warning when output exists with the force flag 1`] = ` |
||||
|
Array [ |
||||
|
"Searching wallpapers", |
||||
|
"The step was done without any error.", |
||||
|
"Downloading wallpaper", |
||||
|
"Overriding wall.jpg", |
||||
|
"Successfully wrote wall.jpg.", |
||||
|
] |
||||
|
`; |
||||
|
|
||||
|
exports[`wall command should print help correctly 1`] = ` |
||||
|
Array [ |
||||
|
"download a wallpaper from wallhaven using search |
||||
|
", |
||||
|
"USAGE |
||||
|
$ nbx wall TERMS |
||||
|
|
||||
|
ARGUMENTS |
||||
|
TERMS The search terms for the wallpaper |
||||
|
|
||||
|
OPTIONS |
||||
|
-a, --anime Enable anime category |
||||
|
-f, --force Override the file if found |
||||
|
-g, --general Enable general category |
||||
|
-h, --help show CLI help |
||||
|
-o, --output=output Output for the wallpaper |
||||
|
-p, --people Enable people category |
||||
|
-r, --random Pick one randomly |
||||
|
-s, --sketchy Enables sketchy search |
||||
|
-v, --verbose Verbose output |
||||
|
--[no-]spinner Enable spinner in cli output, true by default |
||||
|
|
||||
|
EXAMPLE |
||||
|
$ nbx wall -r \\"cat\\" -o \\"wall.jpg\\" -fg |
||||
|
", |
||||
|
"", |
||||
|
] |
||||
|
`; |
||||
@ -0,0 +1,68 @@ |
|||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP |
||||
|
|
||||
|
exports[`prettier should print help correctly 1`] = ` |
||||
|
Array [ |
||||
|
"add prettier to project and format it |
||||
|
", |
||||
|
"USAGE |
||||
|
$ nbx add:prettier |
||||
|
|
||||
|
OPTIONS |
||||
|
-h, --help show CLI help |
||||
|
-v, --verbose Verbose output |
||||
|
--[no-]spinner Enable spinner in cli output, true by default", |
||||
|
"", |
||||
|
] |
||||
|
`; |
||||
|
|
||||
|
exports[`prettier should work with commits 1`] = ` |
||||
|
Array [ |
||||
|
"Adding prettier as a dev dependency", |
||||
|
"The step was done without any error.", |
||||
|
"Adding husky as a dev dependency", |
||||
|
"The step was done without any error.", |
||||
|
"Adding pretty-quick as a dev dependency", |
||||
|
"The step was done without any error.", |
||||
|
"Adding package.json scripts", |
||||
|
"The step was done without any error.", |
||||
|
"Adding .prettierrc config file", |
||||
|
"The step was done without any error.", |
||||
|
"Updating code to match prettier style", |
||||
|
"The step was done without any error.", |
||||
|
] |
||||
|
`; |
||||
|
|
||||
|
exports[`prettier should work with commits 2`] = ` |
||||
|
"<html> |
||||
|
<body> |
||||
|
<a>testokiii</a> |
||||
|
</body> |
||||
|
</html> |
||||
|
" |
||||
|
`; |
||||
|
|
||||
|
exports[`prettier should work without commits 1`] = ` |
||||
|
Array [ |
||||
|
"Adding prettier as a dev dependency", |
||||
|
"The step was done without any error.", |
||||
|
"Adding husky as a dev dependency", |
||||
|
"The step was done without any error.", |
||||
|
"Adding pretty-quick as a dev dependency", |
||||
|
"The step was done without any error.", |
||||
|
"Adding package.json scripts", |
||||
|
"The step was done without any error.", |
||||
|
"Adding .prettierrc config file", |
||||
|
"The step was done without any error.", |
||||
|
"Updating code to match prettier style", |
||||
|
"The step was done without any error.", |
||||
|
] |
||||
|
`; |
||||
|
|
||||
|
exports[`prettier should work without commits 2`] = ` |
||||
|
"<html> |
||||
|
<body> |
||||
|
<a>testokiii</a> |
||||
|
</body> |
||||
|
</html> |
||||
|
" |
||||
|
`; |
||||
@ -0,0 +1,50 @@ |
|||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP |
||||
|
|
||||
|
exports[`tailwind should print help correctly 1`] = ` |
||||
|
Array [ |
||||
|
"add tailwindcss to a project |
||||
|
", |
||||
|
"USAGE |
||||
|
$ nbx add:tailwind |
||||
|
|
||||
|
OPTIONS |
||||
|
-h, --help show CLI help |
||||
|
-v, --verbose Verbose output |
||||
|
--[no-]spinner Enable spinner in cli output, true by default", |
||||
|
"", |
||||
|
] |
||||
|
`; |
||||
|
|
||||
|
exports[`tailwind should work on a react application with commits 1`] = ` |
||||
|
"const purgecss = require('@fullhuman/postcss-purgecss')({ |
||||
|
content: ['./src/**/*.jsx', './src/**/*.js', './src/index.js', './public/index.html'], |
||||
|
css: ['./src/tailwind.css'], |
||||
|
// Include any special characters you're using in this regular expression |
||||
|
defaultExtractor: content => content.match(/[A-Za-z0-9-_:/]+/g) || [], |
||||
|
}); |
||||
|
module.exports = { |
||||
|
plugins: [ |
||||
|
require('tailwindcss')('./tailwind.config.js'), |
||||
|
require('autoprefixer'), |
||||
|
...(process.env.NODE_ENV === 'production' ? [purgecss] : []), |
||||
|
], |
||||
|
}; |
||||
|
" |
||||
|
`; |
||||
|
|
||||
|
exports[`tailwind should work on a react application without commits 1`] = ` |
||||
|
"const purgecss = require('@fullhuman/postcss-purgecss')({ |
||||
|
content: ['./src/**/*.jsx', './src/**/*.js', './src/index.js', './public/index.html'], |
||||
|
css: ['./src/tailwind.css'], |
||||
|
// Include any special characters you're using in this regular expression |
||||
|
defaultExtractor: content => content.match(/[A-Za-z0-9-_:/]+/g) || [], |
||||
|
}); |
||||
|
module.exports = { |
||||
|
plugins: [ |
||||
|
require('tailwindcss')('./tailwind.config.js'), |
||||
|
require('autoprefixer'), |
||||
|
...(process.env.NODE_ENV === 'production' ? [purgecss] : []), |
||||
|
], |
||||
|
}; |
||||
|
" |
||||
|
`; |
||||
@ -0,0 +1,153 @@ |
|||||
|
import { filesystem, system } from 'gluegun'; |
||||
|
const stripANSI = require('strip-ansi'); |
||||
|
import * as prompts from 'prompts'; |
||||
|
import * as latestVersion from 'latest-version'; |
||||
|
import Prettier from '../../commands/add/prettier'; |
||||
|
|
||||
|
jest.setTimeout(30000); |
||||
|
|
||||
|
/* eslint-disable no-console,max-nested-callbacks,@typescript-eslint/ban-ts-ignore */ |
||||
|
let consoleLogOutput: string[]; |
||||
|
let execPath: string; |
||||
|
const originalCwd = process.cwd(); |
||||
|
const originalLog = console.log; |
||||
|
|
||||
|
beforeEach(() => { |
||||
|
consoleLogOutput = []; |
||||
|
console.log = (x: any) => consoleLogOutput.push(stripANSI(x)); |
||||
|
|
||||
|
const tmpDirName = `${new Date().getTime()}-${Math.random() * 100}-add-nbx-test`; |
||||
|
execPath = filesystem.path('/', 'tmp', tmpDirName); |
||||
|
filesystem.dir(execPath); |
||||
|
process.chdir(execPath); |
||||
|
}); |
||||
|
afterEach(() => { |
||||
|
console.log = originalLog; |
||||
|
process.chdir(originalCwd); |
||||
|
jest.restoreAllMocks(); |
||||
|
filesystem.remove(execPath); |
||||
|
}); |
||||
|
|
||||
|
const initWithConfigAndCommit = async () => { |
||||
|
await system.run('git init'); |
||||
|
filesystem.write('.nbxrc', { git: { user: 'aaa', email: 'bbb' } }); |
||||
|
filesystem.write('package.json', {}); |
||||
|
filesystem.write('test.html', '<html><body><a>testokiii</a></body></html>'); |
||||
|
await system.run('touch yarn.lock'); |
||||
|
await system.run('echo node_modules > .gitignore'); |
||||
|
await system.run('git add * .nbxrc .gitignore'); |
||||
|
await system.run('git commit -m "init state"'); |
||||
|
}; |
||||
|
|
||||
|
describe('prettier', () => { |
||||
|
it('should print help correctly', async () => { |
||||
|
try { |
||||
|
await Prettier.run(['-h']); |
||||
|
} catch {} |
||||
|
expect(consoleLogOutput).toMatchSnapshot(); |
||||
|
}); |
||||
|
|
||||
|
it('should work without commits', async () => { |
||||
|
await initWithConfigAndCommit(); |
||||
|
prompts.inject(['**/*.{js,vue,json,ts,tsx,md,yml,html}', false]); |
||||
|
const [latestHusky, latestPrettier, latestPrettyQuick] = await Promise.all([ |
||||
|
latestVersion('husky'), |
||||
|
latestVersion('prettier'), |
||||
|
latestVersion('pretty-quick'), |
||||
|
]); |
||||
|
|
||||
|
await Prettier.run(['--no-spinner']); |
||||
|
|
||||
|
const packageJson = filesystem.read('package.json', 'json'); |
||||
|
const htmlFile = filesystem.read('test.html', 'utf8'); |
||||
|
expect(consoleLogOutput).toMatchSnapshot(); |
||||
|
expect(packageJson).toStrictEqual({ |
||||
|
devDependencies: { |
||||
|
'husky': latestHusky, |
||||
|
'prettier': latestPrettier, |
||||
|
'pretty-quick': latestPrettyQuick, |
||||
|
}, |
||||
|
husky: { |
||||
|
hooks: { |
||||
|
'pre-commit': 'pretty-quick --staged', |
||||
|
}, |
||||
|
}, |
||||
|
scripts: { |
||||
|
'format:check': 'prettier --list-different "**/*.{js,vue,json,ts,tsx,md,yml,html}"', |
||||
|
'format:write': 'prettier --write "**/*.{js,vue,json,ts,tsx,md,yml,html}"', |
||||
|
}, |
||||
|
}); |
||||
|
expect(htmlFile).toMatchSnapshot(); |
||||
|
const after = await system.run('git log --name-status --format="%s"'); |
||||
|
const afterSlitted = after |
||||
|
.split('\n') |
||||
|
.map(val => val.trim()) |
||||
|
.map(val => stripANSI(val)) |
||||
|
.filter(val => val !== ''); |
||||
|
|
||||
|
expect(afterSlitted).toHaveLength(6); |
||||
|
}); |
||||
|
it('should work with commits', async () => { |
||||
|
await initWithConfigAndCommit(); |
||||
|
prompts.inject(['**/*.{js,vue,json,ts,tsx,md,yml,html}', true]); |
||||
|
const [latestHusky, latestPrettier, latestPrettyQuick] = await Promise.all([ |
||||
|
latestVersion('husky'), |
||||
|
latestVersion('prettier'), |
||||
|
latestVersion('pretty-quick'), |
||||
|
]); |
||||
|
|
||||
|
await Prettier.run(['--no-spinner']); |
||||
|
|
||||
|
const packageJson = filesystem.read('package.json', 'json'); |
||||
|
const htmlFile = filesystem.read('test.html', 'utf8'); |
||||
|
expect(consoleLogOutput).toMatchSnapshot(); |
||||
|
expect(packageJson).toStrictEqual({ |
||||
|
devDependencies: { |
||||
|
'husky': latestHusky, |
||||
|
'prettier': latestPrettier, |
||||
|
'pretty-quick': latestPrettyQuick, |
||||
|
}, |
||||
|
husky: { |
||||
|
hooks: { |
||||
|
'pre-commit': 'pretty-quick --staged', |
||||
|
}, |
||||
|
}, |
||||
|
scripts: { |
||||
|
'format:check': 'prettier --list-different "**/*.{js,vue,json,ts,tsx,md,yml,html}"', |
||||
|
'format:write': 'prettier --write "**/*.{js,vue,json,ts,tsx,md,yml,html}"', |
||||
|
}, |
||||
|
}); |
||||
|
expect(htmlFile).toMatchSnapshot(); |
||||
|
const after = await system.run('git log --name-status --format="%s"'); |
||||
|
const afterSlitted = after |
||||
|
.split('\n') |
||||
|
.map(val => val.trim()) |
||||
|
.map(val => stripANSI(val)) |
||||
|
.filter(val => val !== ''); |
||||
|
|
||||
|
expect(afterSlitted).toStrictEqual([ |
||||
|
':art: apply prettier style to project', |
||||
|
'M\tpackage.json', |
||||
|
'M\ttest.html', |
||||
|
':wrench: add prettierrc config file', |
||||
|
'A\t.prettierrc', |
||||
|
':wrench: add script and husky to package.json', |
||||
|
'M\tpackage.json', |
||||
|
`:heavy_plus_sign: add pretty-quick@${latestPrettyQuick} as a dev dependency`, |
||||
|
'M\tpackage.json', |
||||
|
'M\tyarn.lock', |
||||
|
`:heavy_plus_sign: add husky@${latestHusky} as a dev dependency`, |
||||
|
'M\tpackage.json', |
||||
|
'M\tyarn.lock', |
||||
|
`:heavy_plus_sign: add prettier@${latestPrettier} as a dev dependency`, |
||||
|
'M\tpackage.json', |
||||
|
'M\tyarn.lock', |
||||
|
'init state', |
||||
|
'A\t.gitignore', |
||||
|
'A\t.nbxrc', |
||||
|
'A\tpackage.json', |
||||
|
'A\ttest.html', |
||||
|
'A\tyarn.lock', |
||||
|
]); |
||||
|
}); |
||||
|
}); |
||||
@ -0,0 +1,267 @@ |
|||||
|
import { filesystem, system } from 'gluegun'; |
||||
|
const stripANSI = require('strip-ansi'); |
||||
|
import * as prompts from 'prompts'; |
||||
|
import * as latestVersion from 'latest-version'; |
||||
|
import Tailwind from '../../commands/add/tailwind'; |
||||
|
|
||||
|
jest.setTimeout(30000); |
||||
|
|
||||
|
/* eslint-disable no-console,max-nested-callbacks,@typescript-eslint/ban-ts-ignore */ |
||||
|
let consoleLogOutput: string[]; |
||||
|
let execPath: string; |
||||
|
const originalCwd = process.cwd(); |
||||
|
const originalLog = console.log; |
||||
|
|
||||
|
beforeEach(() => { |
||||
|
consoleLogOutput = []; |
||||
|
console.log = (x: any) => consoleLogOutput.push(stripANSI(x)); |
||||
|
|
||||
|
const tmpDirName = `${new Date().getTime()}-${Math.random() * 100}-add-nbx-test`; |
||||
|
execPath = filesystem.path('/', 'tmp', tmpDirName); |
||||
|
filesystem.dir(execPath); |
||||
|
process.chdir(execPath); |
||||
|
}); |
||||
|
afterEach(() => { |
||||
|
console.log = originalLog; |
||||
|
process.chdir(originalCwd); |
||||
|
jest.restoreAllMocks(); |
||||
|
filesystem.remove(execPath); |
||||
|
}); |
||||
|
|
||||
|
const initWithConfigAndCommit = async (packageJson = {}) => { |
||||
|
await system.run('git init'); |
||||
|
filesystem.write('.nbxrc', { git: { user: 'aaa', email: 'bbb' } }); |
||||
|
filesystem.write('package.json', packageJson); |
||||
|
filesystem.write('test.html', '<html><body><a>testokiii</a></body></html>'); |
||||
|
await system.run('touch yarn.lock'); |
||||
|
await system.run('echo node_modules > .gitignore'); |
||||
|
await system.run('git add * .nbxrc .gitignore'); |
||||
|
await system.run('git commit -m "init state"'); |
||||
|
}; |
||||
|
|
||||
|
describe('tailwind', () => { |
||||
|
it('should print help correctly', async () => { |
||||
|
try { |
||||
|
await Tailwind.run(['-h']); |
||||
|
} catch {} |
||||
|
expect(consoleLogOutput).toMatchSnapshot(); |
||||
|
}); |
||||
|
|
||||
|
it('should error if no react is found', async () => { |
||||
|
await initWithConfigAndCommit(); |
||||
|
|
||||
|
try { |
||||
|
await Tailwind.run(['--no-spinner']); |
||||
|
// eslint-disable-next-line unicorn/catch-error-name
|
||||
|
} catch (e) { |
||||
|
expect(e).toEqual(new Error('This script support only for now create react apps.')); |
||||
|
} |
||||
|
const after = await system.run('git log --name-status --format="%s"'); |
||||
|
const afterSlitted = after |
||||
|
.split('\n') |
||||
|
.map(val => val.trim()) |
||||
|
.map(val => stripANSI(val)) |
||||
|
.filter(val => val !== ''); |
||||
|
|
||||
|
expect(afterSlitted).toHaveLength(6); |
||||
|
}); |
||||
|
|
||||
|
it('should work on a react application without commits', async () => { |
||||
|
await initWithConfigAndCommit({ |
||||
|
name: 'sample', |
||||
|
version: '0.1.0', |
||||
|
private: true, |
||||
|
dependencies: { |
||||
|
'react-scripts': '3.3.1', |
||||
|
}, |
||||
|
scripts: { |
||||
|
start: 'react-scripts start', |
||||
|
build: 'react-scripts build', |
||||
|
test: 'react-scripts test', |
||||
|
eject: 'react-scripts eject', |
||||
|
}, |
||||
|
eslintConfig: { |
||||
|
extends: 'react-app', |
||||
|
}, |
||||
|
browserslist: { |
||||
|
production: ['>0.2%', 'not dead', 'not op_mini all'], |
||||
|
development: ['last 1 chrome version', 'last 1 firefox version', 'last 1 safari version'], |
||||
|
}, |
||||
|
}); |
||||
|
prompts.inject([false]); |
||||
|
|
||||
|
const [tailwind, purgecss, autoprefixer, npmRunAll, postcss] = await Promise.all([ |
||||
|
latestVersion('tailwindcss'), |
||||
|
latestVersion('@fullhuman/postcss-purgecss'), |
||||
|
latestVersion('autoprefixer'), |
||||
|
latestVersion('npm-run-all'), |
||||
|
latestVersion('postcss-cli'), |
||||
|
]); |
||||
|
|
||||
|
await Tailwind.run(['--no-spinner']); |
||||
|
|
||||
|
const status = await system.run('git status --short'); |
||||
|
|
||||
|
const packageJson = filesystem.read('package.json', 'json'); |
||||
|
const after = await system.run('git log --name-status --format="%s"'); |
||||
|
const afterSlitted = after |
||||
|
.split('\n') |
||||
|
.map(val => val.trim()) |
||||
|
.map(val => stripANSI(val)) |
||||
|
.filter(val => val !== ''); |
||||
|
|
||||
|
expect(afterSlitted).toHaveLength(6); |
||||
|
expect(status.split('\n')).toStrictEqual([ |
||||
|
' M .gitignore', |
||||
|
' M package.json', |
||||
|
' M yarn.lock', |
||||
|
'?? postcss.config.js', |
||||
|
'?? src/', |
||||
|
'?? tailwind.config.js', |
||||
|
'', |
||||
|
]); |
||||
|
expect(filesystem.read('postcss.config.js', 'utf8')).toMatchSnapshot(); |
||||
|
expect(packageJson).toStrictEqual({ |
||||
|
name: 'sample', |
||||
|
version: '0.1.0', |
||||
|
private: true, |
||||
|
dependencies: { |
||||
|
'react-scripts': '3.3.1', |
||||
|
'tailwindcss': tailwind, |
||||
|
}, |
||||
|
devDependencies: { |
||||
|
'@fullhuman/postcss-purgecss': purgecss, |
||||
|
'autoprefixer': autoprefixer, |
||||
|
'npm-run-all': npmRunAll, |
||||
|
'postcss-cli': postcss, |
||||
|
}, |
||||
|
scripts: { |
||||
|
'start': 'npm-run-all -p start:css start:js', |
||||
|
'start:css': 'postcss src/css/tailwind.src.css -o src/tailwind.css -w', |
||||
|
'start:js': 'react-scripts start', |
||||
|
'build': 'npm-run-all build:css build:js', |
||||
|
'build:css': 'postcss src/css/tailwind.src.css -o src/tailwind.css --env production', |
||||
|
'build:js': 'react-scripts build', |
||||
|
'test': 'react-scripts test', |
||||
|
'eject': 'react-scripts eject', |
||||
|
}, |
||||
|
eslintConfig: { |
||||
|
extends: 'react-app', |
||||
|
}, |
||||
|
browserslist: { |
||||
|
production: ['>0.2%', 'not dead', 'not op_mini all'], |
||||
|
development: ['last 1 chrome version', 'last 1 firefox version', 'last 1 safari version'], |
||||
|
}, |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
it('should work on a react application with commits', async () => { |
||||
|
await initWithConfigAndCommit({ |
||||
|
name: 'sample', |
||||
|
version: '0.1.0', |
||||
|
private: true, |
||||
|
dependencies: { |
||||
|
'react-scripts': '3.3.1', |
||||
|
}, |
||||
|
scripts: { |
||||
|
start: 'react-scripts start', |
||||
|
build: 'react-scripts build', |
||||
|
test: 'react-scripts test', |
||||
|
eject: 'react-scripts eject', |
||||
|
}, |
||||
|
eslintConfig: { |
||||
|
extends: 'react-app', |
||||
|
}, |
||||
|
browserslist: { |
||||
|
production: ['>0.2%', 'not dead', 'not op_mini all'], |
||||
|
development: ['last 1 chrome version', 'last 1 firefox version', 'last 1 safari version'], |
||||
|
}, |
||||
|
}); |
||||
|
prompts.inject([true]); |
||||
|
|
||||
|
const [tailwind, purgecss, autoprefixer, npmRunAll, postcss] = await Promise.all([ |
||||
|
latestVersion('tailwindcss'), |
||||
|
latestVersion('@fullhuman/postcss-purgecss'), |
||||
|
latestVersion('autoprefixer'), |
||||
|
latestVersion('npm-run-all'), |
||||
|
latestVersion('postcss-cli'), |
||||
|
]); |
||||
|
|
||||
|
await Tailwind.run(['--no-spinner']); |
||||
|
|
||||
|
const packageJson = filesystem.read('package.json', 'json'); |
||||
|
const after = await system.run('git log --name-status --format="%s"'); |
||||
|
const afterSlitted = after |
||||
|
.split('\n') |
||||
|
.map(val => val.trim()) |
||||
|
.map(val => stripANSI(val)) |
||||
|
.filter(val => val !== ''); |
||||
|
|
||||
|
expect(afterSlitted).toStrictEqual([ |
||||
|
':see_no_evil: add generated tailwind to .gitignore', |
||||
|
'M\t.gitignore', |
||||
|
':wrench: add script for tailwind to package.json', |
||||
|
'M\tpackage.json', |
||||
|
':wrench: add tailwind css file', |
||||
|
'A\tsrc/css/tailwind.src.css', |
||||
|
':wrench: add postcss config file', |
||||
|
'A\tpostcss.config.js', |
||||
|
':wrench: add tailwind config file', |
||||
|
'A\ttailwind.config.js', |
||||
|
`:heavy_plus_sign: add tailwindcss@${tailwind} as a dependency`, |
||||
|
'M\tpackage.json', |
||||
|
'M\tyarn.lock', |
||||
|
`:heavy_plus_sign: add postcss-cli@${postcss} as a dev dependency`, |
||||
|
'M\tpackage.json', |
||||
|
'M\tyarn.lock', |
||||
|
`:heavy_plus_sign: add npm-run-all@${npmRunAll} as a dev dependency`, |
||||
|
'M\tpackage.json', |
||||
|
'M\tyarn.lock', |
||||
|
`:heavy_plus_sign: add autoprefixer@${autoprefixer} as a dev dependency`, |
||||
|
'M\tpackage.json', |
||||
|
'M\tyarn.lock', |
||||
|
`:heavy_plus_sign: add @fullhuman/postcss-purgecss@${purgecss} as a dev dependency`, |
||||
|
'M\tpackage.json', |
||||
|
'M\tyarn.lock', |
||||
|
'init state', |
||||
|
'A\t.gitignore', |
||||
|
'A\t.nbxrc', |
||||
|
'A\tpackage.json', |
||||
|
'A\ttest.html', |
||||
|
'A\tyarn.lock', |
||||
|
]); |
||||
|
expect(filesystem.read('postcss.config.js', 'utf8')).toMatchSnapshot(); |
||||
|
expect(packageJson).toStrictEqual({ |
||||
|
name: 'sample', |
||||
|
version: '0.1.0', |
||||
|
private: true, |
||||
|
dependencies: { |
||||
|
'react-scripts': '3.3.1', |
||||
|
'tailwindcss': tailwind, |
||||
|
}, |
||||
|
devDependencies: { |
||||
|
'@fullhuman/postcss-purgecss': purgecss, |
||||
|
'autoprefixer': autoprefixer, |
||||
|
'npm-run-all': npmRunAll, |
||||
|
'postcss-cli': postcss, |
||||
|
}, |
||||
|
scripts: { |
||||
|
'start': 'npm-run-all -p start:css start:js', |
||||
|
'start:css': 'postcss src/css/tailwind.src.css -o src/tailwind.css -w', |
||||
|
'start:js': 'react-scripts start', |
||||
|
'build': 'npm-run-all build:css build:js', |
||||
|
'build:css': 'postcss src/css/tailwind.src.css -o src/tailwind.css --env production', |
||||
|
'build:js': 'react-scripts build', |
||||
|
'test': 'react-scripts test', |
||||
|
'eject': 'react-scripts eject', |
||||
|
}, |
||||
|
eslintConfig: { |
||||
|
extends: 'react-app', |
||||
|
}, |
||||
|
browserslist: { |
||||
|
production: ['>0.2%', 'not dead', 'not op_mini all'], |
||||
|
development: ['last 1 chrome version', 'last 1 firefox version', 'last 1 safari version'], |
||||
|
}, |
||||
|
}); |
||||
|
}); |
||||
|
}); |
||||
@ -0,0 +1,96 @@ |
|||||
|
import { filesystem } from 'gluegun'; |
||||
|
import Wall from '../commands/wall'; |
||||
|
const stripANSI = require('strip-ansi'); |
||||
|
|
||||
|
/* eslint-disable no-console,max-nested-callbacks,@typescript-eslint/ban-ts-ignore */ |
||||
|
let consoleLogOutput: string[]; |
||||
|
let execPath: string; |
||||
|
const originalCwd = process.cwd(); |
||||
|
const originalLog = console.log; |
||||
|
|
||||
|
beforeEach(() => { |
||||
|
consoleLogOutput = []; |
||||
|
console.log = (x: any) => consoleLogOutput.push(stripANSI(x)); |
||||
|
|
||||
|
const tmpDirName = `${new Date().getTime()}-${Math.random() * 100}-add-nbx-test`; |
||||
|
execPath = filesystem.path('/', 'tmp', tmpDirName); |
||||
|
filesystem.dir(execPath); |
||||
|
process.chdir(execPath); |
||||
|
}); |
||||
|
afterEach(() => { |
||||
|
console.log = originalLog; |
||||
|
process.chdir(originalCwd); |
||||
|
jest.restoreAllMocks(); |
||||
|
filesystem.remove(execPath); |
||||
|
}); |
||||
|
|
||||
|
describe('wall command', () => { |
||||
|
it('should print help correctly', async () => { |
||||
|
try { |
||||
|
await Wall.run(['-h']); |
||||
|
} catch {} |
||||
|
expect(consoleLogOutput).toMatchSnapshot(); |
||||
|
}); |
||||
|
|
||||
|
it('should error when no flag is used', async () => { |
||||
|
try { |
||||
|
await Wall.run(['cats']); |
||||
|
// eslint-disable-next-line unicorn/catch-error-name
|
||||
|
} catch (e) { |
||||
|
expect(e).toEqual(new Error('You must use at least one category flag')); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
it('should download wallpaper and console output', async () => { |
||||
|
try { |
||||
|
await Wall.run(['cats', '-g', '--no-spinner']); |
||||
|
// eslint-disable-next-line unicorn/catch-error-name
|
||||
|
} catch {} |
||||
|
const lastEdited = consoleLogOutput.map((item, idx, arr) => { |
||||
|
if (idx === arr.length - 1) { |
||||
|
return item.replace(/wallhaven-.*\.jpg/g, 'wallhaven-thing.jpg'); |
||||
|
} |
||||
|
return item; |
||||
|
}); |
||||
|
expect(lastEdited).toMatchSnapshot(); |
||||
|
const files = filesystem.list('.'); |
||||
|
expect(files && files[0]).toMatch(/wallhaven-.*/); |
||||
|
}); |
||||
|
|
||||
|
it('should download wallpaper and console output to specific file', async () => { |
||||
|
try { |
||||
|
await Wall.run(['cats', '-owall.jpg', '-g', '--no-spinner']); |
||||
|
// eslint-disable-next-line unicorn/catch-error-name
|
||||
|
} catch {} |
||||
|
expect(consoleLogOutput).toMatchSnapshot(); |
||||
|
const files = filesystem.list('.'); |
||||
|
expect(files && files[0]).toBe('wall.jpg'); |
||||
|
}); |
||||
|
|
||||
|
it('should print a warning when output exists', async () => { |
||||
|
expect.assertions(4); |
||||
|
filesystem.write('wall.jpg', { name: 'hello' }); |
||||
|
try { |
||||
|
await Wall.run(['cats', '-owall.jpg', '-g', '--no-spinner']); |
||||
|
// eslint-disable-next-line unicorn/catch-error-name
|
||||
|
} catch (e) { |
||||
|
expect(e).toEqual(new Error('The flag force was not set, aborting')); |
||||
|
} |
||||
|
expect(consoleLogOutput).toMatchSnapshot(); |
||||
|
const files = filesystem.list('.'); |
||||
|
expect(files && files[0]).toBe('wall.jpg'); |
||||
|
expect(filesystem.read('wall.jpg', 'json')).toStrictEqual({ name: 'hello' }); |
||||
|
}); |
||||
|
|
||||
|
it('should print a warning when output exists with the force flag', async () => { |
||||
|
expect.assertions(2); |
||||
|
filesystem.write('wall.jpg', {}); |
||||
|
try { |
||||
|
await Wall.run(['cats', '-owall.jpg', '-f', '-g', '--no-spinner']); |
||||
|
// eslint-disable-next-line unicorn/catch-error-name
|
||||
|
} catch {} |
||||
|
expect(consoleLogOutput).toMatchSnapshot(); |
||||
|
const files = filesystem.list('.'); |
||||
|
expect(files && files[0]).toBe('wall.jpg'); |
||||
|
}); |
||||
|
}); |
||||
@ -0,0 +1,85 @@ |
|||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP |
||||
|
|
||||
|
exports[`BaseAddCommand InitGit() should error when git.mail is missing 1`] = `[Error: Missing config key git.email for git commits]`; |
||||
|
|
||||
|
exports[`BaseAddCommand InitGit() should error when git.user is missing 1`] = `[Error: Missing config key git.user for git commits]`; |
||||
|
|
||||
|
exports[`BaseAddCommand InitGit() should error when no config for git is found 1`] = `[Error: Config not found. Tried to look for a .nbxrc, .nbxrc.json, .nbxrc.yaml, .nbxrc.yml, .nbxrc.js]`; |
||||
|
|
||||
|
exports[`BaseAddCommand InitGit() should error when no git in repository 1`] = `[Error: Could not set git config. Maybe the command was not run in a git repository.]`; |
||||
|
|
||||
|
exports[`BaseAddCommand InitGit() should error when the config is not full 1`] = `[Error: Missing config key git.user for git commits]`; |
||||
|
|
||||
|
exports[`BaseAddCommand InitGit() should error when the git repository is not clean 1`] = `[Error: There is unsaved changed in the git repository, aborting]`; |
||||
|
|
||||
|
exports[`BaseAddCommand addDependency should add the dependancy with git 1`] = ` |
||||
|
Array [ |
||||
|
"Adding chalk as a dependency", |
||||
|
"The step was done without any error.", |
||||
|
] |
||||
|
`; |
||||
|
|
||||
|
exports[`BaseAddCommand addDependency should add the dependancy without git 1`] = ` |
||||
|
Array [ |
||||
|
"Adding chalk as a dependency", |
||||
|
"The step was done without any error.", |
||||
|
] |
||||
|
`; |
||||
|
|
||||
|
exports[`BaseAddCommand addDependency should add the dependancy without git 2`] = ` |
||||
|
" M package.json |
||||
|
M yarn.lock |
||||
|
?? node_modules/ |
||||
|
" |
||||
|
`; |
||||
|
|
||||
|
exports[`BaseAddCommand addDevDependency should add the dependancy with git 1`] = ` |
||||
|
Array [ |
||||
|
"Adding chalk as a dev dependency", |
||||
|
"The step was done without any error.", |
||||
|
] |
||||
|
`; |
||||
|
|
||||
|
exports[`BaseAddCommand addDevDependency should add the dependancy without git 1`] = ` |
||||
|
Array [ |
||||
|
"Adding chalk as a dev dependency", |
||||
|
"The step was done without any error.", |
||||
|
] |
||||
|
`; |
||||
|
|
||||
|
exports[`BaseAddCommand addDevDependency should add the dependancy without git 2`] = ` |
||||
|
" M package.json |
||||
|
M yarn.lock |
||||
|
?? node_modules/ |
||||
|
" |
||||
|
`; |
||||
|
|
||||
|
exports[`BaseAddCommand gitAddUnstaged should add uncommited changes 1`] = ` |
||||
|
"A .nbxrc |
||||
|
A test.11.md |
||||
|
A test.12.md |
||||
|
A test.13.md |
||||
|
A test.14.md |
||||
|
A test.15.md |
||||
|
A test.21.md |
||||
|
A test.22.md |
||||
|
A test.23.md |
||||
|
A test.24.md |
||||
|
A test.25.md |
||||
|
A test.31.md |
||||
|
A test.32.md |
||||
|
A test.33.md |
||||
|
A test.34.md |
||||
|
A test.35.md |
||||
|
A test.41.md |
||||
|
A test.42.md |
||||
|
A test.43.md |
||||
|
A test.44.md |
||||
|
A test.45.md |
||||
|
A test.51.md |
||||
|
A test.52.md |
||||
|
A test.53.md |
||||
|
A test.54.md |
||||
|
A test.55.md |
||||
|
" |
||||
|
`; |
||||
@ -0,0 +1,113 @@ |
|||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP |
||||
|
|
||||
|
exports[`BaseCommand commands getConfig should throw an error when no config is found 1`] = `[Error: Config not found. Tried to look for a .nbxrc, .nbxrc.json, .nbxrc.yaml, .nbxrc.yml, .nbxrc.js]`; |
||||
|
|
||||
|
exports[`BaseCommand commands runWithSpinner should fail on error 1`] = ` |
||||
|
Array [ |
||||
|
"Should be good", |
||||
|
"FAILED !!!", |
||||
|
] |
||||
|
`; |
||||
|
|
||||
|
exports[`BaseCommand commands runWithSpinner should not double success 1`] = ` |
||||
|
Array [ |
||||
|
"Should be good", |
||||
|
"Yay, done.", |
||||
|
] |
||||
|
`; |
||||
|
|
||||
|
exports[`BaseCommand commands runWithSpinner should return the function value 1`] = ` |
||||
|
Array [ |
||||
|
"Should be good", |
||||
|
"Yay, done.", |
||||
|
] |
||||
|
`; |
||||
|
|
||||
|
exports[`BaseCommand commands runWithSpinner should success automatically 1`] = ` |
||||
|
Array [ |
||||
|
"Should be good", |
||||
|
"The step was done without any error.", |
||||
|
] |
||||
|
`; |
||||
|
|
||||
|
exports[`BaseCommand flags help should be set to h 1`] = ` |
||||
|
Array [ |
||||
|
"USAGE |
||||
|
$ nbx [FIRSTARG] [SECONDARG] |
||||
|
|
||||
|
OPTIONS |
||||
|
-h, --help show CLI help |
||||
|
-v, --verbose Verbose output |
||||
|
--[no-]spinner Enable spinner in cli output, true by default", |
||||
|
"", |
||||
|
] |
||||
|
`; |
||||
|
|
||||
|
exports[`BaseCommand flags help should be set to help 1`] = ` |
||||
|
Array [ |
||||
|
"USAGE |
||||
|
$ nbx [FIRSTARG] [SECONDARG] |
||||
|
|
||||
|
OPTIONS |
||||
|
-h, --help show CLI help |
||||
|
-v, --verbose Verbose output |
||||
|
--[no-]spinner Enable spinner in cli output, true by default", |
||||
|
"", |
||||
|
] |
||||
|
`; |
||||
|
|
||||
|
exports[`BaseCommand flags verbose should print args when run 1`] = ` |
||||
|
Array [ |
||||
|
"vvv -----[ args ]----- vvv", |
||||
|
Object { |
||||
|
"firstArg": "firstArg", |
||||
|
"secondArg": "secondArg", |
||||
|
}, |
||||
|
"^^^ -----[ args ]----- ^^^", |
||||
|
"vvv -----[ argv ]----- vvv", |
||||
|
Array [ |
||||
|
"firstArg", |
||||
|
"secondArg", |
||||
|
], |
||||
|
"^^^ -----[ argv ]----- ^^^", |
||||
|
"vvv -----[ flags ]----- vvv", |
||||
|
Object { |
||||
|
"spinner": true, |
||||
|
"verbose": true, |
||||
|
}, |
||||
|
"^^^ -----[ flags ]----- ^^^", |
||||
|
"vvv -----[ SAMPLE ]----- vvv", |
||||
|
Object { |
||||
|
"code": "aaaa", |
||||
|
}, |
||||
|
"^^^ -----[ SAMPLE ]----- ^^^", |
||||
|
] |
||||
|
`; |
||||
|
|
||||
|
exports[`MyNoSpinner should display the start message 1`] = ` |
||||
|
Array [ |
||||
|
"hello from the spinner", |
||||
|
] |
||||
|
`; |
||||
|
|
||||
|
exports[`MyNoSpinner should display the start message and fail message 1`] = ` |
||||
|
Array [ |
||||
|
"hello from the spinner", |
||||
|
"FAIL", |
||||
|
] |
||||
|
`; |
||||
|
|
||||
|
exports[`MyNoSpinner should display the start message and success message 1`] = ` |
||||
|
Array [ |
||||
|
"hello from the spinner", |
||||
|
"SUCCESS", |
||||
|
] |
||||
|
`; |
||||
|
|
||||
|
exports[`MyNoSpinner should display the start message and success message 2`] = ` |
||||
|
Array [ |
||||
|
"hello from the spinner", |
||||
|
"WARNING", |
||||
|
"SUCCESS", |
||||
|
] |
||||
|
`; |
||||
@ -0,0 +1,353 @@ |
|||||
|
import { BaseAddCommand } from './base-add-command'; |
||||
|
import { filesystem, system } from 'gluegun'; |
||||
|
import * as latestVersion from 'latest-version'; |
||||
|
const stripANSI = require('strip-ansi'); |
||||
|
import { flags } from '@oclif/command'; |
||||
|
|
||||
|
/* eslint-disable no-console,max-nested-callbacks,@typescript-eslint/ban-ts-ignore */ |
||||
|
let consoleLogOutput: string[]; |
||||
|
let execPath: string; |
||||
|
const originalCwd = process.cwd(); |
||||
|
const originalLog = console.log; |
||||
|
|
||||
|
beforeEach(() => { |
||||
|
consoleLogOutput = []; |
||||
|
console.log = (x: any) => consoleLogOutput.push(stripANSI(x)); |
||||
|
|
||||
|
const tmpDirName = `${new Date().getTime()}-add-nbx-test`; |
||||
|
execPath = filesystem.path('/', 'tmp', tmpDirName); |
||||
|
filesystem.dir(execPath); |
||||
|
process.chdir(execPath); |
||||
|
}); |
||||
|
afterEach(() => { |
||||
|
console.log = originalLog; |
||||
|
process.chdir(originalCwd); |
||||
|
jest.restoreAllMocks(); |
||||
|
filesystem.remove(execPath); |
||||
|
}); |
||||
|
|
||||
|
class RunCommand extends BaseAddCommand { |
||||
|
static flags = { |
||||
|
...BaseAddCommand.flags, |
||||
|
opt: flags.boolean({ default: false }), |
||||
|
}; |
||||
|
|
||||
|
static args = [{ name: 'command', required: true }, { name: 'arg' }]; |
||||
|
|
||||
|
async run() { |
||||
|
const { |
||||
|
args: { command, arg }, |
||||
|
flags: { opt }, |
||||
|
} = this.parse(RunCommand); |
||||
|
if (opt) { |
||||
|
// @ts-ignore
|
||||
|
return this[command](arg, opt); |
||||
|
} |
||||
|
// @ts-ignore
|
||||
|
return this[command](arg, false); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
const initWithConfigAndCommit = async () => { |
||||
|
await system.run('git init'); |
||||
|
filesystem.write('.nbxrc', { git: { user: 'aaa', email: 'bbb' } }); |
||||
|
filesystem.write('package.json', {}); |
||||
|
await system.run('touch yarn.lock'); |
||||
|
await system.run('git add * .nbxrc'); |
||||
|
await system.run('git commit -m "init state"'); |
||||
|
}; |
||||
|
|
||||
|
describe('BaseAddCommand', () => { |
||||
|
describe('InitGit()', () => { |
||||
|
it('should error when no config for git is found', async () => { |
||||
|
expect.assertions(1); |
||||
|
try { |
||||
|
await RunCommand.run(['initGit']); |
||||
|
// eslint-disable-next-line unicorn/catch-error-name
|
||||
|
} catch (e) { |
||||
|
expect(e).toMatchSnapshot(); |
||||
|
} |
||||
|
}); |
||||
|
it('should error when the config is not full', async () => { |
||||
|
expect.assertions(1); |
||||
|
try { |
||||
|
filesystem.write('.nbxrc', { toto: 'aaa ' }); |
||||
|
await RunCommand.run(['initGit']); |
||||
|
// eslint-disable-next-line unicorn/catch-error-name
|
||||
|
} catch (e) { |
||||
|
expect(e).toMatchSnapshot(); |
||||
|
} |
||||
|
}); |
||||
|
it('should error when git.user is missing', async () => { |
||||
|
expect.assertions(1); |
||||
|
try { |
||||
|
filesystem.write('.nbxrc', { git: { email: 'aaa' } }); |
||||
|
await RunCommand.run(['initGit']); |
||||
|
// eslint-disable-next-line unicorn/catch-error-name
|
||||
|
} catch (e) { |
||||
|
expect(e).toMatchSnapshot(); |
||||
|
} |
||||
|
}); |
||||
|
it('should error when git.mail is missing', async () => { |
||||
|
expect.assertions(1); |
||||
|
try { |
||||
|
filesystem.write('.nbxrc', { git: { user: 'aaa' } }); |
||||
|
await RunCommand.run(['initGit']); |
||||
|
// eslint-disable-next-line unicorn/catch-error-name
|
||||
|
} catch (e) { |
||||
|
expect(e).toMatchSnapshot(); |
||||
|
} |
||||
|
}); |
||||
|
it('should error when no git in repository', async () => { |
||||
|
expect.assertions(1); |
||||
|
try { |
||||
|
filesystem.write('.nbxrc', { git: { user: 'aaa', email: 'bbb' } }); |
||||
|
await RunCommand.run(['initGit']); |
||||
|
// eslint-disable-next-line unicorn/catch-error-name
|
||||
|
} catch (e) { |
||||
|
expect(e).toMatchSnapshot(); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
const actions = [ |
||||
|
{ |
||||
|
name: 'added uncomited file', |
||||
|
actions: ['touch test.md'], |
||||
|
}, |
||||
|
{ |
||||
|
name: 'added file, not commited', |
||||
|
actions: ['touch test.md', 'git add test.md', 'git add .nbxrc'], |
||||
|
}, |
||||
|
{ |
||||
|
name: 'edited commited files', |
||||
|
actions: [ |
||||
|
'touch test.md', |
||||
|
'git add test.md', |
||||
|
'git add .nbxrc', |
||||
|
'git commit -m "test commit"', |
||||
|
'echo hello > test.md', |
||||
|
], |
||||
|
}, |
||||
|
{ |
||||
|
name: 'deleted commited file', |
||||
|
actions: [ |
||||
|
'touch test.md', |
||||
|
'git add test.md', |
||||
|
'git add .nbxrc', |
||||
|
'git commit -m "test commit"', |
||||
|
'rm -f test.md', |
||||
|
], |
||||
|
}, |
||||
|
]; |
||||
|
|
||||
|
for (const action of actions) { |
||||
|
it(`should erro when ${action.name}`, async () => { |
||||
|
filesystem.write('.nbxrc', { git: { user: 'aaa', email: 'bbb' } }); |
||||
|
await system.run('git init'); |
||||
|
for (const step of action.actions) { |
||||
|
// eslint-disable-next-line no-await-in-loop
|
||||
|
await system.run(step); |
||||
|
} |
||||
|
|
||||
|
expect.assertions(1); |
||||
|
try { |
||||
|
await RunCommand.run(['initGit']); |
||||
|
// eslint-disable-next-line unicorn/catch-error-name
|
||||
|
} catch (e) { |
||||
|
expect(e).toEqual(new Error('There is unsaved changed in the git repository, aborting')); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
it('should error when the git repository is not clean', async () => { |
||||
|
await system.run('git init'); |
||||
|
await system.run('touch test.md'); |
||||
|
expect.assertions(1); |
||||
|
try { |
||||
|
filesystem.write('.nbxrc', { git: { user: 'aaa', email: 'bbb' } }); |
||||
|
await RunCommand.run(['initGit']); |
||||
|
// eslint-disable-next-line unicorn/catch-error-name
|
||||
|
} catch (e) { |
||||
|
expect(e).toMatchSnapshot(); |
||||
|
} |
||||
|
}); |
||||
|
it('should work on a clean git repository', async () => { |
||||
|
filesystem.write('.nbxrc', { git: { user: 'aaa', email: 'bbb' } }); |
||||
|
await system.run('git init'); |
||||
|
await system.run('git add .nbxrc'); |
||||
|
await system.run('pwd'); |
||||
|
await system.run('git commit -m "initial commit"'); |
||||
|
await system.run('git status'); |
||||
|
await RunCommand.run(['initGit']); |
||||
|
const gitConfig = filesystem.read('.git/config'); |
||||
|
expect(gitConfig).toBeDefined(); |
||||
|
const gitConfigLines = gitConfig?.split('\n')?.map(value => value.trim()); |
||||
|
expect(gitConfigLines).toContainEqual('email = bbb'); |
||||
|
expect(gitConfigLines).toContainEqual('name = aaa'); |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
describe('hasDirPackageJson', () => { |
||||
|
it('should return false if no packageJson is in the path', async () => { |
||||
|
const result = await RunCommand.run(['hasDirPackageJson']); |
||||
|
expect(result).toBeFalsy(); |
||||
|
}); |
||||
|
it('should return true if no packageJson is in the path', async () => { |
||||
|
filesystem.write('package.json', {}); |
||||
|
const result = await RunCommand.run(['hasDirPackageJson']); |
||||
|
expect(result).toBeTruthy(); |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
describe('hasDependencyInPackageJson', () => { |
||||
|
it('should return false if no packageJson is in the path', async () => { |
||||
|
const result = await RunCommand.run(['hasDependencyInPackageJson', 'testDep']); |
||||
|
expect(result).toBeFalsy(); |
||||
|
}); |
||||
|
it('should return false if the dependencies is not in package json', async () => { |
||||
|
filesystem.write('package.json', { dependencies: {} }); |
||||
|
const result = await RunCommand.run(['hasDependencyInPackageJson', 'testDep']); |
||||
|
expect(result).toBeFalsy(); |
||||
|
}); |
||||
|
it('should return false if there is no dependencies in package json', async () => { |
||||
|
filesystem.write('package.json', {}); |
||||
|
const result = await RunCommand.run(['hasDependencyInPackageJson', 'testDep']); |
||||
|
expect(result).toBeFalsy(); |
||||
|
}); |
||||
|
it('should return true if no packageJson is in the path', async () => { |
||||
|
filesystem.write('package.json', { dependencies: { testDep: 'v1.0.0' } }); |
||||
|
const result = await RunCommand.run(['hasDependencyInPackageJson', 'testDep']); |
||||
|
expect(result).toBeTruthy(); |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
describe('hasDevDependencyInPackageJson', () => { |
||||
|
it('should return false if no packageJson is in the path', async () => { |
||||
|
const result = await RunCommand.run(['hasDevDependencyInPackageJson', 'testDep']); |
||||
|
expect(result).toBeFalsy(); |
||||
|
}); |
||||
|
it('should return false if the dependencies is not in package json', async () => { |
||||
|
filesystem.write('package.json', { devDependencies: {} }); |
||||
|
const result = await RunCommand.run(['hasDevDependencyInPackageJson', 'testDep']); |
||||
|
expect(result).toBeFalsy(); |
||||
|
}); |
||||
|
it('should return false if there is no dependencies in package json', async () => { |
||||
|
filesystem.write('package.json', {}); |
||||
|
const result = await RunCommand.run(['hasDevDependencyInPackageJson', 'testDep']); |
||||
|
expect(result).toBeFalsy(); |
||||
|
}); |
||||
|
it('should return true if no packageJson is in the path', async () => { |
||||
|
filesystem.write('package.json', { devDependencies: { testDep: 'v1.0.0' } }); |
||||
|
const result = await RunCommand.run(['hasDevDependencyInPackageJson', 'testDep']); |
||||
|
expect(result).toBeTruthy(); |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
describe('gitAddUnstaged', () => { |
||||
|
it('should do nothing if nothing has to be done', async () => { |
||||
|
await system.run('git init'); |
||||
|
filesystem.write('.nbxrc', { git: { user: 'aaa', email: 'bbb' } }); |
||||
|
await system.run('touch test.md'); |
||||
|
await system.run('git add * .nbxrc'); |
||||
|
await system.run('git commit -m "test"'); |
||||
|
const before = await system.run('git status -s'); |
||||
|
|
||||
|
await RunCommand.run(['gitAddUnstaged']); |
||||
|
|
||||
|
const after = await system.run('git status -s'); |
||||
|
expect(before).toBe(after); |
||||
|
}); |
||||
|
it('should add uncommited changes', async () => { |
||||
|
await system.run('git init'); |
||||
|
filesystem.write('.nbxrc', { git: { user: 'aaa', email: 'bbb' } }); |
||||
|
await system.run('touch test.{1,2,3,4,5}{1,2,3,4,5}.md'); |
||||
|
|
||||
|
await RunCommand.run(['gitAddUnstaged']); |
||||
|
|
||||
|
const after = await system.run('git status -s'); |
||||
|
expect(after).toMatchSnapshot(); |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
describe('addDevDependency', () => { |
||||
|
it('should add the dependancy with git', async () => { |
||||
|
await initWithConfigAndCommit(); |
||||
|
|
||||
|
const chalkLatest = await latestVersion('chalk'); |
||||
|
|
||||
|
await RunCommand.run(['initGit']); |
||||
|
await RunCommand.run(['addDevDependency', 'chalk', '--opt', '--no-spinner']); |
||||
|
|
||||
|
const after = await system.run('git log --name-status --format="%s" -1'); |
||||
|
const afterSlitted = after |
||||
|
.split('\n') |
||||
|
.map(val => val.trim()) |
||||
|
.map(val => stripANSI(val)) |
||||
|
.filter(val => val !== ''); |
||||
|
const packageJsonFinal = filesystem.read('package.json', 'json'); |
||||
|
|
||||
|
expect(consoleLogOutput).toMatchSnapshot(); |
||||
|
expect(packageJsonFinal).toStrictEqual({ devDependencies: { chalk: chalkLatest } }); |
||||
|
expect(afterSlitted[0]).toBe( |
||||
|
`:heavy_plus_sign: add chalk@${chalkLatest} as a dev dependency`, |
||||
|
); |
||||
|
expect(afterSlitted[1]).toMatch(/package\.json$/); |
||||
|
expect(afterSlitted[2]).toMatch(/yarn\.lock$/); |
||||
|
}); |
||||
|
|
||||
|
it('should add the dependancy without git', async () => { |
||||
|
await initWithConfigAndCommit(); |
||||
|
|
||||
|
const chalkLatest = await latestVersion('chalk'); |
||||
|
|
||||
|
await RunCommand.run(['initGit']); |
||||
|
await RunCommand.run(['addDevDependency', 'chalk', '--no-spinner']); |
||||
|
|
||||
|
const after = await system.run('git status --short'); |
||||
|
const packageJsonFinal = filesystem.read('package.json', 'json'); |
||||
|
|
||||
|
expect(consoleLogOutput).toMatchSnapshot(); |
||||
|
expect(packageJsonFinal).toStrictEqual({ devDependencies: { chalk: chalkLatest } }); |
||||
|
expect(after).toMatchSnapshot(); |
||||
|
}); |
||||
|
}); |
||||
|
describe('addDependency', () => { |
||||
|
it('should add the dependancy with git', async () => { |
||||
|
await initWithConfigAndCommit(); |
||||
|
|
||||
|
const chalkLatest = await latestVersion('chalk'); |
||||
|
|
||||
|
await RunCommand.run(['initGit']); |
||||
|
await RunCommand.run(['addDependency', 'chalk', '--opt', '--no-spinner']); |
||||
|
|
||||
|
const after = await system.run('git log --name-status --format="%s" -1'); |
||||
|
const afterSlitted = after |
||||
|
.split('\n') |
||||
|
.map(val => val.trim()) |
||||
|
.map(val => stripANSI(val)) |
||||
|
.filter(val => val !== ''); |
||||
|
const packageJsonFinal = filesystem.read('package.json', 'json'); |
||||
|
|
||||
|
expect(consoleLogOutput).toMatchSnapshot(); |
||||
|
expect(packageJsonFinal).toStrictEqual({ dependencies: { chalk: chalkLatest } }); |
||||
|
expect(afterSlitted[0]).toBe(`:heavy_plus_sign: add chalk@${chalkLatest} as a dependency`); |
||||
|
expect(afterSlitted[1]).toMatch(/package\.json$/); |
||||
|
expect(afterSlitted[2]).toMatch(/yarn\.lock$/); |
||||
|
}); |
||||
|
|
||||
|
it('should add the dependancy without git', async () => { |
||||
|
await initWithConfigAndCommit(); |
||||
|
|
||||
|
const chalkLatest = await latestVersion('chalk'); |
||||
|
|
||||
|
await RunCommand.run(['initGit']); |
||||
|
await RunCommand.run(['addDependency', 'chalk', '--no-spinner']); |
||||
|
|
||||
|
const after = await system.run('git status --short'); |
||||
|
const packageJsonFinal = filesystem.read('package.json', 'json'); |
||||
|
|
||||
|
expect(consoleLogOutput).toMatchSnapshot(); |
||||
|
expect(packageJsonFinal).toStrictEqual({ dependencies: { chalk: chalkLatest } }); |
||||
|
expect(after).toMatchSnapshot(); |
||||
|
}); |
||||
|
}); |
||||
|
}); |
||||
@ -0,0 +1,255 @@ |
|||||
|
import { BaseCommand, MyNoSpinner } from './base-command'; |
||||
|
import { filesystem } from 'gluegun'; |
||||
|
const stripANSI = require('strip-ansi'); |
||||
|
/* eslint-disable no-console,max-nested-callbacks */ |
||||
|
|
||||
|
let consoleLogOutput: string[]; |
||||
|
const originalLog = console.log; |
||||
|
const originalCwd = process.cwd(); |
||||
|
|
||||
|
beforeEach(() => { |
||||
|
consoleLogOutput = []; |
||||
|
console.log = (x: any) => consoleLogOutput.push(stripANSI(x)); |
||||
|
}); |
||||
|
afterEach(() => { |
||||
|
console.log = originalLog; |
||||
|
process.chdir(originalCwd); |
||||
|
jest.restoreAllMocks(); |
||||
|
}); |
||||
|
|
||||
|
describe('MyNoSpinner', () => { |
||||
|
it('should start with a spinning state', () => { |
||||
|
const spinner = new MyNoSpinner('AA'); |
||||
|
|
||||
|
expect(spinner.isSpinning).toBeTruthy(); |
||||
|
}); |
||||
|
|
||||
|
it('should display the start message', () => { |
||||
|
const message = 'hello from the spinner'; |
||||
|
// eslint-disable-next-line no-new
|
||||
|
new MyNoSpinner(message); |
||||
|
|
||||
|
expect(consoleLogOutput).toMatchSnapshot(); |
||||
|
}); |
||||
|
|
||||
|
it('should display the start message and success message', () => { |
||||
|
const message = 'hello from the spinner'; |
||||
|
const spinner = new MyNoSpinner(message); |
||||
|
spinner.succeed('SUCCESS'); |
||||
|
expect(spinner.isSpinning).toBeFalsy(); |
||||
|
|
||||
|
expect(consoleLogOutput).toMatchSnapshot(); |
||||
|
}); |
||||
|
|
||||
|
it('should display the start message and fail message', () => { |
||||
|
const message = 'hello from the spinner'; |
||||
|
const spinner = new MyNoSpinner(message); |
||||
|
spinner.fail('FAIL'); |
||||
|
expect(spinner.isSpinning).toBeFalsy(); |
||||
|
|
||||
|
expect(consoleLogOutput).toMatchSnapshot(); |
||||
|
}); |
||||
|
|
||||
|
it('should display the start message and success message', () => { |
||||
|
const message = 'hello from the spinner'; |
||||
|
const spinner = new MyNoSpinner(message); |
||||
|
spinner.warn('WARNING'); |
||||
|
expect(spinner.isSpinning).toBeTruthy(); |
||||
|
spinner.succeed('SUCCESS'); |
||||
|
expect(spinner.isSpinning).toBeFalsy(); |
||||
|
|
||||
|
expect(consoleLogOutput).toMatchSnapshot(); |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
class SampleCommand extends BaseCommand { |
||||
|
static flags = { |
||||
|
...BaseCommand.flags, |
||||
|
}; |
||||
|
|
||||
|
static args = [{ name: 'firstArg' }, { name: 'secondArg' }]; |
||||
|
|
||||
|
async run() { |
||||
|
this.vprint({ code: 'aaaa' }, 'SAMPLE'); |
||||
|
return 'hello'; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
class ConfigCommand extends BaseCommand { |
||||
|
static flags = { |
||||
|
...BaseCommand.flags, |
||||
|
}; |
||||
|
|
||||
|
async run() { |
||||
|
return this.getConfig(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
describe('BaseCommand', () => { |
||||
|
describe('flags', () => { |
||||
|
describe('verbose', () => { |
||||
|
it('should print args when run', async () => { |
||||
|
await SampleCommand.run(['-v', 'firstArg', 'secondArg']); |
||||
|
expect(consoleLogOutput).toMatchSnapshot(); |
||||
|
}); |
||||
|
it('should not print args when run', async () => { |
||||
|
await SampleCommand.run(['firstArg', 'secondArg']); |
||||
|
expect(consoleLogOutput).toHaveLength(0); |
||||
|
}); |
||||
|
}); |
||||
|
describe('spinner', () => { |
||||
|
it('should be enable by default', async () => { |
||||
|
await SampleCommand.run(['-v']); |
||||
|
expect(consoleLogOutput).toContainEqual({ verbose: true, spinner: true }); |
||||
|
}); |
||||
|
it('can be disabled', async () => { |
||||
|
await SampleCommand.run(['-v', '--no-spinner']); |
||||
|
expect(consoleLogOutput).toContainEqual({ verbose: true, spinner: false }); |
||||
|
}); |
||||
|
}); |
||||
|
describe('help', () => { |
||||
|
it('should be set to h', async () => { |
||||
|
try { |
||||
|
await SampleCommand.run(['-h']); |
||||
|
} catch {} |
||||
|
expect(consoleLogOutput).toMatchSnapshot(); |
||||
|
}); |
||||
|
it('should be set to help', async () => { |
||||
|
try { |
||||
|
await SampleCommand.run(['--help']); |
||||
|
} catch {} |
||||
|
expect(consoleLogOutput).toMatchSnapshot(); |
||||
|
}); |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
describe('commands', () => { |
||||
|
describe('getConfig', () => { |
||||
|
it('should throw an error when no config is found', async () => { |
||||
|
expect.assertions(1); |
||||
|
try { |
||||
|
process.chdir('/'); |
||||
|
await ConfigCommand.run([]); |
||||
|
// eslint-disable-next-line unicorn/catch-error-name
|
||||
|
} catch (e) { |
||||
|
expect(e).toMatchSnapshot(); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
for (const jsonConfigFileName of ['.nbxrc', '.nbxrc.json']) { |
||||
|
it(`should find configuration in the same folder with the name ${jsonConfigFileName}`, async () => { |
||||
|
expect.assertions(1); |
||||
|
const config = { git: { user: 'AAAA', email: 'BBBB' } }; |
||||
|
const tmpDirName = `${new Date().getTime()}-base-nbx-test`; |
||||
|
const execPath = filesystem.path('/', 'tmp', tmpDirName); |
||||
|
filesystem.dir(execPath); |
||||
|
const path = filesystem.path(execPath, jsonConfigFileName); |
||||
|
filesystem.write(path, config); |
||||
|
|
||||
|
process.chdir(execPath); |
||||
|
try { |
||||
|
const value = await ConfigCommand.run([]); |
||||
|
expect(value).toStrictEqual({ config, path }); |
||||
|
} finally { |
||||
|
filesystem.remove(path); |
||||
|
filesystem.remove(execPath); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
}); |
||||
|
describe('runWithSpinner', () => { |
||||
|
it('should success automatically', async () => { |
||||
|
class SpinnerSuccessCommand extends BaseCommand { |
||||
|
static flags = { |
||||
|
...BaseCommand.flags, |
||||
|
}; |
||||
|
|
||||
|
async run() { |
||||
|
await this.runWithSpinner('Should be good', async () => { |
||||
|
return ''; |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
await SpinnerSuccessCommand.run(['--no-spinner']); |
||||
|
|
||||
|
expect(consoleLogOutput).toMatchSnapshot(); |
||||
|
}); |
||||
|
it('should not double success', async () => { |
||||
|
class SpinnerSuccessCommand extends BaseCommand { |
||||
|
static flags = { |
||||
|
...BaseCommand.flags, |
||||
|
}; |
||||
|
|
||||
|
async run() { |
||||
|
await this.runWithSpinner('Should be good', async spinner => { |
||||
|
spinner.succeed('Yay, done.'); |
||||
|
return ''; |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
await SpinnerSuccessCommand.run(['--no-spinner']); |
||||
|
|
||||
|
expect(consoleLogOutput).toMatchSnapshot(); |
||||
|
}); |
||||
|
it('should fail on error', async () => { |
||||
|
class SpinnerSuccessCommand extends BaseCommand { |
||||
|
static flags = { |
||||
|
...BaseCommand.flags, |
||||
|
}; |
||||
|
|
||||
|
async run() { |
||||
|
try { |
||||
|
await this.runWithSpinner('Should be good', async () => { |
||||
|
throw new Error('FAILED !!!'); |
||||
|
}); |
||||
|
} finally { |
||||
|
// eslint-disable-next-line no-unsafe-finally
|
||||
|
return 'done'; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
try { |
||||
|
await SpinnerSuccessCommand.run(['--no-spinner']); |
||||
|
} finally { |
||||
|
expect(consoleLogOutput).toMatchSnapshot(); |
||||
|
} |
||||
|
}); |
||||
|
it('should run default spinner without flag', async () => { |
||||
|
class SpinnerSuccessCommand extends BaseCommand { |
||||
|
static flags = { |
||||
|
...BaseCommand.flags, |
||||
|
}; |
||||
|
|
||||
|
async run() { |
||||
|
await this.runWithSpinner('Should be good', async () => { |
||||
|
return ''; |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
try { |
||||
|
await SpinnerSuccessCommand.run([]); |
||||
|
} finally { |
||||
|
expect(consoleLogOutput).toHaveLength(0); |
||||
|
} |
||||
|
}); |
||||
|
it('should return the function value', async () => { |
||||
|
class SpinnerSuccessCommand extends BaseCommand { |
||||
|
static flags = { |
||||
|
...BaseCommand.flags, |
||||
|
}; |
||||
|
|
||||
|
async run() { |
||||
|
const ret = await this.runWithSpinner('Should be good', async spinner => { |
||||
|
spinner.succeed('Yay, done.'); |
||||
|
return 'DONE'; |
||||
|
}); |
||||
|
expect(ret).toEqual('DONE'); |
||||
|
} |
||||
|
} |
||||
|
await SpinnerSuccessCommand.run(['--no-spinner']); |
||||
|
|
||||
|
expect(consoleLogOutput).toMatchSnapshot(); |
||||
|
}); |
||||
|
}); |
||||
|
}); |
||||
|
}); |
||||
2935
yarn.lock
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
Write
Preview
Loading…
Cancel
Save
Reference in new issue