Skip to content

Commit

Permalink
test(create-gatsby): add test for init starter in create-gatsby
Browse files Browse the repository at this point in the history
  • Loading branch information
mfrachet committed Dec 1, 2020
1 parent 3ce476b commit 45615bc
Show file tree
Hide file tree
Showing 4 changed files with 199 additions and 32 deletions.
157 changes: 157 additions & 0 deletions packages/create-gatsby/src/__tests__/init-starter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
import { execSync } from "child_process"
import execa from "execa"
import fs from "fs-extra"
import path from "path"
import { initStarter } from "../init-starter"
import { reporter } from "../reporter"

jest.mock(`../utils`)
jest.mock(`execa`)
jest.mock(`child_process`)
jest.mock(`fs-extra`)
jest.mock(`path`)
jest.mock(`../reporter`)
jest.mock(`../get-config-store`, () => {
return {
getConfigStore: (): unknown => {
return {
items: {},
set(key: string, value: unknown): void {
this.items[key] = value
},
get(key: string): unknown {
return this.items[key]
},

__reset(): void {
this.items = {}
},
}
},
}
})

describe(`init-starter`, () => {
beforeEach(() => {
process.chdir = jest.fn()
})

afterEach(() => {
jest.resetAllMocks()
})

describe(`initStarter / cloning`, () => {
it(`reports an error when it s not possible to clone the repo`, async () => {
;(path as any).join.mockImplementation(() => `/somewhere-here`)
;(execa as any).mockImplementation(() => {
throw new Error(`Not possible to clone the repo`)
})

try {
await initStarter(`gatsby-starter-hello-world`, `./somewhere`, [])
} catch (e) {
expect(execa).toBeCalledWith(`git`, [
`clone`,
`gatsby-starter-hello-world`,
`--recursive`,
`--depth=1`,
`--quiet`,
])
expect(reporter.panic).toBeCalledWith(`Not possible to clone the repo`)
expect(reporter.success).not.toBeCalledWith(
`Created site from template`
)
expect(fs.remove).toBeCalledWith(`/somewhere-here`)
}
})

it(`reports a success when everything is going ok`, async () => {
;(path as any).join.mockImplementation(() => `/somewhere-here`)
;(execa as any).mockImplementation(() => Promise.resolve())
;(fs as any).readJSON.mockImplementation(() => {
return { name: `gatsby-project` }
})

await initStarter(`gatsby-starter-hello-world`, `./somewhere`, [])

expect(execa).toBeCalledWith(`git`, [
`clone`,
`gatsby-starter-hello-world`,
`--recursive`,
`--depth=1`,
`--quiet`,
])
expect(reporter.panic).not.toBeCalled()
expect(reporter.success).toBeCalledWith(`Created site from template`)
expect(fs.remove).toBeCalledWith(`/somewhere-here`)
})
})

describe(`initStarter / install`, () => {
it(`process package installation with yarn`, async () => {
process.env.npm_config_user_agent = `yarn`
;(path as any).join.mockImplementation(() => `/somewhere-here`)
;(execa as any).mockImplementation(() => Promise.resolve())
;(fs as any).readJSON.mockImplementation(() => {
return { name: `gatsby-project` }
})

await initStarter(`gatsby-starter-hello-world`, `./somewhere`, [])

expect(fs.remove).toBeCalledWith(`package-lock.json`)
expect(reporter.success).toBeCalledWith(`Installed plugins`)
expect(reporter.panic).not.toBeCalled()
expect(execa).toBeCalledWith(`yarnpkg`, [`--silent`], {
stderr: `inherit`,
})
})

it(`process package installation with NPM`, async () => {
process.env.npm_config_user_agent = `npm`
;(path as any).join.mockImplementation(() => `/somewhere-here`)
;(execa as any).mockImplementation(() => Promise.resolve())
;(fs as any).readJSON.mockImplementation(() => {
return { name: `gatsby-project` }
})

await initStarter(`gatsby-starter-hello-world`, `./somewhere`, [
`one-package`,
])

expect(fs.remove).toBeCalledWith(`yarn.lock`)
expect(reporter.success).toBeCalledWith(`Installed Gatsby`)
expect(reporter.success).toBeCalledWith(`Installed plugins`)
expect(reporter.panic).not.toBeCalled()
expect(execa).toBeCalledWith(
`npm`,
[`install`, `--loglevel`, `error`, `--color`, `always`],
{ stderr: `inherit` }
)
expect(execa).toBeCalledWith(
`npm`,
[`install`, `--loglevel`, `error`, `--color`, `always`, `one-package`],
{ stderr: `inherit` }
)
})

it(`gently informs the user that yarn is not available when trying to use it`, async () => {
process.env.npm_config_user_agent = `yarn`
;(execSync as any).mockImplementation(() => {
throw new Error(`Something wrong occured when trying to use yarn`)
})
;(path as any).join.mockImplementation(() => `/somewhere-here`)
;(execa as any).mockImplementation(() => Promise.resolve())
;(fs as any).readJSON.mockImplementation(() => {
return { name: `gatsby-project` }
})

await initStarter(`gatsby-starter-hello-world`, `./somewhere`, [
`one-package`,
])

expect(reporter.info).toBeCalledWith(
`Woops! Yarn doesn't seem be installed on your machine. You can install it on https://yarnpkg.com/getting-started/install. As a fallback, we will run the next steps with npm.`
)
})
})
})
4 changes: 2 additions & 2 deletions packages/create-gatsby/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import Enquirer from "enquirer"
import cmses from "./cmses.json"
import styles from "./styles.json"
import features from "./features.json"
import { initStarter, getPackageManager, gitSetup } from "./init-starter"
import { initStarter, packageManager, gitSetup } from "./init-starter"
import { installPlugins } from "./install-plugins"
import c from "ansi-colors"
import path from "path"
Expand Down Expand Up @@ -312,7 +312,7 @@ ${c.bold(`Thanks! Here's what we'll now do:`)}

