@@ -6,7 +6,9 @@ package software.aws.toolkits.jetbrains.services.amazonq.lsp.textdocument
66import com.intellij.openapi.application.writeAction
77import com.intellij.openapi.editor.Document
88import com.intellij.openapi.fileEditor.FileDocumentManager
9+ import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx
910import com.intellij.openapi.fileTypes.FileType
11+ import com.intellij.openapi.util.Disposer
1012import com.intellij.openapi.vfs.VirtualFile
1113import com.intellij.openapi.vfs.newvfs.events.VFileContentChangeEvent
1214import com.intellij.openapi.vfs.newvfs.events.VFileEvent
@@ -24,7 +26,6 @@ import io.mockk.mockkStatic
2426import io.mockk.slot
2527import io.mockk.spyk
2628import io.mockk.verify
27- import kotlinx.coroutines.test.TestScope
2829import kotlinx.coroutines.test.advanceUntilIdle
2930import kotlinx.coroutines.test.runTest
3031import kotlinx.coroutines.withContext
@@ -35,9 +36,11 @@ import org.eclipse.lsp4j.DidOpenTextDocumentParams
3536import org.eclipse.lsp4j.DidSaveTextDocumentParams
3637import org.eclipse.lsp4j.jsonrpc.messages.ResponseMessage
3738import org.eclipse.lsp4j.services.TextDocumentService
39+ import org.junit.After
3840import org.junit.Before
3941import org.junit.Rule
4042import org.junit.Test
43+ import org.junit.rules.TestName
4144import software.aws.toolkits.jetbrains.core.coroutines.EDT
4245import software.aws.toolkits.jetbrains.services.amazonq.lsp.AmazonQLanguageServer
4346import software.aws.toolkits.jetbrains.services.amazonq.lsp.AmazonQLspService
@@ -54,9 +57,6 @@ class TextDocumentServiceHandlerTest {
5457 private lateinit var mockTextDocumentService: TextDocumentService
5558 private lateinit var sut: TextDocumentServiceHandler
5659
57- // not ideal
58- private lateinit var testScope: TestScope
59-
6060 @get:Rule
6161 val projectRule = object : CodeInsightTestFixtureRule () {
6262 override fun createTestFixture (): CodeInsightTestFixture {
@@ -74,6 +74,9 @@ class TextDocumentServiceHandlerTest {
7474 @get:Rule
7575 val disposableRule = DisposableRule ()
7676
77+ @get:Rule
78+ val testName = TestName ()
79+
7780 @Before
7881 fun setup () {
7982 mockTextDocumentService = mockk<TextDocumentService >()
@@ -99,13 +102,20 @@ class TextDocumentServiceHandlerTest {
99102 every { mockTextDocumentService.didSave(any()) } returns Unit
100103 every { mockTextDocumentService.didOpen(any()) } returns Unit
101104 every { mockTextDocumentService.didClose(any()) } returns Unit
105+ }
102106
103- testScope = TestScope ()
104- sut = TextDocumentServiceHandler (projectRule.project, testScope)
107+ @After
108+ fun tearDown () {
109+ try {
110+ Disposer .dispose(sut)
111+ } catch (_: Exception ) {
112+ }
105113 }
106114
107115 @Test
108- fun `didSave runs on beforeDocumentSaving` () {
116+ fun `didSave runs on beforeDocumentSaving` () = runTest {
117+ sut = TextDocumentServiceHandler (projectRule.project, this )
118+
109119 // Create test document and file
110120 val uri = URI .create(" file:///test/path/file.txt" )
111121 val document = mockk<Document > {
@@ -127,7 +137,7 @@ class TextDocumentServiceHandlerTest {
127137 sut.beforeDocumentSaving(document)
128138
129139 // Verify the correct LSP method was called with matching parameters
130- testScope. advanceUntilIdle()
140+ advanceUntilIdle()
131141 val paramsSlot = slot<DidSaveTextDocumentParams >()
132142 verify { mockTextDocumentService.didSave(capture(paramsSlot)) }
133143
@@ -142,12 +152,12 @@ class TextDocumentServiceHandlerTest {
142152 fun `didOpen runs on service init` () = runTest {
143153 val content = " test content"
144154 val file = withContext(EDT ) {
145- projectRule.fixture.createFile(" name " , content).also { projectRule.fixture.openFileInEditor(it) }
155+ projectRule.fixture.createFile(testName.methodName , content).also { projectRule.fixture.openFileInEditor(it) }
146156 }
147-
157+ advanceUntilIdle()
148158 sut = TextDocumentServiceHandler (projectRule.project, this )
149-
150159 advanceUntilIdle()
160+
151161 val paramsSlot = mutableListOf<DidOpenTextDocumentParams >()
152162 verify { mockTextDocumentService.didOpen(capture(paramsSlot)) }
153163
@@ -160,15 +170,14 @@ class TextDocumentServiceHandlerTest {
160170
161171 @Test
162172 fun `didOpen runs on fileOpened` () = runTest {
173+ sut = TextDocumentServiceHandler (projectRule.project, this )
174+ advanceUntilIdle()
163175 val content = " test content"
164176 val file = withContext(EDT ) {
165- projectRule.fixture.createFile(" name " , content).also { projectRule.fixture.openFileInEditor(it) }
177+ projectRule.fixture.createFile(testName.methodName , content).also { projectRule.fixture.openFileInEditor(it) }
166178 }
167-
168- sut.fileOpened(mockk(), file)
169-
170179 advanceUntilIdle()
171- testScope.advanceUntilIdle()
180+
172181 val paramsSlot = mutableListOf<DidOpenTextDocumentParams >()
173182 verify { mockTextDocumentService.didOpen(capture(paramsSlot)) }
174183
@@ -181,23 +190,26 @@ class TextDocumentServiceHandlerTest {
181190
182191 @Test
183192 fun `didClose runs on fileClosed` () = runTest {
184- val uri = URI .create(" file:///test/path/file.txt" )
185- val file = createMockVirtualFile(uri)
186-
187- sut.fileClosed(mockk(), file)
193+ sut = TextDocumentServiceHandler (projectRule.project, this )
194+ val file = withContext(EDT ) {
195+ projectRule.fixture.createFile(testName.methodName, " " ).also {
196+ projectRule.fixture.openFileInEditor(it)
197+ FileEditorManagerEx .getInstanceEx(projectRule.project).closeAllFiles()
198+ }
199+ }
188200
189201 advanceUntilIdle()
190- testScope.advanceUntilIdle()
191202 val paramsSlot = slot<DidCloseTextDocumentParams >()
192203 verify { mockTextDocumentService.didClose(capture(paramsSlot)) }
193204
194- assertThat(paramsSlot.captured.textDocument.uri).isEqualTo(normalizeFileUri(uri.toString() ))
205+ assertThat(paramsSlot.captured.textDocument.uri).isEqualTo(file.toNioPath().toUri().toString( ))
195206 }
196207
197208 @Test
198209 fun `didChange runs on content change events` () = runTest {
210+ sut = TextDocumentServiceHandler (projectRule.project, this )
199211 val file = withContext(EDT ) {
200- projectRule.fixture.createFile(" name " , " " ).also {
212+ projectRule.fixture.createFile(testName.methodName , " " ).also {
201213 projectRule.fixture.openFileInEditor(it)
202214
203215 writeAction {
@@ -208,7 +220,6 @@ class TextDocumentServiceHandlerTest {
208220
209221 // Verify the correct LSP method was called with matching parameters
210222 advanceUntilIdle()
211- testScope.advanceUntilIdle()
212223 val paramsSlot = mutableListOf<DidChangeTextDocumentParams >()
213224 verify { mockTextDocumentService.didChange(capture(paramsSlot)) }
214225
@@ -220,6 +231,7 @@ class TextDocumentServiceHandlerTest {
220231
221232 @Test
222233 fun `didSave does not run when URI is empty` () = runTest {
234+ sut = TextDocumentServiceHandler (projectRule.project, this )
223235 val document = mockk<Document >()
224236 val file = createMockVirtualFile(URI .create(" " ))
225237
@@ -235,14 +247,15 @@ class TextDocumentServiceHandlerTest {
235247
236248 sut.beforeDocumentSaving(document)
237249
238- testScope. advanceUntilIdle()
250+ advanceUntilIdle()
239251 verify(exactly = 0 ) { mockTextDocumentService.didSave(any()) }
240252 }
241253 }
242254 }
243255
244256 @Test
245257 fun `didSave does not run when file is null` () = runTest {
258+ sut = TextDocumentServiceHandler (projectRule.project, this )
246259 val document = mockk<Document >()
247260
248261 val fileDocumentManager = mockk<FileDocumentManager > {
@@ -254,23 +267,25 @@ class TextDocumentServiceHandlerTest {
254267
255268 sut.beforeDocumentSaving(document)
256269
257- testScope. advanceUntilIdle()
270+ advanceUntilIdle()
258271 verify(exactly = 0 ) { mockTextDocumentService.didSave(any()) }
259272 }
260273 }
261274
262275 @Test
263276 fun `didChange ignores non-content change events` () = runTest {
277+ sut = TextDocumentServiceHandler (projectRule.project, this )
264278 val nonContentEvent = mockk<VFileEvent >() // Some other type of VFileEvent
265279
266280 sut.after(mutableListOf (nonContentEvent))
267281
268- testScope. advanceUntilIdle()
282+ advanceUntilIdle()
269283 verify(exactly = 0 ) { mockTextDocumentService.didChange(any()) }
270284 }
271285
272286 @Test
273287 fun `didChange skips files without cached documents` () = runTest {
288+ sut = TextDocumentServiceHandler (projectRule.project, this )
274289 val uri = URI .create(" file:///test/path/file.txt" )
275290 val path = mockk<Path > {
276291 every { toUri() } returns uri
@@ -291,7 +306,7 @@ class TextDocumentServiceHandlerTest {
291306
292307 sut.after(mutableListOf (changeEvent))
293308
294- testScope. advanceUntilIdle()
309+ advanceUntilIdle()
295310 verify(exactly = 0 ) { mockTextDocumentService.didChange(any()) }
296311 }
297312 }
0 commit comments