vue-jest icon indicating copy to clipboard operation
vue-jest copied to clipboard

Jest requires `--no-cache` for proper coverage

Open awolden opened this issue 6 years ago • 28 comments

I have been digging into why many of our well tested components/views are not showing up on coverage reports, and I noticed that if I applied the --no-cache flag to jest I started getting appropriate coverage numbers. There seems to be an issue with the vue-jest caching mechanism that may be preventing some from getting appropriate coverage numbers.

We copied our settings from https://github.com/eddyerburgh/vue-test-utils-jest-example

awolden avatar Feb 13 '18 23:02 awolden

I can confirm this issue on vue-enterprise-boilerplate. I've also noticed tests that should pass sometimes failing unless I clear the cache. If there's some information I can collect the next time it happens, I'm happy to post it here.

chrisvfritz avatar Feb 22 '18 04:02 chrisvfritz

Any info is usefu:

  • Jest version
  • Node version
  • OS version

Also, you could delete this line and see if it solves the issue—https://github.com/vuejs/vue-jest/blob/master/vue-jest.js#L6.

eddyerburgh avatar Feb 22 '18 06:02 eddyerburgh

  • Jest: v22.3.0
  • Node: v9.5.0
  • OS: macOS 10.13.3

I also just confirmed that deleting that line fixes the issue, so it does seem to be cache-related.

chrisvfritz avatar Feb 22 '18 08:02 chrisvfritz

Does anyone have an example of a test that fails currently if the cache isn't cleared? I'd like to add a test case to the library when I fix the issue

eddyerburgh avatar Feb 23 '18 21:02 eddyerburgh

The best solution right now might be to remove the getCacheKey function.

The getCacheKey function is returning a different hash when the file data changes, so the issue could be with how Jest uses the cache key.

eddyerburgh avatar Feb 23 '18 22:02 eddyerburgh

I don't have an example of a test that fails, as it's not a persistent problem. At some point, a test will start failing when it shouldn't and I'm not sure what the trigger is. Then I clear the cache and it's all good.

The coverage problem is very reproducible though. On vue-enterprise-boilerplate, running yarn jest --coverage will consistently report 0% for every .vue file unless you also add --no-cache.

chrisvfritz avatar Feb 23 '18 23:02 chrisvfritz

I'm unable to reproduce.

I cloned the vue-enterprise-boilerplate (which is great by the way 😀), ran yarn install, and yarn jest --coverage.

  • node 9.5.0
  • OS: macOS 10.12.6

Results:

---------------------|----------|----------|----------|----------|-------------------|
File                 |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
---------------------|----------|----------|----------|----------|-------------------|
All files            |      100 |       75 |      100 |      100 |                   |
 components          |      100 |       75 |      100 |      100 |                   |
  _base-icon.vue     |      100 |      100 |      100 |      100 |                   |
  _base-input.vue    |      100 |      100 |      100 |      100 |                   |
  nav-bar-routes.vue |      100 |       75 |      100 |      100 |                19 |
  nav-bar.vue        |      100 |      100 |      100 |      100 |                   |
 router/layouts      |      100 |      100 |      100 |      100 |                   |
  main.vue           |      100 |      100 |      100 |      100 |                   |
 router/views        |      100 |      100 |      100 |      100 |                   |
  home.vue           |      100 |      100 |      100 |      100 |                   |
  login.vue          |      100 |      100 |      100 |      100 |                   |
  profile.vue        |      100 |      100 |      100 |      100 |                   |
---------------------|----------|----------|----------|----------|-------------------|

I think the solution is to remove the getCacheKey method temporarily.

eddyerburgh avatar Feb 24 '18 08:02 eddyerburgh

So weird! I'm not sure if this is another option, but it looks like Facebook offers a createCacheKeyFunction utility that may be useful to us. I apologize if you already know about it and it's not appropriate for our use case - I'm just starting to dig my head into this stuff. 😅

