From 6298055a929ce738c1a1ad485057f753bca6536c Mon Sep 17 00:00:00 2001 From: kazuya kawaguchi Date: Sat, 10 Jul 2021 13:39:38 +0900 Subject: [PATCH 1/2] feat: support custom blocks for Vue 3 --- e2e/3.x/custom-block/babel.config.js | 3 ++ e2e/3.x/custom-block/components/Basic.vue | 20 ++++++++++++ e2e/3.x/custom-block/package.json | 38 +++++++++++++++++++++++ e2e/3.x/custom-block/test.js | 34 ++++++++++++++++++++ e2e/3.x/custom-block/transformer.js | 6 ++++ 5 files changed, 101 insertions(+) create mode 100644 e2e/3.x/custom-block/babel.config.js create mode 100644 e2e/3.x/custom-block/components/Basic.vue create mode 100644 e2e/3.x/custom-block/package.json create mode 100644 e2e/3.x/custom-block/test.js create mode 100644 e2e/3.x/custom-block/transformer.js diff --git a/e2e/3.x/custom-block/babel.config.js b/e2e/3.x/custom-block/babel.config.js new file mode 100644 index 00000000..7db9b6f5 --- /dev/null +++ b/e2e/3.x/custom-block/babel.config.js @@ -0,0 +1,3 @@ +module.exports = { + presets: ['@babel/preset-env'] +} diff --git a/e2e/3.x/custom-block/components/Basic.vue b/e2e/3.x/custom-block/components/Basic.vue new file mode 100644 index 00000000..b40054ac --- /dev/null +++ b/e2e/3.x/custom-block/components/Basic.vue @@ -0,0 +1,20 @@ + + + + + +{ + "en": { + "hello": "Hello!" + }, + "ja": { + "hello": "こんにちは!" + } +} + diff --git a/e2e/3.x/custom-block/package.json b/e2e/3.x/custom-block/package.json new file mode 100644 index 00000000..4aa71f4a --- /dev/null +++ b/e2e/3.x/custom-block/package.json @@ -0,0 +1,38 @@ +{ + "name": "vue3-custom-block", + "version": "1.0.0", + "license": "MIT", + "private": true, + "scripts": { + "test": "jest --no-cache --coverage test.js" + }, + "dependencies": { + "vue": "^3.0.3" + }, + "devDependencies": { + "@babel/core": "^7.9.0", + "@babel/preset-env": "^7.9.0", + "@vue/compiler-sfc": "^3.0.3", + "jest": "^26.0.0", + "vue3-jest": "^26.0.0-alpha.10" + }, + "jest": { + "moduleFileExtensions": [ + "js", + "json", + "vue" + ], + "transform": { + "^.+\\.js$": "babel-jest", + "^.+\\.vue$": "vue3-jest" + }, + "moduleNameMapper": { + "^~?__styles/(.*)$": "/components/styles/$1" + }, + "globals": { + "vue-jest": { + "custom": "./transformer.js" + } + } + } +} diff --git a/e2e/3.x/custom-block/test.js b/e2e/3.x/custom-block/test.js new file mode 100644 index 00000000..4ffcb2f8 --- /dev/null +++ b/e2e/3.x/custom-block/test.js @@ -0,0 +1,34 @@ +import { createApp, h } from 'vue' + +import Basic from './components/Basic.vue' + +function mount(Component, props, slots) { + document.getElementsByTagName('html')[0].innerHTML = '' + const el = document.createElement('div') + el.id = 'app' + document.body.appendChild(el) + const Parent = { + render() { + return h(Component, props, slots) + } + } + return createApp(Parent).mount(el) +} + +test('custom block transformer', () => { + // const filePath = resolve(__dirname, './components/I18n.vue') + // const fileString = readFileSync(filePath, { encoding: 'utf8' }) + + // const { code } = jestVue.process(fileString, filePath, { + // moduleFileExtensions: ['js', 'vue'], + // transform: { + // "^.+\\.js$": "babel-jest", + // "^.+\\.vue$": "vue3-jest" + // }, + // }) + + // expect(code).toMatchSnapshot() + console.log('basic', Basic) + // const wrapper = mount(I18n) + // console.log(wrapper) +}) diff --git a/e2e/3.x/custom-block/transformer.js b/e2e/3.x/custom-block/transformer.js new file mode 100644 index 00000000..c94afaed --- /dev/null +++ b/e2e/3.x/custom-block/transformer.js @@ -0,0 +1,6 @@ +module.exports = { + process({ blocks, vueOptionsNamespace, filename, config }) { + console.log('custom block transformer', blocks, '---', config) + return '' + } +} From 522f99c353ee34e71627b6b7f10ababb3de299d8 Mon Sep 17 00:00:00 2001 From: kazuya kawaguchi Date: Mon, 12 Jul 2021 00:45:30 +0900 Subject: [PATCH 2/2] implement custom blocks --- .../custom-block/__snapshots__/test.js.snap | 30 ++++++++++ e2e/3.x/custom-block/components/Multiple.vue | 26 +++++++++ e2e/3.x/custom-block/package.json | 4 +- e2e/3.x/custom-block/test.js | 57 +++++++++---------- e2e/3.x/custom-block/transformer.js | 21 ++++++- packages/vue3-jest/lib/constants.js | 2 +- packages/vue3-jest/lib/generate-code.js | 14 ++++- .../vue3-jest/lib/process-custom-blocks.js | 16 +++--- packages/vue3-jest/lib/process.js | 22 ++++--- 9 files changed, 139 insertions(+), 53 deletions(-) create mode 100644 e2e/3.x/custom-block/__snapshots__/test.js.snap create mode 100644 e2e/3.x/custom-block/components/Multiple.vue diff --git a/e2e/3.x/custom-block/__snapshots__/test.js.snap b/e2e/3.x/custom-block/__snapshots__/test.js.snap new file mode 100644 index 00000000..dba5165c --- /dev/null +++ b/e2e/3.x/custom-block/__snapshots__/test.js.snap @@ -0,0 +1,30 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Basic 1`] = ` +Array [ + Object { + "en": Object { + "hello": "Hello!", + }, + "ja": Object { + "hello": "こんにちは!", + }, + }, +] +`; + +exports[`Multiple blocks 1`] = ` +Array [ + Object { + "en": Object { + "hello": "Hello!", + }, + "ja": Object { + "hello": "こんにちは!", + }, + }, + Object { + "foo": "foo", + }, +] +`; diff --git a/e2e/3.x/custom-block/components/Multiple.vue b/e2e/3.x/custom-block/components/Multiple.vue new file mode 100644 index 00000000..f204d041 --- /dev/null +++ b/e2e/3.x/custom-block/components/Multiple.vue @@ -0,0 +1,26 @@ + + + + + +{ + "en": { + "hello": "Hello!" + }, + "ja": { + "hello": "こんにちは!" + } +} + + + +{ + "foo": "foo" +} + diff --git a/e2e/3.x/custom-block/package.json b/e2e/3.x/custom-block/package.json index 4aa71f4a..9585c34c 100644 --- a/e2e/3.x/custom-block/package.json +++ b/e2e/3.x/custom-block/package.json @@ -31,7 +31,9 @@ }, "globals": { "vue-jest": { - "custom": "./transformer.js" + "transform": { + "custom": "./transformer.js" + } } } } diff --git a/e2e/3.x/custom-block/test.js b/e2e/3.x/custom-block/test.js index 4ffcb2f8..79556a9c 100644 --- a/e2e/3.x/custom-block/test.js +++ b/e2e/3.x/custom-block/test.js @@ -1,34 +1,33 @@ -import { createApp, h } from 'vue' - import Basic from './components/Basic.vue' +import Multiple from './components/Multiple.vue' -function mount(Component, props, slots) { - document.getElementsByTagName('html')[0].innerHTML = '' - const el = document.createElement('div') - el.id = 'app' - document.body.appendChild(el) - const Parent = { - render() { - return h(Component, props, slots) +test('Basic', () => { + expect(Basic.__custom).toMatchObject([ + { + en: { + hello: 'Hello!' + }, + ja: { + hello: 'こんにちは!' + } } - } - return createApp(Parent).mount(el) -} - -test('custom block transformer', () => { - // const filePath = resolve(__dirname, './components/I18n.vue') - // const fileString = readFileSync(filePath, { encoding: 'utf8' }) - - // const { code } = jestVue.process(fileString, filePath, { - // moduleFileExtensions: ['js', 'vue'], - // transform: { - // "^.+\\.js$": "babel-jest", - // "^.+\\.vue$": "vue3-jest" - // }, - // }) + ]) + expect(Basic.__custom).toMatchSnapshot() +}) - // expect(code).toMatchSnapshot() - console.log('basic', Basic) - // const wrapper = mount(I18n) - // console.log(wrapper) +test('Multiple blocks', () => { + expect(Multiple.__custom).toMatchObject([ + { + en: { + hello: 'Hello!' + }, + ja: { + hello: 'こんにちは!' + } + }, + { + foo: 'foo' + } + ]) + expect(Multiple.__custom).toMatchSnapshot() }) diff --git a/e2e/3.x/custom-block/transformer.js b/e2e/3.x/custom-block/transformer.js index c94afaed..e51da0f5 100644 --- a/e2e/3.x/custom-block/transformer.js +++ b/e2e/3.x/custom-block/transformer.js @@ -1,6 +1,21 @@ +function convert(content) { + return JSON.stringify(JSON.parse(content)) + .replace(/\u2028/g, '\\u2028') // LINE SEPARATOR + .replace(/\u2029/g, '\\u2029') // PARAGRAPH SEPARATOR + .replace(/\\/g, '\\\\') + .replace(/'/g, "\\'") +} + module.exports = { - process({ blocks, vueOptionsNamespace, filename, config }) { - console.log('custom block transformer', blocks, '---', config) - return '' + process({ blocks, componentNamespace, filename, config }) { + const ret = blocks.reduce((codes, block) => { + codes.push( + `${componentNamespace}.__custom = ${componentNamespace}.__custom || [];${componentNamespace}.__custom.push(${convert( + block.content + )});` + ) + return codes + }, []) + return ret } } diff --git a/packages/vue3-jest/lib/constants.js b/packages/vue3-jest/lib/constants.js index 742ef7d4..3bcab3f5 100644 --- a/packages/vue3-jest/lib/constants.js +++ b/packages/vue3-jest/lib/constants.js @@ -1,5 +1,5 @@ module.exports = { - vueOptionsNamespace: '__options__', + vueComponentNamespace: 'Component', defaultVueJestConfig: { transform: {} } diff --git a/packages/vue3-jest/lib/generate-code.js b/packages/vue3-jest/lib/generate-code.js index f4af783a..d6f406b8 100644 --- a/packages/vue3-jest/lib/generate-code.js +++ b/packages/vue3-jest/lib/generate-code.js @@ -15,13 +15,15 @@ function addToSourceMap(node, result) { } } -module.exports = function generateCode( +module.exports = function generateCode({ scriptResult, scriptSetupResult, templateResult, + customBlocksResult, + componentNamespace, filename, stylesResult -) { +}) { var node = new SourceNode(null, null, null) addToSourceMap(node, scriptResult) addToSourceMap(node, scriptSetupResult) @@ -63,5 +65,13 @@ module.exports = function generateCode( ) } + if (Array.isArray(customBlocksResult)) { + customBlocksResult.forEach(codes => { + codes.forEach(code => { + node.add(`;((${componentNamespace}) => { ${code} })(exports.default);`) + }) + }) + } + return node.toStringWithSourceMap({ file: filename }) } diff --git a/packages/vue3-jest/lib/process-custom-blocks.js b/packages/vue3-jest/lib/process-custom-blocks.js index 17516fa5..e5926eef 100644 --- a/packages/vue3-jest/lib/process-custom-blocks.js +++ b/packages/vue3-jest/lib/process-custom-blocks.js @@ -1,14 +1,13 @@ const { getVueJestConfig, getCustomTransformer } = require('./utils') -const vueOptionsNamespace = require('./constants').vueOptionsNamespace function applyTransformer( transformer, blocks, - vueOptionsNamespace, + componentNamespace, filename, config ) { - return transformer.process({ blocks, vueOptionsNamespace, filename, config }) + return transformer.process({ blocks, componentNamespace, filename, config }) } function groupByType(acc, block) { @@ -17,9 +16,9 @@ function groupByType(acc, block) { return acc } -module.exports = function(allBlocks, filename, config) { +module.exports = (allBlocks, filename, componentNamespace, config) => { const blocksByType = allBlocks.reduce(groupByType, {}) - const code = [] + const codes = [] for (const [type, blocks] of Object.entries(blocksByType)) { const transformer = getCustomTransformer( getVueJestConfig(config).transform, @@ -29,13 +28,12 @@ module.exports = function(allBlocks, filename, config) { const codeStr = applyTransformer( transformer, blocks, - vueOptionsNamespace, + componentNamespace, filename, config ) - code.push(codeStr) + codes.push(codeStr) } } - - return code.length ? code.join('\n') : '' + return codes } diff --git a/packages/vue3-jest/lib/process.js b/packages/vue3-jest/lib/process.js index d16f330f..82b19621 100644 --- a/packages/vue3-jest/lib/process.js +++ b/packages/vue3-jest/lib/process.js @@ -5,7 +5,7 @@ const babelTransformer = require('babel-jest') const typescriptTransformer = require('./transformers/typescript') const coffeescriptTransformer = require('./transformers/coffee') const _processStyle = require('./process-style') -// const processCustomBlocks = require('./process-custom-blocks') +const processCustomBlocks = require('./process-custom-blocks') const getVueJestConfig = require('./utils').getVueJestConfig const getTsJestConfig = require('./utils').getTsJestConfig const logResultErrors = require('./utils').logResultErrors @@ -14,6 +14,7 @@ const getCustomTransformer = require('./utils').getCustomTransformer const loadSrc = require('./utils').loadSrc const generateCode = require('./generate-code') const mapLines = require('./map-lines') +const vueComponentNamespace = require('./constants').vueComponentNamespace function resolveTransformer(lang = 'js', vueJestConfig) { const transformer = getCustomTransformer(vueJestConfig['transform'], lang) @@ -133,23 +134,28 @@ function processStyle(styles, filename, config) { module.exports = function(src, filename, config) { const { descriptor } = parse(src, { filename }) + const componentNamespace = + getVueJestConfig(config)['componentNamespace'] || vueComponentNamespace const templateResult = processTemplate(descriptor, filename, config) const scriptResult = processScript(descriptor.script, filename, config) const scriptSetupResult = processScriptSetup(descriptor, filename, config) const stylesResult = processStyle(descriptor.styles, filename, config) - // const customBlocksResult = processCustomBlocks( - // descriptor.customBlocks, - // filename, - // config - // ) - const output = generateCode( + const customBlocksResult = processCustomBlocks( + descriptor.customBlocks, + filename, + componentNamespace, + config + ) + const output = generateCode({ scriptResult, scriptSetupResult, templateResult, + customBlocksResult, + componentNamespace, filename, stylesResult - ) + }) return { code: output.code,