Skip to content
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

Refactoring options api to use vue-router/composables break basic unit tests #3802

Open
renatodeleao opened this issue Nov 1, 2022 · 1 comment
Labels

Comments

@renatodeleao
Copy link

renatodeleao commented Nov 1, 2022

Version

3.6.5

Reproduction link

stackblitz.com

Steps to reproduce

  1. Giving a basic options API component
    <!-- using options API -->
    <template>
       <div>{{ msg }}</div>
    </template>
    
    <script>
    export default {
      computed: {
          msg() {
             return `My route name is ${this.$route.name}`;
          }
      }
    };
    </script>
  2. refactoring to composition api
    <!-- Refactoring using composition-api -->
    <script>
    import { useRoute } from 'vue-router/composables';
    import { computed } from 'vue';
    
    export default {
      setup() {
        const $route = useRoute();
        const msg = computed(() => {
          `My route name is ${$route.name}`;
        });
    
        return {
          msg,
        };
      },
    };
    </script>
  3. The test that worked before, now breaks.
    import { mount } from '@vue/test-utils';
    import SomeComponent from './SomeComponent.vue';
    
    const $route = {
      path: '/some/path',
    };
    
    function Wrapper() {
      return mount(SomeComponent, {
        mocks: {
          $route,
        },
      });
    }
    
    test('mount component',  () => {
      const wrapper = Wrapper();
      
      expect(wrapper.exists()).toBe(true);
      // TypeError: Cannot read properties of undefined (reading 'currentRoute')
    });

What is expected?

using options/composition-api should not affect the test suite output

What is actually happening?

Using options/composition-api requires different ways to test (mock)


Additional Comments

Link to reproduction with same component written in "options API" mode
https://stackblitz.com/edit/vitejs-vite-rdjvxj?file=src%2Fviews%2FAbout.test.js

Heya! 👋
While I was waiting for the 3.6.x release, I rolled some in-house vue-router hooks as per #3760 (comment). This allowed refactoring some options-API components to composition-api "mode" while keeping my test suite intact.

I thought the refactor to use the official package hooks would be a simple find/replace but my test suite broke. After some digging, the reason is that the hooks implementation relies on router.currentRoute property and afterEach hook, which made the tests using the simplest $route mock as suggested in vue-test-utils docs to fail.

Of course there's several ways to fix it: updating the test mocks as below; setting up a router with localVue as per docs; stubbing modules jest.mock(); etc;

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

const $route = {
  path: '/some/path',
};

function Wrapper() {
  return mount(SomeComponent, {
    mocks: {
-      $route,
+      $router: { currentRoute: $route, afterEach: vitest.fn() },
    },
  });
}

Question

If you went this way1, I'm sure there are good reasons for it. I'm just curious on why didn't you go with a similar approach as vue-router@4, as in, with a reactive object derived from getCurrentInstance().proxy.$route as per2 which kept tests working without any change — but surely break some other stuff.


Cheers and thanks for your work on the router! Feel free to close this if you think it's related with @vue/test-utils docs instead ✌️

Footnotes

  1. https://github.com/vuejs/vue-router/blob/e3273b3db905f0d162d57725fba0c459ea5bb463/src/composables/globals.js#L23-L30

  2. https://github.com/vuejs/vue-router/pull/3763/commits/f1eb2b1dba9b5cc5011b230a3121c882d883c4c0#diff-2042e0452c0d0edd730403740acc8d4337382101087ad62a677e1e2fdae05e8fR8-R17

@posva
Copy link
Member

posva commented Nov 3, 2022

Any mock to the router does indeed need a bit more if they use the composables. I think some cookbook entry would be a nice thing if anybody is up for the PR

I had to go with that version because [2] didn't work in all scenarios 😔

Ideally a Vue 2 version of https://github.com/posva/vue-router-mock would be perfect

@posva posva added the docs label Nov 3, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants