1+ import { describe , it , expect , vi , beforeEach , afterEach } from 'vitest'
2+ import type { ResolvedResult } from 'eslint-import-context'
3+
4+ vi . mock ( 'eslint-import-context' , ( ) => {
5+ let mockContext : { cwd ?: string } | null = null
6+
7+ return {
8+ useRuleContext : vi . fn ( ( ) => mockContext ) ,
9+ __setMockContext : ( context : { cwd ?: string } | null ) => {
10+ mockContext = context
11+ } ,
12+ __getMockContext : ( ) => mockContext ,
13+ }
14+ } )
15+
16+ import { resolve , createTypeScriptImportResolver } from 'eslint-import-resolver-typescript'
17+ import { useRuleContext } from 'eslint-import-context'
18+
19+ const mockModule = await import ( 'eslint-import-context' ) as any
20+
21+ describe ( 'Context-aware import resolution' , ( ) => {
22+ const originalCwd = process . cwd ( )
23+ const testCwd1 = '/test/project1'
24+ const testCwd2 = '/test/project2'
25+
26+ beforeEach ( ( ) => {
27+ vi . clearAllMocks ( )
28+ mockModule . __setMockContext ( null )
29+ } )
30+
31+ afterEach ( ( ) => {
32+ mockModule . __setMockContext ( null )
33+ } )
34+
35+ describe ( 'Dynamic cwd resolution' , ( ) => {
36+ it ( 'should use context.cwd when available' , ( ) => {
37+ const mockResolve = vi . fn ( ) . mockReturnValue ( { found : false } as ResolvedResult )
38+ const mockResolverFactory = vi . fn ( ) . mockImplementation ( ( ) => ( { sync : mockResolve } ) )
39+ vi . doMock ( 'unrs-resolver' , ( ) => ( { ResolverFactory : mockResolverFactory } ) )
40+
41+ mockModule . __setMockContext ( { cwd : testCwd1 } )
42+
43+ resolve ( 'some-module' , '/test/file.ts' , { } )
44+
45+ expect ( useRuleContext ) . toHaveBeenCalled ( )
46+ expect ( mockResolve ) . toHaveBeenCalled ( )
47+ } )
48+
49+ it ( 'should fallback to process.cwd() when context is null' , ( ) => {
50+ const mockResolve = vi . fn ( ) . mockReturnValue ( { found : false } as ResolvedResult )
51+ const mockResolverFactory = vi . fn ( ) . mockImplementation ( ( ) => ( { sync : mockResolve } ) )
52+ vi . doMock ( 'unrs-resolver' , ( ) => ( { ResolverFactory : mockResolverFactory } ) )
53+
54+ mockModule . __setMockContext ( null )
55+
56+ resolve ( 'some-module' , '/test/file.ts' , { } )
57+
58+ expect ( useRuleContext ) . toHaveBeenCalled ( )
59+ expect ( mockResolve ) . toHaveBeenCalled ( )
60+ } )
61+
62+ it ( 'should fallback to process.cwd() when context.cwd is undefined' , ( ) => {
63+ const mockResolve = vi . fn ( ) . mockReturnValue ( { found : false } as ResolvedResult )
64+ const mockResolverFactory = vi . fn ( ) . mockImplementation ( ( ) => ( { sync : mockResolve } ) )
65+ vi . doMock ( 'unrs-resolver' , ( ) => ( { ResolverFactory : mockResolverFactory } ) )
66+
67+ mockModule . __setMockContext ( { } )
68+
69+ resolve ( 'some-module' , '/test/file.ts' , { } )
70+
71+ expect ( useRuleContext ) . toHaveBeenCalled ( )
72+ expect ( mockResolve ) . toHaveBeenCalled ( )
73+ } )
74+ } )
75+
76+ describe ( 'Cache key generation' , ( ) => {
77+ it ( 'should generate cache key with null character separator' , ( ) => {
78+ const mockResolverFactory = vi . fn ( )
79+ vi . doMock ( 'unrs-resolver' , ( ) => ( {
80+ ResolverFactory : mockResolverFactory . mockImplementation ( ( ) => ( {
81+ sync : vi . fn ( ) . mockReturnValue ( { found : false } as ResolvedResult )
82+ } ) )
83+ } ) )
84+
85+ mockModule . __setMockContext ( { cwd : testCwd1 } )
86+
87+ resolve ( 'some-module' , '/test/file.ts' , { } )
88+
89+ expect ( mockResolverFactory ) . toHaveBeenCalledTimes ( 1 )
90+ } )
91+
92+ it ( 'should create separate cache entries for different cwd values' , ( ) => {
93+ const mockResolverFactory = vi . fn ( )
94+ vi . doMock ( 'unrs-resolver' , ( ) => ( {
95+ ResolverFactory : mockResolverFactory . mockImplementation ( ( ) => ( {
96+ sync : vi . fn ( ) . mockReturnValue ( { found : false } as ResolvedResult )
97+ } ) )
98+ } ) )
99+
100+ // First resolution with testCwd1
101+ mockModule . __setMockContext ( { cwd : testCwd1 } )
102+ resolve ( 'some-module' , '/test/file.ts' , { } )
103+
104+ // Second resolution with testCwd2 should create new resolver
105+ mockModule . __setMockContext ( { cwd : testCwd2 } )
106+ resolve ( 'some-module' , '/test/file.ts' , { } )
107+
108+ expect ( mockResolverFactory ) . toHaveBeenCalledTimes ( 2 )
109+ } )
110+
111+ it ( 'should reuse cache for same cwd and options' , ( ) => {
112+ const mockResolverFactory = vi . fn ( )
113+ vi . doMock ( 'unrs-resolver' , ( ) => ( {
114+ ResolverFactory : mockResolverFactory . mockImplementation ( ( ) => ( {
115+ sync : vi . fn ( ) . mockReturnValue ( { found : false } as ResolvedResult )
116+ } ) )
117+ } ) )
118+
119+ mockModule . __setMockContext ( { cwd : testCwd1 } )
120+
121+ resolve ( 'some-module' , '/test/file1.ts' , { } )
122+ resolve ( 'another-module' , '/test/file2.ts' , { } )
123+
124+ expect ( mockResolverFactory ) . toHaveBeenCalledTimes ( 1 )
125+ } )
126+ } )
127+
128+ describe ( 'createTypeScriptImportResolver context switching' , ( ) => {
129+ it ( 'should update cwd and recreate resolver when context changes' , ( ) => {
130+ const mockResolverFactory = vi . fn ( )
131+ const mockCloneWithOptions = vi . fn ( )
132+
133+ const mockResolver = {
134+ sync : vi . fn ( ) . mockReturnValue ( { found : false } as ResolvedResult ) ,
135+ cloneWithOptions : mockCloneWithOptions
136+ }
137+
138+ vi . doMock ( 'unrs-resolver' , ( ) => ( {
139+ ResolverFactory : mockResolverFactory . mockImplementation ( ( ) => mockResolver )
140+ } ) )
141+
142+ mockModule . __setMockContext ( null )
143+ const resolver = createTypeScriptImportResolver ( { project : [ './tsconfig.json' ] } )
144+
145+ resolver . resolve ( 'some-module' , '/test/file.ts' )
146+
147+ mockModule . __setMockContext ( { cwd : testCwd1 } )
148+ resolver . resolve ( 'another-module' , '/test/file.ts' )
149+
150+ expect ( useRuleContext ) . toHaveBeenCalledTimes ( 2 )
151+ expect ( mockCloneWithOptions ) . toHaveBeenCalled ( )
152+ } )
153+
154+ it ( 'should create new resolver when no existing resolver and context changes' , ( ) => {
155+ const mockResolverFactory = vi . fn ( )
156+
157+ const mockResolver = {
158+ sync : vi . fn ( ) . mockReturnValue ( { found : false } as ResolvedResult )
159+ }
160+
161+ vi . doMock ( 'unrs-resolver' , ( ) => ( {
162+ ResolverFactory : mockResolverFactory . mockImplementation ( ( ) => mockResolver )
163+ } ) )
164+
165+ mockModule . __setMockContext ( null )
166+ const resolver = createTypeScriptImportResolver ( { project : [ './tsconfig.json' ] } )
167+
168+ mockModule . __setMockContext ( { cwd : testCwd1 } )
169+ resolver . resolve ( 'some-module' , '/test/file.ts' )
170+
171+ expect ( mockResolverFactory ) . toHaveBeenCalled ( )
172+ } )
173+
174+ it ( 'should not recreate resolver when cwd remains the same' , ( ) => {
175+ const mockResolverFactory = vi . fn ( )
176+ const mockCloneWithOptions = vi . fn ( )
177+
178+ const mockResolver = {
179+ sync : vi . fn ( ) . mockReturnValue ( { found : false } as ResolvedResult ) ,
180+ cloneWithOptions : mockCloneWithOptions
181+ }
182+
183+ vi . doMock ( 'unrs-resolver' , ( ) => ( {
184+ ResolverFactory : mockResolverFactory . mockImplementation ( ( ) => mockResolver )
185+ } ) )
186+
187+ mockModule . __setMockContext ( { cwd : testCwd1 } )
188+ const resolver = createTypeScriptImportResolver ( { project : [ './tsconfig.json' ] } )
189+
190+ resolver . resolve ( 'some-module' , '/test/file1.ts' )
191+ resolver . resolve ( 'another-module' , '/test/file2.ts' )
192+
193+ expect ( useRuleContext ) . toHaveBeenCalledTimes ( 2 )
194+ expect ( mockCloneWithOptions ) . not . toHaveBeenCalled ( )
195+ } )
196+
197+ it ( 'should handle interfaceVersion and name properties correctly' , ( ) => {
198+ mockModule . __setMockContext ( null )
199+ const resolver = createTypeScriptImportResolver ( )
200+
201+ expect ( resolver . interfaceVersion ) . toBe ( 3 )
202+ expect ( resolver . name ) . toBe ( 'eslint-import-resolver-typescript' )
203+ } )
204+ } )
205+
206+ describe ( 'Function signature compatibility' , ( ) => {
207+ it ( 'should handle optional parameters correctly in resolve function' , ( ) => {
208+ mockModule . __setMockContext ( { cwd : testCwd1 } )
209+
210+ expect ( ( ) => resolve ( 'module' , '/file.ts' , { } , null ) ) . not . toThrow ( )
211+ expect ( ( ) => resolve ( 'module' , '/file.ts' ) ) . not . toThrow ( )
212+ expect ( ( ) => resolve ( 'module' , '/file.ts' , undefined ) ) . not . toThrow ( )
213+ } )
214+
215+ it ( 'should handle optional parameters correctly in createTypeScriptImportResolver' , ( ) => {
216+ mockModule . __setMockContext ( null )
217+
218+ expect ( ( ) => createTypeScriptImportResolver ( { } ) ) . not . toThrow ( )
219+ expect ( ( ) => createTypeScriptImportResolver ( ) ) . not . toThrow ( )
220+ expect ( ( ) => createTypeScriptImportResolver ( null ) ) . not . toThrow ( )
221+ } )
222+ } )
223+ } )
0 commit comments