diff --git a/addons/docs/jest.config.js b/addons/docs/jest.config.js new file mode 100644 index 000000000000..3303f51ba1b8 --- /dev/null +++ b/addons/docs/jest.config.js @@ -0,0 +1,9 @@ +module.exports = { + testEnvironment: 'node', + transform: { + '^.+\\.stories\\.[jt]sx?$': '@storybook/addon-storyshots/injectFileName', + '^.+\\.[jt]sx?$': '../../scripts/babel-jest.js', + '^.+\\.mdx$': '@storybook/addon-docs/jest-transform-mdx', + '^.+\\.vue$': 'vue-jest' + } +}; diff --git a/addons/docs/package.json b/addons/docs/package.json index 3347b56b8368..ee3c611349fc 100644 --- a/addons/docs/package.json +++ b/addons/docs/package.json @@ -87,9 +87,12 @@ "cross-spawn": "^7.0.1", "jest-specific-snapshot": "^2.0.0", "lit-html": "^1.0.0", + "memory-fs": "^0.5.0", "require-from-string": "^2.0.2", "styled-components": "^5.0.1", "tmp": "^0.1.0", + "vue-jest": "^3.0.5", + "vue-loader": "^15.9.0", "web-component-analyzer": "^1.0.3" }, "peerDependencies": { diff --git a/addons/docs/src/frameworks/vue/__testfixtures__/sfc-component/input.vue b/addons/docs/src/frameworks/vue/__testfixtures__/sfc-component/input.vue new file mode 100644 index 000000000000..595bf4017589 --- /dev/null +++ b/addons/docs/src/frameworks/vue/__testfixtures__/sfc-component/input.vue @@ -0,0 +1,70 @@ + + + + + diff --git a/addons/docs/src/frameworks/vue/vue-properties.test.ts b/addons/docs/src/frameworks/vue/vue-properties.test.ts new file mode 100644 index 000000000000..9d1c9c66868e --- /dev/null +++ b/addons/docs/src/frameworks/vue/vue-properties.test.ts @@ -0,0 +1,110 @@ +import 'jest-specific-snapshot'; +import path from 'path'; +import fs from 'fs'; +import Memoryfs from 'memory-fs'; +import VueLoaderPlugin from 'vue-loader/lib/plugin'; +import webpack from 'webpack'; + +import { transformFileSync, transformSync } from '@babel/core'; +import requireFromString from 'require-from-string'; + +import { extractProps } from './extractProps'; + +// File hierarchy: +// __testfixtures__ / some-test-case / input.* +const inputRegExp = /^input\..*$/; + +const transformToModule = (inputCode: string) => { + const options = { + presets: [ + [ + '@babel/preset-env', + { + targets: { + esmodules: true, + }, + }, + ], + ], + }; + const { code } = transformSync(inputCode, options); + return normalizeNewlines(code); +}; + +const annotateWithDocgen = (inputPath: string) => { + const options = {}; + const compiler = webpack({ + context: __dirname, + entry: inputPath, + output: { + path: path.resolve(__dirname), + filename: 'bundle.js', + }, + module: { + rules: [ + { + test: /\.vue$/, + use: [{ loader: 'vue-loader' }], + }, + { + test: /\.vue$/, + enforce: 'post', + loader: 'vue-docgen-loader', + options, + }, + { + test: /\.vue.js$/, + enforce: 'post', + loader: 'vue-docgen-loader', + options, + }, + ], + }, + plugins: [new VueLoaderPlugin()], + }); + + compiler.outputFileSystem = new Memoryfs(); + + return new Promise((resolve, reject) => { + compiler.run((err, stats) => { + if (err) { + return reject(err); + } + + if (stats.hasErrors()) { + return reject(new Error(stats.toJson().errors.join(','))); + } + + return resolve(stats); + }); + }); +}; + +const normalizeNewlines = (string: string) => string.replace(/\\r\\n/g, '\\n'); + +describe('react component properties', () => { + const fixturesDir = path.join(__dirname, '__testfixtures__'); + fs.readdirSync(fixturesDir, { withFileTypes: true }).forEach(testEntry => { + if (testEntry.isDirectory()) { + const testDir = path.join(fixturesDir, testEntry.name); + const testFile = fs.readdirSync(testDir).find(fileName => inputRegExp.test(fileName)); + if (testFile) { + it(testEntry.name, async () => { + const inputPath = path.join(testDir, testFile); + + // snapshot the output of babel-plugin-react-docgen + const docgenPretty = (await annotateWithDocgen(inputPath)) as string; + expect(docgenPretty).toMatchSpecificSnapshot(path.join(testDir, 'docgen.snapshot')); + + // transform into an uglier format that's works with require-from-string + const docgenModule = transformToModule(docgenPretty); + + // snapshot the output of component-properties/react + const { component } = requireFromString(docgenModule); + const properties = extractProps(component); + expect(properties).toMatchSpecificSnapshot(path.join(testDir, 'properties.snapshot')); + }); + } + } + }); +}); diff --git a/addons/docs/src/typings.d.ts b/addons/docs/src/typings.d.ts index 4a41c83bba2e..be2af1e45b1f 100644 --- a/addons/docs/src/typings.d.ts +++ b/addons/docs/src/typings.d.ts @@ -8,6 +8,8 @@ declare module 'remark-slug'; declare module 'remark-external-links'; declare module 'babel-plugin-react-docgen'; declare module 'require-from-string'; +declare module 'memory-fs'; +declare module 'vue-loader/lib/plugin'; declare module 'tmp'; declare module 'cross-spawn'; declare module 'styled-components'; diff --git a/yarn.lock b/yarn.lock index 6a07d64d0452..15d3506c8fef 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4288,6 +4288,16 @@ resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e" integrity sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw== +"@types/strip-bom@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/strip-bom/-/strip-bom-3.0.0.tgz#14a8ec3956c2e81edb7520790aecf21c290aebd2" + integrity sha1-FKjsOVbC6B7bdSB5CuzyHCkK69I= + +"@types/strip-json-comments@0.0.30": + version "0.0.30" + resolved "https://registry.yarnpkg.com/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz#9aa30c04db212a9a0649d6ae6fd50accc40748a1" + integrity sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ== + "@types/symlink-or-copy@^1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@types/symlink-or-copy/-/symlink-or-copy-1.2.0.tgz#4151a81b4052c80bc2becbae09f3a9ec010a9c7a" @@ -6405,7 +6415,7 @@ babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015 babel-runtime "^6.22.0" babel-template "^6.24.1" -babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.1: +babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.1, babel-plugin-transform-es2015-modules-commonjs@^6.26.0: version "6.26.2" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz#58a793863a9e7ca870bdc5a881117ffac27db6f3" integrity sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q== @@ -8900,16 +8910,16 @@ clone-response@1.0.2, clone-response@^1.0.2: dependencies: mimic-response "^1.0.0" +clone@2.x, clone@^2.0.0, clone@^2.1.1, clone@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" + integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18= + clone@^1.0.1, clone@^1.0.2: version "1.0.4" resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= -clone@^2.0.0, clone@^2.1.1, clone@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" - integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18= - closest-file-data@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/closest-file-data/-/closest-file-data-0.1.4.tgz#975f87c132f299d24a0375b9f63ca3fb88f72b3a" @@ -9270,7 +9280,7 @@ concurrently@^5.0.2, concurrently@^5.1.0: tree-kill "^1.2.2" yargs "^13.3.0" -config-chain@^1.1.11: +config-chain@^1.1.11, config-chain@^1.1.12: version "1.1.12" resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.12.tgz#0fde8d091200eb5e808caf25fe618c02f48e4efa" integrity sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA== @@ -10035,7 +10045,7 @@ css-what@^3.2.1: resolved "https://registry.yarnpkg.com/css-what/-/css-what-3.2.1.tgz#f4a8f12421064621b456755e34a03a2c22df5da1" integrity sha512-WwOrosiQTvyms+Ti5ZC5vGEK0Vod3FTt1ca+payZqvKuGJF+dq7bG63DstxtN0dpm6FxY27a/zS3Wten+gEtGw== -css@^2.0.0, css@^2.2.1, css@^2.2.4: +css@^2.0.0, css@^2.1.0, css@^2.2.1, css@^2.2.4: version "2.2.4" resolved "https://registry.yarnpkg.com/css/-/css-2.2.4.tgz#c646755c73971f2bba6a601e2cf2fd71b1298929" integrity sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw== @@ -11170,6 +11180,16 @@ editions@^1.1.1: resolved "https://registry.yarnpkg.com/editions/-/editions-1.3.4.tgz#3662cb592347c3168eb8e498a0ff73271d67f50b" integrity sha512-gzao+mxnYDzIysXKMQi/+M1mjy/rjestjg6OPoYTtI+3Izp23oiGZitsl9lPDPiTGXbcSIk1iJWhliSaglxnUg== +editorconfig@^0.15.3: + version "0.15.3" + resolved "https://registry.yarnpkg.com/editorconfig/-/editorconfig-0.15.3.tgz#bef84c4e75fb8dcb0ce5cee8efd51c15999befc5" + integrity sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g== + dependencies: + commander "^2.19.0" + lru-cache "^4.1.5" + semver "^5.6.0" + sigmund "^1.0.1" + ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" @@ -13017,6 +13037,13 @@ extglob@^2.0.4: snapdragon "^0.8.1" to-regex "^3.0.1" +extract-from-css@^0.4.4: + version "0.4.4" + resolved "https://registry.yarnpkg.com/extract-from-css/-/extract-from-css-0.4.4.tgz#1ea7df2e7c7c6eb9922fa08e8adaea486f6f8f92" + integrity sha1-HqffLnx8brmSL6COitrqSG9vj5I= + dependencies: + css "^2.1.0" + extract-zip@1.6.7, extract-zip@^1.6.6: version "1.6.7" resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.6.7.tgz#a840b4b8af6403264c8db57f4f1a74333ef81fe9" @@ -17758,6 +17785,17 @@ js-base64@^2.1.8: resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.5.1.tgz#1efa39ef2c5f7980bb1784ade4a8af2de3291121" integrity sha512-M7kLczedRMYX4L8Mdh4MzyAMM9O5osx+4FcOQuTvr3A9F2D9S5JXheN0ewNbrvK2UatkTRhL5ejGmGSjNMiZuw== +js-beautify@^1.6.14: + version "1.10.3" + resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.10.3.tgz#c73fa10cf69d3dfa52d8ed624f23c64c0a6a94c1" + integrity sha512-wfk/IAWobz1TfApSdivH5PJ0miIHgDoYb1ugSqHcODPmaYu46rYe5FVuIEkhjg8IQiv6rDNPyhsqbsohI/C2vQ== + dependencies: + config-chain "^1.1.12" + editorconfig "^0.15.3" + glob "^7.1.3" + mkdirp "~0.5.1" + nopt "~4.0.1" + js-levenshtein@^1.1.3: version "1.1.6" resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.6.tgz#c6cee58eb3550372df8deb85fad5ce66ce01d59d" @@ -20704,6 +20742,14 @@ node-ask@^1.0.1: resolved "https://registry.yarnpkg.com/node-ask/-/node-ask-1.0.1.tgz#caaa1076cc58e0364267a0903e3eadfac158396b" integrity sha1-yqoQdsxY4DZCZ6CQPj6t+sFYOWs= +node-cache@^4.1.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/node-cache/-/node-cache-4.2.1.tgz#efd8474dee4edec4138cdded580f5516500f7334" + integrity sha512-BOb67bWg2dTyax5kdef5WfU3X8xu4wPg+zHzkvls0Q/QpYycIFRLEEIdAx9Wma43DxG6Qzn4illdZoYseKWa4A== + dependencies: + clone "2.x" + lodash "^4.17.15" + node-cleanup@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/node-cleanup/-/node-cleanup-2.1.2.tgz#7ac19abd297e09a7f72a71545d951b517e4dde2c" @@ -20938,7 +20984,7 @@ nodemon@^2.0.2: dependencies: abbrev "1" -nopt@^4.0.1: +nopt@^4.0.1, nopt@~4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00= @@ -26898,6 +26944,11 @@ side-channel@^1.0.2: es-abstract "^1.17.0-next.1" object-inspect "^1.7.0" +sigmund@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" + integrity sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA= + signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" @@ -27991,7 +28042,7 @@ strip-indent@^3.0.0: dependencies: min-indent "^1.0.0" -strip-json-comments@^2.0.1, strip-json-comments@~2.0.1: +strip-json-comments@^2.0.0, strip-json-comments@^2.0.1, strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= @@ -29140,6 +29191,16 @@ tsconfig-paths@^3.4.0: minimist "^1.2.0" strip-bom "^3.0.0" +tsconfig@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/tsconfig/-/tsconfig-7.0.0.tgz#84538875a4dc216e5c4a5432b3a4dec3d54e91b7" + integrity sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw== + dependencies: + "@types/strip-bom" "^3.0.0" + "@types/strip-json-comments" "0.0.30" + strip-bom "^3.0.0" + strip-json-comments "^2.0.0" + tslib@1.10.0, tslib@^1.10.0, tslib@^1.7.1, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: version "1.10.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" @@ -30292,6 +30353,22 @@ vue-hot-reload-api@^2.3.0: resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz#532955cc1eb208a3d990b3a9f9a70574657e08f2" integrity sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog== +vue-jest@^3.0.5: + version "3.0.5" + resolved "https://registry.yarnpkg.com/vue-jest/-/vue-jest-3.0.5.tgz#d6f124b542dcbff207bf9296c19413f4c40b70c9" + integrity sha512-xWDxde91pDqYBGDlODENZ3ezPgw+IQFoVDtf+5Awlg466w3KvMSqWzs8PxcTeTr+wmAHi0j+a+Lm3R7aUJa1jA== + dependencies: + babel-plugin-transform-es2015-modules-commonjs "^6.26.0" + chalk "^2.1.0" + extract-from-css "^0.4.4" + find-babel-config "^1.1.0" + js-beautify "^1.6.14" + node-cache "^4.1.1" + object-assign "^4.1.1" + source-map "^0.5.6" + tsconfig "^7.0.0" + vue-template-es2015-compiler "^1.6.0" + vue-loader@^15.7.0: version "15.8.3" resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-15.8.3.tgz#857cb9e30eb5fc25e66db48dce7e4f768602a23c" @@ -30303,6 +30380,17 @@ vue-loader@^15.7.0: vue-hot-reload-api "^2.3.0" vue-style-loader "^4.1.0" +vue-loader@^15.9.0: + version "15.9.0" + resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-15.9.0.tgz#5d4b0378a4606188fc83e587ed23c94bc3a10998" + integrity sha512-FeDHvTSpwyLeF7LIV1PYkvqUQgTJ8UmOxhSlCyRSxaXCKk+M6NF4tDQsLsPPNeDPyR7TfRQ8MLg6v+8PsDV9xQ== + dependencies: + "@vue/component-compiler-utils" "^3.1.0" + hash-sum "^1.0.2" + loader-utils "^1.1.0" + vue-hot-reload-api "^2.3.0" + vue-style-loader "^4.1.0" + vue-property-decorator@8.3.0: version "8.3.0" resolved "https://registry.yarnpkg.com/vue-property-decorator/-/vue-property-decorator-8.3.0.tgz#536f027dc7d626f37c8d85a2dc02f0a6cb979440" @@ -30326,7 +30414,7 @@ vue-template-compiler@^2.0.0, vue-template-compiler@^2.6.8: de-indent "^1.0.2" he "^1.1.0" -vue-template-es2015-compiler@^1.9.0: +vue-template-es2015-compiler@^1.6.0, vue-template-es2015-compiler@^1.9.0: version "1.9.1" resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz#1ee3bc9a16ecbf5118be334bb15f9c46f82f5825" integrity sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==