Skip to content

Commit

Permalink
feat: support vue-jest@v5 (intlify#23)
Browse files Browse the repository at this point in the history
  • Loading branch information
XavierChevalier committed Nov 30, 2021
1 parent afaa5c3 commit d21ed55
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 70 deletions.
2 changes: 1 addition & 1 deletion e2e/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@
"@vue/test-utils": "^1.0.4",
"jest": "^26.x",
"vue-i18n-jest": "file:../",
"vue-jest": "^4.0.0-beta.3"
"vue-jest": "^5.0.0-alpha.10"
}
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
"main": "./lib/index.js",
"peerDependencies": {
"vue": "^2.5",
"vue-jest": "^4.0.0-beta.3",
"vue-jest": "^5.0.0-alpha.10",
"vue-template-compiler": "^2.5"
},
"repository": {
Expand Down
64 changes: 31 additions & 33 deletions src/process.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,74 +14,72 @@ type ProcessParameter = {
/** All of the blocks matching your type, returned from `@vue/component-compiler-utils` */
blocks: SFCCustomBlock[]
/** The internal namespace for a component's Vue Options in vue-jest */
vueOptionsNamespace: string
componentNamespace: string
/** The SFC file being processed */
filename: string
}

const VUE_I18N_OPTION = '__i18n'
const VUE_I18N_BLOCK_TYPE = 'i18n'

type JsonI18nBlockMessages = Record<string, unknown>

/**
* Process vue-i18n contents inside of a custom block and prepare it for execution in a testing environment.
*/
export default function process ({ blocks, vueOptionsNamespace, filename }: ProcessParameter) : string {
const i18nResources = blocks.map(block => {
if (block.type !== 'i18n') return

const value = parseI18nBlockToJSON(block, filename)
.replace(/\u2028/g, '\\u2028') // LINE SEPARATOR
.replace(/\u2029/g, '\\u2029') // PARAGRAPH SEPARATOR
.replace(/\\/g, '\\\\')
.replace(/'/g, "\\'")
return `'${value}'`
}).filter((s): s is string => !!s)

// vueOptions.__i18n = [
// '<json encoded block 1>',
// '<json encoded block 2>'
// ]
const i18nOption = `${vueOptionsNamespace}.${VUE_I18N_OPTION}`
const code = i18nResources.length ? `${i18nOption} = [\n${i18nResources.join(',\n')}\n]` : ''
debug('generatedCode', code)
return code
export default function process ({ blocks, componentNamespace, filename }: ProcessParameter): string[] {
const i18nOption = `${componentNamespace}.${VUE_I18N_OPTION}`
const generatedCode = blocks
.reduce((blocksValues, block) => {
if (block.type !== VUE_I18N_BLOCK_TYPE) return blocksValues

const i18nBlockConfig = {
locale: (block.attrs && block.attrs.locale) || '',
resource: parseI18nBlockToJSON(block, filename)
}

return blocksValues.concat(`${i18nOption}.push(${JSON.stringify(i18nBlockConfig)});`)
}, [] as string[])

if (generatedCode.length > 0) {
generatedCode.unshift(`${i18nOption} = ${i18nOption} || [];`)
}

debug('generatedCode', generatedCode)

return generatedCode
}

/**
* Parse custom `<i18n>` block content to JSON string.
* @param block SFC block returned from `@vue/component-compiler-utils`
* @param filename The SFC file being processed
*/
function parseI18nBlockToJSON (block: SFCCustomBlock, filename: string): string {
function parseI18nBlockToJSON (block: SFCCustomBlock, filename: string): JsonI18nBlockMessages {
const lang = block.attrs && block.attrs.lang
const locale = block.attrs && block.attrs.locale
const src = block.attrs && block.attrs.src
const content = src
? readFileSync(getAbsolutePath(src, filename)).toString()
: block.content

return convertToJSON(content, lang, locale)
return convertToJSON(content, lang)
}

/**
* Convert JSON/YAML/JSON5 to minified JSON string.
* @param source JSON/YAML/JSON5 encoded string
* @param lang Language used in `source`. Supported JSON, YAML or JSON5.
* @param locale Attribute "locale" on <i18n> block will be added.
* @returns {string} A minified JSON string
*/
function convertToJSON (source: string, lang: string, locale: string): string {
const stringify = locale
? (parseResult: any) => JSON.stringify({ [locale]: parseResult })
: JSON.stringify

function convertToJSON (source: string, lang: string): JsonI18nBlockMessages {
switch (lang) {
case 'yaml':
case 'yml':
return stringify(parseYAML(source))
return parseYAML(source) as JsonI18nBlockMessages
case 'json5':
return stringify(parseJSON5(source))
return parseJSON5(source)
default: // fallback to 'json'
return stringify(JSON.parse(source))
return JSON.parse(source)
}
}

Expand Down
78 changes: 44 additions & 34 deletions test/__snapshots__/process.test.ts.snap
Original file line number Diff line number Diff line change
@@ -1,66 +1,76 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`process (default.vue) returns expected string: default.vue 1`] = `
"__vue__options__.__i18n = [
'{\\"ja\\":{\\"hello\\":\\"こんにちは!\\"},\\"en\\":{\\"hello\\":\\"hello!\\"}}'
]"
Array [
"Component.__i18n = Component.__i18n || [];",
"Component.__i18n.push({\\"locale\\":\\"\\",\\"resource\\":{\\"ja\\":{\\"hello\\":\\"こんにちは!\\"},\\"en\\":{\\"hello\\":\\"hello!\\"}}});",
]
`;

exports[`process (json.vue) returns expected string: json.vue 1`] = `
"__vue__options__.__i18n = [
'{\\"ja\\":{\\"hello\\":\\"こんにちは!\\"},\\"en\\":{\\"hello\\":\\"hello!\\"}}'
]"
Array [
"Component.__i18n = Component.__i18n || [];",
"Component.__i18n.push({\\"locale\\":\\"\\",\\"resource\\":{\\"ja\\":{\\"hello\\":\\"こんにちは!\\"},\\"en\\":{\\"hello\\":\\"hello!\\"}}});",
]
`;

exports[`process (json-locale.vue) returns expected string: json-locale.vue 1`] = `
"__vue__options__.__i18n = [
'{\\"ja\\":{\\"hello\\":\\"こんにちは!\\"}}',
'{\\"en\\":{\\"hello\\":\\"hello!\\"}}'
]"
Array [
"Component.__i18n = Component.__i18n || [];",
"Component.__i18n.push({\\"locale\\":\\"ja\\",\\"resource\\":{\\"hello\\":\\"こんにちは!\\"}});",
"Component.__i18n.push({\\"locale\\":\\"en\\",\\"resource\\":{\\"hello\\":\\"hello!\\"}});",
]
`;

exports[`process (json-src-import.vue) returns expected string: json-src-import.vue 1`] = `
"__vue__options__.__i18n = [
'{\\"ja\\":{\\"hello\\":\\"こんにちは!\\"},\\"en\\":{\\"hello\\":\\"hello!\\"}}'
]"
Array [
"Component.__i18n = Component.__i18n || [];",
"Component.__i18n.push({\\"locale\\":\\"\\",\\"resource\\":{\\"ja\\":{\\"hello\\":\\"こんにちは!\\"},\\"en\\":{\\"hello\\":\\"hello!\\"}}});",
]
`;

exports[`process (json5.vue) returns expected string: json5.vue 1`] = `
"__vue__options__.__i18n = [
'{\\"ja\\":{\\"hello\\":\\"こんにちは!\\"},\\"en\\":{\\"hello\\":\\"hello!\\"}}'
]"
Array [
"Component.__i18n = Component.__i18n || [];",
"Component.__i18n.push({\\"locale\\":\\"\\",\\"resource\\":{\\"ja\\":{\\"hello\\":\\"こんにちは!\\"},\\"en\\":{\\"hello\\":\\"hello!\\"}}});",
]
`;

exports[`process (json5-locale.vue) returns expected string: json5-locale.vue 1`] = `
"__vue__options__.__i18n = [
'{\\"ja\\":{\\"hello\\":\\"こんにちは!\\"}}',
'{\\"en\\":{\\"hello\\":\\"hello!\\"}}'
]"
Array [
"Component.__i18n = Component.__i18n || [];",
"Component.__i18n.push({\\"locale\\":\\"ja\\",\\"resource\\":{\\"hello\\":\\"こんにちは!\\"}});",
"Component.__i18n.push({\\"locale\\":\\"en\\",\\"resource\\":{\\"hello\\":\\"hello!\\"}});",
]
`;

exports[`process (json5-src-import.vue) returns expected string: json5-src-import.vue 1`] = `
"__vue__options__.__i18n = [
'{\\"ja\\":{\\"hello\\":\\"こんにちは!\\"},\\"en\\":{\\"hello\\":\\"hello!\\"}}'
]"
Array [
"Component.__i18n = Component.__i18n || [];",
"Component.__i18n.push({\\"locale\\":\\"\\",\\"resource\\":{\\"ja\\":{\\"hello\\":\\"こんにちは!\\"},\\"en\\":{\\"hello\\":\\"hello!\\"}}});",
]
`;

exports[`process (no-i18n.vue) returns expected string: no-i18n.vue 1`] = `""`;
exports[`process (no-i18n.vue) returns expected string: no-i18n.vue 1`] = `Array []`;

exports[`process (yaml.vue) returns expected string: yaml.vue 1`] = `
"__vue__options__.__i18n = [
'{\\"ja\\":{\\"hello\\":\\"こんにちは!\\"},\\"en\\":{\\"hello\\":\\"hello!\\"}}'
]"
Array [
"Component.__i18n = Component.__i18n || [];",
"Component.__i18n.push({\\"locale\\":\\"\\",\\"resource\\":{\\"ja\\":{\\"hello\\":\\"こんにちは!\\"},\\"en\\":{\\"hello\\":\\"hello!\\"}}});",
]
`;

exports[`process (yaml-locale.vue) returns expected string: yaml-locale.vue 1`] = `
"__vue__options__.__i18n = [
'{\\"ja\\":{\\"hello\\":\\"こんにちは!\\"}}',
'{\\"en\\":{\\"hello\\":\\"hello!\\"}}'
]"
Array [
"Component.__i18n = Component.__i18n || [];",
"Component.__i18n.push({\\"locale\\":\\"ja\\",\\"resource\\":{\\"hello\\":\\"こんにちは!\\"}});",
"Component.__i18n.push({\\"locale\\":\\"en\\",\\"resource\\":{\\"hello\\":\\"hello!\\"}});",
]
`;

exports[`process (yaml-src-import.vue) returns expected string: yaml-src-import.vue 1`] = `
"__vue__options__.__i18n = [
'{\\"ja\\":{\\"hello\\":\\"こんにちは!\\"},\\"en\\":{\\"hello\\":\\"hello!\\"}}'
]"
Array [
"Component.__i18n = Component.__i18n || [];",
"Component.__i18n.push({\\"locale\\":\\"\\",\\"resource\\":{\\"ja\\":{\\"hello\\":\\"こんにちは!\\"},\\"en\\":{\\"hello\\":\\"hello!\\"}}});",
]
`;
2 changes: 1 addition & 1 deletion test/process.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ describe('process', () => {
const fileContent = readFileSync(filePath).toString()
const { customBlocks: blocks } = parseComponent(fileContent)

const code = process({ blocks, vueOptionsNamespace: '__vue__options__', filename: filePath })
const code = process({ blocks, componentNamespace: 'Component', filename: filePath })

expect(code).toMatchSnapshot(file)
})
Expand Down

0 comments on commit d21ed55

Please sign in to comment.