Skip to content

Failed parse using external template #45

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
mazipan opened this issue Jan 17, 2018 · 10 comments
Open

Failed parse using external template #45

mazipan opened this issue Jan 17, 2018 · 10 comments

Comments

@mazipan
Copy link

mazipan commented Jan 17, 2018

I used external template like :

<template
  src="vue2-simplert-core/simplert.html">
</template>

Success when building production file using [email protected].
But unit test failed to run using [email protected]

Here some snippet of my Jest configuration :

 "jest": {
    "mapCoverage": true,
    "coverageDirectory": "test/coverage",
    "moduleNameMapper": {
      "^vue$": "vue/dist/vue.common.js"
    },
    "moduleFileExtensions": [
      "js",
      "vue"
    ],
    "transform": {
      "^.+\\.js$": "<rootDir>/node_modules/babel-jest",
      ".*\\.(vue)$": "<rootDir>/node_modules/vue-jest"
    }
  }

Error that I got is :

ENOENT: no such file or directory, open '~/project/src/vue2-simplert-core/simplert.html'

if I look into error message, it because pointing to my project root folder instead of node_modules folder.

Is there any missing from my side ?

Thanks for all response 👍

@eddyerburgh
Copy link
Member

What's the absolute path of simplert.html?

@mazipan
Copy link
Author

mazipan commented Jan 17, 2018

It's coming from other npm repository, so should be coming from node_modules folder.

@eddyerburgh
Copy link
Member

Does this resolve correctly when you use vue-loader?

@mazipan
Copy link
Author

mazipan commented Jan 17, 2018

Sure, working like charm...
That's why I create this issue.
Maybe my bad, because I am not familiar with Jest configuration.
But I want to know from your side first. Maybe you have some suggestions.

@eddyerburgh
Copy link
Member

This is a problem on our side we need to fix. At the moment, we only look for a src that is relative, not in node_modules

Thanks for bring it to my attention, I'll look to get a fix in place 🙂

@laggingreflex
Copy link

laggingreflex commented Apr 23, 2019

I'm using relative templates but I still have an issue. The templates do get parsed, but I think they're not "interpreted" correctly.

Repro: https://github.com/laggingreflex/repro-vue-jest-template

It works in the browser but running jest it gives this error

> jest
Cannot use <template> as component root element because it may contain multiple nodes.
 FAIL  src/test.js
  ● Test suite failed to run

Taking hint from the error, if I change my App/template.vue from

<template>
  <div>App</div>
</template>

to just

  <div>App</div>

the test passes, but that's not the correct format for template - the app doesn't work in the browser.

@eddyerburgh
Copy link
Member

@laggingreflex can you open a new issue for this so that I can track it?

robwozniak added a commit to robwozniak/vue-jest that referenced this issue Jun 28, 2019
robwozniak added a commit to robwozniak/vue-jest that referenced this issue Jun 28, 2019
@robwozniak
Copy link

This is a problem on our side we need to fix. At the moment, we only look for a src that is relative, not in node_modules

Thanks for bring it to my attention, I'll look to get a fix in place

@eddyerburgh please check my PR and let me know what do you think 🤞
Sample scenario:

// TestComponent.spec.js

import { mount } from '@vue/test-utils'
import MyComponent from './MyComponent.vue'

describe('Sample test', () => {
  it('...', () => {
    const wrapper = mount(MyComponent)
    expect(...)
  })
  ...
})
// MyComponent.vue

<template src="@node/dependency/src/MyComponent.html"/>
<script src="@node/dependency/src/MyComponent.js"/>
// jest.config.js

module.exports = {
  'moduleNameMapper': {
    '^@node/dependency/(.*)$': '/node_modules/@node/dependency/$1',
    '^vue$': 'vue/dist/vue.common.js'
  },
  'moduleFileExtensions': [
    'js',
    'vue'
  ],
  'transform': {
    '^.+\\.js$': '/node_modules/babel-jest',
    '.*\\.vue$': '/node_modules/vue-jest'
  },
  'transformIgnorePatterns': ['/node_modules/dependency/node_modules']
}

