Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add jest recipe #4

Merged
merged 7 commits into from
Jul 8, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 13 additions & 8 deletions src/commands/react-native-ci-cli.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { GluegunCommand } from 'gluegun'
import runLint from '../recipies/lint'
import { intro, outro } from '@clack/prompts'
import { SKIP_INTERACTIVE_COMMAND } from '../constants'
import runLint from '../recipies/lint'
import runJest from '../recipies/jest'

const command: GluegunCommand = {
name: 'react-native-ci-cli',
Expand All @@ -10,19 +11,18 @@ const command: GluegunCommand = {

if (toolbox.isGitDirty() == null) {
outro('This is not a git repository. Exiting.')

return
}

if (toolbox.isGitDirty() == true) {
outro('Please commit your changes before running this command. Exiting.')

return
}

const lintExecutor = await runLint(toolbox)
const jestExecutor = await runJest(toolbox)

const executors = [lintExecutor].filter(Boolean)
const executors = [lintExecutor, jestExecutor].filter(Boolean)

if (executors.length === 0) {
outro('Nothing to do here. Cheers! 🎉')
Expand All @@ -31,13 +31,18 @@ const command: GluegunCommand = {

outro("Let's roll")

const executorResults = await Promise.all(
executors.map((executor) => executor(toolbox))
const executorResults = await executors.reduce(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One last think, let's put it in some utils (not necessarly extension as I think it's not strictly related tool for CLI)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

extracted to /src/utils/sequentialPromiseMap.ts in 7ddc6c5

(executorsChain, executor) =>
km1chno marked this conversation as resolved.
Show resolved Hide resolved
executorsChain.then((executorResults) =>
executor(toolbox).then((result) => [...executorResults, result])
),
Promise.resolve([])
)
const usedFlags = (await executorResults).join(' --')

const usedFlags = executorResults.join(' ')

toolbox.print.success(
`We're all set. Next time you can use silent command: npx create-react-native-ci-cli --${SKIP_INTERACTIVE_COMMAND} ${usedFlags}`
`We're all set 🎉.\nNext time you can use silent command: npx create-react-native-ci-cli --${SKIP_INTERACTIVE_COMMAND} ${usedFlags}.`
)
},
}
Expand Down
17 changes: 0 additions & 17 deletions src/extensions/cli-extension.ts

This file was deleted.

35 changes: 35 additions & 0 deletions src/extensions/dependencies.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { GluegunToolbox } from 'gluegun'

module.exports = (toolbox: GluegunToolbox) => {
const { filesystem, packageManager, print } = toolbox

const exists = (name: string, dev: boolean) => {
km1chno marked this conversation as resolved.
Show resolved Hide resolved
const packageJSON = filesystem.read('package.json', 'json')
return (
(!dev && packageJSON?.dependencies[name]) ||
(dev && packageJSON?.devDependencies[name])
maciekstosio marked this conversation as resolved.
Show resolved Hide resolved
)
}

const add = async (name: string, dev: boolean) => {
km1chno marked this conversation as resolved.
Show resolved Hide resolved
if (exists(name, dev)) {
print.info(`${name} already installed, skipping adding dependency.`)
return
}

const spinner = print.spin(
`📦 Installing ${name} as ${dev ? 'devDependency' : 'dependency'}...`
)

await packageManager.add(name, { dev })

spinner.stop()

print.info(`✔ Installed ${name}.`)
}

toolbox.dependencies = {
exists,
add,
}
}
19 changes: 19 additions & 0 deletions src/extensions/scripts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { GluegunToolbox } from 'gluegun'

module.exports = (toolbox: GluegunToolbox) => {
const { patching, print } = toolbox

const add = async (name: string, command: string) => {
await patching.update('package.json', (config) => {
if (config.scripts[name]) {
return config
}

config.scripts[name] = command

print.info(`✔ Added script "${name}": "${command}" to package.json.`)
})
}

toolbox.scripts = { add }
}
39 changes: 39 additions & 0 deletions src/recipies/jest.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { confirm } from '@clack/prompts'
import { Toolbox } from 'gluegun/build/types/domain/toolbox'

const COMMAND = 'jest'

const execute = () => async (toolbox: Toolbox) => {
await toolbox.dependencies.add('jest', '', true)
km1chno marked this conversation as resolved.
Show resolved Hide resolved

await toolbox.scripts.add('test', 'jest')

await toolbox.template.generate({
template: 'jest.ejf',
target: `.github/workflows/jest.yml`,
})

toolbox.print.info('✔ Created Jest workflow.')

return `--${COMMAND}`
}

const run = async (
toolbox: Toolbox
): Promise<(toolbox: Toolbox) => Promise<string> | null> => {
if (toolbox.skipInteractiveForCommand(COMMAND)) {
return execute()
}

const proceed = await confirm({
message: 'Do you want to run Jest on your project on every PR?',
})

if (!proceed) {
return
}

return execute()
}

export default run
24 changes: 3 additions & 21 deletions src/recipies/lint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,34 +4,16 @@ import { confirm } from '@clack/prompts'
const COMMAND = 'lint'

const execute = () => async (toolbox: Toolbox) => {
const packageJSON = toolbox.filesystem.read('package.json', 'json')
await toolbox.dependencies.add('eslint', '', true)
km1chno marked this conversation as resolved.
Show resolved Hide resolved

if (!packageJSON?.devDependencies?.eslint) {
const spinner = toolbox.print.spin('Installing ESLint...')

await toolbox.packageManager.add('eslint', { dev: true })

spinner.stop()

toolbox.print.info('Installed ESLint.')
}

await toolbox.patching.update('package.json', (config) => {
if (!config.scripts.lint) {
config.scripts.lint = 'eslint "**/*.{js,jsx,ts,tsx}"'

toolbox.print.info('Added ESLint script to package.json')
}

return config
})
await toolbox.scripts.add('lint', 'eslint "**/*.{js,jsx,ts,tsx}"')

await toolbox.template.generate({
template: 'lint.ejf',
target: `.github/workflows/lint.yml`,
})

toolbox.print.info('Created ESLint workflow.')
toolbox.print.info('Created ESLint workflow.')

return `--${COMMAND}`
}
Expand Down
14 changes: 14 additions & 0 deletions src/templates/jest.ejf
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
name: Run Jest tests
on: [pull_request]

jobs:
test:
name: Jest
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: 📦 Install dependencies
run: yarn

- name: 🎭 Run Jest
run: yarn test