vuejs / test-utils

Vue Test Utils for Vue 3
https://test-utils.vuejs.org
MIT License
1.01k stars 235 forks source link

Typescript interface error RouterLink.d.ts #143

Closed shaneostonstowe closed 4 years ago

shaneostonstowe commented 4 years ago

I have installed a VueJS 3 app and upgraded test-utils to the latest alpha. An attempt to serve the app locally returns this error:

node_modules/@vue/test-utils/dist/components/RouterLinkStub.d.ts:5:12 - error TS2707: Generic type 'ComponentOptionsBase<Props, RawBindings, D, C, M, Mixin, Extends, E, EE>' requires between 8 and 9 type arguments.

5 } & {}>) & import("vue").ComponentOptionsBase<Readonly<{
             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
6     to: any;
  ~~~~~~~~~~~~
7 } & {}>, unknown, unknown, {}, {}, Record<string, any>, string> & {
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

It seems the interface ComponentOptionsBase is incorrectly specified or RouterLink.d.ts has the wrong number of arguments.

Is this expected behaviour or is this an issue? Is there a workaround?

rtbo commented 4 years ago

This has to do with vue-test-utils-next relying on vue-3.0.0-beta.12 and your app likely on vue-3.0.0-beta.15.

I have the same issue. I tried downgrading vue to beta.12, but I now have other typing issues.

I'm ending up testing vue3 without type checks

lmiller1990 commented 4 years ago

That (may) fix it. I will try repro tonight and see if it does.

I will do a release for the latest Vue 3 beta in the next day or two! We just merged up something that was blocking this.

lmiller1990 commented 4 years ago

Alpha 7 is out now: https://github.com/vuejs/vue-test-utils-next/releases/tag/2.0.0-alpha.7

Can you see if this resolves your issue?

lmiller1990 commented 4 years ago

@rtbo can you give this another try?

rtbo commented 4 years ago

Same problem with vue-test-utils-next-2.0.0-alpha.8.

Repro:

git clone git@github.com:rtbo/testvue3-ts
cd testvue3-ts
yarn install
yarn test:unit

 ERROR  Failed to compile with 2 errors

 error  in /home/remi/dev/test/testvue3-ts/node_modules/@vue/test-utils/dist/components/RouterLinkStub.d.ts

ERROR in /home/remi/dev/test/testvue3-ts/node_modules/@vue/test-utils/dist/components/RouterLinkStub.d.ts(5,12):
5:12 Generic type 'ComponentOptionsBase<Props, RawBindings, D, C, M, Mixin, Extends, E, EE>' requires between 8 and 9 type arguments.
    3 | } & {}, unknown, unknown, {}, {}, Record<string, any>, import("vue").VNodeProps & {
    4 |     to: any;
  > 5 | } & {}>) & import("vue").ComponentOptionsBase<Readonly<{
      |            ^
    6 |     to: any;
    7 | } & {}>, unknown, unknown, {}, {}, Record<string, any>, string> & {
    8 |     props: {

 error  in /home/remi/dev/test/testvue3-ts/tests/unit/example.spec.ts

ERROR in /home/remi/dev/test/testvue3-ts/tests/unit/example.spec.ts(8,34):
8:34 No overload matches this call.
  The last overload gave the following error.
    Argument of type '{}' is not assignable to parameter of type 'ComponentOptionsWithObjectProps<readonly string[] | Readonly<ComponentObjectPropsOptions<Data>>, unknown, unknown, {}, {}, Record<string, any>, ComponentOptionsMixin, ComponentOptionsMixin, string, Readonly<...> | Readonly<...>>'.
      Property 'props' is missing in type '{}' but required in type '{ props: readonly string[] | Readonly<ComponentObjectPropsOptions<Data>>; }'.
     6 |   it("renders props.msg when passed", () => {
     7 |     const msg = "new message";
  >  8 |     const wrapper = shallowMount(HelloWorld, {
       |                                  ^
     9 |       props: { msg }
    10 |     });
    11 |     expect(wrapper.text()).to.include(msg);
lmiller1990 commented 4 years ago

Can you share your test? Code-base? Are you only the latest beta for Vue? I am on beta 16 and alpha 8 for Vue and VTU respectively.

There is a template you could use here to repro: https://github.com/lmiller1990/vtu-next-demo.

I can' see where you are using RouterLink here. Or this just happens as soon as you run test:unit?

rtbo commented 4 years ago

@lmiller1990 the repo URL is in my previous message. Here again https://github.com/rtbo/testvue3-ts

I've started a template with vue-cli that includes vue-router and unit tests. I then activated vue-next with vue add vue-next. I think that's pretty much my testing code base (apart may be one or 2 tweaks).

rtbo commented 4 years ago

With https://github.com/lmiller1990/vtu-next-demo I don't have compilation error.

lmiller1990 commented 4 years ago

Weird one. One obvious problem is you are doing export default Vue.extend in your HelloWorld.vue file, but even changing that did nothing.

I'll keep playing around. I guess it is some conflicting type definitions somewhere...

BlakeTheAwesome commented 4 years ago

Just adding a data point: I'm getting this in my repo when I npm run my build, serve or test:e2e scripts. My package.json looks like:

{
  "name": "vue3-starter",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "test:unit": "vue-cli-service test:unit",
    "test:e2e": "vue-cli-service test:e2e",
    "lint": "vue-cli-service lint"
  },
  "dependencies": {
    "@types/chart.js": "^2.9.21",
    "chart.js": "^2.9.3",
    "core-js": "^3.6.4",
    "vue": "^3.0.0-beta.17",
    "vue-router": "^4.0.0-alpha.14"
  },
  "devDependencies": {
    "@babel/node": "^7.8.7",
    "@babel/preset-env": "^7.9.0",
    "@cypress/webpack-preprocessor": "^5.4.1",
    "@types/jest": "^25.2.1",
    "@typescript-eslint/eslint-plugin": "^2.34.0",
    "@typescript-eslint/parser": "^2.34.0",
    "@vue/cli-plugin-babel": "~4.3.0",
    "@vue/cli-plugin-e2e-cypress": "~4.3.0",
    "@vue/cli-plugin-eslint": "~4.3.0",
    "@vue/cli-plugin-typescript": "^4.3.1",
    "@vue/cli-plugin-unit-jest": "~4.4.6",
    "@vue/cli-service": "^4.4.0",
    "@vue/compiler-sfc": "^3.0.0-beta.17",
    "@vue/eslint-config-prettier": "^6.0.0",
    "@vue/eslint-config-typescript": "^5.0.2",
    "@vue/test-utils": "^2.0.0-alpha.8",
    "babel-eslint": "^10.1.0",
    "babel-jest": "^25.2.6",
    "eslint": "^6.7.2",
    "eslint-plugin-prettier": "^3.1.1",
    "eslint-plugin-vue": "^7.0.0-alpha.3",
    "jest": "^25.2.7",
    "prettier": "^1.19.1",
    "sass": "^1.26.5",
    "sass-loader": "^8.0.2",
    "ts-jest": "^25.3.1",
    "ts-loader": "^7.0.4",
    "typescript": "^3.8.3",
    "vue-cli-plugin-vue-next": "^0.1.3",
    "vue-cli-plugin-vuetify": "^2.0.5",
    "vue-jest": "^5.0.0-alpha.1",
    "vue-loader": "^16.0.0-alpha.3"
  }
}
lmiller1990 commented 4 years ago

I am getting this in your repo too, I cannot repro in my own template. Not sure why npm run serve is even looking at a test file, though?? The mere presence of VTU next breaks something??

I wonder if we should write a cli-plugin for test-utils next and see if that helps with the dependency weirdness.

lmiller1990 commented 4 years ago

Potential stupid solution: simplify the RouterStub definitions (no real reason it needs to be strongly typed with defineComponent.

I will try this today. TS is hard sometimes!

cexbrayat commented 4 years ago

Yes, this is basically the same root issue than #143 It's a bit annoying but we should be able to fix it eventually.

Right now you can:

module.exports = {
  chainWebpack: config => {
    // fork-ts-checker is sadly ignoring the Vue shim
    // and throws incorrect errors
    // we disable it as it is just a nice to have to speed up the build
    config.plugins.delete('fork-ts-checker');
    config.module
      .rule('ts')
      .use('ts-loader')
      .tap(options => {
        return { ...options, transpileOnly: false };
      });
  }
};

I haven't found the root reason why we need this, but hopefully I will. In the meantime, if you want to have a proper minimal CLI setup with TS, you can check out the first step of my tutorial (shameless plug, I know, but you'll be able to download all the necessary config files, and be up and running in no time).

@lmiller1990 Yes, just having bad typings in VTU breaks yarn serve because the CLI is not properly configured: we just have one tsconfig which compiles all the TS file, where we should have two config (one dedicated to the project, and one dedicated to the tests). I've been meaning to change that for a while as well.

lmiller1990 commented 4 years ago

Is there something we can do on our end? Adding that transpileOnly mod is pretty hard, many people will not know/want to extend their webpack config. Ideally you should just add vue-jest, vue-test-utils and be ready to rock and roll.

We should add this to the README, perhaps. Or maybe we need a vue-test-utils-next cli plugin.

cexbrayat commented 4 years ago

@lmiller1990 I think we should be able to fix the first issue on VTU side. For the second one, I spent some time debugging it and came with this workaround, but I was hoping to discuss it with @sodatea . This might be a good occasion to have his opinion on the matter 🙂 (cc @sodatea )

sodatea commented 4 years ago

I've also encountered this issue when working on vue-class-component integration.

Yeah, while there are type issues to fix in the test-utils, skipLibCheck is the fix for common Vue CLI projects.

we should have two config (one dedicated to the project, and one dedicated to the tests)

After a second thought, I think it may not be the best option. If we have a dedicate tsconfig for test, what about production mode? Shall we have 3 different configs or just reuse one for both test and production? Both options don't feel right to me.

Actually, after reading https://github.com/formik/tsdx/issues/529, I'm inclined to have skipLibCheck enabled for all new projects. (Should be turned off for libraries, considering https://github.com/facebook/create-react-app/issues/8964, but we don't have a dedicated library template, so I guess we just need to document it somewhere)

cexbrayat commented 4 years ago

skipLibCheck is indeed a common workaround, and it's usually OK to use in an app (but IIRC it also disable checking local d.ts files which was the reason it did not become the default option in Angular CLI projects for example).

Anyway, we should really fix the issue in VTU at one point.

For the separate tsconfig: you don't need a third one for production. The point of having a tsconfig.spec.json is usually to extend the app one to include the spec.ts files. That way, having a compilation error in a test file does not impact serving the app, which is really handy when developing an app. It also speeds up the compilation a lot in big projects, as TS has half the files to compile. It also allows a more fine-tuning for types (for example you only include jest or jasmine types in the tsconfig for tests, as it does not make sense fo an application). You can also decide to have slightly less strict settings in test than in the rest of the application. I really think it would be a great win for TS developers :)

sodatea commented 4 years ago

The point of having a tsconfig.spec.json is usually to extend the app one to include the spec.ts files.

Oh, that makes sense.

but IIRC it also disable checking local d.ts files which was the reason it did not become the default option in Angular CLI projects for example

🤔 Hmm, We can discuss it in a separate thread. But as far as I can tell, the community seems more inclined to not recommend skipLibCheck, esp. considering the Vue 2 TS definitions are not that perfect compared to Angular or Vue 3.

lmiller1990 commented 4 years ago

I don't understand why we need a workaround. What is the actual problem? Why does exporting a component with defineComponent cause this problem in the first place? I have used defineComponent many times and not had this problem in any of my other projects.

sodatea commented 4 years ago

@lmiller1990 The bug here is that the published version of dist/components/RouterLinkStub is still built from vue@3.0.0-beta.12. There's a breaking change related to the type definitions in beta.15 https://github.com/vuejs/vue-next/pull/626

Maybe due to the cache from rollup-plugin-typescript2 (under node_modules/.cache, need to set the clean option to true to disable it https://github.com/ezolenko/rollup-plugin-typescript2#plugin-options)

A clean build of this repo fixes this issue.

lmiller1990 commented 4 years ago

I wonder if the cache was the problem - we have definitely done a release since beta.15.

I will do another release with the latest, cleaned build in the next day or so! Thanks. I guess we should move to beta now (I don't see any blockers) after this fix is released.

sodatea commented 4 years ago

See this file: https://unpkg.com/browse/@vue/test-utils@2.0.0-alpha.8/dist/components/RouterLinkStub.d.ts

If it's correctly built from vue >= 3.0.0-beta.15, there should be something like ComponentOptionsMixin in it.

cexbrayat commented 4 years ago

Now that @lmiller1990 released 2.0.0-beta.0, I can confirm that the workaround for skipLibCheck is no longer needed.

lmiller1990 commented 4 years ago

Great!