From f856d09e9ba6d8dc4fc22f9120e0c1f1d9eb0122 Mon Sep 17 00:00:00 2001 From: "coderabbitai[bot]" <136622811+coderabbitai[bot]@users.noreply.github.com> Date: Sun, 25 May 2025 06:16:42 +0000 Subject: [PATCH 1/2] =?UTF-8?q?=F0=9F=93=9D=20CodeRabbit=20Chat:=20Add=20u?= =?UTF-8?q?nit=20test=20file=20context-aware.spec.ts?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/unit/context-aware.spec.ts | 223 +++++++++++++++++++++++++++++++ 1 file changed, 223 insertions(+) create mode 100644 tests/unit/context-aware.spec.ts diff --git a/tests/unit/context-aware.spec.ts b/tests/unit/context-aware.spec.ts new file mode 100644 index 0000000..2927065 --- /dev/null +++ b/tests/unit/context-aware.spec.ts @@ -0,0 +1,223 @@ +import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest' +import type { ResolvedResult } from 'eslint-import-context' + +vi.mock('eslint-import-context', () => { + let mockContext: { cwd?: string } | null = null + + return { + useRuleContext: vi.fn(() => mockContext), + __setMockContext: (context: { cwd?: string } | null) => { + mockContext = context + }, + __getMockContext: () => mockContext, + } +}) + +import { resolve, createTypeScriptImportResolver } from 'eslint-import-resolver-typescript' +import { useRuleContext } from 'eslint-import-context' + +const mockModule = await import('eslint-import-context') as any + +describe('Context-aware import resolution', () => { + const originalCwd = process.cwd() + const testCwd1 = '/test/project1' + const testCwd2 = '/test/project2' + + beforeEach(() => { + vi.clearAllMocks() + mockModule.__setMockContext(null) + }) + + afterEach(() => { + mockModule.__setMockContext(null) + }) + + describe('Dynamic cwd resolution', () => { + it('should use context.cwd when available', () => { + const mockResolve = vi.fn().mockReturnValue({ found: false } as ResolvedResult) + const mockResolverFactory = vi.fn().mockImplementation(() => ({ sync: mockResolve })) + vi.doMock('unrs-resolver', () => ({ ResolverFactory: mockResolverFactory })) + + mockModule.__setMockContext({ cwd: testCwd1 }) + + resolve('some-module', '/test/file.ts', {}) + + expect(useRuleContext).toHaveBeenCalled() + expect(mockResolve).toHaveBeenCalled() + }) + + it('should fallback to process.cwd() when context is null', () => { + const mockResolve = vi.fn().mockReturnValue({ found: false } as ResolvedResult) + const mockResolverFactory = vi.fn().mockImplementation(() => ({ sync: mockResolve })) + vi.doMock('unrs-resolver', () => ({ ResolverFactory: mockResolverFactory })) + + mockModule.__setMockContext(null) + + resolve('some-module', '/test/file.ts', {}) + + expect(useRuleContext).toHaveBeenCalled() + expect(mockResolve).toHaveBeenCalled() + }) + + it('should fallback to process.cwd() when context.cwd is undefined', () => { + const mockResolve = vi.fn().mockReturnValue({ found: false } as ResolvedResult) + const mockResolverFactory = vi.fn().mockImplementation(() => ({ sync: mockResolve })) + vi.doMock('unrs-resolver', () => ({ ResolverFactory: mockResolverFactory })) + + mockModule.__setMockContext({}) + + resolve('some-module', '/test/file.ts', {}) + + expect(useRuleContext).toHaveBeenCalled() + expect(mockResolve).toHaveBeenCalled() + }) + }) + + describe('Cache key generation', () => { + it('should generate cache key with null character separator', () => { + const mockResolverFactory = vi.fn() + vi.doMock('unrs-resolver', () => ({ + ResolverFactory: mockResolverFactory.mockImplementation(() => ({ + sync: vi.fn().mockReturnValue({ found: false } as ResolvedResult) + })) + })) + + mockModule.__setMockContext({ cwd: testCwd1 }) + + resolve('some-module', '/test/file.ts', {}) + + expect(mockResolverFactory).toHaveBeenCalledTimes(1) + }) + + it('should create separate cache entries for different cwd values', () => { + const mockResolverFactory = vi.fn() + vi.doMock('unrs-resolver', () => ({ + ResolverFactory: mockResolverFactory.mockImplementation(() => ({ + sync: vi.fn().mockReturnValue({ found: false } as ResolvedResult) + })) + })) + + // First resolution with testCwd1 + mockModule.__setMockContext({ cwd: testCwd1 }) + resolve('some-module', '/test/file.ts', {}) + + // Second resolution with testCwd2 should create new resolver + mockModule.__setMockContext({ cwd: testCwd2 }) + resolve('some-module', '/test/file.ts', {}) + + expect(mockResolverFactory).toHaveBeenCalledTimes(2) + }) + + it('should reuse cache for same cwd and options', () => { + const mockResolverFactory = vi.fn() + vi.doMock('unrs-resolver', () => ({ + ResolverFactory: mockResolverFactory.mockImplementation(() => ({ + sync: vi.fn().mockReturnValue({ found: false } as ResolvedResult) + })) + })) + + mockModule.__setMockContext({ cwd: testCwd1 }) + + resolve('some-module', '/test/file1.ts', {}) + resolve('another-module', '/test/file2.ts', {}) + + expect(mockResolverFactory).toHaveBeenCalledTimes(1) + }) + }) + + describe('createTypeScriptImportResolver context switching', () => { + it('should update cwd and recreate resolver when context changes', () => { + const mockResolverFactory = vi.fn() + const mockCloneWithOptions = vi.fn() + + const mockResolver = { + sync: vi.fn().mockReturnValue({ found: false } as ResolvedResult), + cloneWithOptions: mockCloneWithOptions + } + + vi.doMock('unrs-resolver', () => ({ + ResolverFactory: mockResolverFactory.mockImplementation(() => mockResolver) + })) + + mockModule.__setMockContext(null) + const resolver = createTypeScriptImportResolver({ project: ['./tsconfig.json'] }) + + resolver.resolve('some-module', '/test/file.ts') + + mockModule.__setMockContext({ cwd: testCwd1 }) + resolver.resolve('another-module', '/test/file.ts') + + expect(useRuleContext).toHaveBeenCalledTimes(2) + expect(mockCloneWithOptions).toHaveBeenCalled() + }) + + it('should create new resolver when no existing resolver and context changes', () => { + const mockResolverFactory = vi.fn() + + const mockResolver = { + sync: vi.fn().mockReturnValue({ found: false } as ResolvedResult) + } + + vi.doMock('unrs-resolver', () => ({ + ResolverFactory: mockResolverFactory.mockImplementation(() => mockResolver) + })) + + mockModule.__setMockContext(null) + const resolver = createTypeScriptImportResolver({ project: ['./tsconfig.json'] }) + + mockModule.__setMockContext({ cwd: testCwd1 }) + resolver.resolve('some-module', '/test/file.ts') + + expect(mockResolverFactory).toHaveBeenCalled() + }) + + it('should not recreate resolver when cwd remains the same', () => { + const mockResolverFactory = vi.fn() + const mockCloneWithOptions = vi.fn() + + const mockResolver = { + sync: vi.fn().mockReturnValue({ found: false } as ResolvedResult), + cloneWithOptions: mockCloneWithOptions + } + + vi.doMock('unrs-resolver', () => ({ + ResolverFactory: mockResolverFactory.mockImplementation(() => mockResolver) + })) + + mockModule.__setMockContext({ cwd: testCwd1 }) + const resolver = createTypeScriptImportResolver({ project: ['./tsconfig.json'] }) + + resolver.resolve('some-module', '/test/file1.ts') + resolver.resolve('another-module', '/test/file2.ts') + + expect(useRuleContext).toHaveBeenCalledTimes(2) + expect(mockCloneWithOptions).not.toHaveBeenCalled() + }) + + it('should handle interfaceVersion and name properties correctly', () => { + mockModule.__setMockContext(null) + const resolver = createTypeScriptImportResolver() + + expect(resolver.interfaceVersion).toBe(3) + expect(resolver.name).toBe('eslint-import-resolver-typescript') + }) + }) + + describe('Function signature compatibility', () => { + it('should handle optional parameters correctly in resolve function', () => { + mockModule.__setMockContext({ cwd: testCwd1 }) + + expect(() => resolve('module', '/file.ts', {}, null)).not.toThrow() + expect(() => resolve('module', '/file.ts')).not.toThrow() + expect(() => resolve('module', '/file.ts', undefined)).not.toThrow() + }) + + it('should handle optional parameters correctly in createTypeScriptImportResolver', () => { + mockModule.__setMockContext(null) + + expect(() => createTypeScriptImportResolver({})).not.toThrow() + expect(() => createTypeScriptImportResolver()).not.toThrow() + expect(() => createTypeScriptImportResolver(null)).not.toThrow() + }) + }) +}) \ No newline at end of file From 3f13c81ec294b9cc5357bb4bd7abbe23db36b073 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Sun, 25 May 2025 06:17:20 +0000 Subject: [PATCH 2/2] [autofix.ci] apply automated fixes --- tests/unit/context-aware.spec.ts | 145 +++++++++++++++++++------------ 1 file changed, 89 insertions(+), 56 deletions(-) diff --git a/tests/unit/context-aware.spec.ts b/tests/unit/context-aware.spec.ts index 2927065..5c2cf02 100644 --- a/tests/unit/context-aware.spec.ts +++ b/tests/unit/context-aware.spec.ts @@ -3,7 +3,7 @@ import type { ResolvedResult } from 'eslint-import-context' vi.mock('eslint-import-context', () => { let mockContext: { cwd?: string } | null = null - + return { useRuleContext: vi.fn(() => mockContext), __setMockContext: (context: { cwd?: string } | null) => { @@ -13,10 +13,13 @@ vi.mock('eslint-import-context', () => { } }) -import { resolve, createTypeScriptImportResolver } from 'eslint-import-resolver-typescript' +import { + resolve, + createTypeScriptImportResolver, +} from 'eslint-import-resolver-typescript' import { useRuleContext } from 'eslint-import-context' -const mockModule = await import('eslint-import-context') as any +const mockModule = (await import('eslint-import-context')) as any describe('Context-aware import resolution', () => { const originalCwd = process.cwd() @@ -34,40 +37,58 @@ describe('Context-aware import resolution', () => { describe('Dynamic cwd resolution', () => { it('should use context.cwd when available', () => { - const mockResolve = vi.fn().mockReturnValue({ found: false } as ResolvedResult) - const mockResolverFactory = vi.fn().mockImplementation(() => ({ sync: mockResolve })) - vi.doMock('unrs-resolver', () => ({ ResolverFactory: mockResolverFactory })) + const mockResolve = vi + .fn() + .mockReturnValue({ found: false } as ResolvedResult) + const mockResolverFactory = vi + .fn() + .mockImplementation(() => ({ sync: mockResolve })) + vi.doMock('unrs-resolver', () => ({ + ResolverFactory: mockResolverFactory, + })) mockModule.__setMockContext({ cwd: testCwd1 }) - + resolve('some-module', '/test/file.ts', {}) - + expect(useRuleContext).toHaveBeenCalled() expect(mockResolve).toHaveBeenCalled() }) it('should fallback to process.cwd() when context is null', () => { - const mockResolve = vi.fn().mockReturnValue({ found: false } as ResolvedResult) - const mockResolverFactory = vi.fn().mockImplementation(() => ({ sync: mockResolve })) - vi.doMock('unrs-resolver', () => ({ ResolverFactory: mockResolverFactory })) + const mockResolve = vi + .fn() + .mockReturnValue({ found: false } as ResolvedResult) + const mockResolverFactory = vi + .fn() + .mockImplementation(() => ({ sync: mockResolve })) + vi.doMock('unrs-resolver', () => ({ + ResolverFactory: mockResolverFactory, + })) mockModule.__setMockContext(null) - + resolve('some-module', '/test/file.ts', {}) - + expect(useRuleContext).toHaveBeenCalled() expect(mockResolve).toHaveBeenCalled() }) it('should fallback to process.cwd() when context.cwd is undefined', () => { - const mockResolve = vi.fn().mockReturnValue({ found: false } as ResolvedResult) - const mockResolverFactory = vi.fn().mockImplementation(() => ({ sync: mockResolve })) - vi.doMock('unrs-resolver', () => ({ ResolverFactory: mockResolverFactory })) + const mockResolve = vi + .fn() + .mockReturnValue({ found: false } as ResolvedResult) + const mockResolverFactory = vi + .fn() + .mockImplementation(() => ({ sync: mockResolve })) + vi.doMock('unrs-resolver', () => ({ + ResolverFactory: mockResolverFactory, + })) mockModule.__setMockContext({}) - + resolve('some-module', '/test/file.ts', {}) - + expect(useRuleContext).toHaveBeenCalled() expect(mockResolve).toHaveBeenCalled() }) @@ -78,14 +99,14 @@ describe('Context-aware import resolution', () => { const mockResolverFactory = vi.fn() vi.doMock('unrs-resolver', () => ({ ResolverFactory: mockResolverFactory.mockImplementation(() => ({ - sync: vi.fn().mockReturnValue({ found: false } as ResolvedResult) - })) + sync: vi.fn().mockReturnValue({ found: false } as ResolvedResult), + })), })) mockModule.__setMockContext({ cwd: testCwd1 }) - + resolve('some-module', '/test/file.ts', {}) - + expect(mockResolverFactory).toHaveBeenCalledTimes(1) }) @@ -93,18 +114,18 @@ describe('Context-aware import resolution', () => { const mockResolverFactory = vi.fn() vi.doMock('unrs-resolver', () => ({ ResolverFactory: mockResolverFactory.mockImplementation(() => ({ - sync: vi.fn().mockReturnValue({ found: false } as ResolvedResult) - })) + sync: vi.fn().mockReturnValue({ found: false } as ResolvedResult), + })), })) // First resolution with testCwd1 mockModule.__setMockContext({ cwd: testCwd1 }) resolve('some-module', '/test/file.ts', {}) - + // Second resolution with testCwd2 should create new resolver mockModule.__setMockContext({ cwd: testCwd2 }) resolve('some-module', '/test/file.ts', {}) - + expect(mockResolverFactory).toHaveBeenCalledTimes(2) }) @@ -112,15 +133,15 @@ describe('Context-aware import resolution', () => { const mockResolverFactory = vi.fn() vi.doMock('unrs-resolver', () => ({ ResolverFactory: mockResolverFactory.mockImplementation(() => ({ - sync: vi.fn().mockReturnValue({ found: false } as ResolvedResult) - })) + sync: vi.fn().mockReturnValue({ found: false } as ResolvedResult), + })), })) mockModule.__setMockContext({ cwd: testCwd1 }) - + resolve('some-module', '/test/file1.ts', {}) resolve('another-module', '/test/file2.ts', {}) - + expect(mockResolverFactory).toHaveBeenCalledTimes(1) }) }) @@ -129,67 +150,79 @@ describe('Context-aware import resolution', () => { it('should update cwd and recreate resolver when context changes', () => { const mockResolverFactory = vi.fn() const mockCloneWithOptions = vi.fn() - + const mockResolver = { sync: vi.fn().mockReturnValue({ found: false } as ResolvedResult), - cloneWithOptions: mockCloneWithOptions + cloneWithOptions: mockCloneWithOptions, } - + vi.doMock('unrs-resolver', () => ({ - ResolverFactory: mockResolverFactory.mockImplementation(() => mockResolver) + ResolverFactory: mockResolverFactory.mockImplementation( + () => mockResolver, + ), })) mockModule.__setMockContext(null) - const resolver = createTypeScriptImportResolver({ project: ['./tsconfig.json'] }) - + const resolver = createTypeScriptImportResolver({ + project: ['./tsconfig.json'], + }) + resolver.resolve('some-module', '/test/file.ts') - + mockModule.__setMockContext({ cwd: testCwd1 }) resolver.resolve('another-module', '/test/file.ts') - + expect(useRuleContext).toHaveBeenCalledTimes(2) expect(mockCloneWithOptions).toHaveBeenCalled() }) it('should create new resolver when no existing resolver and context changes', () => { const mockResolverFactory = vi.fn() - + const mockResolver = { - sync: vi.fn().mockReturnValue({ found: false } as ResolvedResult) + sync: vi.fn().mockReturnValue({ found: false } as ResolvedResult), } - + vi.doMock('unrs-resolver', () => ({ - ResolverFactory: mockResolverFactory.mockImplementation(() => mockResolver) + ResolverFactory: mockResolverFactory.mockImplementation( + () => mockResolver, + ), })) mockModule.__setMockContext(null) - const resolver = createTypeScriptImportResolver({ project: ['./tsconfig.json'] }) - + const resolver = createTypeScriptImportResolver({ + project: ['./tsconfig.json'], + }) + mockModule.__setMockContext({ cwd: testCwd1 }) resolver.resolve('some-module', '/test/file.ts') - + expect(mockResolverFactory).toHaveBeenCalled() }) it('should not recreate resolver when cwd remains the same', () => { const mockResolverFactory = vi.fn() const mockCloneWithOptions = vi.fn() - + const mockResolver = { sync: vi.fn().mockReturnValue({ found: false } as ResolvedResult), - cloneWithOptions: mockCloneWithOptions + cloneWithOptions: mockCloneWithOptions, } - + vi.doMock('unrs-resolver', () => ({ - ResolverFactory: mockResolverFactory.mockImplementation(() => mockResolver) + ResolverFactory: mockResolverFactory.mockImplementation( + () => mockResolver, + ), })) mockModule.__setMockContext({ cwd: testCwd1 }) - const resolver = createTypeScriptImportResolver({ project: ['./tsconfig.json'] }) - + const resolver = createTypeScriptImportResolver({ + project: ['./tsconfig.json'], + }) + resolver.resolve('some-module', '/test/file1.ts') resolver.resolve('another-module', '/test/file2.ts') - + expect(useRuleContext).toHaveBeenCalledTimes(2) expect(mockCloneWithOptions).not.toHaveBeenCalled() }) @@ -197,7 +230,7 @@ describe('Context-aware import resolution', () => { it('should handle interfaceVersion and name properties correctly', () => { mockModule.__setMockContext(null) const resolver = createTypeScriptImportResolver() - + expect(resolver.interfaceVersion).toBe(3) expect(resolver.name).toBe('eslint-import-resolver-typescript') }) @@ -206,7 +239,7 @@ describe('Context-aware import resolution', () => { describe('Function signature compatibility', () => { it('should handle optional parameters correctly in resolve function', () => { mockModule.__setMockContext({ cwd: testCwd1 }) - + expect(() => resolve('module', '/file.ts', {}, null)).not.toThrow() expect(() => resolve('module', '/file.ts')).not.toThrow() expect(() => resolve('module', '/file.ts', undefined)).not.toThrow() @@ -214,10 +247,10 @@ describe('Context-aware import resolution', () => { it('should handle optional parameters correctly in createTypeScriptImportResolver', () => { mockModule.__setMockContext(null) - + expect(() => createTypeScriptImportResolver({})).not.toThrow() expect(() => createTypeScriptImportResolver()).not.toThrow() expect(() => createTypeScriptImportResolver(null)).not.toThrow() }) }) -}) \ No newline at end of file +})