@vladiiliev
Copy link

vladiiliev commented Jun 8, 2020

Hello guys. We have a project that is in a similar situation.
This is part of our Webpack configuration (aliases section):

    resolve: {
        alias: {
            assets: path.join(process.cwd(), 'src/assets'),
            controllers: path.join(process.cwd(), 'src/controllers'),
            views: path.join(process.cwd(), 'src/views')
        }
    }

As we can see, each alias is a reference to the "src" directory. And this is how we use them in vue files:

<template>
    <div />
</template>

<script lang="ts" src="controllers/components/FieldClick.ts"></script>

OK, to use Jest we need to replicate the above case in a configuration. This is how it looks:

module.exports = {
    transform: {
        '^.+\\.[t|j]sx?$': '<rootDir>/node_modules/babel-jest',
        '^.+\\.vue$': '<rootDir>/node_modules/vue-jest'
    },
    modulePaths: ['<rootDir>/src'],
    moduleFileExtensions: ['ts', 'tsx', 'js', 'vue', 'json']
};

And the result after the transformation from "vue-jest" is:
ENOENT, no such file or directory

Which is absolutely logical, judging by these lines of code in "vue-jest/lib/process":

parts.script.content = fs.readFileSync(join(filePath, '..', parts.script.src), 'utf8')

To the authors: You need to rethink your code to cover cases like ours.
moduleNameMapper is useless in the above case if you think it will be useful.

WORKAROUND

We created a file (vue-jest.js) that replicates the function from "vue-jest/lib/process" with the following content:

const process = require('vue-jest/lib/process');
const path = require('path');

module.exports = {
    process: (src, filePath, jestConfig) => {
        return process(src, path.join(jestConfig['modulePaths'][0], path.basename(filePath)), jestConfig);
    }
};

Then in the jest configuration, we just refer to this file:

transform: {
        '^.+\\.[t|j]sx?$': '<rootDir>/node_modules/babel-jest',
        '^.+\\.vue$': '<rootDir>/vue-jest.js'
    },

Now it works like a charm! I hope it helps someone.

@GadQ
Copy link

GadQ commented Sep 14, 2020

I have the same issue with aliast in src of the template in vue-jest 3.0.6 (and I believe 4.x will have the same problem)

In index.vue I have:

<template src="@components/template.html" />

package.json:

{
  "scripts": {
    "start": "webpack-dev-server",
    "test": "jest",
    "tdd": "jest --watch"
  },
  "repository": "GadQ/vue-jest-template-alias",
  "dependencies": {
    "vue": "^2.6.10"
  },
  "devDependencies": {
    "babel-core": "7.0.0-bridge.0",
    "jest": "^26.4.1",
    "vue-jest": "^3.0.6",
    "vue-loader": "^15.7.0",
    "vue-template-compiler": "^2.6.10",
    "webpack": "^4.30.0",
    "webpack-cli": "^3.3.1",
    "webpack-dev-server": "^3.3.1"
  }
}

jest.config.js:

module.exports = {
  moduleFileExtensions: [ 'js', 'vue' ],
  transform: {
    '^.+\\.vue$': 'vue-jest'
  },
  moduleNameMapper: {
    '^vue$': 'vue/dist/vue.js',
    '^@components/(.*)$': '<RootDir>/components',
  },
  collectCoverage: true,
  collectCoverageFrom: [
    'src/**/*.{js,vue}'
  ]
}

When I run the test I get:
ENOENT: no such file or directory, open '/home/xyz/template-alias/src/App/@components/template.html'

Alias isn't resolved, but added as relative to tested index.vue directory path.

When i use relative path test works i.e.

<template src="./components/template.html" />

Besides that webpack/vue-loader doesn't have any problem with path with alias and build project correctly.

Reproduction repository: https://github.com/GadQ/vue-jest-template-alias.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants