From d21ed55e4cb10ac73618470ef67cbb6235f38414 Mon Sep 17 00:00:00 2001 From: XavierChevalier Date: Tue, 30 Nov 2021 17:19:06 +0100 Subject: [PATCH] feat: support vue-jest@v5 (#23) Refs: #23 --- e2e/package.json | 2 +- package.json | 2 +- src/process.ts | 64 ++++++++++---------- test/__snapshots__/process.test.ts.snap | 78 ++++++++++++++----------- test/process.test.ts | 2 +- 5 files changed, 78 insertions(+), 70 deletions(-) diff --git a/e2e/package.json b/e2e/package.json index 71a312e..9ee53ac 100644 --- a/e2e/package.json +++ b/e2e/package.json @@ -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" } } diff --git a/package.json b/package.json index 22d4e07..ae5ebc6 100644 --- a/package.json +++ b/package.json @@ -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": { diff --git a/src/process.ts b/src/process.ts index 7869cd1..ca49817 100644 --- a/src/process.ts +++ b/src/process.ts @@ -14,36 +14,40 @@ 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 /** * 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 = [ - // '', - // '' - // ] - 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 } /** @@ -51,37 +55,31 @@ export default function process ({ blocks, vueOptionsNamespace, filename }: Proc * @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 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) } } diff --git a/test/__snapshots__/process.test.ts.snap b/test/__snapshots__/process.test.ts.snap index bca3444..f69ac18 100644 --- a/test/__snapshots__/process.test.ts.snap +++ b/test/__snapshots__/process.test.ts.snap @@ -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!\\"}}});", +] `; diff --git a/test/process.test.ts b/test/process.test.ts index ce1f89a..35f01d1 100644 --- a/test/process.test.ts +++ b/test/process.test.ts @@ -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) })