Skip to content

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

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

Closed
renatodeleao opened this issue Nov 1, 2022 · 1 comment

Comments

@renatodeleao
Copy link

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.

const route = effectScope(true).run(() =>
shallowReactive(Object.assign({}, root.$router.currentRoute))
)
root._$route = route
root.$router.afterEach(to => {
Object.assign(route, to)
})

Steps

  1. Giving a basic options API component
    <!-- using composition API -->
    <template>
       <div>{{ msg }}</div>
    </template>
    
    <script>
    import { useRoute } from 'vue-router/composables';
    import { computed } from 'vue';
    
    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')
    });

One of The Fixes

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() },
    },
  });
}

test('mount component',  () => {
  const wrapper = Wrapper();
  
  expect(wrapper.exists()).toBe(true);
});

...or setting up a router with localVue as per docs... or stubbing modules jest.mock().

Expectations

  • using options/composition-api should not affect the test suite output — implementation details?!

Reproducing Demos

@vue/[email protected]
[email protected]
[email protected]
`vitest` (can be any test runner)

Question

If you've went this way, I'm sure there are good reasons for it. But curious on why didn't you gt with a similar approach as vue-router@4, as in, with a reactive object derived from getCurrentInstance().proxy.$route as per f1eb2b1#diff-2042e0452c0d0edd730403740acc8d4337382101087ad62a677e1e2fdae05e8fR8-R17 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 ✌️

@vue-bot
Copy link

vue-bot commented Nov 1, 2022

Hello, thank you for taking time filling this issue!

However, we kindly ask you to use our Issue Helper when creating new issues, in order to ensure every issue provides the necessary information for us to investigate. This explains why your issue has been automatically closed by me (your robot friend!).

I hope to see your helper-created issue very soon!

@vue-bot vue-bot closed this as completed Nov 1, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants