Skip to content
This repository was archived by the owner on Apr 22, 2024. It is now read-only.

Commit 588555a

Browse files
committed
✅ test: add tests
1 parent aaf85bf commit 588555a

File tree

10 files changed

+9306
-302
lines changed

10 files changed

+9306
-302
lines changed

generator/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ module.exports = (api, options, rootOptions) => {
134134
debug('postProcessFiles called')
135135
if (!api.hasPlugin('typescript')) { return }
136136
const tsConfigRaw = files['tsconfig.json']
137+
if (!tsConfigRaw) { return }
137138
const tsConfig = JSON.parse(tsConfigRaw)
138139
tsConfig.compilerOptions.types.push('webpack')
139140
tsConfig.compilerOptions.types.push('webpack-env')

package.json

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,26 @@
1414
"deepmerge": "^2.1.1",
1515
"dotenv": "^6.0.0",
1616
"flat": "^4.0.0",
17+
"rimraf": "^2.6.3",
1718
"vue": "^2.5.16",
1819
"vue-i18n": "^8.0.0"
1920
},
2021
"devDependencies": {
22+
"@vue/cli": "^3.4.1",
23+
"@vue/cli-service": "^3.4.1",
24+
"@vue/cli-test-utils": "^3.4.1",
2125
"conventional-changelog-cli": "^1.2.0",
2226
"conventional-github-releaser": "^1.1.3",
2327
"eslint": "^5.12.0",
2428
"eslint-plugin-vue": "^5.1.0",
25-
"git-commit-message-convention": "git://github.com/kazupon/git-commit-message-convention.git"
29+
"git-commit-message-convention": "git://github.com/kazupon/git-commit-message-convention.git",
30+
"inquirer": "^6.0.0",
31+
"jest": "^24.1.0"
2632
},
2733
"homepage": "https://github.com/kazupon/vue-cli-plugin-i18n#readme",
34+
"jest": {
35+
"testEnvironment": "node"
36+
},
2837
"keywords": [
2938
"plugin",
3039
"vue",
@@ -39,8 +48,11 @@
3948
},
4049
"scripts": {
4150
"changelog": "conventional-changelog -i CHANGELOG.md -s -n ./node_modules/git-commit-message-convention/convention.js",
51+
"clean": "rimraf coverage tests/e2e/projects/*",
4252
"lint": "eslint --fix --ext .js .",
4353
"release": "conventional-github-releaser -n ./node_modules/git-commit-message-convention/convention.js",
44-
"test": "npm run lint"
54+
"test": "npm run test:unit",
55+
"test:unit": "jest ./tests/unit/*.spec.js",
56+
"test:e2e": "jest ./tests/e2e/*.spec.js"
4557
}
4658
}

tests/e2e/javascript.spec.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
jest.setTimeout(10 * 60 * 1000)
2+
3+
const create = require('../helper/create')
4+
5+
beforeEach(() => {
6+
jest.mock('inquirer', () => {
7+
return require('../helper/mockInquirer')
8+
})
9+
})
10+
11+
afterEach(() => {
12+
jest.clearAllMocks()
13+
jest.unmock('inquirer')
14+
})
15+
16+
test(`javascript project`, async () => {
17+
const { expectPrompts } = require('inquirer')
18+
19+
const projectName = `vue-i18n-js`
20+
const plugins = {
21+
'@vue/cli-plugin-babel': {},
22+
}
23+
expectPrompts([{
24+
useDefault: true
25+
}, {
26+
useDefault: true
27+
}, {
28+
useDefault: true
29+
}, {
30+
useDefault: true
31+
}])
32+
const project = await create(projectName, { plugins })
33+
const pkg = JSON.parse(await project.read('package.json') )
34+
35+
expect(project.has('.env')).toBe(true)
36+
expect(project.has('src/i18n.js')).toBe(true)
37+
expect(project.has('src/locales/en.json')).toBe(true)
38+
expect(project.has('src/components/HelloI18n.vue')).toBe(false)
39+
expect(pkg.dependencies['vue-i18n']).not.toBeUndefined()
40+
expect(pkg.devDependencies['vue-cli-plugin-i18n']).not.toBeUndefined()
41+
expect(pkg.devDependencies['@kazupon/vue-i18n-loader']).toBeUndefined()
42+
})

