|
| 1 | +// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. |
| 2 | +// SPDX-License-Identifier: Apache-2.0 |
| 3 | + |
| 4 | +package software.aws.toolkits.jetbrains.services.codewhisperer.util |
| 5 | + |
| 6 | +import com.intellij.codeInsight.CodeInsightSettings |
| 7 | +import com.intellij.openapi.Disposable |
| 8 | +import com.intellij.openapi.application.ApplicationManager |
| 9 | +import com.intellij.openapi.util.Disposer |
| 10 | +import com.intellij.testFramework.HeavyPlatformTestCase |
| 11 | +import com.intellij.testFramework.replaceService |
| 12 | +import org.assertj.core.api.Assertions.assertThat |
| 13 | +import org.mockito.kotlin.spy |
| 14 | +import org.mockito.kotlin.times |
| 15 | +import org.mockito.kotlin.verify |
| 16 | + |
| 17 | +class CodeInsightsSettingsFacadeTest : HeavyPlatformTestCase() { |
| 18 | + private lateinit var settings: CodeInsightSettings |
| 19 | + private lateinit var sut: CodeInsightsSettingsFacade |
| 20 | + |
| 21 | + override fun setUp() { |
| 22 | + super.setUp() |
| 23 | + sut = spy(CodeInsightsSettingsFacade()) |
| 24 | + settings = spy { CodeInsightSettings() } |
| 25 | + |
| 26 | + ApplicationManager.getApplication().replaceService( |
| 27 | + CodeInsightSettings::class.java, |
| 28 | + settings, |
| 29 | + testRootDisposable |
| 30 | + ) |
| 31 | + } |
| 32 | + |
| 33 | + fun testDisableCodeInsightUntilShouldRevertWhenParentIsDisposed() { |
| 34 | + @Suppress("ObjectLiteralToLambda") // JUnit 3 doesn't support SAM lambdas |
| 35 | + val myFakePopup = object : Disposable { override fun dispose() {} } |
| 36 | + Disposer.register(testRootDisposable, myFakePopup) |
| 37 | + |
| 38 | + // assume users' enable the following two codeinsight functionalities |
| 39 | + settings.TAB_EXITS_BRACKETS_AND_QUOTES = true |
| 40 | + assertThat(settings.TAB_EXITS_BRACKETS_AND_QUOTES).isTrue |
| 41 | + settings.AUTOCOMPLETE_ON_CODE_COMPLETION = true |
| 42 | + assertThat(settings.AUTO_POPUP_COMPLETION_LOOKUP).isTrue |
| 43 | + |
| 44 | + // codewhisperer disable them while popup is shown |
| 45 | + sut.disableCodeInsightUntil(myFakePopup) |
| 46 | + |
| 47 | + assertThat(settings.TAB_EXITS_BRACKETS_AND_QUOTES).isFalse |
| 48 | + assertThat(settings.AUTO_POPUP_COMPLETION_LOOKUP).isFalse |
| 49 | + assertThat(sut.pendingRevertCounts).isEqualTo(2) |
| 50 | + |
| 51 | + // popup is closed and disposed |
| 52 | + Disposer.dispose(myFakePopup) |
| 53 | + |
| 54 | + // revert changes made by codewhisperer |
| 55 | + verify(sut, times(2)).revertAll() |
| 56 | + assertThat(settings.TAB_EXITS_BRACKETS_AND_QUOTES).isTrue |
| 57 | + assertThat(settings.AUTO_POPUP_COMPLETION_LOOKUP).isTrue |
| 58 | + } |
| 59 | + |
| 60 | + fun testRevertAllShouldRevertBackAllChangesMadeByCodewhisperer() { |
| 61 | + settings.TAB_EXITS_BRACKETS_AND_QUOTES = true |
| 62 | + assertThat(settings.TAB_EXITS_BRACKETS_AND_QUOTES).isTrue |
| 63 | + settings.AUTOCOMPLETE_ON_CODE_COMPLETION = true |
| 64 | + assertThat(settings.AUTO_POPUP_COMPLETION_LOOKUP).isTrue |
| 65 | + |
| 66 | + sut.disableCodeInsightUntil(testRootDisposable) |
| 67 | + |
| 68 | + assertThat(settings.TAB_EXITS_BRACKETS_AND_QUOTES).isFalse |
| 69 | + assertThat(settings.AUTO_POPUP_COMPLETION_LOOKUP).isFalse |
| 70 | + |
| 71 | + assertThat(sut.pendingRevertCounts).isEqualTo(2) |
| 72 | + |
| 73 | + sut.revertAll() |
| 74 | + assertThat(sut.pendingRevertCounts).isEqualTo(0) |
| 75 | + assertThat(settings.TAB_EXITS_BRACKETS_AND_QUOTES).isTrue |
| 76 | + assertThat(settings.AUTO_POPUP_COMPLETION_LOOKUP).isTrue |
| 77 | + } |
| 78 | + |
| 79 | + fun testDisableCodeInsightUntilShouldAlwaysFlushPendingRevertsBeforeMakingNextChanges() { |
| 80 | + @Suppress("ObjectLiteralToLambda") // JUnit 3 doesn't support SAM lambdas |
| 81 | + val myFakePopup = object : Disposable { override fun dispose() {} } |
| 82 | + Disposer.register(testRootDisposable, myFakePopup) |
| 83 | + |
| 84 | + @Suppress("ObjectLiteralToLambda") // JUnit 3 doesn't support SAM lambdas |
| 85 | + val myAnotherFakePopup = object : Disposable { override fun dispose() {} } |
| 86 | + Disposer.register(testRootDisposable, myAnotherFakePopup) |
| 87 | + |
| 88 | + // assume users' enable the following two codeinsight functionalities |
| 89 | + settings.TAB_EXITS_BRACKETS_AND_QUOTES = true |
| 90 | + assertThat(settings.TAB_EXITS_BRACKETS_AND_QUOTES).isTrue |
| 91 | + settings.AUTOCOMPLETE_ON_CODE_COMPLETION = true |
| 92 | + assertThat(settings.AUTO_POPUP_COMPLETION_LOOKUP).isTrue |
| 93 | + |
| 94 | + // codewhisperer disable them while popup_1 is shown |
| 95 | + sut.disableCodeInsightUntil(myFakePopup) |
| 96 | + assertThat(settings.TAB_EXITS_BRACKETS_AND_QUOTES).isFalse |
| 97 | + assertThat(settings.AUTO_POPUP_COMPLETION_LOOKUP).isFalse |
| 98 | + assertThat(sut.pendingRevertCounts).isEqualTo(2) |
| 99 | + verify(sut, times(1)).revertAll() |
| 100 | + |
| 101 | + // unexpected issue happens and popup_1 is not disposed correctly and popup_2 is created |
| 102 | + sut.disableCodeInsightUntil(myAnotherFakePopup) |
| 103 | + assertThat(settings.TAB_EXITS_BRACKETS_AND_QUOTES).isFalse |
| 104 | + assertThat(settings.AUTO_POPUP_COMPLETION_LOOKUP).isFalse |
| 105 | + // should still be 2 because previous ones should be reverted before preceding next changes |
| 106 | + assertThat(sut.pendingRevertCounts).isEqualTo(2) |
| 107 | + verify(sut, times(1 + 1)).revertAll() |
| 108 | + |
| 109 | + Disposer.dispose(myAnotherFakePopup) |
| 110 | + |
| 111 | + assertThat(sut.pendingRevertCounts).isEqualTo(0) |
| 112 | + verify(sut, times(1 + 1 + 1)).revertAll() |
| 113 | + assertThat(settings.TAB_EXITS_BRACKETS_AND_QUOTES).isTrue |
| 114 | + assertThat(settings.AUTO_POPUP_COMPLETION_LOOKUP).isTrue |
| 115 | + } |
| 116 | + |
| 117 | + fun testDisposeShouldCallRevertAllToRevertAllChangesMadeByCodeWhisperer() { |
| 118 | + sut.dispose() |
| 119 | + verify(sut).revertAll() |
| 120 | + } |
| 121 | +} |
0 commit comments