diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index de8b0335..00000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,27 +0,0 @@ -version: 2 -jobs: - build: - docker: - - image: circleci/node:10.16.3 - - working_directory: ~/repo - - steps: - - checkout - - # Download and cache dependencies - - restore_cache: - keys: - - node-10-dependencies-{{ checksum "package.json" }} - # fallback to using the latest cache if no exact match is found - - node-10-dependencies- - - - run: yarn install - - - save_cache: - paths: - - node_modules - key: node-10-dependencies-{{ checksum "package.json" }} - - # run tests! - - run: yarn test diff --git a/.github/workflows/node.yml b/.github/workflows/node.yml index b19bf866..c0675923 100644 --- a/.github/workflows/node.yml +++ b/.github/workflows/node.yml @@ -20,26 +20,17 @@ jobs: test: strategy: matrix: - node: [10, 12, 14] + node: [14, 16, 18] runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Use Node.js ${{ matrix.node }} - uses: actions/setup-node@v2 + uses: actions/setup-node@v3 with: node-version: ${{ matrix.node }} + cache: yarn - - name: Get yarn cache directory path - id: yarn-cache - run: echo "::set-output name=dir::$(yarn cache dir)" - - name: Cache Dependencies - uses: actions/cache@v2 - with: - path: ${{ steps.yarn-cache.outputs.dir }} - key: yarn-${{ hashFiles('**/yarn.lock') }} - restore-keys: | - yarn- - name: Install Project Dependencies run: yarn --frozen-lockfile diff --git a/.gitignore b/.gitignore index 03280d22..606f99ec 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,6 @@ pids *.pid.lock package-lock.json +/e2e/**/yarn.lock + +.vscode diff --git a/README.md b/README.md index d23bea16..38e53f22 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,290 @@ -# vue-jest-next +# vue-jest -Jest Vue transformer for Vue 3 with source map support (WIP). +Jest transformer for Vue Single File Components. -Docs for current stable version (targeting Vue 2.x): https://github.com/vuejs/vue-jest/ +## Installation -## TODO (supported in vue-jest@4.x but not vue-jest@next): +Since we need to support a variety of Vue and Jest versions, vue-jest doesn't follow semantic versioning. -- [ ] Support loading styles -- [ ] Support custom blocks +| Vue version | Jest Version | npm Package | Branch | +| ----------- | ----------------- | ------------------- | ------ | +| Vue 2 | Jest 26 and below | `vue-jest@4` | | +| Vue 3 | Jest 26 and below | `vue-jest@5` | | +| Vue 2 | Jest 27 and above | `@vue/vue2-jest@27` | 27.x | +| Vue 3 | Jest 27 and above | `@vue/vue3-jest@27` | 27.x | +| Vue 2 | Jest 28 and above | `@vue/vue2-jest@28` | 28.x | +| Vue 3 | Jest 28 and above | `@vue/vue3-jest@28` | 28.x | + +```bash +# Vue 2 +npm install --save-dev @vue/vue2-jest@28 # (use the appropriate version) +yarn add @vue/vue2-jest@28 --dev + +# Vue 3 +npm install --save-dev @vue/vue3-jest@28 # (use the appropriate version) +yarn add @vue/vue3-jest@28 --dev +``` + +## Setup + +To use `vue-jest` as a transformer for your `.vue` files, map them to the appropriate `vue-jest` module: + +```json +{ + "jest": { + "transform": { + "^.+\\.vue$": "@vue/vue2-jest" // Update to match your installed version + } + } +} +``` + +A full config will look like this. + +```json +{ + "jest": { + "moduleFileExtensions": ["js", "json", "vue"], + "transform": { + "^.+\\.js$": "babel-jest", + "^.+\\.vue$": "@vue/vue2-jest" + } + } +} +``` + +### Usage with Babel 7 + +If you use [jest](https://github.com/facebook/jest) > 24.0.0 and [babel-jest](https://github.com/facebook/jest/tree/master/packages/babel-jest) make sure to install babel-core@bridge + +```bash +npm install --save-dev babel-core@bridge +yarn add babel-core@bridge --dev +``` + +## Supported languages for SFC sections + +vue-jest compiles ` diff --git a/e2e/2.x/babel-in-package/components/Coffee.vue b/e2e/2.x/babel-in-package/components/Coffee.vue new file mode 100644 index 00000000..1d3b1bed --- /dev/null +++ b/e2e/2.x/babel-in-package/components/Coffee.vue @@ -0,0 +1,8 @@ + + + diff --git a/e2e/2.x/babel-in-package/components/Tsx.vue b/e2e/2.x/babel-in-package/components/Tsx.vue new file mode 100644 index 00000000..6b1040d3 --- /dev/null +++ b/e2e/2.x/babel-in-package/components/Tsx.vue @@ -0,0 +1,14 @@ + diff --git a/e2e/2.x/babel-in-package/components/TypeScript.vue b/e2e/2.x/babel-in-package/components/TypeScript.vue new file mode 100644 index 00000000..145560ab --- /dev/null +++ b/e2e/2.x/babel-in-package/components/TypeScript.vue @@ -0,0 +1,21 @@ + + + diff --git a/e2e/2.x/babel-in-package/components/TypeScriptChild.vue b/e2e/2.x/babel-in-package/components/TypeScriptChild.vue new file mode 100644 index 00000000..985a1f72 --- /dev/null +++ b/e2e/2.x/babel-in-package/components/TypeScriptChild.vue @@ -0,0 +1,13 @@ + + + diff --git a/e2e/2.x/babel-in-package/package.json b/e2e/2.x/babel-in-package/package.json new file mode 100644 index 00000000..b9ebc577 --- /dev/null +++ b/e2e/2.x/babel-in-package/package.json @@ -0,0 +1,43 @@ +{ + "name": "vue2-babel-in-package", + "version": "1.0.0", + "license": "MIT", + "private": true, + "scripts": { + "test": "jest --no-cache test.js" + }, + "dependencies": { + "source-map": "0.5.6", + "vue": "^2.7.7", + "vue-template-compiler": "^2.7.7" + }, + "devDependencies": { + "@babel/core": "^7.9.0", + "@babel/preset-env": "^7.9.0", + "@vue/babel-preset-jsx": "^1.2.4", + "@vue/test-utils": "^1.1.0", + "@vue/vue2-jest": "^29.0.0", + "coffeescript": "^2.3.2", + "jest": "29.x", + "jest-environment-jsdom": "29.x", + "typescript": "^4.6.4" + }, + "jest": { + "testEnvironment": "jsdom", + "moduleFileExtensions": [ + "js", + "json", + "vue" + ], + "transform": { + "^.+\\.js$": "babel-jest", + "^.+\\.vue$": "@vue/vue2-jest" + } + }, + "babel": { + "presets": [ + "@babel/env", + "@vue/babel-preset-jsx" + ] + } +} diff --git a/e2e/2.x/babel-in-package/test.js b/e2e/2.x/babel-in-package/test.js new file mode 100644 index 00000000..06709f6d --- /dev/null +++ b/e2e/2.x/babel-in-package/test.js @@ -0,0 +1,25 @@ +import { mount } from '@vue/test-utils' +import TypeScript from './components/TypeScript.vue' +import Basic from './components/Basic.vue' +import Coffee from './components/Coffee.vue' +import Tsx from './components/Tsx.vue' + +test('processes .vue files', () => { + const wrapper = mount(Basic) + wrapper.vm.toggleClass() +}) + +test('processes .vue file with lang set to coffee', () => { + const wrapper = mount(Coffee) + expect(wrapper.vm).toBeTruthy() +}) + +test('processes .vue files with lang set to ts(typescript)', () => { + const wrapper = mount(TypeScript) + expect(wrapper.vm).toBeTruthy() +}) + +test('processes .vue files with lang set to tsx(typescript)', () => { + const wrapper = mount(Tsx) + expect(wrapper.text()).toContain('tsx components') +}) diff --git a/e2e/2.x/babel-in-package/tsconfig.json b/e2e/2.x/babel-in-package/tsconfig.json new file mode 100644 index 00000000..98e192f0 --- /dev/null +++ b/e2e/2.x/babel-in-package/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "ES2017", + "lib": ["dom", "es6"], + "module": "ES2015", + "moduleResolution": "node", + "types": ["vue-typescript-import-dts", "node"], + "isolatedModules": false, + "experimentalDecorators": true, + "noImplicitAny": true, + "noImplicitThis": true, + "strictNullChecks": true, + "removeComments": true, + "emitDecoratorMetadata": true, + "suppressImplicitAnyIndexErrors": true, + "allowSyntheticDefaultImports": true, + "sourceMap": true, + "esModuleInterop": true + } +} diff --git a/e2e/2.x/basic/__snapshots__/test.js.snap b/e2e/2.x/basic/__snapshots__/test.js.snap new file mode 100644 index 00000000..f8f9c647 --- /dev/null +++ b/e2e/2.x/basic/__snapshots__/test.js.snap @@ -0,0 +1,113 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`generates source maps for .vue files 1`] = ` +{ + "file": "./components/Basic.vue", + "mappings": ";;;;;;eAuBe;AACb,MAAI,EAAE,OADO;AAEb,UAAQ,EAAE;AACR,kBAAc,EAAE,SAAS,cAAT,GAA0B;AACxC,aAAO;AACL,WAAG,EAAE,KAAK,OADL;AAEL,YAAI,EAAE,CAAC,KAAK,OAFP;AAGL,cAAM,EAAE,KAAK;AAHR,OAAP;AAKD;AAPO,GAFG;AAWb,MAAI,EAAE,SAAS,IAAT,GAAgB;AACpB,WAAO;AACL,SAAG,EAAE,4BADA;AAEL,aAAO,EAAE;AAFJ,KAAP;AAID,GAhBY;AAiBb,SAAO,EAAE;AACP,eAAW,EAAE,SAAS,WAAT,GAAuB;AAClC,WAAK,OAAL,GAAe,CAAC,KAAK,OAArB;AACD;AAHM;AAjBI", + "names": [], + "sources": [ + "components/Basic.vue", + ], + "sourcesContent": [ + " + + + + + + +", + ], + "version": 3, +} +`; + +exports[`generates source maps using src attributes 1`] = ` +{ + "file": "./components/SourceMapsSrc.vue", + "mappings": ";;;;;;eAAe;AACbA,MAAI,EAAE,OADO;AAEbC,UAAQ,EAAE;AACRC,kBAAc,EAAE,SAASA,cAAT,GAA0B;AACxC,aAAO;AACLC,WAAG,EAAE,KAAKC,OADL;AAELC,YAAI,EAAE,CAAC,KAAKD,OAFP;AAGLE,cAAM,EAAE,KAAKF;AAHR,OAAP;AAKD;AAPO,GAFG;AAWbG,MAAI,EAAE,SAASA,IAAT,GAAgB;AACpB,WAAO;AACLC,SAAG,EAAE,4BADA;AAELJ,aAAO,EAAE;AAFJ,KAAP;AAID,GAhBY;AAiBbK,SAAO,EAAE;AACPC,eAAW,EAAE,SAASA,WAAT,GAAuB;AAClC,WAAKN,OAAL,GAAe,CAAC,KAAKA,OAArB;AACD;AAHM;AAjBI,C", + "names": [ + "name", + "computed", + "headingClasses", + "red", + "isCrazy", + "blue", + "shadow", + "data", + "msg", + "methods", + "toggleClass", + ], + "sources": [ + "SourceMapsSrc.vue", + ], + "sourcesContent": [ + "export default { + name: 'basic', + computed: { + headingClasses: function headingClasses() { + return { + red: this.isCrazy, + blue: !this.isCrazy, + shadow: this.isCrazy + } + } + }, + data: function data() { + return { + msg: 'Welcome to Your Vue.js App', + isCrazy: false + } + }, + methods: { + toggleClass: function toggleClass() { + this.isCrazy = !this.isCrazy + } + } +} +", + ], + "version": 3, +} +`; diff --git a/e2e/2.x/basic/babel.config.js b/e2e/2.x/basic/babel.config.js new file mode 100644 index 00000000..3ba5f43c --- /dev/null +++ b/e2e/2.x/basic/babel.config.js @@ -0,0 +1,4 @@ +module.exports = { + presets: ['@babel/preset-env'], + plugins: ['transform-vue-jsx'] +} diff --git a/e2e/2.x/basic/components/Basic.vue b/e2e/2.x/basic/components/Basic.vue new file mode 100644 index 00000000..a37429b0 --- /dev/null +++ b/e2e/2.x/basic/components/Basic.vue @@ -0,0 +1,47 @@ + + + + + + + diff --git a/e2e/2.x/basic/components/BasicSrc.html b/e2e/2.x/basic/components/BasicSrc.html new file mode 100644 index 00000000..67c4dfde --- /dev/null +++ b/e2e/2.x/basic/components/BasicSrc.html @@ -0,0 +1,3 @@ +
+