await gitSetup(data.project)

const pm = await getPackageManager()
const pm = await packageManager()
const runCommand = pm === `npm` ? `npm run` : `yarn`

reporter.info(
Expand Down
58 changes: 28 additions & 30 deletions packages/create-gatsby/src/init-starter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { spin } from "tiny-spin"
import { getConfigStore } from "./get-config-store"
type PackageManager = "yarn" | "npm"
import c from "ansi-colors"
import { clearLine } from "./utils"

const packageManagerConfigKey = `cli.packageManager`

Expand All @@ -16,25 +17,21 @@ const kebabify = (str: string): string =>
.replace(/[^a-zA-Z]+/g, `-`)
.toLowerCase()

export const getPackageManager = (): PackageManager =>
getConfigStore().get(packageManagerConfigKey)
export const packageManager = (npmConfigUserAgent?: string): PackageManager => {
const configStore = getConfigStore()
const actualPackageManager = configStore.get(packageManagerConfigKey)

export const setPackageManager = (packageManager: PackageManager): void => {
getConfigStore().set(packageManagerConfigKey, packageManager)
}
if (actualPackageManager) return actualPackageManager

const ESC = `\u001b`
if (npmConfigUserAgent?.includes(`yarn`)) {
configStore.set(packageManagerConfigKey, `yarn`)
return `yarn`
}

configStore.set(packageManagerConfigKey, `npm`)
return `npm`
}

export const clearLine = (count = 1): Promise<boolean> =>
new Promise(resolve => {
// First move the cursor up one line...
process.stderr.moveCursor(0, -count, () => {
// ... then clear that line. This is the ANSI escape sequence for "clear whole line"
// List of escape sequences: http://ascii-table.com/ansi-escape-sequences.php
process.stderr.write(`${ESC}[2K`)
resolve()
})
})
// Checks the existence of yarn package
// We use yarnpkg instead of yarn to avoid conflict with Hadoop yarn
// Refer to https://github.com/yarnpkg/yarn/issues/673
Expand All @@ -43,6 +40,9 @@ const checkForYarn = (): boolean => {
execSync(`yarnpkg --version`, { stdio: `ignore` })
return true
} catch (e) {
reporter.info(
`Woops! Yarn doesn't seem be installed on your machine. You can install it on https://yarnpkg.com/getting-started/install. As a fallback, we will run the next steps with npm.`
)
return false
}
}
Expand Down Expand Up @@ -117,36 +117,34 @@ const install = async (
const npmConfigUserAgent = process.env.npm_config_user_agent

try {
if (!getPackageManager()) {
if (npmConfigUserAgent?.includes(`yarn`)) {
setPackageManager(`yarn`)
} else {
setPackageManager(`npm`)
}
}
const pm = packageManager(npmConfigUserAgent)

const options: Options = {
stderr: `inherit`,
}

const config = [`--loglevel`, `error`, `--color`, `always`]

if (getPackageManager() === `yarn` && checkForYarn()) {
await fs.remove(`package-lock.json`)
if (pm === `yarn` && checkForYarn()) {
const args = packages.length
? [`add`, `--silent`, ...packages]
: [`--silent`]

await fs.remove(`package-lock.json`)
await execa(`yarnpkg`, args, options)
} else {
await fs.remove(`yarn.lock`)

await execa(`npm`, [`install`, ...config], options)
await clearLine()

reporter.success(`Installed Gatsby`)
reporter.info(`${c.blueBright(c.symbols.pointer)} Installing plugins...`)

await execa(`npm`, [`install`, ...config, ...packages], options)
await clearLine()
reporter.success(`Installed plugins`)
}

reporter.success(`Installed plugins`)
} catch (e) {
reporter.panic(e.message)
} finally {
Expand All @@ -161,9 +159,7 @@ const clone = async (
branch?: string
): Promise<void> => {
const branchProps = branch ? [`-b`, branch] : []

const stop = spin(`Cloning site template`)

const args = [
`clone`,
...branchProps,
Expand All @@ -176,11 +172,13 @@ const clone = async (

try {
await execa(`git`, args)

reporter.success(`Created site from template`)
} catch (err) {
reporter.panic(err.message)
}

stop()
reporter.success(`Created site from template`)
await fs.remove(path.join(rootPath, `.git`))
}

Expand Down
12 changes: 12 additions & 0 deletions packages/create-gatsby/src/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
const ESC = `\u001b`

export const clearLine = (count = 1): Promise<boolean> =>
new Promise(resolve => {
// First move the cursor up one line...
process.stderr.moveCursor(0, -count, () => {
// ... then clear that line. This is the ANSI escape sequence for "clear whole line"
// List of escape sequences: http://ascii-table.com/ansi-escape-sequences.php
process.stderr.write(`${ESC}[2K`)
resolve()
})
})

0 comments on commit 45615bc

Please sign in to comment.