tests/e2e/projects/.gitkeep

Whitespace-only changes.

tests/e2e/typescript.spec.js

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
jest.setTimeout(10 * 60 * 1000)
2+
3+
const create = require('../helper/create')
4+
5+
beforeEach(() => {
6+
jest.mock('inquirer', () => {
7+
return require('../helper/mockInquirer')
8+
})
9+
})
10+
11+
afterEach(() => {
12+
jest.clearAllMocks()
13+
jest.unmock('inquirer')
14+
})
15+
16+
test(`typescript project`, async () => {
17+
const { expectPrompts } = require('inquirer')
18+
19+
const projectName = `vue-i18n-ts`
20+
const plugins = {
21+
'@vue/cli-plugin-babel': {},
22+
'@vue/cli-plugin-typescript': {
23+
classComponent: true
24+
}
25+
}
26+
expectPrompts([{
27+
input: 'ja'
28+
}, {
29+
input: 'ja'
30+
}, {
31+
input: 'loc'
32+
}, {
33+
confirm: true
34+
}])
35+
const project = await create(projectName, { plugins })
36+
const pkg = JSON.parse(await project.read('package.json') )
37+
38+
expect(project.has('.env')).toBe(true)
39+
expect(project.has('src/i18n.ts')).toBe(true)
40+
expect(project.has('src/loc/ja.json')).toBe(true)
41+
expect(project.has('src/components/HelloI18n.vue')).toBe(true)
42+
expect(pkg.dependencies['vue-i18n']).not.toBeUndefined()
43+
expect(pkg.devDependencies['vue-cli-plugin-i18n']).not.toBeUndefined()
44+
expect(pkg.devDependencies['@kazupon/vue-i18n-loader']).not.toBeUndefined()
45+
})

tests/helper/create.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
const path = require('path')
2+
const createTestProject = require('@vue/cli-test-utils/createTestProject')
3+
4+
async function create (name, presets) {
5+
const project = await createTestProject(
6+
name, presets, path.join(process.cwd(), './tests/e2e/projects')
7+
)
8+
9+
// mocking...
10+
const pkg = JSON.parse(await project.read('package.json'))
11+
pkg.devDependencies['vue-cli-plugin-i18n'] = '../../../..'
12+
await project.write('package.json', JSON.stringify(pkg, null, 2))
13+
14+
const invoke = require('@vue/cli/lib/invoke')
15+
await invoke('i18n', {}, project.dir)
16+
return Promise.resolve(project)
17+
}
18+
19+
module.exports = create

tests/helper/createMockService.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
const Service = require('@vue/cli-service')
2+
3+
module.exports = (plugins = [], context = '/', init = true, mode) => {
4+
const service = new Service(context, {
5+
plugins,
6+
useBuiltIn: false
7+
})
8+
if (init) {
9+
service.init(mode)
10+
}
11+
return service
12+
}

