44package software.aws.toolkits.jetbrains.services.amazonq.lsp.auth
55
66import com.intellij.openapi.Disposable
7- import com.intellij.openapi.components.service
87import com.intellij.openapi.components.serviceIfCreated
98import com.intellij.openapi.project.Project
109import com.intellij.testFramework.ProjectExtension
10+ import com.intellij.testFramework.replaceService
1111import com.intellij.util.messages.MessageBus
1212import com.intellij.util.messages.MessageBusConnection
13+ import io.mockk.coEvery
1314import io.mockk.every
1415import io.mockk.just
1516import io.mockk.mockk
1617import io.mockk.mockkStatic
1718import io.mockk.runs
1819import io.mockk.spyk
1920import io.mockk.verify
21+ import kotlinx.coroutines.test.advanceUntilIdle
22+ import kotlinx.coroutines.test.runTest
2023import org.eclipse.lsp4j.jsonrpc.messages.ResponseMessage
2124import org.junit.jupiter.api.BeforeEach
2225import org.junit.jupiter.api.Test
@@ -26,6 +29,7 @@ import software.aws.toolkits.core.credentials.ToolkitBearerTokenProvider
2629import software.aws.toolkits.jetbrains.core.credentials.AwsBearerTokenConnection
2730import software.aws.toolkits.jetbrains.core.credentials.ToolkitConnectionManager
2831import software.aws.toolkits.jetbrains.core.credentials.sso.PKCEAuthorizationGrantToken
32+ import software.aws.toolkits.jetbrains.core.credentials.sso.bearer.BearerTokenAuthState
2933import software.aws.toolkits.jetbrains.core.credentials.sso.bearer.InteractiveBearerTokenProvider
3034import software.aws.toolkits.jetbrains.services.amazonq.lsp.AmazonQLanguageServer
3135import software.aws.toolkits.jetbrains.services.amazonq.lsp.AmazonQLspService
@@ -69,20 +73,20 @@ class DefaultAuthCredentialsServiceTest {
6973 }
7074
7175 val mockLspService = mockk<AmazonQLspService >()
72- every {
73- mockLspService.executeSync <CompletableFuture <ResponseMessage >>(any())
76+ coEvery {
77+ mockLspService.executeIfRunning <CompletableFuture <ResponseMessage >>(any())
7478 } coAnswers {
7579 val func = firstArg< suspend AmazonQLspService .(AmazonQLanguageServer ) -> CompletableFuture <ResponseMessage >>()
7680 func.invoke(mockLspService, mockLanguageServer)
7781 }
7882
7983 every {
8084 mockLanguageServer.updateTokenCredentials(any())
81- } returns CompletableFuture < ResponseMessage >( )
85+ } returns CompletableFuture .completedFuture( ResponseMessage () )
8286
8387 every {
8488 mockLanguageServer.deleteTokenCredentials()
85- } returns CompletableFuture .completedFuture( Unit )
89+ } returns Unit
8690
8791 every { project.getService(AmazonQLspService ::class .java) } returns mockLspService
8892 every { project.serviceIfCreated<AmazonQLspService >() } returns mockLspService
@@ -101,8 +105,9 @@ class DefaultAuthCredentialsServiceTest {
101105 mockConnection = createMockConnection(accessToken)
102106 mockConnectionManager = mockk {
103107 every { activeConnectionForFeature(any()) } returns mockConnection
108+ every { connectionStateForFeature(any()) } returns BearerTokenAuthState .AUTHORIZED
104109 }
105- every { project.service< ToolkitConnectionManager >() } returns mockConnectionManager
110+ project.replaceService( ToolkitConnectionManager :: class .java, mockConnectionManager, project)
106111 mockkStatic(" software.aws.toolkits.jetbrains.utils.FunctionUtilsKt" )
107112 // these set so init doesn't always emit
108113 every { isQConnected(any()) } returns false
@@ -142,64 +147,70 @@ class DefaultAuthCredentialsServiceTest {
142147 }
143148
144149 @Test
145- fun `activeConnectionChanged updates token when connection ID matches Q connection` () {
146- sut = DefaultAuthCredentialsService (project, mockEncryptionManager)
150+ fun `activeConnectionChanged updates token when connection ID matches Q connection` () = runTest {
151+ sut = DefaultAuthCredentialsService (project, mockEncryptionManager, this )
147152 val newConnection = createMockConnection(" new-token" , " connection-id" )
148153 every { mockConnection.id } returns " connection-id"
149154
150155 sut.activeConnectionChanged(newConnection)
151156
157+ advanceUntilIdle()
152158 verify(exactly = 1 ) { mockLanguageServer.updateTokenCredentials(any()) }
153159 }
154160
155161 @Test
156- fun `activeConnectionChanged does not update token when connection ID differs` () {
157- sut = DefaultAuthCredentialsService (project, mockEncryptionManager)
162+ fun `activeConnectionChanged does not update token when connection ID differs` () = runTest {
163+ sut = DefaultAuthCredentialsService (project, mockEncryptionManager, this )
158164 val newConnection = createMockConnection(" new-token" , " different-id" )
159165 every { mockConnection.id } returns " q-connection-id"
160166
161167 sut.activeConnectionChanged(newConnection)
162168
169+ advanceUntilIdle()
163170 verify(exactly = 0 ) { mockLanguageServer.updateTokenCredentials(any()) }
164171 }
165172
166173 @Test
167- fun `onChange updates token with new connection` () {
168- sut = DefaultAuthCredentialsService (project, mockEncryptionManager)
174+ fun `onChange updates token with new connection` () = runTest {
175+ sut = DefaultAuthCredentialsService (project, mockEncryptionManager, this )
169176 setupMockConnectionManager(" updated-token" )
170177
171178 sut.onChange(" providerId" , listOf (" new-scope" ))
172179
180+ advanceUntilIdle()
173181 verify(exactly = 1 ) { mockLanguageServer.updateTokenCredentials(any()) }
174182 }
175183
176184 @Test
177- fun `init does not update token when Q is not connected` () {
185+ fun `init does not update token when Q is not connected` () = runTest {
178186 every { isQConnected(project) } returns false
179187 every { isQExpired(project) } returns false
180188
181- sut = DefaultAuthCredentialsService (project, mockEncryptionManager)
189+ sut = DefaultAuthCredentialsService (project, mockEncryptionManager, this )
182190
191+ advanceUntilIdle()
183192 verify(exactly = 0 ) { mockLanguageServer.updateTokenCredentials(any()) }
184193 }
185194
186195 @Test
187- fun `init does not update token when Q is expired` () {
196+ fun `init does not update token when Q is expired` () = runTest {
188197 every { isQConnected(project) } returns true
189198 every { isQExpired(project) } returns true
190199
191- sut = DefaultAuthCredentialsService (project, mockEncryptionManager)
200+ sut = DefaultAuthCredentialsService (project, mockEncryptionManager, this )
192201
202+ advanceUntilIdle()
193203 verify(exactly = 0 ) { mockLanguageServer.updateTokenCredentials(any()) }
194204 }
195205
196206 @Test
197- fun `test updateTokenCredentials unencrypted success` () {
207+ fun `test updateTokenCredentials unencrypted success` () = runTest {
198208 val isEncrypted = false
199- sut = DefaultAuthCredentialsService (project, mockEncryptionManager)
209+ sut = DefaultAuthCredentialsService (project, mockEncryptionManager, this )
200210
201211 sut.updateTokenCredentials(mockConnection, isEncrypted)
202212
213+ advanceUntilIdle()
203214 verify(exactly = 1 ) {
204215 mockLanguageServer.updateTokenCredentials(
205216 UpdateCredentialsPayload (
@@ -214,8 +225,8 @@ class DefaultAuthCredentialsServiceTest {
214225 }
215226
216227 @Test
217- fun `test updateTokenCredentials encrypted success` () {
218- sut = DefaultAuthCredentialsService (project, mockEncryptionManager)
228+ fun `test updateTokenCredentials encrypted success` () = runTest {
229+ sut = DefaultAuthCredentialsService (project, mockEncryptionManager, this )
219230
220231 val encryptedToken = " encryptedToken"
221232 val isEncrypted = true
@@ -224,6 +235,7 @@ class DefaultAuthCredentialsServiceTest {
224235
225236 sut.updateTokenCredentials(mockConnection, isEncrypted)
226237
238+ advanceUntilIdle()
227239 verify(atLeast = 1 ) {
228240 mockLanguageServer.updateTokenCredentials(
229241 UpdateCredentialsPayload (
@@ -238,22 +250,24 @@ class DefaultAuthCredentialsServiceTest {
238250 }
239251
240252 @Test
241- fun `test deleteTokenCredentials success` () {
242- sut = DefaultAuthCredentialsService (project, mockEncryptionManager)
253+ fun `test deleteTokenCredentials success` () = runTest {
254+ sut = DefaultAuthCredentialsService (project, mockEncryptionManager, this )
243255
244- every { mockLanguageServer.deleteTokenCredentials() } returns CompletableFuture .completedFuture( Unit )
256+ every { mockLanguageServer.deleteTokenCredentials() } returns Unit
245257
246258 sut.deleteTokenCredentials()
247259
260+ advanceUntilIdle()
248261 verify(exactly = 1 ) { mockLanguageServer.deleteTokenCredentials() }
249262 }
250263
251264 @Test
252- fun `init results in token update` () {
265+ fun `init results in token update` () = runTest {
253266 every { isQConnected(any()) } returns true
254267 every { isQExpired(any()) } returns false
255- sut = DefaultAuthCredentialsService (project, mockEncryptionManager)
268+ sut = DefaultAuthCredentialsService (project, mockEncryptionManager, this )
256269
270+ advanceUntilIdle()
257271 verify(exactly = 1 ) { mockLanguageServer.updateTokenCredentials(any()) }
258272 }
259273}
0 commit comments