Skip to content

Commit

Permalink
Print welcome messages, start test
Browse files Browse the repository at this point in the history
  • Loading branch information
Stephen Hanson committed Oct 30, 2023
1 parent 8fb926a commit 1a101ca
Show file tree
Hide file tree
Showing 14 changed files with 100 additions and 24 deletions.
5 changes: 5 additions & 0 deletions __mocks__/child_process.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { vi } from 'vitest';

export const spawnSync = vi.fn();
export const execSync = vi.fn();
export const exec = vi.fn();
3 changes: 3 additions & 0 deletions __mocks__/fs-extra.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import actualfs from 'fs-extra';
import { fs } from 'memfs';
import { vi } from 'vitest';

const DONT_MOCK_PATTERNS = ['templates/'];

export default {
...fs.promises,
// todo: build actual mock
copySync: vi.fn(),
exists(path) {
return new Promise((resolve) => {
fs.exists(path, (exists) => resolve(exists));
Expand Down
3 changes: 3 additions & 0 deletions __mocks__/process.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default {
chdir: vi.fn(),
};
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
"lint:prettier": "prettier --check '**/*' --ignore-unknown",
"lint:types": "tsc",
"fix:prettier": "prettier --write '**/*' --ignore-unknown",
"test": "vitest watch",
"test:run": "test run",
"test": "vitest",
"test:run": "vitest run",
"test:all": "yarn lint && yarn test:run"
},
"bin": {
Expand Down Expand Up @@ -51,7 +51,8 @@
"src/commands/templates",
"__mocks__/**/*.js",
"bin/belt.js",
"/build"
"/build",
"vitest.setup.js"
],
"rules": {
"no-console": "off",
Expand Down
12 changes: 9 additions & 3 deletions src/cli.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,26 @@
import { program } from 'commander';
import buildAction from './util/buildAction';
import printWelcome from './util/print/printWelcome';

export default function runCli() {
program
.name('thoughtbelt')
.description(
'Perform React Native and Expo setup and redundant tasks without your pants falling down!',
)
.showHelpAfterError();

program
.command('create', { isDefault: true })
.description('Create new app')
.argument(
'appName',
'[appName]',
'The name of the app and directory it will be created in',
'',
)
.action(buildAction(import('./commands/createApp')))
.action(buildAction(import('./commands/createApp')));

program
.command('eslint')
.description('Configure ESLint')
.action(buildAction(import('./commands/eslint')));
Expand All @@ -30,7 +35,8 @@ export default function runCli() {
.description('Install and configure TypeScript')
.action(buildAction(import('./commands/typescript')));

program.showHelpAfterError().parse();
printWelcome();
program.parse();
}

runCli();
27 changes: 27 additions & 0 deletions src/commands/__tests__/createApp.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { confirm } from '@inquirer/prompts';
import { vol } from 'memfs';
import { Mock, afterEach, test, vi } from 'vitest';
import print from '../../util/print';
import { createApp } from '../createApp';

vi.mock('@inquirer/prompts', () => ({
confirm: vi.fn(),
}));
vi.mock('../../util/addDependency');
vi.mock('../../util/print', () => ({ default: vi.fn() }));

afterEach(() => {
vol.reset();
(print as Mock).mockReset();
});

test("doesn't error", async () => {
(confirm as Mock).mockResolvedValueOnce(true);
vi.spyOn(process, 'chdir').mockImplementation(() => {
const json = {
'package.json': '{ "dependencies": {}, "devDependencies": {} }',
};
vol.fromJSON(json, './');
});
await createApp('MyApp');
});
6 changes: 1 addition & 5 deletions src/commands/__tests__/typescript.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,8 @@ import addDependency from '../../util/addDependency';
import print from '../../util/print';
import addTypescript from '../typescript';

vi.mock('fs-extra');
vi.mock('../../util/addDependency');
vi.mock('../../util/print', () => ({
// __esModule: true,
default: vi.fn(),
}));
vi.mock('../../util/print', () => ({ default: vi.fn() }));

afterEach(() => {
vol.reset();
Expand Down
25 changes: 19 additions & 6 deletions src/commands/createApp.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,20 @@
import { input } from '@inquirer/prompts';
import { confirm, input } from '@inquirer/prompts';
import { execSync, spawnSync } from 'child_process';
import createScaffold from './createScaffold';
import print from '../util/print';
import addEslint from './eslint';
import createScaffold from './scaffold';
import addTypescript from './typescript';

export async function createApp(name: string | undefined) {
const appName = name || (await getAppName());
await printIntro();

spawnSync('npx', ['--yes', 'create-expo-app@latest', appName], {
stdio: 'inherit',
});

process.chdir(`./${appName}`);

execSync('git init');
execSync('git add .');
execSync('git commit -m "Initial commit"');

await addTypescript();
execSync('git add .');
execSync('git commit -m "Add TypeScript"');
Expand Down Expand Up @@ -45,3 +43,18 @@ export default function createAppAction(...args: unknown[]) {
const appNameArg = (args[0] as string[])[0];
return createApp(appNameArg);
}

async function printIntro() {
print('👖 Let’s get started!');
print(`\nWe will now perform the following tasks:
- Create a new app using the latest create-expo-app
- Add and configure TypeScript
- Add and configure ESLint
- Add and configure Prettier
- Create the project directory structure
`);

if (!(await confirm({ message: 'Ready to proceed?' }))) {
process.exit(0);
}
}
6 changes: 3 additions & 3 deletions src/commands/eslint.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import chalk from 'chalk';
import { log } from 'console';
import * as eta from 'eta';
import fs from 'fs-extra';
import path from 'path';
Expand All @@ -8,6 +7,7 @@ import addDependency from '../util/addDependency';
import getProjectDir from '../util/getProjectDir';
import isEslintConfigured from '../util/isEslintConfigured';
import isPackageInstalled from '../util/isPackageInstalled';
import print from '../util/print';
import writeFile from '../util/writeFile';

const dirname = fileURLToPath(new URL('.', import.meta.url));
Expand All @@ -16,7 +16,7 @@ export default async function addEslint() {
const projectDir = await getProjectDir();

if (await isEslintConfigured()) {
log('eslint config already exists');
print('eslint config already exists');
} else {
const hasTypeScript = await isPackageInstalled('typescript');

Expand All @@ -34,6 +34,6 @@ export default async function addEslint() {

await addDependency('@thoughtbot/eslint-config', { dev: true });

log(chalk.green('🎉 ESLint successfully configured'));
print(chalk.green('🎉 ESLint successfully configured'));
}
}
8 changes: 4 additions & 4 deletions src/commands/createScaffold.ts → src/commands/scaffold.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import chalk from 'chalk';
import { log } from 'console';
import fs from 'fs-extra';
import path from 'path';
import { URL, fileURLToPath } from 'url';
import print from '../util/print';

const dirname = fileURLToPath(new URL('.', import.meta.url));

export default async function createScaffold() {
console.log(chalk.bold('👖 Creating directory structure'));
console.log(`
print(chalk.bold('👖 Creating directory structure'));
print(`
src/
components/
util/
hooks/
test/
`);
fs.copySync(path.join(dirname, 'templates', 'scaffold', 'src'), './src');
log('✅ Created directories');
print('✅ Created directories');
}
8 changes: 8 additions & 0 deletions src/util/print/__tests__/printWelcome.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { test, vi } from 'vitest';
import printWelcome from '../printWelcome';

vi.mock('../../print', () => ({ default: vi.fn() }));

test('doesnt error', () => {
printWelcome();
});
9 changes: 9 additions & 0 deletions src/util/print/printWelcome.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import chalk from 'chalk';
import print from '../print';

export default function printWelcome() {
print(chalk.bold('\n\n\t👖 thoughtbelt 👖\n'));
print(
'Perform project setup and redundant tasks\n without your pants falling down!\n\n',
);
}
1 change: 1 addition & 0 deletions vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ import { configDefaults, defineConfig } from 'vitest/config';
export default defineConfig({
test: {
exclude: [...configDefaults.exclude, 'build/**/*'],
setupFiles: ['./vitest.setup.js'],
},
});
4 changes: 4 additions & 0 deletions vitest.setup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { vi } from 'vitest';

vi.mock('child_process');
vi.mock('fs-extra');

0 comments on commit 1a101ca

Please sign in to comment.