From 1a804792acd7efe318c421e7194f049c14af0f1b Mon Sep 17 00:00:00 2001 From: vansh-nagar Date: Tue, 22 Sep 2026 14:51:08 +0530 Subject: [PATCH] test(nuxt): cover pages router instrumentation Fixes #13813 Co-Authored-By: OpenAI Codex --- .../nuxt/test/runtime/plugins/client.test.ts | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 packages/nuxt/test/runtime/plugins/client.test.ts diff --git a/packages/nuxt/test/runtime/plugins/client.test.ts b/packages/nuxt/test/runtime/plugins/client.test.ts new file mode 100644 index 000000000000..daf96f276c78 --- /dev/null +++ b/packages/nuxt/test/runtime/plugins/client.test.ts @@ -0,0 +1,67 @@ +import { getClient } from '@sentry/core'; +import { browserTracingIntegration, vueIntegration } from '@sentry/vue'; +import { afterEach, describe, expect, it, vi } from 'vitest'; +import clientPlugin from '../../../src/runtime/plugins/sentry.client'; + +vi.mock(import('@sentry/core'), async importOriginal => { + const actual = await importOriginal(); + return { ...actual, getClient: vi.fn() }; +}); + +vi.mock(import('@sentry/vue'), async importOriginal => { + const actual = await importOriginal(); + return { ...actual, browserTracingIntegration: vi.fn(), vueIntegration: vi.fn() }; +}); + +vi.mock(import('nuxt/app'), () => ({ + defineNuxtPlugin: vi.fn(plugin => plugin), + isNuxtError: vi.fn(), +})); + +type ClientPlugin = { + setup: (nuxtApp: { $router?: unknown; hook: ReturnType }) => Promise; +}; + +describe('Sentry client plugin', () => { + afterEach(() => { + vi.resetAllMocks(); + }); + + it('instruments the Nuxt pages router with path-based route labels', async () => { + const router = { beforeEach: vi.fn(), onError: vi.fn() }; + const integration = { name: 'BrowserTracing' }; + const addIntegration = vi.fn(); + vi.mocked(getClient).mockReturnValue({ addIntegration } as never); + vi.mocked(browserTracingIntegration).mockReturnValue(integration as never); + + await (clientPlugin as ClientPlugin).setup({ $router: router, hook: vi.fn() }); + + expect(browserTracingIntegration).toHaveBeenCalledWith({ router, routeLabel: 'path' }); + expect(addIntegration).toHaveBeenCalledWith(integration); + }); + + it('does not create router instrumentation without an initialized client', async () => { + vi.mocked(getClient).mockReturnValue(undefined); + + await (clientPlugin as ClientPlugin).setup({ $router: {}, hook: vi.fn() }); + + expect(browserTracingIntegration).not.toHaveBeenCalled(); + }); + + it('only adds the Vue integration when the Nuxt app has no pages router', async () => { + const vueApp = {}; + const integration = { name: 'Vue' }; + const addIntegration = vi.fn(); + const hook = vi.fn(); + vi.mocked(getClient).mockReturnValue({ addIntegration } as never); + vi.mocked(vueIntegration).mockReturnValue(integration as never); + + await (clientPlugin as ClientPlugin).setup({ hook }); + const appCreatedHook = hook.mock.calls.find(([name]) => name === 'app:created')?.[1]; + appCreatedHook(vueApp); + + expect(browserTracingIntegration).not.toHaveBeenCalled(); + expect(addIntegration).toHaveBeenCalledOnce(); + expect(addIntegration).toHaveBeenCalledWith(integration); + }); +});