diff --git a/.run/Run Plugin Tests.run.xml b/.run/Run Plugin Tests.run.xml
deleted file mode 100644
index ae9ae135..00000000
--- a/.run/Run Plugin Tests.run.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
- true
- true
- false
-
-
-
diff --git a/src/main/kotlin/com/dsoftware/ghmanager/ui/GhActionsToolWindowFactory.kt b/src/main/kotlin/com/dsoftware/ghmanager/ui/GhActionsToolWindowFactory.kt
index 72dd473c..8542e226 100644
--- a/src/main/kotlin/com/dsoftware/ghmanager/ui/GhActionsToolWindowFactory.kt
+++ b/src/main/kotlin/com/dsoftware/ghmanager/ui/GhActionsToolWindowFactory.kt
@@ -43,7 +43,6 @@ internal class ProjectRepositories(val toolWindow: ToolWindow) {
class GhActionsToolWindowFactory : ToolWindowFactory, DumbAware {
private lateinit var settingsService: GhActionsSettingsService
- private val accountManager = service()
private val projectReposMap = mutableMapOf()
private val scope = CoroutineScope(SupervisorJob())
@@ -68,6 +67,7 @@ class GhActionsToolWindowFactory : ToolWindowFactory, DumbAware {
updateRepos(toolWindow, it)
}
}
+ val accountManager = service()
scope.launch {
accountManager.accountsState.collect {
updateRepos(toolWindow, repositoriesManager.knownRepositories)
@@ -104,23 +104,23 @@ class GhActionsToolWindowFactory : ToolWindowFactory, DumbAware {
if ((GHAccountsUtil.accounts.isEmpty() && settingsService.state.useGitHubSettings)
|| (!settingsService.state.useGitHubSettings && settingsService.state.apiToken == "")
) {
- noGitHubAccountPanel(disposable, projectRepos)
+ createNoAccountPanel(disposable, projectRepos)
} else if (projectRepos.knownRepositories.isEmpty()) {
- noRepositories(disposable, projectRepos)
+ createNoReposPanel(disposable, projectRepos)
} else {
val countRepos = projectRepos.knownRepositories.count {
settingsService.state.customRepos[it.remote.url]?.included ?: false
}
if (settingsService.state.useCustomRepos && countRepos == 0) {
- noActiveRepositories(disposable, projectRepos)
+ createNoActiveReposPanel(disposable, projectRepos)
} else {
- ghAccountAndReposConfigured(disposable, projectRepos)
+ createRepoWorkflowsPanels(disposable, projectRepos)
}
}
}
}
- private fun noActiveRepositories(
+ private fun createNoActiveReposPanel(
disposable: Disposable,
projectRepositories: ProjectRepositories
) =
@@ -148,7 +148,7 @@ class GhActionsToolWindowFactory : ToolWindowFactory, DumbAware {
)
}
- private fun noGitHubAccountPanel(
+ private fun createNoAccountPanel(
disposable: Disposable,
projectRepositories: ProjectRepositories
) = with(projectRepositories.toolWindow.contentManager) {
@@ -182,7 +182,7 @@ class GhActionsToolWindowFactory : ToolWindowFactory, DumbAware {
)
}
- private fun noRepositories(
+ private fun createNoReposPanel(
disposable: Disposable,
projectRepositories: ProjectRepositories
) = with(projectRepositories.toolWindow.contentManager) {
@@ -203,7 +203,7 @@ class GhActionsToolWindowFactory : ToolWindowFactory, DumbAware {
return accounts.firstOrNull { it.server.equals(repo.repository.serverPath, true) }
}
- private fun ghAccountAndReposConfigured(
+ private fun createRepoWorkflowsPanels(
parentDisposable: Disposable,
projectRepositories: ProjectRepositories
) =
diff --git a/src/test/kotlin/com/dsoftware/ghmanager/GitHubActionsManagerBaseTest.kt b/src/test/kotlin/com/dsoftware/ghmanager/GitHubActionsManagerBaseTest.kt
new file mode 100644
index 00000000..a52c606b
--- /dev/null
+++ b/src/test/kotlin/com/dsoftware/ghmanager/GitHubActionsManagerBaseTest.kt
@@ -0,0 +1,151 @@
+package com.dsoftware.ghmanager
+
+import com.dsoftware.ghmanager.ui.GhActionsToolWindowFactory
+import com.intellij.openapi.components.service
+import com.intellij.openapi.diagnostic.Logger
+import com.intellij.openapi.project.Project
+import com.intellij.openapi.wm.ToolWindow
+import com.intellij.platform.ide.progress.runWithModalProgressBlocking
+import com.intellij.testFramework.PlatformTestUtil
+import com.intellij.testFramework.RunAll
+import com.intellij.testFramework.fixtures.BasePlatformTestCase
+import com.intellij.toolWindow.ToolWindowHeadlessManagerImpl.MockToolWindow
+import com.intellij.util.ThrowableRunnable
+import com.intellij.util.concurrency.annotations.RequiresEdt
+import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.yield
+import org.jetbrains.plugins.github.api.GithubApiRequestExecutor
+import org.jetbrains.plugins.github.api.GithubApiRequests
+import org.jetbrains.plugins.github.api.GithubServerPath
+import org.jetbrains.plugins.github.api.data.GithubRepo
+import org.jetbrains.plugins.github.api.data.GithubResponsePage
+import org.jetbrains.plugins.github.authentication.GHAccountsUtil
+import org.jetbrains.plugins.github.authentication.accounts.GHAccountManager
+import org.jetbrains.plugins.github.authentication.accounts.GithubAccount
+import org.jetbrains.plugins.github.util.GHHostedRepositoriesManager
+
+
+/**
+ *
+ * The base class for JUnit platform tests of the github plugin.
+ * Extend this test to write a test on GitHub which has the following features/limitations:
+ *
+ * * This is a "platform test case", which means that IDEA "almost" production platform is set up before the test starts.
+ * * Project base directory is the root of everything.
+ *
+ *
+ * All tests inherited from this class are required to have a token to access the Github server.
+ * They are set up in Environment variables:
+ * `idea_test_github_host
+ * idea_test_github_token1
// token test user
+ * idea_test_github_token2` // token user with configured test repositories
+ *
+ */
+abstract class GitHubActionsManagerBaseTest : BasePlatformTestCase() {
+ private lateinit var accountManager: GHAccountManager
+ private lateinit var organisation: String
+ protected lateinit var repositoriesManager: GHHostedRepositoriesManager
+ protected lateinit var mainAccount: AccountData
+
+ private val mainRepos = mutableSetOf()
+ protected lateinit var myProject: Project
+ protected lateinit var factory: GhActionsToolWindowFactory
+ protected lateinit var toolWindow: ToolWindow
+ override fun setUp() {
+ super.setUp()
+ myProject = project
+ factory = GhActionsToolWindowFactory()
+ toolWindow = MockToolWindow(myProject)
+ val host =
+ GithubServerPath.from(System.getenv("idea_test_github_host") ?: System.getenv("idea.test.github.host"))
+ val token1 = System.getenv("idea_test_github_token1") ?: System.getenv("idea.test.github.token1")
+
+ assertNotNull(token1)
+ accountManager = service()
+ repositoriesManager = project.service()
+
+ organisation = System.getenv("idea_test_github_org") ?: System.getenv("idea.test.github.org")
+ assertNotNull(organisation)
+ mainAccount = createAccountData(host, token1)
+ setCurrentAccount(mainAccount)
+ }
+
+ private fun createAccountData(host: GithubServerPath, token: String): AccountData {
+ val account = GHAccountManager.createAccount("token", host)
+ runBlocking { accountManager.updateAccount(account, token) }
+ val executor = service().create(token)
+ val username = executor.execute(GithubApiRequests.CurrentUser.get(account.server)).login
+ val repos =
+ executor.execute>(GithubApiRequests.CurrentUser.Repos.get(account.server))
+ repos.items.forEach { mainRepos.add(it.name) }
+
+ return AccountData(token, account, username, executor)
+ }
+
+
+ protected open fun setCurrentAccount(accountData: AccountData?) {
+ GHAccountsUtil.setDefaultAccount(myProject, accountData?.account)
+ }
+
+ protected data class AccountData(
+ val token: String,
+ val account: GithubAccount,
+ val username: String,
+ val executor: GithubApiRequestExecutor
+ )
+
+
+ @Throws(Exception::class)
+ override fun tearDown() {
+ RunAll(
+ ThrowableRunnable { setCurrentAccount(null) },
+ ThrowableRunnable { if (::accountManager.isInitialized) runBlocking { accountManager.updateAccounts(emptyMap()) } },
+ ThrowableRunnable { super.tearDown() }
+ ).run()
+ }
+
+//
+// private fun deleteRepos(account: AccountData, repos: Collection) {
+// setCurrentAccount(account)
+// for (repo in repos) {
+// retry(LOG, true) {
+// account.executor.execute(GithubApiRequests.Repos.delete(repo))
+// val info = account.executor.execute(GithubApiRequests.Repos.get(repo))
+// check(info == null) { "Repository still exists" }
+// }
+// }
+// }
+
+ companion object {
+ private const val RETRIES = 3
+
+ internal fun retry(LOG: Logger, exception: Boolean = true, action: () -> Unit) {
+ for (i in 1..RETRIES) {
+ try {
+ LOG.debug("Attempt #$i")
+ return action()
+ } catch (e: Throwable) {
+ if (i == RETRIES) {
+ if (exception) throw e
+ else {
+ LOG.error(e)
+ return
+ }
+ }
+ Thread.sleep(1000L)
+ }
+ }
+ }
+ }
+}
+
+@RequiresEdt
+fun executeSomeCoroutineTasksAndDispatchAllInvocationEvents(project: Project) {
+ repeat(3) {
+ PlatformTestUtil.dispatchAllInvocationEventsInIdeEventQueue()
+ runWithModalProgressBlocking(project, "") {
+ yield()
+ }
+ PlatformTestUtil.dispatchAllInvocationEventsInIdeEventQueue()
+ }
+}
\ No newline at end of file
diff --git a/src/test/kotlin/com/dsoftware/ghmanager/ToolWindowFactoryTest.kt b/src/test/kotlin/com/dsoftware/ghmanager/ToolWindowFactoryTest.kt
new file mode 100644
index 00000000..74a52eeb
--- /dev/null
+++ b/src/test/kotlin/com/dsoftware/ghmanager/ToolWindowFactoryTest.kt
@@ -0,0 +1,16 @@
+package com.dsoftware.ghmanager
+
+import com.intellij.ui.components.JBPanelWithEmptyText
+import junit.framework.TestCase
+
+
+class ToolWindowFactoryTest : GitHubActionsManagerBaseTest() {
+ fun testNoGitHubAccountPanel() {
+ factory.init(toolWindow)
+ executeSomeCoroutineTasksAndDispatchAllInvocationEvents(project)
+
+ TestCase.assertEquals(1, toolWindow.contentManager.contentCount)
+ val panel = toolWindow.contentManager.contents[0].component
+ TestCase.assertTrue(panel is JBPanelWithEmptyText)
+ }
+}
\ No newline at end of file