Skip to content

Commit 7061b12

Browse files
author
mfrachet
committed
test(create-gatsby): add test for init starter in create-gatsby
1 parent 5812c81 commit 7061b12

File tree

4 files changed

+199
-32
lines changed

4 files changed

+199
-32
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
import { execSync } from "child_process"
2+
import execa from "execa"
3+
import fs from "fs-extra"
4+
import path from "path"
5+
import { initStarter } from "../init-starter"
6+
import { reporter } from "../reporter"
7+
8+
jest.mock(`../utils`)
9+
jest.mock(`execa`)
10+
jest.mock(`child_process`)
11+
jest.mock(`fs-extra`)
12+
jest.mock(`path`)
13+
jest.mock(`../reporter`)
14+
jest.mock(`../get-config-store`, () => {
15+
return {
16+
getConfigStore: (): unknown => {
17+
return {
18+
items: {},
19+
set(key: string, value: unknown): void {
20+
this.items[key] = value
21+
},
22+
get(key: string): unknown {
23+
return this.items[key]
24+
},
25+
26+
__reset(): void {
27+
this.items = {}
28+
},
29+
}
30+
},
31+
}
32+
})
33+
34+
describe(`init-starter`, () => {
35+
beforeEach(() => {
36+
process.chdir = jest.fn()
37+
})
38+
39+
afterEach(() => {
40+
jest.resetAllMocks()
41+
})
42+
43+
describe(`initStarter / cloning`, () => {
44+
it(`reports an error when it s not possible to clone the repo`, async () => {
45+
;(path as any).join.mockImplementation(() => `/somewhere-here`)
46+
;(execa as any).mockImplementation(() => {
47+
throw new Error(`Not possible to clone the repo`)
48+
})
49+
50+
try {
51+
await initStarter(`gatsby-starter-hello-world`, `./somewhere`, [])
52+
} catch (e) {
53+
expect(execa).toBeCalledWith(`git`, [
54+
`clone`,
55+
`gatsby-starter-hello-world`,
56+
`--recursive`,
57+
`--depth=1`,
58+
`--quiet`,
59+
])
60+
expect(reporter.panic).toBeCalledWith(`Not possible to clone the repo`)
61+
expect(reporter.success).not.toBeCalledWith(
62+
`Created site from template`
63+
)
64+
expect(fs.remove).toBeCalledWith(`/somewhere-here`)
65+
}
66+
})
67+
68+
it(`reports a success when everything is going ok`, async () => {
69+
;(path as any).join.mockImplementation(() => `/somewhere-here`)
70+
;(execa as any).mockImplementation(() => Promise.resolve())
71+
;(fs as any).readJSON.mockImplementation(() => {
72+
return { name: `gatsby-project` }
73+
})
74+
75+
await initStarter(`gatsby-starter-hello-world`, `./somewhere`, [])
76+
77+
expect(execa).toBeCalledWith(`git`, [
78+
`clone`,
79+
`gatsby-starter-hello-world`,
80+
`--recursive`,
81+
`--depth=1`,
82+
`--quiet`,
83+
])
84+
expect(reporter.panic).not.toBeCalled()
85+
expect(reporter.success).toBeCalledWith(`Created site from template`)
86+
expect(fs.remove).toBeCalledWith(`/somewhere-here`)
87+
})
88+
})
89+
90+
describe(`initStarter / install`, () => {
91+
it(`process package installation with yarn`, async () => {
92+
process.env.npm_config_user_agent = `yarn`
93+
;(path as any).join.mockImplementation(() => `/somewhere-here`)
94+
;(execa as any).mockImplementation(() => Promise.resolve())
95+
;(fs as any).readJSON.mockImplementation(() => {
96+
return { name: `gatsby-project` }
97+
})
98+
99+
await initStarter(`gatsby-starter-hello-world`, `./somewhere`, [])
100+
101+
expect(fs.remove).toBeCalledWith(`package-lock.json`)
102+
expect(reporter.success).toBeCalledWith(`Installed plugins`)
103+
expect(reporter.panic).not.toBeCalled()
104+
expect(execa).toBeCalledWith(`yarnpkg`, [`--silent`], {
105+
stderr: `inherit`,
106+
})
107+
})
108+
109+
it(`process package installation with NPM`, async () => {
110+
process.env.npm_config_user_agent = `npm`
111+
;(path as any).join.mockImplementation(() => `/somewhere-here`)
112+
;(execa as any).mockImplementation(() => Promise.resolve())
113+
;(fs as any).readJSON.mockImplementation(() => {
114+
return { name: `gatsby-project` }
115+
})
116+
117+
await initStarter(`gatsby-starter-hello-world`, `./somewhere`, [
118+
`one-package`,
119+
])
120+
121+
expect(fs.remove).toBeCalledWith(`yarn.lock`)
122+
expect(reporter.success).toBeCalledWith(`Installed Gatsby`)
123+
expect(reporter.success).toBeCalledWith(`Installed plugins`)
124+
expect(reporter.panic).not.toBeCalled()
125+
expect(execa).toBeCalledWith(
126+
`npm`,
127+
[`install`, `--loglevel`, `error`, `--color`, `always`],
128+
{ stderr: `inherit` }
129+
)
130+
expect(execa).toBeCalledWith(
131+
`npm`,
132+
[`install`, `--loglevel`, `error`, `--color`, `always`, `one-package`],
133+
{ stderr: `inherit` }
134+
)
135+
})
136+
137+
it(`gently informs the user that yarn is not available when trying to use it`, async () => {
138+
process.env.npm_config_user_agent = `yarn`
139+
;(execSync as any).mockImplementation(() => {
140+
throw new Error(`Something wrong occured when trying to use yarn`)
141+
})
142+
;(path as any).join.mockImplementation(() => `/somewhere-here`)
143+
;(execa as any).mockImplementation(() => Promise.resolve())
144+
;(fs as any).readJSON.mockImplementation(() => {
145+
return { name: `gatsby-project` }
146+
})
147+
148+
await initStarter(`gatsby-starter-hello-world`, `./somewhere`, [
149+
`one-package`,
150+
])
151+
152+
expect(reporter.info).toBeCalledWith(
153+
`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.`
154+
)
155+
})
156+
})
157+
})