(And as an aside about the boilerplate, please don't hesitate to let me know if you have any suggestions/questions about how I'm managing unit tests there, including the global helpers in tests/unit/setup.js. I'd be honored to get feedback from the test master himself!)

chrisvfritz avatar Feb 24 '18 17:02 chrisvfritz

Thanks @chrisvfritz , I wasn't aware of that method. Would you be able to use it on this line—https://github.com/vuejs/vue-jest/blob/master/vue-jest.js#L6- and see if it fixes the issue. I'm still unable to reproduce the bug locally

eddyerburgh avatar Feb 27 '18 21:02 eddyerburgh

Definitely! It looks like we need a list of files whose content can be used as a key. What do you recommend we use in our case?

chrisvfritz avatar Feb 28 '18 04:02 chrisvfritz

Sorry, I didn't see this message! I've removed cacheing as a temporary fix in 2.1.1.

I believe we just use the filename, and then set getCacheKey to createCacheKeyFunction. It should be called with the correct arguments

eddyerburgh avatar Mar 05 '18 07:03 eddyerburgh

I've been running --no-cache for some time to get around this issue, if a second confirmation helps. Just stumbled across this bug as I was looking for the reason for the cache removal in 2.1.1.

robcresswell avatar Mar 05 '18 13:03 robcresswell

Same issue here, --no-cache avoids the issue as well

websmurf avatar May 24 '18 10:05 websmurf

After creating a project using vue init webpack my-project I was getting 0% coverage for some Vue components. Just reporting in that --no-cache fixed the issue as well. Hope this can help anyone who searches for this in Google.

Eitz avatar May 30 '18 14:05 Eitz

I've also encountered @chrisvfritz 's issue with tests failing until the cache is cleared or jest is called with no-cache. Other people here are also encountering it on the same tests.

TheCycoONE avatar Jun 19 '18 13:06 TheCycoONE

I also recently had this issue which was causing none of the .vue files to show in the coverage reports. Running with --no-cache resolved the issue.

DamianMullins avatar Oct 19 '18 20:10 DamianMullins

I can confirm this issue still exists on [email protected] and [email protected] (and also with @vue/[email protected]). Using --no-cache resolves the problem.

ashmenon avatar Oct 24 '18 12:10 ashmenon

This issue came out of nowhere for me, took me way too long to recognize that it's a cache error.

FIX

All tests work again with adding --no-cache to the test script:

"test:unit": "vue-cli-service test:unit --no-cache"

SETUP

"devDependencies": {
    ....
    "@vue/cli-plugin-babel": "^3.0.5",
    "@vue/cli-plugin-unit-jest": "^3.0.5",
    "@vue/cli-service": "^3.0.5",
    "@vue/test-utils": "^1.0.0-beta.20",
    "babel-core": "7.0.0-bridge.0",
    "babel-jest": "^23.0.1",
    ...
  }

jest.config.js

module.exports = {
  moduleFileExtensions: ["js", "jsx", "json", "vue"],
  verbose: true,
  transform: {
    "^.+\\.vue$": "vue-jest",
    ".+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$":
      "jest-transform-stub",
    "^.+\\.jsx?$": "babel-jest"
  },
  moduleNameMapper: {
    "^@/(.*)$": "<rootDir>/src/$1"
  },
  snapshotSerializers: ["jest-serializer-vue"],
  testMatch: [
    "**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)"
  ],
  testURL: "http://localhost/"
};

ERROR

Here is the error from console:

jest-haste-map: @providesModule naming collision:
  Duplicate module name: _my-module_
  Paths: C:\...\frontend\package.json collides with C:\...\frontend\src\package.json

This warning is caused by a @providesModule declaration with the same name across two different files.
 FAIL  tests/unit/App.spec.js
  ● Test suite failed to run

    Cannot find module 'C:\...\frontend\node_modules\@babel\runtime/helpers/builtin/interopRequireDefault' from 'App.spec.js'

      1 | import { shallowMount, createLocalVue } from "@vue/test-utils";
      2 | import VueRouter from "vue-router";
    > 3 | import App from "@/App.vue";
        |                              ^
      4 |
      5 | const localVue = createLocalVue();
      6 | localVue.use(VueRouter);

      at Resolver.resolveModule (node_modules/jest-resolve/build/index.js:221:17)
      at Object.<anonymous> (tests/unit/App.spec.js:3:30)

TEST

@eddyerburgh

Does anyone have an example of a test that fails currently if the cache isn't cleared? I'd like to add a test case to the library when I fix the issue

Even the most simple isVueInstance test fails:

import { shallowMount, createLocalVue } from "@vue/test-utils";
import VueRouter from "vue-router";
import App from "@/App.vue";

const localVue = createLocalVue();
localVue.use(VueRouter);
const router = new VueRouter();

describe("App", () => {
  test("is a Vue instance", () => {
    const wrapper = shallowMount(App, { localVue, router });
    expect(wrapper.isVueInstance()).toBeTruthy();
  });
});

..but again, other tests fail, too.

bennettdams avatar Nov 01 '18 17:11 bennettdams

"test:unit": "vue-cli-service test:unit --no-cache" worked for me!! Thanks.

Royalone94 avatar Dec 13 '18 18:12 Royalone94

This one is a little frustrating for me. Using --no-cache fixes the test, but if I'm using it in conjunction with --watch then changes aren't picked up as I make them, so the only way to see if I've broken something is to manually run jest. First world problems, but it'd be nice to have my test runner up while building so as to make the flow a bit less tedious.

example.spec.ts

import { shallowMount } from '@vue/test-utils'
import Example from './example.vue'

describe('stuff', () => {
  it('works', () => {
    const wrapper = shallowMount(Example);
    expect(wrapper.text()).toMatch('Hello')
  })
})

example.vue

<template>
  <div class="primary">{{ msg }}</div>
</template>

<script lang="ts" src="./example.ts"></script>
<style lang="scss" src="./example.scss"></style>

example.ts

export default {
  data() {
    return {
      msg: 'Hello Vue'
    }
  }
}

So if I have jest --watch --no-cache running, and change msg in example.ts to 'Hey Vue' the change isn't picked up and jest still thinks it's passing. Not sure if there's a way around that in jest or if it's the purview of vue-jest but seems relevant to the conversation here.

Jack-Barry avatar Dec 15 '18 21:12 Jack-Barry

@Jack-Barry I'm experiencing the exact same issue, did you find a workaround?

couellet avatar Feb 23 '19 17:02 couellet

@couellet For me it was a matter of giving up on keeping my TypeScript in a separate file, and might have also been partly due to pulling in updated dependencies.

If I put my business logic between the <script> tags instead of in its own file it's working for me using Jest 23.6.0, vue-jest 3.0.3, ts-jest 23.10.5, @vue/test-utils 1.0.0-beta.29.

Not a huge deal for our project, just was hoping to keep the business logic in a proper .ts file since the VS Code support for linting those tends to work a bit more predictably than when TS is in a .vue file.

Jack-Barry avatar Feb 25 '19 14:02 Jack-Barry

@Jack-Barry We're using the same setup, with the .ts file in a separate file for better TypeScript support in unit tests. I guess we'll live with that until the next version of Vue which will have a better TypeScript support. Thanks!

couellet avatar Feb 25 '19 15:02 couellet

I have the same problem with .pug files. My components usually have this structure:

Header/
  Header.css
  Header.pug
  Header.spec.ts
  Header.vue

bameda avatar Mar 05 '19 18:03 bameda

For others struggling with the cache not being cleared during --watchAll here is my solution (hack) to get around this issue:

package.json

{
  "scripts": {
    "test": "jest --no-cache -u",
    "test:watch": "onchange 'src/**/*' -i -- yarn test",
  },
  "devDependencies": {
    "onchange": "^7.0.2",
  },
}
yarn test:watch

JGJP avatar Oct 09 '20 05:10 JGJP

Is this issue linked to code coverage reporting import statements as uncovered lines? I'm encountering this with a vue/gridsome project.

jest: 26.6.3 vue-jest: 3.0.7 node: v10.16.2 (windows)

no cache doesn't seem to help, this is my jest config:


module.exports = {
  moduleFileExtensions: ["js", "jsx", "json", "vue"],
  transform: {
    "^.+\\.vue$": require.resolve("vue-jest"),
    "^.+\\.jsx?$": require.resolve("babel-jest"),
  },
  transformIgnorePatterns: ["/node_modules/"],
  moduleNameMapper: {
    "^~/(.*)$": "<rootDir>/src/$1",
  },
  testMatch: ["**/tests/unit/**/*.spec.[jt]s?(x)", "**/__tests__/*.[jt]s?(x)"],
  collectCoverage: true,
  collectCoverageFrom: [
    "src/**/*.{js,vue}",
    "!src/main.js", // No need to cover bootstrap file
  ],
};

michaelmoneypenny avatar Nov 17 '20 16:11 michaelmoneypenny

Even with "vue-jest": "^4.0.0-rc.0", my command vue-cli-service test:unit --no-cache --collect-coverage results in line 122 being uncovered, while line 122 doesn't even exist. The other lines are weird as well

image

ricardovanlaarhoven avatar Dec 31 '20 12:12 ricardovanlaarhoven

I think the source map is incorrect, which results in the incorrect coverage...

lmiller1990 avatar Jan 17 '21 23:01 lmiller1990