{{ msg }}

+
\ No newline at end of file diff --git a/e2e/2.x/basic/components/BasicSrc.js b/e2e/2.x/basic/components/BasicSrc.js new file mode 100644 index 00000000..3aeef17c --- /dev/null +++ b/e2e/2.x/basic/components/BasicSrc.js @@ -0,0 +1,23 @@ +export default { + name: 'basic', + computed: { + headingClasses: function headingClasses() { + return { + red: this.isCrazy, + blue: !this.isCrazy, + shadow: this.isCrazy + } + } + }, + data: function data() { + return { + msg: 'Welcome to Your Vue.js App', + isCrazy: false + } + }, + methods: { + toggleClass: function toggleClass() { + this.isCrazy = !this.isCrazy + } + } +} diff --git a/e2e/2.x/basic/components/BasicSrc.vue b/e2e/2.x/basic/components/BasicSrc.vue new file mode 100644 index 00000000..2fbf9f1e --- /dev/null +++ b/e2e/2.x/basic/components/BasicSrc.vue @@ -0,0 +1,3 @@ + + + diff --git a/e2e/2.x/basic/components/Coffee.vue b/e2e/2.x/basic/components/Coffee.vue new file mode 100644 index 00000000..1d3b1bed --- /dev/null +++ b/e2e/2.x/basic/components/Coffee.vue @@ -0,0 +1,8 @@ + + + diff --git a/e2e/2.x/basic/components/CoffeeScript.vue b/e2e/2.x/basic/components/CoffeeScript.vue new file mode 100644 index 00000000..979664d9 --- /dev/null +++ b/e2e/2.x/basic/components/CoffeeScript.vue @@ -0,0 +1,8 @@ + + + diff --git a/e2e/2.x/basic/components/Constructor.vue b/e2e/2.x/basic/components/Constructor.vue new file mode 100644 index 00000000..c81625e8 --- /dev/null +++ b/e2e/2.x/basic/components/Constructor.vue @@ -0,0 +1,9 @@ + + + diff --git a/e2e/2.x/basic/components/ExtendedTsConfig.vue b/e2e/2.x/basic/components/ExtendedTsConfig.vue new file mode 100644 index 00000000..8dc7001f --- /dev/null +++ b/e2e/2.x/basic/components/ExtendedTsConfig.vue @@ -0,0 +1,34 @@ + + + diff --git a/e2e/2.x/basic/components/FunctionalSFC.vue b/e2e/2.x/basic/components/FunctionalSFC.vue new file mode 100644 index 00000000..1395f320 --- /dev/null +++ b/e2e/2.x/basic/components/FunctionalSFC.vue @@ -0,0 +1,5 @@ + diff --git a/e2e/2.x/basic/components/FunctionalSFCParent.vue b/e2e/2.x/basic/components/FunctionalSFCParent.vue new file mode 100644 index 00000000..01509456 --- /dev/null +++ b/e2e/2.x/basic/components/FunctionalSFCParent.vue @@ -0,0 +1,14 @@ + + + diff --git a/e2e/2.x/basic/components/FunctionalSFCRender.vue b/e2e/2.x/basic/components/FunctionalSFCRender.vue new file mode 100644 index 00000000..4bf47201 --- /dev/null +++ b/e2e/2.x/basic/components/FunctionalSFCRender.vue @@ -0,0 +1,17 @@ + + + diff --git a/e2e/2.x/basic/components/Jade.vue b/e2e/2.x/basic/components/Jade.vue new file mode 100644 index 00000000..4195a137 --- /dev/null +++ b/e2e/2.x/basic/components/Jade.vue @@ -0,0 +1,9 @@ + + + diff --git a/e2e/2.x/basic/components/Jsx.vue b/e2e/2.x/basic/components/Jsx.vue new file mode 100644 index 00000000..958891b9 --- /dev/null +++ b/e2e/2.x/basic/components/Jsx.vue @@ -0,0 +1,7 @@ + diff --git a/e2e/2.x/basic/components/ModuleRequiringEsModuleInterop.js b/e2e/2.x/basic/components/ModuleRequiringEsModuleInterop.js new file mode 100644 index 00000000..fed7caa7 --- /dev/null +++ b/e2e/2.x/basic/components/ModuleRequiringEsModuleInterop.js @@ -0,0 +1 @@ +module.exports = () => false diff --git a/e2e/2.x/basic/components/NamedExport.vue b/e2e/2.x/basic/components/NamedExport.vue new file mode 100644 index 00000000..1d2c6f0f --- /dev/null +++ b/e2e/2.x/basic/components/NamedExport.vue @@ -0,0 +1,7 @@ + diff --git a/e2e/2.x/basic/components/NoScript.vue b/e2e/2.x/basic/components/NoScript.vue new file mode 100644 index 00000000..976b9f7d --- /dev/null +++ b/e2e/2.x/basic/components/NoScript.vue @@ -0,0 +1,12 @@ + + + diff --git a/e2e/2.x/basic/components/Pug.vue b/e2e/2.x/basic/components/Pug.vue new file mode 100644 index 00000000..eddf14e4 --- /dev/null +++ b/e2e/2.x/basic/components/Pug.vue @@ -0,0 +1,11 @@ + + + diff --git a/e2e/2.x/basic/components/PugBase.pug b/e2e/2.x/basic/components/PugBase.pug new file mode 100644 index 00000000..93fdad14 --- /dev/null +++ b/e2e/2.x/basic/components/PugBase.pug @@ -0,0 +1,2 @@ +div(class='pug-base') + block component \ No newline at end of file diff --git a/e2e/2.x/basic/components/PugRelativeExtends.vue b/e2e/2.x/basic/components/PugRelativeExtends.vue new file mode 100644 index 00000000..963ec0fa --- /dev/null +++ b/e2e/2.x/basic/components/PugRelativeExtends.vue @@ -0,0 +1,11 @@ + + + diff --git a/e2e/2.x/basic/components/RenderFunction.vue b/e2e/2.x/basic/components/RenderFunction.vue new file mode 100644 index 00000000..fcabb646 --- /dev/null +++ b/e2e/2.x/basic/components/RenderFunction.vue @@ -0,0 +1,8 @@ + diff --git a/e2e/2.x/basic/components/ScriptAndScriptSetup.vue b/e2e/2.x/basic/components/ScriptAndScriptSetup.vue new file mode 100644 index 00000000..e3aa2fcb --- /dev/null +++ b/e2e/2.x/basic/components/ScriptAndScriptSetup.vue @@ -0,0 +1,23 @@ + + + + + diff --git a/e2e/2.x/basic/components/ScriptSetup.vue b/e2e/2.x/basic/components/ScriptSetup.vue new file mode 100644 index 00000000..6c413862 --- /dev/null +++ b/e2e/2.x/basic/components/ScriptSetup.vue @@ -0,0 +1,20 @@ + + + diff --git a/e2e/2.x/basic/components/SourceMapsSrc.vue b/e2e/2.x/basic/components/SourceMapsSrc.vue new file mode 100644 index 00000000..2fbf9f1e --- /dev/null +++ b/e2e/2.x/basic/components/SourceMapsSrc.vue @@ -0,0 +1,3 @@ + + + diff --git a/e2e/2.x/basic/components/TemplateString.vue b/e2e/2.x/basic/components/TemplateString.vue new file mode 100644 index 00000000..7454d234 --- /dev/null +++ b/e2e/2.x/basic/components/TemplateString.vue @@ -0,0 +1,21 @@ + + + diff --git a/e2e/2.x/basic/components/TypeScript.vue b/e2e/2.x/basic/components/TypeScript.vue new file mode 100644 index 00000000..145560ab --- /dev/null +++ b/e2e/2.x/basic/components/TypeScript.vue @@ -0,0 +1,21 @@ + + + diff --git a/e2e/2.x/basic/components/TypeScriptChild.vue b/e2e/2.x/basic/components/TypeScriptChild.vue new file mode 100644 index 00000000..985a1f72 --- /dev/null +++ b/e2e/2.x/basic/components/TypeScriptChild.vue @@ -0,0 +1,13 @@ + + + diff --git a/e2e/2.x/basic/components/coffee.spec.js b/e2e/2.x/basic/components/coffee.spec.js new file mode 100644 index 00000000..163edcb2 --- /dev/null +++ b/e2e/2.x/basic/components/coffee.spec.js @@ -0,0 +1,28 @@ +import { shallowMount, mount } from '@vue/test-utils' +import Coffee from './resources/Coffee.vue' +import CoffeeScript from './resources/CoffeeScript.vue' +import CoffeeES6 from './resources/CoffeeES6.vue' +import CoffeeScriptES6 from './resources/CoffeeScriptES6.vue' + +describe('Test CoffeeScript - coffee.spec.js', () => { + test('processes .vue file with lang set to coffee', () => { + shallowMount(Coffee) + }) + + test('processes .vue file with lang set to coffeescript', () => { + shallowMount(CoffeeScript) + }) + + test('processes .vue file with lang set to coffee (ES6)', () => { + shallowMount(CoffeeES6) + }) + + test('processes .vue file with lang set to coffeescript (ES6)', () => { + shallowMount(CoffeeScriptES6) + }) + + test('processes .vue file with lang set to coffeescript (ES6)', () => { + const wrapper = mount(CoffeeScriptES6) + expect(typeof wrapper).toBe('object') + }) +}) diff --git a/e2e/2.x/basic/components/relative/PugRelativeBase.pug b/e2e/2.x/basic/components/relative/PugRelativeBase.pug new file mode 100644 index 00000000..2347fc06 --- /dev/null +++ b/e2e/2.x/basic/components/relative/PugRelativeBase.pug @@ -0,0 +1,2 @@ +div(class='pug-relative-base') + block component \ No newline at end of file diff --git a/e2e/2.x/basic/package.json b/e2e/2.x/basic/package.json new file mode 100644 index 00000000..152b804c --- /dev/null +++ b/e2e/2.x/basic/package.json @@ -0,0 +1,58 @@ +{ + "name": "vue2-basic", + "version": "1.0.0", + "license": "MIT", + "private": true, + "scripts": { + "test": "jest --no-cache --coverage test.js" + }, + "dependencies": { + "vue": "^2.7.7", + "vue-template-compiler": "^2.7.7" + }, + "devDependencies": { + "@babel/core": "^7.9.0", + "@babel/preset-env": "^7.9.0", + "@vue/test-utils": "^1.1.0", + "@vue/vue2-jest": "^29.0.0", + "babel-helper-vue-jsx-merge-props": "^2.0.3", + "babel-plugin-syntax-jsx": "^6.18.0", + "babel-plugin-transform-vue-jsx": "^3.7.0", + "coffeescript": "^2.3.2", + "jade": "^1.11.0", + "jest": "29.x", + "jest-environment-jsdom": "29.x", + "pug": "^3.0.1", + "sass": "^1.23.7", + "typescript": "^4.6.4" + }, + "jest": { + "testEnvironment": "jsdom", + "moduleFileExtensions": [ + "js", + "json", + "vue" + ], + "transform": { + "^.+\\.js$": "babel-jest", + "^.+\\.vue$": "@vue/vue2-jest" + }, + "moduleNameMapper": { + "^~?__styles/(.*)$": "/components/styles/$1" + }, + "globals": { + "vue-jest": { + "pug": { + "basedir": "./" + }, + "templateCompiler": { + "transpileOptions": { + "transforms": { + "dangerousTaggedTemplateString": true + } + } + } + } + } + } +} diff --git a/e2e/2.x/basic/test.js b/e2e/2.x/basic/test.js new file mode 100644 index 00000000..9eb6b525 --- /dev/null +++ b/e2e/2.x/basic/test.js @@ -0,0 +1,204 @@ +import { mount } from '@vue/test-utils' +import TypeScript from './components/TypeScript.vue' +import TemplateString from './components/TemplateString.vue' +import { resolve } from 'path' +import { readFileSync } from 'fs' +import jestVue from '@vue/vue2-jest' +import RenderFunction from './components/RenderFunction.vue' +import Jade from './components/Jade.vue' +import FunctionalSFC from './components/FunctionalSFC.vue' +import FunctionalSFCRender from './components/FunctionalSFCRender.vue' +import Basic from './components/Basic.vue' +import BasicSrc from './components/BasicSrc.vue' +import { randomExport } from './components/NamedExport.vue' +import Coffee from './components/Coffee.vue' +import CoffeeScript from './components/CoffeeScript.vue' +import FunctionalSFCParent from './components/FunctionalSFCParent.vue' +import NoScript from './components/NoScript.vue' +import Pug from './components/Pug.vue' +import PugRelative from './components/PugRelativeExtends.vue' +import Jsx from './components/Jsx.vue' +import Constructor from './components/Constructor.vue' +import { compileStyle } from '@vue/component-compiler-utils' +import ScriptSetup from './components/ScriptSetup' +import ScriptAndScriptSetup from './components/ScriptAndScriptSetup' +import ExtendedTsConfig from './components/ExtendedTsConfig.vue' + +jest.mock('@vue/component-compiler-utils', () => ({ + ...jest.requireActual('@vue/component-compiler-utils'), + compileStyle: jest.fn(() => ({ errors: [], code: '' })) +})) + +beforeEach(() => jest.clearAllMocks()) +test('processes .vue files', () => { + const wrapper = mount(Basic) + expect(wrapper.vm.msg).toEqual('Welcome to Your Vue.js App') + wrapper.vm.toggleClass() +}) + +test('processes .vue files with src attributes', () => { + const wrapper = mount(BasicSrc) + wrapper.vm.toggleClass() +}) + +test('handles named exports', () => { + expect(randomExport).toEqual(42) +}) + +test('generates source maps for .vue files', () => { + const filePath = './components/Basic.vue' + const fileString = readFileSync(resolve(__dirname, filePath), { + encoding: 'utf8' + }) + const config = { + moduleFileExtensions: ['js', 'vue'] + } + + const { map } = jestVue.process(fileString, filePath, { + config + }) + + expect(JSON.parse(map)).toMatchSnapshot() +}) + +test('generates source maps using src attributes', () => { + const filePath = './components/SourceMapsSrc.vue' + const fileString = readFileSync(resolve(__dirname, filePath), { + encoding: 'utf8' + }) + + const config = { moduleFileExtensions: ['js', 'vue'] } + + const { map } = jestVue.process(fileString, filePath, { config }) + + expect(JSON.parse(map)).toMatchSnapshot() +}) + +test('processes .vue file using jsx', () => { + const wrapper = mount(Jsx) + expect(wrapper.element.tagName).toBe('DIV') +}) + +test('processes extended functions', () => { + const wrapper = mount(Constructor) + expect(wrapper.element.tagName).toBe('DIV') +}) + +test('processes .vue file with lang set to coffee', () => { + const wrapper = mount(Coffee) + expect(wrapper.element.tagName).toBe('DIV') +}) + +test('processes .vue file with lang set to coffeescript', () => { + const wrapper = mount(CoffeeScript) + expect(wrapper.element.tagName).toBe('DIV') +}) + +test('processes .vue files with lang set to typescript', () => { + const wrapper = mount(TypeScript) + expect(wrapper.element.tagName).toBe('DIV') +}) + +test('processes .vue files with template strings in the template', () => { + const wrapper = mount(TemplateString) + expect(wrapper.attributes('data-sth')).toBe(` + query { + id + } + `) +}) + +test('processes functional components', () => { + const clickSpy = jest.fn() + const wrapper = mount(FunctionalSFC, { + context: { + props: { msg: { id: 1, title: 'foo' }, onClick: clickSpy } + } + }) + expect(wrapper.text().trim()).toBe('foo') + wrapper.trigger('click') + expect(clickSpy).toHaveBeenCalledWith(1) +}) + +test('processes functional components using render function', () => { + const wrapper = mount(FunctionalSFCRender) + const CSS_CLASSES = ['ModuleClass'] + expect(wrapper.classes().toString()).toBe(CSS_CLASSES.toString()) +}) + +test('processes SFC with functional template from parent', () => { + const wrapper = mount(FunctionalSFCParent) + expect(wrapper.text().trim()).toBe('foo') +}) + +test('handles missing script block', () => { + const wrapper = mount(NoScript) + expect(wrapper.element.tagName).toBe('FOOTER') +}) + +test('processes .vue file with jade template', () => { + const wrapper = mount(Jade) + expect(wrapper.element.tagName).toBe('DIV') + expect(wrapper.classes()).toContain('jade') +}) + +test('processes pug templates', () => { + const wrapper = mount(Pug) + expect(wrapper.element.tagName).toBe('DIV') + expect(wrapper.classes()).toContain('pug-base') + expect(wrapper.find('.pug-extended').exists()).toBeTruthy() +}) + +test('supports relative paths when extending templates from .pug files', () => { + const wrapper = mount(PugRelative) + expect(wrapper.element.tagName).toBe('DIV') + expect(wrapper.find('.pug-relative-base').exists()).toBeTruthy() +}) + +test('processes SFC with no template', () => { + const wrapper = mount(RenderFunction) + expect(wrapper.element.tagName).toBe('SECTION') +}) + +test('processes SFC with + + +{ + "en": { + "hello": "Hello!" + }, + "ja": { + "hello": "こんにちは!" + } +} + diff --git a/e2e/2.x/custom-block/components/Multiple.vue b/e2e/2.x/custom-block/components/Multiple.vue new file mode 100644 index 00000000..f204d041 --- /dev/null +++ b/e2e/2.x/custom-block/components/Multiple.vue @@ -0,0 +1,26 @@ + + + + + +{ + "en": { + "hello": "Hello!" + }, + "ja": { + "hello": "こんにちは!" + } +} + + + +{ + "foo": "foo" +} + diff --git a/e2e/2.x/custom-block/package.json b/e2e/2.x/custom-block/package.json new file mode 100644 index 00000000..0b0442f6 --- /dev/null +++ b/e2e/2.x/custom-block/package.json @@ -0,0 +1,41 @@ +{ + "name": "vue2-custom-block", + "version": "1.0.0", + "license": "MIT", + "private": true, + "scripts": { + "test": "jest --no-cache --coverage test.js" + }, + "dependencies": { + "vue": "^2.7.7", + "vue-template-compiler": "^2.7.7" + }, + "devDependencies": { + "@babel/core": "^7.9.0", + "@babel/preset-env": "^7.9.0", + "@vue/vue2-jest": "^29.0.0", + "jest": "29.x", + "jest-environment-jsdom": "29.x" + }, + "jest": { + "moduleFileExtensions": [ + "js", + "json", + "vue" + ], + "transform": { + "^.+\\.js$": "babel-jest", + "^.+\\.vue$": "@vue/vue2-jest" + }, + "moduleNameMapper": { + "^~?__styles/(.*)$": "/components/styles/$1" + }, + "globals": { + "vue-jest": { + "transform": { + "custom": "./transformer.js" + } + } + } + } +} diff --git a/e2e/2.x/custom-block/test.js b/e2e/2.x/custom-block/test.js new file mode 100644 index 00000000..79556a9c --- /dev/null +++ b/e2e/2.x/custom-block/test.js @@ -0,0 +1,33 @@ +import Basic from './components/Basic.vue' +import Multiple from './components/Multiple.vue' + +test('Basic', () => { + expect(Basic.__custom).toMatchObject([ + { + en: { + hello: 'Hello!' + }, + ja: { + hello: 'こんにちは!' + } + } + ]) + expect(Basic.__custom).toMatchSnapshot() +}) + +test('Multiple blocks', () => { + expect(Multiple.__custom).toMatchObject([ + { + en: { + hello: 'Hello!' + }, + ja: { + hello: 'こんにちは!' + } + }, + { + foo: 'foo' + } + ]) + expect(Multiple.__custom).toMatchSnapshot() +}) diff --git a/e2e/2.x/custom-block/transformer.js b/e2e/2.x/custom-block/transformer.js new file mode 100644 index 00000000..b0266930 --- /dev/null +++ b/e2e/2.x/custom-block/transformer.js @@ -0,0 +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 }) { + const ret = blocks.reduce((codes, block) => { + codes.push( + `${vueOptionsNamespace}.__custom = ${vueOptionsNamespace}.__custom || [];${vueOptionsNamespace}.__custom.push(${convert( + block.content + )});` + ) + return codes + }, []) + return ret.join('') + } +} diff --git a/e2e/2.x/custom-transformers/babel-transformer.js b/e2e/2.x/custom-transformers/babel-transformer.js new file mode 100644 index 00000000..193503e5 --- /dev/null +++ b/e2e/2.x/custom-transformers/babel-transformer.js @@ -0,0 +1,4 @@ +const { createTransformer } = require('babel-jest').default +module.exports = createTransformer({ + presets: ['@babel/preset-env'] +}) diff --git a/e2e/2.x/custom-transformers/components/Scss.vue b/e2e/2.x/custom-transformers/components/Scss.vue new file mode 100644 index 00000000..474edea9 --- /dev/null +++ b/e2e/2.x/custom-transformers/components/Scss.vue @@ -0,0 +1,18 @@ + + + + + diff --git a/e2e/2.x/custom-transformers/package.json b/e2e/2.x/custom-transformers/package.json new file mode 100644 index 00000000..7d5609c9 --- /dev/null +++ b/e2e/2.x/custom-transformers/package.json @@ -0,0 +1,49 @@ +{ + "name": "vue2-custom-transformers", + "version": "1.0.0", + "license": "MIT", + "private": true, + "scripts": { + "test": "jest --no-cache --coverage test.js" + }, + "dependencies": { + "vue": "^2.7.7", + "vue-template-compiler": "^2.7.7" + }, + "devDependencies": { + "@babel/core": "^7.9.0", + "@babel/preset-env": "^7.9.0", + "@vue/test-utils": "^1.1.0", + "@vue/vue2-jest": "^29.0.0", + "babel-jest": "29.x", + "jest": "29.x", + "jest-environment-jsdom": "29.x", + "postcss": "^7.0.13", + "postcss-color-function": "^4.0.1", + "sass": "^1.23.7" + }, + "jest": { + "testEnvironment": "jsdom", + "moduleFileExtensions": [ + "js", + "json", + "vue" + ], + "transform": { + "^.+\\.js$": "./babel-transformer.js", + "^.+\\.vue$": "@vue/vue2-jest" + }, + "moduleNameMapper": { + "^~?__styles/(.*)$": "/components/styles/$1" + }, + "globals": { + "vue-jest": { + "transform": { + "^scss$": "./scss-transformer.js", + "^pcss|postcss$": "./pcss-transformer.js", + "^js$": "./babel-transformer.js" + } + } + } + } +} diff --git a/e2e/2.x/custom-transformers/pcss-transformer.js b/e2e/2.x/custom-transformers/pcss-transformer.js new file mode 100644 index 00000000..3fc383f0 --- /dev/null +++ b/e2e/2.x/custom-transformers/pcss-transformer.js @@ -0,0 +1,7 @@ +const postcss = require('postcss') +var colorFunction = require('postcss-color-function') +module.exports = { + process: function(content, filepath, config, attrs) { + return postcss([colorFunction()]).process(content).css + } +} diff --git a/e2e/2.x/custom-transformers/scss-transformer.js b/e2e/2.x/custom-transformers/scss-transformer.js new file mode 100644 index 00000000..15eb6cb0 --- /dev/null +++ b/e2e/2.x/custom-transformers/scss-transformer.js @@ -0,0 +1,26 @@ +const cssTree = require('css-tree') + +module.exports = { + preprocess: function preprocess(src, filepath, config, attrs) { + return `${src}\n .g{width: 10px}` + }, + postprocess: function postprocess(src, filepath, config, attrs) { + const ast = cssTree.parse(src) + const obj = cssTree + .findAll(ast, node => node.type === 'ClassSelector') + .reduce((acc, cssNode) => { + acc[cssNode.name] = cssNode.name + + return acc + }, {}) + + if (!attrs.themed) { + return JSON.stringify(obj) + } + + return JSON.stringify({ + light: obj, + dark: obj + }) + } +} diff --git a/e2e/2.x/custom-transformers/test.js b/e2e/2.x/custom-transformers/test.js new file mode 100644 index 00000000..8794fe21 --- /dev/null +++ b/e2e/2.x/custom-transformers/test.js @@ -0,0 +1,15 @@ +import { mount } from '@vue/test-utils' +import Scss from './components/Scss.vue' + +test('processes SCSS using user specified post transforms', () => { + const wrapper = mount(Scss) + expect(wrapper.vm.$style.light.a).toBeUndefined() + expect(wrapper.vm.$style.light.f).toEqual('f') + expect(wrapper.vm.$style.dark.f).toEqual('f') + expect(wrapper.vm.$style.dark.g).toEqual('g') +}) + +test('processes SCSS using user specified pre transforms', () => { + const wrapper = mount(Scss) + expect(wrapper.vm.$style.g).toEqual('g') +}) diff --git a/e2e/2.x/sass-importer/entry/babel-transformer.js b/e2e/2.x/sass-importer/entry/babel-transformer.js new file mode 100644 index 00000000..193503e5 --- /dev/null +++ b/e2e/2.x/sass-importer/entry/babel-transformer.js @@ -0,0 +1,4 @@ +const { createTransformer } = require('babel-jest').default +module.exports = createTransformer({ + presets: ['@babel/preset-env'] +}) diff --git a/e2e/2.x/sass-importer/entry/components/Entry.vue b/e2e/2.x/sass-importer/entry/components/Entry.vue new file mode 100644 index 00000000..63adb0ce --- /dev/null +++ b/e2e/2.x/sass-importer/entry/components/Entry.vue @@ -0,0 +1,24 @@ + + + + + diff --git a/e2e/2.x/sass-importer/entry/package.json b/e2e/2.x/sass-importer/entry/package.json new file mode 100644 index 00000000..5637c767 --- /dev/null +++ b/e2e/2.x/sass-importer/entry/package.json @@ -0,0 +1,49 @@ +{ + "name": "vue2-sass-importer-entry", + "version": "1.0.0", + "license": "MIT", + "private": true, + "scripts": { + "test": "jest --no-cache --coverage test.js" + }, + "dependencies": { + "vue": "^2.7.7", + "vue-template-compiler": "^2.7.7", + "vue2-sass-importer-lib": "file:../lib", + "vue2-sass-importer-sass-lib": "file:../sass-lib-v2" + }, + "devDependencies": { + "@babel/core": "^7.9.0", + "@babel/preset-env": "^7.9.0", + "@vue/vue2-jest": "^29.0.0", + "@vue/test-utils": "^1.1.0", + "babel-jest": "29.x", + "jest": "29.x", + "jest-environment-jsdom": "29.x", + "postcss": "^7.0.13", + "postcss-color-function": "^4.0.1", + "sass": "^1.23.7" + }, + "jest": { + "testEnvironment": "jsdom", + "moduleFileExtensions": [ + "js", + "json", + "vue" + ], + "transformIgnorePatterns": [ + "/node_modules/.*(? { + const wrapper = mount(Entry) + expect(wrapper).toBeDefined() +}) diff --git a/e2e/2.x/sass-importer/lib/index.vue b/e2e/2.x/sass-importer/lib/index.vue new file mode 100644 index 00000000..50d3742c --- /dev/null +++ b/e2e/2.x/sass-importer/lib/index.vue @@ -0,0 +1,11 @@ + + + diff --git a/e2e/2.x/sass-importer/lib/package.json b/e2e/2.x/sass-importer/lib/package.json new file mode 100644 index 00000000..6d9b3678 --- /dev/null +++ b/e2e/2.x/sass-importer/lib/package.json @@ -0,0 +1,19 @@ +{ + "name": "vue2-sass-importer-lib", + "version": "1.0.0", + "license": "MIT", + "private": true, + "main": "index.vue", + "files": [ + "index.vue" + ], + "scripts": { + "test": "echo 'No tests found.'" + }, + "dependencies": { + "vue2-sass-importer-sass-lib": "file:../sass-lib-v1" + }, + "peerDependencies": { + "vue": "^2.7.7" + } +} diff --git a/e2e/2.x/sass-importer/sass-lib-v1/index.scss b/e2e/2.x/sass-importer/sass-lib-v1/index.scss new file mode 100644 index 00000000..05795e0f --- /dev/null +++ b/e2e/2.x/sass-importer/sass-lib-v1/index.scss @@ -0,0 +1,3 @@ +@mixin my-v1-mixin { + color: blue; +} diff --git a/e2e/2.x/sass-importer/sass-lib-v1/package.json b/e2e/2.x/sass-importer/sass-lib-v1/package.json new file mode 100644 index 00000000..cc5fc32c --- /dev/null +++ b/e2e/2.x/sass-importer/sass-lib-v1/package.json @@ -0,0 +1,12 @@ +{ + "name": "vue2-sass-importer-sass-lib", + "version": "1.0.0", + "license": "MIT", + "private": true, + "files": [ + "index.scss" + ], + "scripts": { + "test": "echo 'No tests found.'" + } +} diff --git a/e2e/2.x/sass-importer/sass-lib-v2/index.scss b/e2e/2.x/sass-importer/sass-lib-v2/index.scss new file mode 100644 index 00000000..8f5e144d --- /dev/null +++ b/e2e/2.x/sass-importer/sass-lib-v2/index.scss @@ -0,0 +1,3 @@ +@mixin my-v2-mixin { + color: red; +} diff --git a/e2e/2.x/sass-importer/sass-lib-v2/package.json b/e2e/2.x/sass-importer/sass-lib-v2/package.json new file mode 100644 index 00000000..b9b40960 --- /dev/null +++ b/e2e/2.x/sass-importer/sass-lib-v2/package.json @@ -0,0 +1,12 @@ +{ + "name": "vue2-sass-importer-sass-lib", + "version": "2.0.0", + "license": "MIT", + "private": true, + "files": [ + "index.scss" + ], + "scripts": { + "test": "echo 'No tests found.'" + } +} diff --git a/e2e/2.x/style/babel.config.js b/e2e/2.x/style/babel.config.js new file mode 100644 index 00000000..7db9b6f5 --- /dev/null +++ b/e2e/2.x/style/babel.config.js @@ -0,0 +1,3 @@ +module.exports = { + presets: ['@babel/preset-env'] +} diff --git a/e2e/2.x/style/colors.less b/e2e/2.x/style/colors.less new file mode 100644 index 00000000..7b9ea3f9 --- /dev/null +++ b/e2e/2.x/style/colors.less @@ -0,0 +1 @@ +@primary-color: "red"; diff --git a/e2e/2.x/style/colors.scss b/e2e/2.x/style/colors.scss new file mode 100644 index 00000000..d7cf8edb --- /dev/null +++ b/e2e/2.x/style/colors.scss @@ -0,0 +1 @@ +$primary-color: #333; diff --git a/e2e/2.x/style/components/External.vue b/e2e/2.x/style/components/External.vue new file mode 100644 index 00000000..a73939a0 --- /dev/null +++ b/e2e/2.x/style/components/External.vue @@ -0,0 +1,17 @@ + + + + + diff --git a/e2e/2.x/style/components/Less.vue b/e2e/2.x/style/components/Less.vue new file mode 100644 index 00000000..3e94f459 --- /dev/null +++ b/e2e/2.x/style/components/Less.vue @@ -0,0 +1,18 @@ + + + diff --git a/e2e/2.x/style/components/PostCss.vue b/e2e/2.x/style/components/PostCss.vue new file mode 100644 index 00000000..1d748f32 --- /dev/null +++ b/e2e/2.x/style/components/PostCss.vue @@ -0,0 +1,31 @@ + + + + + diff --git a/e2e/2.x/style/components/Sass.vue b/e2e/2.x/style/components/Sass.vue new file mode 100644 index 00000000..a76ec392 --- /dev/null +++ b/e2e/2.x/style/components/Sass.vue @@ -0,0 +1,20 @@ + + + + + + + diff --git a/e2e/2.x/style/components/Scss.vue b/e2e/2.x/style/components/Scss.vue new file mode 100644 index 00000000..36e2b582 --- /dev/null +++ b/e2e/2.x/style/components/Scss.vue @@ -0,0 +1,30 @@ + + + + + + + diff --git a/e2e/2.x/style/components/Stylus.vue b/e2e/2.x/style/components/Stylus.vue new file mode 100644 index 00000000..7a790344 --- /dev/null +++ b/e2e/2.x/style/components/Stylus.vue @@ -0,0 +1,17 @@ + + + + + diff --git a/e2e/2.x/style/components/relative/resource.styl b/e2e/2.x/style/components/relative/resource.styl new file mode 100644 index 00000000..a1417501 --- /dev/null +++ b/e2e/2.x/style/components/relative/resource.styl @@ -0,0 +1 @@ +standard-space = 11px \ No newline at end of file diff --git a/e2e/2.x/style/components/styles/external.css b/e2e/2.x/style/components/styles/external.css new file mode 100644 index 00000000..365af23e --- /dev/null +++ b/e2e/2.x/style/components/styles/external.css @@ -0,0 +1,3 @@ +.testClass { + background-color: red; +} diff --git a/e2e/2.x/style/components/styles/less-a.less b/e2e/2.x/style/components/styles/less-a.less new file mode 100644 index 00000000..6b45a74c --- /dev/null +++ b/e2e/2.x/style/components/styles/less-a.less @@ -0,0 +1,7 @@ +@import "variables"; +.c { + color: @primary-color; +} +.d { + background-color: @primary-color; +} diff --git a/e2e/2.x/style/components/styles/sass-a.sass b/e2e/2.x/style/components/styles/sass-a.sass new file mode 100644 index 00000000..222ddb76 --- /dev/null +++ b/e2e/2.x/style/components/styles/sass-a.sass @@ -0,0 +1,4 @@ +@import "./sass-b" + +.a + background-color: blue diff --git a/e2e/2.x/style/components/styles/sass-b.sass b/e2e/2.x/style/components/styles/sass-b.sass new file mode 100644 index 00000000..ec96d2c0 --- /dev/null +++ b/e2e/2.x/style/components/styles/sass-b.sass @@ -0,0 +1,2 @@ +.b + background-color: blue diff --git a/e2e/2.x/style/components/styles/scss-a.scss b/e2e/2.x/style/components/styles/scss-a.scss new file mode 100644 index 00000000..30630635 --- /dev/null +++ b/e2e/2.x/style/components/styles/scss-a.scss @@ -0,0 +1,5 @@ +@import "./scss-b"; + +.a { + background-color: blue +} diff --git a/e2e/2.x/style/components/styles/scss-b.scss b/e2e/2.x/style/components/styles/scss-b.scss new file mode 100644 index 00000000..b8341292 --- /dev/null +++ b/e2e/2.x/style/components/styles/scss-b.scss @@ -0,0 +1,3 @@ +.b { + background-color: blue; +} diff --git a/e2e/2.x/style/jest.config.js b/e2e/2.x/style/jest.config.js new file mode 100644 index 00000000..ee5fa002 --- /dev/null +++ b/e2e/2.x/style/jest.config.js @@ -0,0 +1,23 @@ +const os = require('node:os') + +/** @type {import('@jest/types').Config.InitialOptions} */ +module.exports = { + testEnvironment: 'jsdom', + moduleFileExtensions: ['js', 'json', 'vue'], + transform: { + '^.+\\.js$': 'babel-jest', + '^.+\\.vue$': '@vue/vue2-jest' + }, + moduleNameMapper: { + '^~tmp/(.*)': `${os.tmpdir()}/$1`, + '^~?__styles/(.*)$': '/components/styles/$1' + }, + globals: { + 'vue-jest': { + resources: { + scss: ['variables.scss'], + less: ['variables.less'] + } + } + } +} diff --git a/e2e/2.x/style/package.json b/e2e/2.x/style/package.json new file mode 100644 index 00000000..26fa1828 --- /dev/null +++ b/e2e/2.x/style/package.json @@ -0,0 +1,25 @@ +{ + "name": "vue2-style", + "version": "1.0.0", + "license": "MIT", + "private": true, + "scripts": { + "test": "node setup.js && jest --no-cache test.js" + }, + "dependencies": { + "vue": "^2.7.7", + "vue-template-compiler": "^2.7.7" + }, + "devDependencies": { + "@babel/core": "^7.9.0", + "@babel/preset-env": "^7.9.0", + "@vue/test-utils": "^1.1.0", + "@vue/vue2-jest": "^29.0.0", + "jest": "29.x", + "jest-environment-jsdom": "29.x", + "less": "^3.9.0", + "postcss": "^7.0.13", + "sass": "^1.23.7", + "stylus": "^0.54.5" + } +} diff --git a/e2e/2.x/style/setup.js b/e2e/2.x/style/setup.js new file mode 100644 index 00000000..70852065 --- /dev/null +++ b/e2e/2.x/style/setup.js @@ -0,0 +1,14 @@ +const fs = require('fs') +const os = require('node:os') + +const testDir = '../../../node_modules/vue-jest-test' + +if (!fs.existsSync(testDir)) { + fs.mkdirSync(testDir) +} + +fs.openSync(`${os.tmpdir()}/absolute.scss`, 'w') +fs.openSync(`${testDir}/_partial.scss`, 'w') +fs.openSync(`${testDir}/foo.bar.scss`, 'w') +fs.openSync(`${testDir}/baz.css`, 'w') +fs.openSync(`${testDir}/qux.sass`, 'w') diff --git a/e2e/2.x/style/test.js b/e2e/2.x/style/test.js new file mode 100644 index 00000000..af0777bd --- /dev/null +++ b/e2e/2.x/style/test.js @@ -0,0 +1,51 @@ +import { mount } from '@vue/test-utils' +import Stylus from './components/Stylus.vue' +import Scss from './components/Scss.vue' +import Sass from './components/Sass.vue' +import Less from './components/Less.vue' +import PostCss from './components/PostCss.vue' +import External from './components/External.vue' + +test('processes Less', () => { + const wrapper = mount(Less) + expect(wrapper.element.tagName).toBe('DIV') + expect(wrapper.vm.$style.a).toEqual('a') +}) + +test('processes PostCSS', () => { + const wrapper = mount(PostCss) + expect(wrapper.element.tagName).toBe('SECTION') + expect(wrapper.vm.$style.a).toEqual('a') + expect(wrapper.vm.$style.b).toEqual('b') +}) + +test('processes Sass', () => { + const wrapper = mount(Sass) + expect(wrapper.vm.$style.a).toEqual('a') + expect(wrapper.vm.$style.b).toEqual('b') + expect(wrapper.vm.$style.c).toEqual('c') + expect(wrapper.vm.$style.light).toBeUndefined() +}) + +test('processes SCSS with resources', () => { + const wrapper = mount(Scss) + expect(wrapper.vm.$style.a).toEqual('a') + expect(wrapper.vm.$style.b).toEqual('b') + expect(wrapper.vm.$style.c).toEqual('c') +}) + +test('process Stylus', () => { + const wrapper = mount(Stylus) + expect(wrapper.vm).toBeTruthy() + expect(wrapper.vm.css.a).toEqual('a') + expect(wrapper.vm.$style.b).toEqual('b') +}) + +test('process External', () => { + const wrapper = mount(External) + expect(wrapper.vm).toBeTruthy() + expect(wrapper.vm.$style.testClass).toEqual('testClass') + expect(wrapper.vm.$style2.testClass).toEqual('testClass') + expect(wrapper.vm.$style3.testClass).toEqual('testClass') + expect(wrapper.vm.css.a).toEqual('a') +}) diff --git a/e2e/2.x/style/variables.less b/e2e/2.x/style/variables.less new file mode 100644 index 00000000..57319a4a --- /dev/null +++ b/e2e/2.x/style/variables.less @@ -0,0 +1,3 @@ +@import "./colors.less"; + +@font-size: 16px; diff --git a/e2e/2.x/style/variables.scss b/e2e/2.x/style/variables.scss new file mode 100644 index 00000000..4f8d9064 --- /dev/null +++ b/e2e/2.x/style/variables.scss @@ -0,0 +1,3 @@ +@import './colors.scss'; + +$font-size: 16px; diff --git a/e2e/3.x/babel-in-package/components/Tsx.vue b/e2e/3.x/babel-in-package/components/Tsx.vue new file mode 100644 index 00000000..7a1062c3 --- /dev/null +++ b/e2e/3.x/babel-in-package/components/Tsx.vue @@ -0,0 +1,7 @@ + diff --git a/e2e/3.x/babel-in-package/package.json b/e2e/3.x/babel-in-package/package.json index 23c24c39..5c2ffe0f 100644 --- a/e2e/3.x/babel-in-package/package.json +++ b/e2e/3.x/babel-in-package/package.json @@ -7,19 +7,21 @@ "test": "jest --no-cache test.js" }, "dependencies": { - "vue": "^3.0.3" + "vue": "^3.2.22" }, "devDependencies": { "@babel/core": "^7.9.0", "@babel/preset-env": "^7.9.0", - "@vue/compiler-sfc": "^3.0.3", + "@vue/babel-plugin-jsx": "^1.1.5", + "@vue/vue3-jest": "^29.0.0", "coffeescript": "^2.3.2", - "jest": "^26.0.0", - "ts-jest": "^26.4.4", - "typescript": "^4.1.2", - "vue3-jest": "^26.0.0-alpha.10" + "jest": "29.x", + "jest-environment-jsdom": "29.x", + "ts-jest": "^29.0.0-next.0", + "typescript": "^4.6.4" }, "jest": { + "testEnvironment": "jsdom", "moduleFileExtensions": [ "js", "json", @@ -27,12 +29,15 @@ ], "transform": { "^.+\\.js$": "babel-jest", - "^.+\\.vue$": "vue3-jest" + "^.+\\.vue$": "@vue/vue3-jest" } }, "babel": { "presets": [ "@babel/env" + ], + "plugins": [ + "@vue/babel-plugin-jsx" ] } } diff --git a/e2e/3.x/babel-in-package/test.js b/e2e/3.x/babel-in-package/test.js index 8bc52e74..e5b7d33d 100644 --- a/e2e/3.x/babel-in-package/test.js +++ b/e2e/3.x/babel-in-package/test.js @@ -3,6 +3,7 @@ import { createApp, h } from 'vue' import TypeScript from './components/TypeScript.vue' import Basic from './components/Basic.vue' import Coffee from './components/Coffee.vue' +import Tsx from './components/Tsx.vue' function mount(Component, props, slots) { document.getElementsByTagName('html')[0].innerHTML = '' @@ -34,3 +35,8 @@ test('processes .vue files with lang set to typescript', () => { expect(document.querySelector('#parent').textContent).toBe('Parent') expect(document.querySelector('#child').textContent).toBe('Child') }) + +test('processes .vue files with lang set to tsx(typescript)', () => { + mount(Tsx) + expect(document.querySelector('div').textContent).toContain('tsx components') +}) diff --git a/e2e/3.x/basic/__snapshots__/test.js.snap b/e2e/3.x/basic/__snapshots__/test.js.snap index a10f241c..7ced6a2a 100644 --- a/e2e/3.x/basic/__snapshots__/test.js.snap +++ b/e2e/3.x/basic/__snapshots__/test.js.snap @@ -1,12 +1,12 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`generates source maps for .vue files 1`] = ` -"\\"use strict\\"; +""use strict"; -Object.defineProperty(exports, \\"__esModule\\", { +Object.defineProperty(exports, "__esModule", { value: true }); -exports[\\"default\\"] = void 0; +exports["default"] = void 0; var _default = { name: 'basic', computed: { @@ -30,28 +30,36 @@ var _default = { } } }; -exports[\\"default\\"] = _default; -\\"use strict\\"; -Object.defineProperty(exports, \\"__esModule\\", { value: true }); -exports.render = void 0; -var vue_1 = require(\\"vue\\"); -var _hoisted_1 = { class: \\"hello\\" }; -function render(_ctx, _cache) { - return (vue_1.openBlock(), vue_1.createBlock(\\"div\\", _hoisted_1, [ - vue_1.createVNode(\\"h1\\", { class: _ctx.headingClasses }, vue_1.toDisplayString(_ctx.msg), 3 /* TEXT, CLASS */) - ])); -} +exports["default"] = _default; +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); exports.render = render; -;exports.default = {...exports.default, render};;exports.default = {...exports.default, __cssModules: {\\"css\\":{\\"testA\\":\\"testA\\"},\\"$style\\":{\\"testB\\":\\"testB\\"}}}" + +var _vue = require("vue"); + +var _hoisted_1 = { + "class": "hello" +}; + +function render(_ctx, _cache) { + return (0, _vue.openBlock)(), (0, _vue.createElementBlock)("div", _hoisted_1, [(0, _vue.createElementVNode)("h1", { + "class": (0, _vue.normalizeClass)(_ctx.headingClasses) + }, (0, _vue.toDisplayString)(_ctx.msg), 3 + /* TEXT, CLASS */ + )]); +};exports.default = {...exports.default, render};;exports.default = {...exports.default, __cssModules: {"css":{"testA":"testA"},"$style":{"testB":"testB"}}}" `; exports[`generates source maps using src attributes 1`] = ` -"\\"use strict\\"; +""use strict"; -Object.defineProperty(exports, \\"__esModule\\", { +Object.defineProperty(exports, "__esModule", { value: true }); -exports[\\"default\\"] = void 0; +exports["default"] = void 0; var _default = { name: 'basic', computed: { @@ -75,17 +83,25 @@ var _default = { } } }; -exports[\\"default\\"] = _default; -\\"use strict\\"; -Object.defineProperty(exports, \\"__esModule\\", { value: true }); -exports.render = void 0; -var vue_1 = require(\\"vue\\"); -var _hoisted_1 = { class: \\"hello\\" }; -function render(_ctx, _cache) { - return (vue_1.openBlock(), vue_1.createBlock(\\"div\\", _hoisted_1, [ - vue_1.createVNode(\\"h1\\", { class: _ctx.headingClasses }, vue_1.toDisplayString(_ctx.msg), 3 /* TEXT, CLASS */) - ])); -} +exports["default"] = _default; +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); exports.render = render; -;exports.default = {...exports.default, render};" + +var _vue = require("vue"); + +var _hoisted_1 = { + "class": "hello" +}; + +function render(_ctx, _cache) { + return (0, _vue.openBlock)(), (0, _vue.createElementBlock)("div", _hoisted_1, [(0, _vue.createElementVNode)("h1", { + "class": (0, _vue.normalizeClass)(_ctx.headingClasses) + }, (0, _vue.toDisplayString)(_ctx.msg), 3 + /* TEXT, CLASS */ + )]); +};exports.default = {...exports.default, render};" `; diff --git a/e2e/3.x/basic/components/CompilerDirective.vue b/e2e/3.x/basic/components/CompilerDirective.vue new file mode 100644 index 00000000..9ae9a9a2 --- /dev/null +++ b/e2e/3.x/basic/components/CompilerDirective.vue @@ -0,0 +1,5 @@ + diff --git a/e2e/3.x/basic/components/ExtendedTsConfig.vue b/e2e/3.x/basic/components/ExtendedTsConfig.vue new file mode 100644 index 00000000..8dc7001f --- /dev/null +++ b/e2e/3.x/basic/components/ExtendedTsConfig.vue @@ -0,0 +1,34 @@ + + + diff --git a/e2e/3.x/basic/components/ModuleRequiringEsModuleInterop.js b/e2e/3.x/basic/components/ModuleRequiringEsModuleInterop.js new file mode 100644 index 00000000..fed7caa7 --- /dev/null +++ b/e2e/3.x/basic/components/ModuleRequiringEsModuleInterop.js @@ -0,0 +1 @@ +module.exports = () => false diff --git a/e2e/3.x/basic/components/ScriptAndScriptSetup.vue b/e2e/3.x/basic/components/ScriptAndScriptSetup.vue new file mode 100644 index 00000000..e3aa2fcb --- /dev/null +++ b/e2e/3.x/basic/components/ScriptAndScriptSetup.vue @@ -0,0 +1,23 @@ + + + + + diff --git a/e2e/3.x/basic/components/ScriptSetupSugarRef.vue b/e2e/3.x/basic/components/ScriptSetupSugarRef.vue new file mode 100644 index 00000000..268a78a7 --- /dev/null +++ b/e2e/3.x/basic/components/ScriptSetupSugarRef.vue @@ -0,0 +1,17 @@ + + + diff --git a/e2e/3.x/basic/jest.config.js b/e2e/3.x/basic/jest.config.js new file mode 100644 index 00000000..4552a185 --- /dev/null +++ b/e2e/3.x/basic/jest.config.js @@ -0,0 +1,26 @@ +const vTestDirective = require('./v-test-directive') + +module.exports = { + testEnvironment: 'jsdom', + moduleFileExtensions: ['js', 'json', 'vue', 'ts'], + transform: { + '^.+\\.ts$': 'ts-jest', + '^.+\\.js$': 'babel-jest', + '^.+\\.vue$': '@vue/vue3-jest' + }, + moduleNameMapper: { + '^~?__styles/(.*)$': '/components/styles/$1' + }, + globals: { + 'vue-jest': { + pug: { + basedir: './' + }, + compilerOptions: { + directiveTransforms: { + test: vTestDirective + } + } + } + } +} diff --git a/e2e/3.x/basic/package.json b/e2e/3.x/basic/package.json index 95365075..802d2608 100644 --- a/e2e/3.x/basic/package.json +++ b/e2e/3.x/basic/package.json @@ -7,46 +7,23 @@ "test": "jest --no-cache --coverage test.js" }, "dependencies": { - "vue": "^3.0.3" + "vue": "^3.2.22" }, "devDependencies": { "@babel/core": "^7.9.0", "@babel/preset-env": "^7.9.0", - "@vue/compiler-sfc": "^3.0.3", + "@vue/vue3-jest": "^29.0.0", "babel-helper-vue-jsx-merge-props": "^2.0.3", "babel-plugin-syntax-jsx": "^6.18.0", "babel-plugin-transform-vue-jsx": "^3.7.0", "coffeescript": "^2.3.2", "jade": "^1.11.0", - "jest": "^26.0.0", + "jest": "29.x", + "jest-environment-jsdom": "29.x", "pug": "^2.0.3", - "ts-jest": "^26.4.4", - "typescript": "^4.1.2", + "ts-jest": "^29.0.0-next.0", + "typescript": "^4.6.4", "vue-class-component": "^8.0.0-beta.4", - "vue3-jest": "^26.0.0-alpha.10", "vue-property-decorator": "^10.0.0-rc.3" - }, - "jest": { - "moduleFileExtensions": [ - "js", - "json", - "vue", - "ts" - ], - "transform": { - "^.+\\.ts$": "ts-jest", - "^.+\\.js$": "babel-jest", - "^.+\\.vue$": "vue3-jest" - }, - "moduleNameMapper": { - "^~?__styles/(.*)$": "/components/styles/$1" - }, - "globals": { - "vue-jest": { - "pug": { - "basedir": "./" - } - } - } } } diff --git a/e2e/3.x/basic/test.js b/e2e/3.x/basic/test.js index 16360102..504c44c7 100644 --- a/e2e/3.x/basic/test.js +++ b/e2e/3.x/basic/test.js @@ -11,7 +11,7 @@ import ClassComponent from './components/ClassComponent.vue' import ClassComponentWithMixin from './components/ClassComponentWithMixin.vue' import ClassComponentProperty from './components/ClassComponentProperty.vue' import TypeScript from './components/TypeScript.vue' -import jestVue from 'vue3-jest' +import jestVue from '@vue/vue3-jest' import RenderFunction from './components/RenderFunction.vue' import FunctionalSFC from './components/FunctionalSFC.vue' import CoffeeScript from './components/CoffeeScript.vue' @@ -20,7 +20,11 @@ import NoScript from './components/NoScript.vue' import PugRelative from './components/PugRelativeExtends.vue' import { randomExport } from './components/NamedExport.vue' import ScriptSetup from './components/ScriptSetup.vue' +import ScriptSetupSugarRef from './components/ScriptSetupSugarRef.vue' import FunctionalRenderFn from './components/FunctionalRenderFn.vue' +import CompilerDirective from './components/CompilerDirective.vue' +import ExtendedTsConfig from './components/ExtendedTsConfig.vue' +import ScriptAndScriptSetup from './components/ScriptAndScriptSetup.vue' // TODO: JSX for Vue 3? TSX? import Jsx from './components/Jsx.vue' @@ -35,7 +39,9 @@ function mount(Component, props, slots) { return h(Component, props, slots) } } - createApp(Parent).mount(el) + const app = createApp(Parent) + app.directive('test', el => el.setAttribute('data-test', 'value')) + app.mount(el) } test('supports + + +{ + "en": { + "hello": "Hello!" + }, + "ja": { + "hello": "こんにちは!" + } +} + 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 new file mode 100644 index 00000000..33edb595 --- /dev/null +++ b/e2e/3.x/custom-block/package.json @@ -0,0 +1,41 @@ +{ + "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", + "@vue/vue3-jest": "^29.0.0", + "jest": "29.x", + "jest-environment-jsdom": "29.x" + }, + "jest": { + "moduleFileExtensions": [ + "js", + "json", + "vue" + ], + "transform": { + "^.+\\.js$": "babel-jest", + "^.+\\.vue$": "@vue/vue3-jest" + }, + "moduleNameMapper": { + "^~?__styles/(.*)$": "/components/styles/$1" + }, + "globals": { + "vue-jest": { + "transform": { + "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..79556a9c --- /dev/null +++ b/e2e/3.x/custom-block/test.js @@ -0,0 +1,33 @@ +import Basic from './components/Basic.vue' +import Multiple from './components/Multiple.vue' + +test('Basic', () => { + expect(Basic.__custom).toMatchObject([ + { + en: { + hello: 'Hello!' + }, + ja: { + hello: 'こんにちは!' + } + } + ]) + expect(Basic.__custom).toMatchSnapshot() +}) + +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 new file mode 100644 index 00000000..e51da0f5 --- /dev/null +++ b/e2e/3.x/custom-block/transformer.js @@ -0,0 +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, 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/e2e/3.x/custom-transformers/babel-transformer.js b/e2e/3.x/custom-transformers/babel-transformer.js index 2be39a8a..193503e5 100644 --- a/e2e/3.x/custom-transformers/babel-transformer.js +++ b/e2e/3.x/custom-transformers/babel-transformer.js @@ -1,4 +1,4 @@ -const { createTransformer } = require('babel-jest') +const { createTransformer } = require('babel-jest').default module.exports = createTransformer({ presets: ['@babel/preset-env'] }) diff --git a/e2e/3.x/custom-transformers/components/Scss.vue b/e2e/3.x/custom-transformers/components/Scss.vue index 6b88eb24..474edea9 100644 --- a/e2e/3.x/custom-transformers/components/Scss.vue +++ b/e2e/3.x/custom-transformers/components/Scss.vue @@ -1,7 +1,7 @@ diff --git a/e2e/3.x/custom-transformers/package.json b/e2e/3.x/custom-transformers/package.json index 4ba9d191..b09c1a5b 100644 --- a/e2e/3.x/custom-transformers/package.json +++ b/e2e/3.x/custom-transformers/package.json @@ -7,21 +7,23 @@ "test": "jest --no-cache --coverage test.js" }, "dependencies": { - "@vue/compiler-sfc": "^3.0.3", - "vue": "^3.0.3" + "vue": "^3.2.22" }, "devDependencies": { "@babel/core": "^7.9.0", "@babel/preset-env": "^7.9.0", - "babel-jest": "^26.0.0", - "extract-from-css": "^0.4.4", - "jest": "^26.0.0", + "@vue/test-utils": "^2.0.0-rc.10", + "@vue/vue3-jest": "^29.0.0", + "babel-jest": "29.x", + "css-tree": "^2.0.1", + "jest": "29.x", + "jest-environment-jsdom": "29.x", "postcss": "^7.0.13", "postcss-color-function": "^4.0.1", - "sass": "^1.23.7", - "vue3-jest": "^26.0.0-alpha.10" + "sass": "^1.23.7" }, "jest": { + "testEnvironment": "jsdom", "moduleFileExtensions": [ "js", "json", @@ -29,7 +31,7 @@ ], "transform": { "^.+\\.js$": "./babel-transformer.js", - "^.+\\.vue$": "vue3-jest" + "^.+\\.vue$": "@vue/vue3-jest" }, "moduleNameMapper": { "^~?__styles/(.*)$": "/components/styles/$1" diff --git a/e2e/3.x/custom-transformers/scss-transformer.js b/e2e/3.x/custom-transformers/scss-transformer.js index b2ca2848..15eb6cb0 100644 --- a/e2e/3.x/custom-transformers/scss-transformer.js +++ b/e2e/3.x/custom-transformers/scss-transformer.js @@ -1,14 +1,18 @@ -const cssExtract = require('extract-from-css') +const cssTree = require('css-tree') + module.exports = { preprocess: function preprocess(src, filepath, config, attrs) { return `${src}\n .g{width: 10px}` }, postprocess: function postprocess(src, filepath, config, attrs) { - const cssNames = cssExtract.extractClasses(src) - const obj = {} - for (let i = 0, l = cssNames.length; i < l; i++) { - obj[cssNames[i]] = cssNames[i] - } + const ast = cssTree.parse(src) + const obj = cssTree + .findAll(ast, node => node.type === 'ClassSelector') + .reduce((acc, cssNode) => { + acc[cssNode.name] = cssNode.name + + return acc + }, {}) if (!attrs.themed) { return JSON.stringify(obj) diff --git a/e2e/3.x/custom-transformers/test.js b/e2e/3.x/custom-transformers/test.js index 406e7d6c..8794fe21 100644 --- a/e2e/3.x/custom-transformers/test.js +++ b/e2e/3.x/custom-transformers/test.js @@ -1,21 +1,15 @@ -// import { createApp, h } from 'vue' - -// import Scss from './components/Scss.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) -// } -// } -// createApp(Parent).mount(el) -// } - -// TODO: Figure this out with Vue 3. `$style` no longer exists. -test.todo('processes SCSS using user specified post transforms') - -test.todo('processes SCSS using user specified pre transforms') +import { mount } from '@vue/test-utils' +import Scss from './components/Scss.vue' + +test('processes SCSS using user specified post transforms', () => { + const wrapper = mount(Scss) + expect(wrapper.vm.$style.light.a).toBeUndefined() + expect(wrapper.vm.$style.light.f).toEqual('f') + expect(wrapper.vm.$style.dark.f).toEqual('f') + expect(wrapper.vm.$style.dark.g).toEqual('g') +}) + +test('processes SCSS using user specified pre transforms', () => { + const wrapper = mount(Scss) + expect(wrapper.vm.$style.g).toEqual('g') +}) diff --git a/e2e/3.x/javascript/package.json b/e2e/3.x/javascript/package.json index 64b0db6e..a7d1aefb 100644 --- a/e2e/3.x/javascript/package.json +++ b/e2e/3.x/javascript/package.json @@ -7,16 +7,18 @@ "test": "jest --no-cache test.js" }, "dependencies": { - "vue": "^3.0.3" + "vue": "^3.2.22" }, "devDependencies": { "@babel/core": "^7.9.0", "@babel/preset-env": "^7.9.0", + "@vue/vue3-jest": "^29.0.0", "coffeescript": "^2.3.2", - "jest": "^26.0.0", - "vue3-jest": "^26.0.0-alpha.10" + "jest": "29.x", + "jest-environment-jsdom": "29.x" }, "jest": { + "testEnvironment": "jsdom", "moduleFileExtensions": [ "js", "json", @@ -24,7 +26,7 @@ ], "transform": { "^.+\\.js$": "babel-jest", - "^.+\\.vue$": "vue3-jest" + "^.+\\.vue$": "@vue/vue3-jest" } }, "babel": { diff --git a/e2e/3.x/sass-importer/entry/babel-transformer.js b/e2e/3.x/sass-importer/entry/babel-transformer.js new file mode 100644 index 00000000..193503e5 --- /dev/null +++ b/e2e/3.x/sass-importer/entry/babel-transformer.js @@ -0,0 +1,4 @@ +const { createTransformer } = require('babel-jest').default +module.exports = createTransformer({ + presets: ['@babel/preset-env'] +}) diff --git a/e2e/3.x/sass-importer/entry/components/Entry.vue b/e2e/3.x/sass-importer/entry/components/Entry.vue new file mode 100644 index 00000000..367e3f6b --- /dev/null +++ b/e2e/3.x/sass-importer/entry/components/Entry.vue @@ -0,0 +1,24 @@ + + + + + diff --git a/e2e/3.x/sass-importer/entry/package.json b/e2e/3.x/sass-importer/entry/package.json new file mode 100644 index 00000000..da99c925 --- /dev/null +++ b/e2e/3.x/sass-importer/entry/package.json @@ -0,0 +1,48 @@ +{ + "name": "vue3-sass-importer-entry", + "version": "1.0.0", + "license": "MIT", + "private": true, + "scripts": { + "test": "jest --no-cache --coverage test.js" + }, + "dependencies": { + "vue": "^3.2.22", + "vue3-sass-importer-lib": "file:../lib", + "vue3-sass-importer-sass-lib": "file:../sass-lib-v2" + }, + "devDependencies": { + "@babel/core": "^7.9.0", + "@babel/preset-env": "^7.9.0", + "@vue/test-utils": "^2.0.0-rc.10", + "@vue/vue3-jest": "^29.0.0", + "babel-jest": "29.x", + "jest": "29.x", + "jest-environment-jsdom": "29.x", + "postcss": "^7.0.13", + "postcss-color-function": "^4.0.1", + "sass": "^1.23.7" + }, + "jest": { + "testEnvironment": "jsdom", + "moduleFileExtensions": [ + "js", + "json", + "vue" + ], + "transformIgnorePatterns": [ + "/node_modules/.*(? { + const wrapper = mount(Entry) + expect(wrapper).toBeDefined() +}) diff --git a/e2e/3.x/sass-importer/lib/index.vue b/e2e/3.x/sass-importer/lib/index.vue new file mode 100644 index 00000000..fc3c0231 --- /dev/null +++ b/e2e/3.x/sass-importer/lib/index.vue @@ -0,0 +1,11 @@ + + + diff --git a/e2e/3.x/sass-importer/lib/package.json b/e2e/3.x/sass-importer/lib/package.json new file mode 100644 index 00000000..6f19b178 --- /dev/null +++ b/e2e/3.x/sass-importer/lib/package.json @@ -0,0 +1,19 @@ +{ + "name": "vue3-sass-importer-lib", + "version": "1.0.0", + "license": "MIT", + "private": true, + "main": "index.vue", + "files": [ + "index.vue" + ], + "scripts": { + "test": "echo 'No tests found.'" + }, + "dependencies": { + "vue3-sass-importer-sass-lib": "file:../sass-lib-v1" + }, + "peerDependencies": { + "vue": "^3.2.22" + } +} diff --git a/e2e/3.x/sass-importer/sass-lib-v1/index.scss b/e2e/3.x/sass-importer/sass-lib-v1/index.scss new file mode 100644 index 00000000..05795e0f --- /dev/null +++ b/e2e/3.x/sass-importer/sass-lib-v1/index.scss @@ -0,0 +1,3 @@ +@mixin my-v1-mixin { + color: blue; +} diff --git a/e2e/3.x/sass-importer/sass-lib-v1/package.json b/e2e/3.x/sass-importer/sass-lib-v1/package.json new file mode 100644 index 00000000..5717428c --- /dev/null +++ b/e2e/3.x/sass-importer/sass-lib-v1/package.json @@ -0,0 +1,12 @@ +{ + "name": "vue3-sass-importer-sass-lib", + "version": "1.0.0", + "license": "MIT", + "private": true, + "files": [ + "index.scss" + ], + "scripts": { + "test": "echo 'No tests found.'" + } +} diff --git a/e2e/3.x/sass-importer/sass-lib-v2/index.scss b/e2e/3.x/sass-importer/sass-lib-v2/index.scss new file mode 100644 index 00000000..8f5e144d --- /dev/null +++ b/e2e/3.x/sass-importer/sass-lib-v2/index.scss @@ -0,0 +1,3 @@ +@mixin my-v2-mixin { + color: red; +} diff --git a/e2e/3.x/sass-importer/sass-lib-v2/package.json b/e2e/3.x/sass-importer/sass-lib-v2/package.json new file mode 100644 index 00000000..d06a853a --- /dev/null +++ b/e2e/3.x/sass-importer/sass-lib-v2/package.json @@ -0,0 +1,12 @@ +{ + "name": "vue3-sass-importer-sass-lib", + "version": "2.0.0", + "license": "MIT", + "private": true, + "files": [ + "index.scss" + ], + "scripts": { + "test": "echo 'No tests found.'" + } +} diff --git a/e2e/3.x/style/colors.less b/e2e/3.x/style/colors.less new file mode 100644 index 00000000..7b9ea3f9 --- /dev/null +++ b/e2e/3.x/style/colors.less @@ -0,0 +1 @@ +@primary-color: "red"; diff --git a/e2e/3.x/style/colors.scss b/e2e/3.x/style/colors.scss new file mode 100644 index 00000000..d7cf8edb --- /dev/null +++ b/e2e/3.x/style/colors.scss @@ -0,0 +1 @@ +$primary-color: #333; diff --git a/e2e/3.x/style/components/External.vue b/e2e/3.x/style/components/External.vue index 90b1df56..55fd7ae4 100644 --- a/e2e/3.x/style/components/External.vue +++ b/e2e/3.x/style/components/External.vue @@ -6,6 +6,10 @@ + + + + + diff --git a/e2e/3.x/typescript/src/components/ScriptSetup.vue b/e2e/3.x/typescript/src/components/ScriptSetup.vue new file mode 100644 index 00000000..b5de8edc --- /dev/null +++ b/e2e/3.x/typescript/src/components/ScriptSetup.vue @@ -0,0 +1,18 @@ + + + diff --git a/e2e/3.x/typescript/src/shims-vue.d.ts b/e2e/3.x/typescript/src/shims-vue.d.ts new file mode 100644 index 00000000..64c3fd9e --- /dev/null +++ b/e2e/3.x/typescript/src/shims-vue.d.ts @@ -0,0 +1,5 @@ +declare module '*.vue' { + import type { DefineComponent } from 'vue'; + const component: DefineComponent<{}, {}, any>; + export default component; +} diff --git a/e2e/3.x/typescript/src/test.ts b/e2e/3.x/typescript/src/test.ts new file mode 100644 index 00000000..a20b3d77 --- /dev/null +++ b/e2e/3.x/typescript/src/test.ts @@ -0,0 +1,30 @@ +import { createApp, h } from 'vue' + +import Basic from '@/components/Basic.vue' +import ScriptSetup from '@/components/ScriptSetup.vue' + +function mount(Component: any) { + document.getElementsByTagName('html')[0].innerHTML = '' + const el = document.createElement('div') + el.id = 'app' + document.body.appendChild(el) + const Parent = { + render() { + return h(Component) + } + } + createApp(Parent).mount(el) +} + +test('processes .vue files', () => { + mount(Basic) + expect(document.querySelector('h1')!.textContent).toBe( + 'Welcome to Your Vue.js App' + ) +}) + +test('supports