packages/create-gatsby/src/index.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import Enquirer from "enquirer"
22
import cmses from "./cmses.json"
33
import styles from "./styles.json"
44
import features from "./features.json"
5-
import { initStarter, getPackageManager, gitSetup } from "./init-starter"
5+
import { initStarter, packageManager, gitSetup } from "./init-starter"
66
import { installPlugins } from "./install-plugins"
77
import c from "ansi-colors"
88
import path from "path"
@@ -312,7 +312,7 @@ ${c.bold(`Thanks! Here's what we'll now do:`)}
312312

313313
await gitSetup(data.project)
314314

315-
const pm = await getPackageManager()
315+
const pm = await packageManager()
316316
const runCommand = pm === `npm` ? `npm run` : `yarn`
317317

318318
reporter.info(

packages/create-gatsby/src/init-starter.ts

+28-30
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { spin } from "tiny-spin"
77
import { getConfigStore } from "./get-config-store"
88
type PackageManager = "yarn" | "npm"
99
import c from "ansi-colors"
10+
import { clearLine } from "./utils"
1011

1112
const packageManagerConfigKey = `cli.packageManager`
1213

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

19-
export const getPackageManager = (): PackageManager =>
20-
getConfigStore().get(packageManagerConfigKey)
20+
export const packageManager = (npmConfigUserAgent?: string): PackageManager => {
21+
const configStore = getConfigStore()
22+
const actualPackageManager = configStore.get(packageManagerConfigKey)
2123

22-
export const setPackageManager = (packageManager: PackageManager): void => {
23-
getConfigStore().set(packageManagerConfigKey, packageManager)
24-
}
24+
if (actualPackageManager) return actualPackageManager
2525

26-
const ESC = `\u001b`
26+
if (npmConfigUserAgent?.includes(`yarn`)) {
27+
configStore.set(packageManagerConfigKey, `yarn`)
28+
return `yarn`
29+
}
30+
31+
configStore.set(packageManagerConfigKey, `npm`)
32+
return `npm`
33+
}
2734

28-
export const clearLine = (count = 1): Promise<boolean> =>
29-
new Promise(resolve => {
30-
// First move the cursor up one line...
31-
process.stderr.moveCursor(0, -count, () => {
32-
// ... then clear that line. This is the ANSI escape sequence for "clear whole line"
33-
// List of escape sequences: http://ascii-table.com/ansi-escape-sequences.php
34-
process.stderr.write(`${ESC}[2K`)
35-
resolve()
36-
})
37-
})
3835
// Checks the existence of yarn package
3936
// We use yarnpkg instead of yarn to avoid conflict with Hadoop yarn
4037
// Refer to https://github.com/yarnpkg/yarn/issues/673
@@ -43,6 +40,9 @@ const checkForYarn = (): boolean => {
4340
execSync(`yarnpkg --version`, { stdio: `ignore` })
4441
return true
4542
} catch (e) {
43+
reporter.info(
44+
`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.`
45+
)
4646
return false
4747
}
4848
}
@@ -117,36 +117,34 @@ const install = async (
117117
const npmConfigUserAgent = process.env.npm_config_user_agent
118118

119119
try {
120-
if (!getPackageManager()) {
121-
if (npmConfigUserAgent?.includes(`yarn`)) {
122-
setPackageManager(`yarn`)
123-
} else {
124-
setPackageManager(`npm`)
125-
}
126-
}
120+
const pm = packageManager(npmConfigUserAgent)
121+
127122
const options: Options = {
128123
stderr: `inherit`,
129124
}
130125

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

133-
if (getPackageManager() === `yarn` && checkForYarn()) {
134-
await fs.remove(`package-lock.json`)
128+
if (pm === `yarn` && checkForYarn()) {
135129
const args = packages.length
136130
? [`add`, `--silent`, ...packages]
137131
: [`--silent`]
132+
133+
await fs.remove(`package-lock.json`)
138134
await execa(`yarnpkg`, args, options)
139135
} else {
140136
await fs.remove(`yarn.lock`)
141-
142137
await execa(`npm`, [`install`, ...config], options)
143138
await clearLine()
139+
144140
reporter.success(`Installed Gatsby`)
145141
reporter.info(`${c.blueBright(c.symbols.pointer)} Installing plugins...`)
142+
146143
await execa(`npm`, [`install`, ...config, ...packages], options)
147144
await clearLine()
148-
reporter.success(`Installed plugins`)
149145
}
146+
147+
reporter.success(`Installed plugins`)
150148
} catch (e) {
151149
reporter.panic(e.message)
152150
} finally {
@@ -161,9 +159,7 @@ const clone = async (
161159
branch?: string
162160
): Promise<void> => {
163161
const branchProps = branch ? [`-b`, branch] : []
164-
165162
const stop = spin(`Cloning site template`)
166-
167163
const args = [
168164
`clone`,
169165
...branchProps,
@@ -176,11 +172,13 @@ const clone = async (
176172

177173
try {
178174
await execa(`git`, args)
175+
176+
reporter.success(`Created site from template`)
179177
} catch (err) {
180178
reporter.panic(err.message)
181179
}
180+
182181
stop()
183-
reporter.success(`Created site from template`)
184182
await fs.remove(path.join(rootPath, `.git`))
185183
}
186184

packages/create-gatsby/src/utils.ts

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
const ESC = `\u001b`
2+
3+
export const clearLine = (count = 1): Promise<boolean> =>
4+
new Promise(resolve => {
5+
// First move the cursor up one line...
6+
process.stderr.moveCursor(0, -count, () => {
7+
// ... then clear that line. This is the ANSI escape sequence for "clear whole line"
8+
// List of escape sequences: http://ascii-table.com/ansi-escape-sequences.php
9+
process.stderr.write(`${ESC}[2K`)
10+
resolve()
11+
})
12+
})

0 commit comments

Comments
 (0)