You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Vitest中验证Quasar Q-btn组件:to属性触发的router.push行为?

Hey there! The issue here is that Quasar's Q-btn doesn't directly call the router.push() from the useRouter() hook you mocked—it uses Quasar's own integrated routing utilities under the hood, specifically relying on either $q.router or the global $router instance provided by Vue Router in the Quasar context. Your current mock only covers the useRouter() hook, but the button isn't using that directly.

Here's how to fix your test properly:

1. Mock the Quasar Router Instance

Since Q-btn leverages Quasar's $q.router for navigation when using the :to prop, you need to inject a mocked version of this into your component's mounting context:

import { mount } from '@vue/test-utils';
import QBtn from 'quasar/src/components/btn/QBtn.vue';
import vi from 'vitest';

test('click on button navigates to someView', async () => {
  // Create a mock push function
  const mockPush = vi.fn();
  
  // Mount the QBtn with mocked Quasar router and Vue Router instances
  const wrapper = mount(QBtn, {
    global: {
      provide: {
        // Mock Quasar's $q.router which Q-btn uses for navigation
        $q: {
          router: { push: mockPush }
        }
      },
      // Also mock global $router as a fallback (some cases might use this)
      mocks: {
        $router: { push: mockPush }
      }
    },
    props: {
      to: { name: 'someView' }
    }
  });

  // Trigger the button click
  await wrapper.trigger('click');

  // Verify the push was called correctly
  expect(mockPush).toHaveBeenCalledOnce();
  expect(mockPush).toHaveBeenCalledWith({ name: 'someView' });
});

If you're using Quasar's official testing extension (@quasar/quasar-app-extension-testing-unit-vitest), use mountQuasar to automatically set up the Quasar environment, which simplifies mocking routing:

import { mountQuasar } from '@quasar/quasar-app-extension-testing-unit-vitest';
import QBtn from 'quasar/src/components/btn/QBtn.vue';
import vi from 'vitest';

test('click on button navigates to someView', async () => {
  const mockPush = vi.fn();
  
  // Mock the router instance returned by useRouter
  vi.mock('vue-router', () => ({
    useRouter: vi.fn(() => ({ push: mockPush }))
  }));

  // Mount with Quasar's helper
  const wrapper = await mountQuasar(QBtn, {
    props: {
      to: { name: 'someView' }
    }
  });

  await wrapper.trigger('click');
  
  expect(mockPush).toHaveBeenCalledOnce();
  expect(mockPush).toHaveBeenCalledWith({ name: 'someView' });
});

Why Your Original Test Failed

Quasar components are designed to work within the Quasar ecosystem. When you use :to on Q-btn, it doesn't invoke the useRouter() hook directly in your code—it uses Quasar's internal references to the router (either $q.router or the global $router). Your initial mock only covered the useRouter() export, which the button doesn't rely on for its navigation logic.

内容的提问来源于stack exchange,提问作者G.Brown

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 21:37:43