From f8879a82f95e7640d379e1e4b3ef30dec4ff8f3a Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Fri, 9 Jan 2026 19:58:35 +0900 Subject: [PATCH] fix(mocker): fix mock transform with class --- packages/mocker/src/node/esmWalker.ts | 11 +++++++ test/core/test/injector-mock.test.ts | 46 +++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/packages/mocker/src/node/esmWalker.ts b/packages/mocker/src/node/esmWalker.ts index 41420995a03c..aae80e955b59 100644 --- a/packages/mocker/src/node/esmWalker.ts +++ b/packages/mocker/src/node/esmWalker.ts @@ -157,6 +157,17 @@ export function esmWalker( identifiers.push([node, parentStack.slice(0)]) } } + else if (node.type === 'ClassDeclaration' && node.id) { + // A class declaration name could shadow an import, so add its name to the parent scope + const parentScope = findParentScope(parentStack) + if (parentScope) { + setScope(parentScope, node.id.name) + } + } + else if (node.type === 'ClassExpression' && node.id) { + // A class expression name could shadow an import, so add its name to the scope + setScope(node, node.id.name) + } else if (isFunctionNode(node)) { // If it is a function declaration, it could be shadowing an import // Add its name to the scope so it won't get replaced diff --git a/test/core/test/injector-mock.test.ts b/test/core/test/injector-mock.test.ts index 8e0f93831b20..0d581f84847a 100644 --- a/test/core/test/injector-mock.test.ts +++ b/test/core/test/injector-mock.test.ts @@ -1117,6 +1117,52 @@ const Baz = class extends Foo {} `) }) + test('classDeclaration shadowing import', () => { + const input = `\ +import { Bar } from "./repro.js" +{ + class Bar { + test() {} + } + const Zoo = class Zoo extends Bar {} +} +` + expect(hoistSimpleCodeWithoutMocks(input)).toMatchInlineSnapshot(` + "vi.mock('faker'); + const __vi_import_0__ = await import("./repro.js"); + import {vi} from "vitest"; + + { + class Bar { + test() {} + } + const Zoo = class Zoo extends Bar {} + }" + `) + }) + + test('classExpression name shadowing import', () => { + const input = `\ +import { Foo } from "./foo.js" +const Bar = class Foo { + static create() { + return new Foo() + } +} +` + expect(hoistSimpleCodeWithoutMocks(input)).toMatchInlineSnapshot(` + "vi.mock('faker'); + const __vi_import_0__ = await import("./foo.js"); + import {vi} from "vitest"; + + const Bar = class Foo { + static create() { + return new Foo() + } + }" + `) + }) + test('import assertion attribute', () => { expect( hoistSimpleCodeWithoutMocks(`