tests/helper/mockInquirer.js

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
let pendingAssertions
2+
3+
exports.prompt = prompts => {
4+
if (!pendingAssertions) {
5+
throw new Error(`inquirer was mocked and used without pending assertions: ${prompts}`)
6+
}
7+
8+
const answers = {}
9+
let skipped = 0
10+
prompts.forEach((prompt, i) => {
11+
if (prompt.when && !prompt.when(answers)) {
12+
skipped++
13+
return
14+
}
15+
16+
const setValue = val => {
17+
if (prompt.validate) {
18+
const res = prompt.validate(val)
19+
if (res !== true) {
20+
throw new Error(`validation failed for prompt: ${prompt}`)
21+
}
22+
}
23+
answers[prompt.name] = prompt.filter
24+
? prompt.filter(val)
25+
: val
26+
}
27+
28+
const a = pendingAssertions[i - skipped]
29+
if (!a) {
30+
console.error(`no matching assertion for prompt:`, prompt)
31+
console.log(prompts)
32+
console.log(pendingAssertions)
33+
}
34+
35+
if (a.message) {
36+
const message = typeof prompt.message === 'function'
37+
? prompt.message(answers)
38+
: prompt.message
39+
expect(message).toMatch(a.message)
40+
}
41+
42+
const choices = typeof prompt.choices === 'function'
43+
? prompt.choices(answers)
44+
: prompt.choices
45+
if (a.choices) {
46+
expect(choices.length).toBe(a.choices.length)
47+
a.choices.forEach((c, i) => {
48+
const expected = a.choices[i]
49+
if (expected) {
50+
expect(choices[i].name).toMatch(expected)
51+
}
52+
})
53+
}
54+
55+
if (a.input != null) {
56+
expect(prompt.type).toBe('input')
57+
setValue(a.input)
58+
}
59+
60+
if (a.choose != null) {
61+
expect(prompt.type === 'list' || prompt.type === 'rawList').toBe(true)
62+
setValue(choices[a.choose].value)
63+
}
64+
65+
if (a.check != null) {
66+
expect(prompt.type).toBe('checkbox')
67+
setValue(a.check.map(i => choices[i].value))
68+
}
69+
70+
if (a.confirm != null) {
71+
expect(prompt.type).toBe('confirm')
72+
setValue(a.confirm)
73+
}
74+
75+
if (a.useDefault) {
76+
expect('default' in prompt).toBe(true)
77+
setValue(
78+
typeof prompt.default === 'function'
79+
? prompt.default(answers)
80+
: prompt.default
81+
)
82+
}
83+
})
84+
85+
expect(prompts.length).toBe(pendingAssertions.length + skipped)
86+
pendingAssertions = null
87+
88+
return Promise.resolve(answers)
89+
}
90+
91+
exports.expectPrompts = assertions => {
92+
pendingAssertions = assertions
93+
}

tests/unit/generator.spec.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
const generateWithPlugin = require('@vue/cli-test-utils/generateWithPlugin')
2+
3+
test('javascript', async () => {
4+
const projectName = 'vue-i18n-gen-js'
5+
const { pkg, files } = await generateWithPlugin([{
6+
id: '@vue/cli-service',
7+
apply: () => {},
8+
options: { projectName }
9+
}, {
10+
id: 'i18n',
11+
apply: require('../../generator'),
12+
options: { localeDir: 'locales' }
13+
}])
14+
15+
// check files
16+
const i18n = files['src/i18n.js']
17+
expect(i18n).toMatch(`const locales = require.context('./locales', true, /[A-Za-z0-9-_,\\s]+\\.json$/i)`)
18+
const pack = files['package.json']
19+
expect(pack).toMatch(`"vue-i18n": "^8.0.0"`)
20+
})
21+
22+
test('typescript', async () => {
23+
const projectName = 'vue-i18n-gen-ts'
24+
const { pkg, files } = await generateWithPlugin([{
25+
id: '@vue/cli-service',
26+
apply: () => {},
27+
options: { projectName }
28+
}, {
29+
id: '@vue/cli-plugin-typescript',
30+
apply: () => {},
31+
options: { projectName }
32+
}, {
33+
id: 'i18n',
34+
apply: require('../../generator'),
35+
options: { locale: 'ja', localeDir: 'loc', enableInSFC: true }
36+
}])
37+
38+
// check files
39+
const i18n = files['src/i18n.ts']
40+
expect(i18n).toMatch(`const locales = require.context('./loc', true, /[A-Za-z0-9-_,\\s]+\\.json$/i)`)
41+
const sfc = files['src/components/HelloI18n.vue']
42+
expect(sfc).toMatch(`export default Vue.extend({`)
43+
const pack = files['package.json']
44+
expect(pack).toMatch(`"vue-i18n": "^8.0.0"`)
45+
expect(pack).toMatch(`"@kazupon/vue-i18n-loader": "^0.3.0"`)
46+
expect(pack).toMatch(`"@types/webpack": "^4.4.0"`)
47+
})

0 commit comments

Comments
 (0)