From e1b3337c2f47dc336ab55aaf181683f1aa9070ab Mon Sep 17 00:00:00 2001 From: Uladzislau Date: Fri, 27 Sep 2024 16:58:09 +0200 Subject: [PATCH] Fix for compatibility problems Signed-off-by: Uladzislau --- .gitignore | 1 + .gitlab-ci.yml | 2 + build.gradle.kts | 168 +++++----- gradle.properties | 1 + .../formainframe/vfs/MFVFileCreateEvent.kt | 73 +++++ .../formainframe/vfs/MFVFileCreateEvent.kt | 73 +++++ .../formainframe/vfs/MFVFileCreateEvent.kt | 73 +++++ .../vfs/MFVFilePropertyChangeEvent.kt | 81 +++++ .../tso/config/ui/TSOSessionDialog.kt | 1 - .../vfs/MFVFileCreateEventDelegate.kt | 80 +++++ .../vfs/MFVirtualFileSystemModel.kt | 3 +- .../formainframe/config/ConfigTestSpec.kt | 35 +-- .../DatasetFileFetchProviderTestSpec.kt | 42 +-- .../dataops/JobFetchProviderTestSpec.kt | 34 +- .../actions/EditMaskActionTestSpec.kt | 91 ++++-- .../explorer/actions/GoToJobActionTestSpec.kt | 46 ++- .../explorer/actions/RenameActionTestSpec.kt | 76 ++++- .../ui/ChangeEncodingDialogTestSpec.kt | 293 +++++++++++------- .../explorer/ui/ExplorerTreeViewTestSpec.kt | 17 +- .../ui/SelectTSOSessionDialogTestSpec.kt | 35 ++- .../explorer/ui/UssFileNodeTestSpec.kt | 114 ++----- .../formainframe/explorer/ui/dummyClasses.kt | 131 -------- .../testutils/WithApplicationShouldSpec.kt | 26 +- .../ibagroup/formainframe/testutils/misc.kt | 2 +- .../tso/config/TSOSessionConfigTestSpec.kt | 91 +++--- .../utils/EncodingUtilsTestSpec.kt | 29 +- 26 files changed, 973 insertions(+), 645 deletions(-) create mode 100644 src/IC-231/kotlin/eu/ibagroup/formainframe/vfs/MFVFileCreateEvent.kt create mode 100644 src/IC-233/kotlin/eu/ibagroup/formainframe/vfs/MFVFileCreateEvent.kt create mode 100644 src/IC-243/kotlin/eu/ibagroup/formainframe/vfs/MFVFileCreateEvent.kt create mode 100644 src/IC-243/kotlin/eu/ibagroup/formainframe/vfs/MFVFilePropertyChangeEvent.kt create mode 100644 src/main/kotlin/eu/ibagroup/formainframe/vfs/MFVFileCreateEventDelegate.kt delete mode 100644 src/test/kotlin/eu/ibagroup/formainframe/explorer/ui/dummyClasses.kt diff --git a/.gitignore b/.gitignore index 4659e48f4..821755ad5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ .gradle .idea +.intellijPlatform /build /ide_for_launch diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index fdc5a6530..7a72f1f9e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -5,6 +5,7 @@ build-job: matrix: - PRODUCT_NAME: "IC-231" - PRODUCT_NAME: "IC-233" + - PRODUCT_NAME: "IC-243" script: - | echo "Build is going to proceed with the next Java:" @@ -31,6 +32,7 @@ test-job: matrix: - PRODUCT_NAME: "IC-231" - PRODUCT_NAME: "IC-233" + - PRODUCT_NAME: "IC-243" script: - | echo "Test is going to proceed with the next Java:" diff --git a/build.gradle.kts b/build.gradle.kts index 53732fb73..d1a38e1de 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -13,8 +13,7 @@ */ import org.jetbrains.changelog.Changelog -import org.jetbrains.intellij.tasks.ClasspathIndexCleanupTask -import org.jetbrains.kotlin.gradle.tasks.KotlinCompile +import org.jetbrains.intellij.platform.gradle.TestFrameworkType import java.time.LocalDate import java.time.ZoneId import java.time.format.DateTimeFormatter @@ -24,17 +23,41 @@ fun environment(key: String) = providers.environmentVariable(key) fun dateValue(pattern: String): String = LocalDate.now(ZoneId.of("Europe/Warsaw")).format(DateTimeFormatter.ofPattern(pattern)) -plugins { - id("org.jetbrains.intellij") version "1.17.4" - id("org.jetbrains.changelog") version "2.2.1" - kotlin("jvm") version "1.9.22" - java - id("org.jetbrains.kotlinx.kover") version "0.8.3" - id("org.owasp.dependencycheck") version "10.0.4" -} +// https://github.com/kotest/kotest-intellij-plugin/blob/master/build.gradle.kts +data class PluginDescriptor( + val jvmTargetVersion: JavaVersion, // the Java version to use during the plugin build + val since: String, // earliest version string this is compatible with + val until: String, // latest version string this is compatible with, can be wildcard like 202.* + // https://github.com/JetBrains/gradle-intellij-plugin#intellij-platform-properties + val sdkVersion: String, // the version string passed to the intellij sdk gradle plugin + val sourceFolder: String // used as the source root for specifics of this build +) -apply(plugin = "kotlin") -apply(plugin = "org.jetbrains.intellij") +val plugins = listOf( + PluginDescriptor( + jvmTargetVersion = JavaVersion.VERSION_17, + since = properties("pluginSinceBuild").get(), + until = "232.*", + sdkVersion = "2023.1.7", + sourceFolder = "IC-231" + ), + PluginDescriptor( + jvmTargetVersion = JavaVersion.VERSION_17, + since = "233.11799", + until = "242.*", + sdkVersion = "2023.3", + sourceFolder = "IC-233" + ), + PluginDescriptor( + jvmTargetVersion = JavaVersion.VERSION_21, + since = "243.12818", + until = properties("pluginUntilBuild").get(), + sdkVersion = "243-EAP-SNAPSHOT", + sourceFolder = "IC-243" + ) +) +val productName = System.getenv("PRODUCT_NAME") ?: "IC-231" +val descriptor = plugins.first { it.sourceFolder == productName } group = properties("pluginGroup").get() version = properties("pluginVersion").get() @@ -42,37 +65,56 @@ val remoteRobotVersion = "0.11.23" val okHttp3Version = "4.12.0" val kotestVersion = "5.9.1" val retrofit2Vertion = "2.11.0" -val junitVersion = "5.10.3" +val junitVersion = "5.11.1" val mockkVersion = "1.13.12" val ibmMqVersion = "9.4.0.0" val jGraphTVersion = "1.5.2" val zoweKotlinSdkVersion = "0.5.0" val javaAnalyticsVersion = "3.5.1" +plugins { + id("org.jetbrains.intellij.platform") version "2.1.0" + id("org.jetbrains.changelog") version "2.2.1" + kotlin("jvm") version "1.9.22" + java + id("org.jetbrains.kotlinx.kover") version "0.8.3" + id("org.owasp.dependencycheck") version "10.0.4" +} + repositories { mavenCentral() maven { url = uri("https://zowe.jfrog.io/zowe/libs-release") - } - maven { - url = uri("https://packages.jetbrains.team/maven/p/ij/intellij-dependencies") flatDir { dir("libs") } - metadataSources { - mavenPom() - artifact() - ignoreGradleMetadataRedirection() - } + } + intellijPlatform { + defaultRepositories() + jetbrainsRuntime() } } java { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 + sourceCompatibility = descriptor.jvmTargetVersion + targetCompatibility = descriptor.jvmTargetVersion +} + +kotlin { + compilerOptions { + jvmToolchain(JavaLanguageVersion.of(descriptor.jvmTargetVersion.toString()).asInt()) + } } dependencies { + intellijPlatform { +// intellijIdeaCommunity(descriptor.sdkVersion) +// TO TEST EAP: + intellijIdeaCommunity(descriptor.sdkVersion, useInstaller = false) + jetbrainsRuntime() + instrumentationTools() + testFramework(TestFrameworkType.Plugin.Java) + } implementation(group = "com.squareup.retrofit2", name = "retrofit", version = retrofit2Vertion) implementation("com.squareup.retrofit2:converter-gson:$retrofit2Vertion") implementation("com.squareup.retrofit2:converter-scalars:$retrofit2Vertion") @@ -90,46 +132,15 @@ dependencies { testImplementation("com.intellij.remoterobot:remote-fixtures:$remoteRobotVersion") testImplementation("com.squareup.okhttp3:mockwebserver:$okHttp3Version") testImplementation("com.squareup.okhttp3:okhttp-tls:$okHttp3Version") + testImplementation("com.intellij.remoterobot:ide-launcher:$remoteRobotVersion") testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:$junitVersion") testRuntimeOnly("org.junit.vintage:junit-vintage-engine:$junitVersion") - testImplementation("com.intellij.remoterobot:ide-launcher:$remoteRobotVersion") } -data class PluginDescriptor( - val since: String, // earliest version string this is compatible with - val until: String, // latest version string this is compatible with, can be wildcard like 202.* - // https://github.com/JetBrains/gradle-intellij-plugin#intellij-platform-properties - val sdkVersion: String, // the version string passed to the intellij sdk gradle plugin - val sourceFolder: String, // used as the source root for specifics of this build - val deps: List // dependent plugins of this plugin -) - -val plugins = listOf( - PluginDescriptor( - since = properties("pluginSinceBuild").get(), - until = "232.*", - sdkVersion = "IC-2023.1.7", - sourceFolder = "IC-231", - deps = listOf("java", "org.jetbrains.plugins.gradle", "org.jetbrains.kotlin") - ), - PluginDescriptor( - since = "233.11799", - until = properties("pluginUntilBuild").get(), - sdkVersion = "IC-2023.3", - sourceFolder = "IC-233", - deps = listOf("java", "org.jetbrains.plugins.gradle", "org.jetbrains.kotlin") - ) -) -val productName = System.getenv("PRODUCT_NAME") ?: "IC-231" -val descriptor = plugins.first { it.sourceFolder == productName } - -intellij { - version.set(descriptor.sdkVersion) - plugins.addAll(*descriptor.deps.toTypedArray()) - // !Development only! - // downloadSources.set(true) - // In Settings | Advanced Settings enable option Download sources in section Build Tools. Gradle. - // Then invoke Reload All Gradle Projects action from the Gradle tool window. +intellijPlatform { + pluginConfiguration { + version = "${properties("pluginVersion").get()}-${descriptor.since.substringBefore(".")}" + } } // Configure Gradle Changelog Plugin - read more: https://github.com/JetBrains/gradle-changelog-plugin @@ -166,6 +177,7 @@ kover { classes(providers.provider { "eu.ibagroup.formainframe.*" }) } excludes { + classes(providers.provider { "eu.ibagroup.formainframe.vfs.MFVFileCreateEvent" }) classes(providers.provider { "eu.ibagroup.formainframe.vfs.MFVFilePropertyChangeEvent" }) } } @@ -181,19 +193,11 @@ tasks { gradleVersion = properties("gradleVersion").get() } - withType { - kotlinOptions { - jvmTarget = JavaVersion.VERSION_17.toString() - languageVersion = org.jetbrains.kotlin.config.LanguageVersion.LATEST_STABLE.versionString - } - } - withType { duplicatesStrategy = DuplicatesStrategy.EXCLUDE } patchPluginXml { - version.set("${properties("pluginVersion").get()}-${descriptor.since.substringBefore(".")}") sinceBuild.set(descriptor.since) untilBuild.set(descriptor.until) @@ -215,12 +219,12 @@ tasks { ) } - withType { - onlyIf { - gradle.startParameter.taskNames.contains("test") - } - dependsOn(compileTestKotlin) - } +// withType { +// onlyIf { +// gradle.startParameter.taskNames.contains("test") +// } +// dependsOn(compileTestKotlin) +// } // // withType { @@ -248,7 +252,7 @@ tasks { if (desc.parent == null) { // will match the outermost suite val output = "Results: ${result.resultType} (${result.testCount} tests, ${result.successfulTestCount} passed, " + - "${result.failedTestCount} failed, ${result.skippedTestCount} skipped)" + "${result.failedTestCount} failed, ${result.skippedTestCount} skipped)" val fileName = "./build/reports/tests/${result.resultType}.txt" File(fileName).writeText(output) } @@ -298,14 +302,16 @@ tasks { ) } - downloadRobotServerPlugin { - version.set(remoteRobotVersion) - } +// TODO: fix +// downloadRobotServerPlugin { +// version.set(remoteRobotVersion) +// } - runIdeForUiTests { - systemProperty("idea.trust.all.projects", "true") - systemProperty("ide.show.tips.on.startup.default.value", "false") - } +// TODO: fix +// runIdeForUiTests { +// systemProperty("idea.trust.all.projects", "true") +// systemProperty("ide.show.tips.on.startup.default.value", "false") +// } } /** diff --git a/gradle.properties b/gradle.properties index c4c25b97a..e1b1e2488 100644 --- a/gradle.properties +++ b/gradle.properties @@ -21,6 +21,7 @@ pluginSinceBuild=231.9423 pluginUntilBuild= # Gradle Releases -> https://github.com/gradle/gradle/releases gradleVersion=8.7 +# UI tests setup systemProp.ideLaunchFolder=".\\ide_for_launch" systemProp.forMainframePath="build\\distributions\\for-mainframe-2.0.0-IC-2023.1.zip" systemProp.remoteRobotUrl="http://127.0.0.1" diff --git a/src/IC-231/kotlin/eu/ibagroup/formainframe/vfs/MFVFileCreateEvent.kt b/src/IC-231/kotlin/eu/ibagroup/formainframe/vfs/MFVFileCreateEvent.kt new file mode 100644 index 000000000..bcfa4d4f2 --- /dev/null +++ b/src/IC-231/kotlin/eu/ibagroup/formainframe/vfs/MFVFileCreateEvent.kt @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2024 IBA Group. + * + * This program and the accompanying materials are made available under the terms of the + * Eclipse Public License v2.0 which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-v20.html + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBA Group + * Zowe Community + */ + +package eu.ibagroup.formainframe.vfs + +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.openapi.vfs.VirtualFileSystem +import com.intellij.openapi.vfs.newvfs.events.VFileEvent +import eu.ibagroup.formainframe.vfs.MFVirtualFileSystem.Companion.MF_VFS_CHANGES_TOPIC + +/** + * MF virtual file create event. Carries info about the created MF virtual file. + * Use it together with [MF_VFS_CHANGES_TOPIC] + * @property requestor an instance to describe the event requester + * @property parent the created MF virtual file's parent + * @property childName the created file's name + * @property isDirectory indicates whether the created MF virtual file is a directory + * @property delegate the delegate to execute the necessary functions + */ +class MFVFileCreateEvent( + requestor: Any?, + private val parent: MFVirtualFile, + private val childName: String, + private val isDirectory: Boolean, + private val delegate: MFVFileCreateEventDelegate +) : VFileEvent(requestor, false) { + + override fun equals(other: Any?): Boolean { + var otherIsDirectory: Boolean? = null + var otherChildName: String? = null + var otherParent: MFVirtualFile? = null + if (other is MFVFileCreateEvent) { + otherIsDirectory = other.isDirectory + otherChildName = other.childName + otherParent = other.parent + } + return delegate.equals( + this, isDirectory, childName, parent, other, otherIsDirectory, otherChildName, otherParent + ) + } + + override fun hashCode(): Int { + return delegate.hashCode(parent, isDirectory, childName) + } + + override fun computePath(): String { + return delegate.computePath(parent, childName) + } + + override fun getFile(): VirtualFile { + return delegate.getFile(parent, childName) + } + + override fun getFileSystem(): VirtualFileSystem { + return delegate.getFileSystem(parent) + } + + override fun isValid(): Boolean { + return delegate.isValid(parent, childName) + } + +} diff --git a/src/IC-233/kotlin/eu/ibagroup/formainframe/vfs/MFVFileCreateEvent.kt b/src/IC-233/kotlin/eu/ibagroup/formainframe/vfs/MFVFileCreateEvent.kt new file mode 100644 index 000000000..05cb1aa74 --- /dev/null +++ b/src/IC-233/kotlin/eu/ibagroup/formainframe/vfs/MFVFileCreateEvent.kt @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2024 IBA Group. + * + * This program and the accompanying materials are made available under the terms of the + * Eclipse Public License v2.0 which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-v20.html + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBA Group + * Zowe Community + */ + +package eu.ibagroup.formainframe.vfs + +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.openapi.vfs.VirtualFileSystem +import com.intellij.openapi.vfs.newvfs.events.VFileEvent +import eu.ibagroup.formainframe.vfs.MFVirtualFileSystem.Companion.MF_VFS_CHANGES_TOPIC + +/** + * MF virtual file create event. Carries info about the created MF virtual file. + * Use it together with [MF_VFS_CHANGES_TOPIC] + * @property requestor an instance to describe the event requester + * @property parent the created MF virtual file's parent + * @property childName the created file's name + * @property isDirectory indicates whether the created MF virtual file is a directory + * @property delegate the delegate to execute the necessary functions + */ +class MFVFileCreateEvent( + requestor: Any?, + private val parent: MFVirtualFile, + private val childName: String, + private val isDirectory: Boolean, + private val delegate: MFVFileCreateEventDelegate +) : VFileEvent(requestor) { + + override fun equals(other: Any?): Boolean { + var otherIsDirectory: Boolean? = null + var otherChildName: String? = null + var otherParent: MFVirtualFile? = null + if (other is MFVFileCreateEvent) { + otherIsDirectory = other.isDirectory + otherChildName = other.childName + otherParent = other.parent + } + return delegate.equals( + this, isDirectory, childName, parent, other, otherIsDirectory, otherChildName, otherParent + ) + } + + override fun hashCode(): Int { + return delegate.hashCode(parent, isDirectory, childName) + } + + override fun computePath(): String { + return delegate.computePath(parent, childName) + } + + override fun getFile(): VirtualFile { + return delegate.getFile(parent, childName) + } + + override fun getFileSystem(): VirtualFileSystem { + return delegate.getFileSystem(parent) + } + + override fun isValid(): Boolean { + return delegate.isValid(parent, childName) + } + +} diff --git a/src/IC-243/kotlin/eu/ibagroup/formainframe/vfs/MFVFileCreateEvent.kt b/src/IC-243/kotlin/eu/ibagroup/formainframe/vfs/MFVFileCreateEvent.kt new file mode 100644 index 000000000..05cb1aa74 --- /dev/null +++ b/src/IC-243/kotlin/eu/ibagroup/formainframe/vfs/MFVFileCreateEvent.kt @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2024 IBA Group. + * + * This program and the accompanying materials are made available under the terms of the + * Eclipse Public License v2.0 which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-v20.html + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBA Group + * Zowe Community + */ + +package eu.ibagroup.formainframe.vfs + +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.openapi.vfs.VirtualFileSystem +import com.intellij.openapi.vfs.newvfs.events.VFileEvent +import eu.ibagroup.formainframe.vfs.MFVirtualFileSystem.Companion.MF_VFS_CHANGES_TOPIC + +/** + * MF virtual file create event. Carries info about the created MF virtual file. + * Use it together with [MF_VFS_CHANGES_TOPIC] + * @property requestor an instance to describe the event requester + * @property parent the created MF virtual file's parent + * @property childName the created file's name + * @property isDirectory indicates whether the created MF virtual file is a directory + * @property delegate the delegate to execute the necessary functions + */ +class MFVFileCreateEvent( + requestor: Any?, + private val parent: MFVirtualFile, + private val childName: String, + private val isDirectory: Boolean, + private val delegate: MFVFileCreateEventDelegate +) : VFileEvent(requestor) { + + override fun equals(other: Any?): Boolean { + var otherIsDirectory: Boolean? = null + var otherChildName: String? = null + var otherParent: MFVirtualFile? = null + if (other is MFVFileCreateEvent) { + otherIsDirectory = other.isDirectory + otherChildName = other.childName + otherParent = other.parent + } + return delegate.equals( + this, isDirectory, childName, parent, other, otherIsDirectory, otherChildName, otherParent + ) + } + + override fun hashCode(): Int { + return delegate.hashCode(parent, isDirectory, childName) + } + + override fun computePath(): String { + return delegate.computePath(parent, childName) + } + + override fun getFile(): VirtualFile { + return delegate.getFile(parent, childName) + } + + override fun getFileSystem(): VirtualFileSystem { + return delegate.getFileSystem(parent) + } + + override fun isValid(): Boolean { + return delegate.isValid(parent, childName) + } + +} diff --git a/src/IC-243/kotlin/eu/ibagroup/formainframe/vfs/MFVFilePropertyChangeEvent.kt b/src/IC-243/kotlin/eu/ibagroup/formainframe/vfs/MFVFilePropertyChangeEvent.kt new file mode 100644 index 000000000..7984abb4e --- /dev/null +++ b/src/IC-243/kotlin/eu/ibagroup/formainframe/vfs/MFVFilePropertyChangeEvent.kt @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2024 IBA Group. + * + * This program and the accompanying materials are made available under the terms of the + * Eclipse Public License v2.0 which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-v20.html + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBA Group + * Zowe Community + */ + +package eu.ibagroup.formainframe.vfs + +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.openapi.vfs.VirtualFileSystem +import com.intellij.openapi.vfs.newvfs.events.VFileEvent +import eu.ibagroup.formainframe.vfs.MFVirtualFileSystem.Companion.MF_VFS_CHANGES_TOPIC + +/** + * MF virtual file property change event. Carries info about a property of a MF virtual file being changed. + * Use it together with [MF_VFS_CHANGES_TOPIC] + * @property requestor an instance to describe the event requester + * @property file the MF virtual file to change property of + * @property propName the name of the property to change + * @property oldValue the old value of the property being changed + * @property newValue the possible new value of the property being changed + * @property delegate the delegate to execute the necessary functions + */ +class MFVFilePropertyChangeEvent( + requestor: Any?, + private val file: MFVirtualFile, + private val propName: MFVirtualFile.PropName, + private val oldValue: Any, + private val newValue: Any, + private val delegate: MFVFilePropertyChangeEventDelegate +) : VFileEvent(requestor) { + + init { + delegate.checkPropValid(requestor, propName, oldValue, newValue) + } + + override fun equals(other: Any?): Boolean { + var otherFile: MFVirtualFile? = null + var otherPropName: MFVirtualFile.PropName? = null + var otherOldValue: Any? = null + var otherNewValue: Any? = null + if (other is MFVFilePropertyChangeEvent) { + otherFile = other.file + otherPropName = other.propName + otherOldValue = other.oldValue + otherNewValue = other.newValue + } + return delegate.equals( + this, file, propName, oldValue, newValue, other, otherFile, otherPropName, otherOldValue, otherNewValue + ) + } + + override fun hashCode(): Int { + return delegate.hashCode(propName, oldValue, newValue, file) + } + + override fun computePath(): String { + return delegate.computePath(file) + } + + override fun getFile(): VirtualFile { + return delegate.getFile(file) + } + + override fun getFileSystem(): VirtualFileSystem { + return delegate.getFileSystem(file) + } + + override fun isValid(): Boolean { + return delegate.isValid(file) + } + +} diff --git a/src/main/kotlin/eu/ibagroup/formainframe/tso/config/ui/TSOSessionDialog.kt b/src/main/kotlin/eu/ibagroup/formainframe/tso/config/ui/TSOSessionDialog.kt index 979c94635..ce2416155 100644 --- a/src/main/kotlin/eu/ibagroup/formainframe/tso/config/ui/TSOSessionDialog.kt +++ b/src/main/kotlin/eu/ibagroup/formainframe/tso/config/ui/TSOSessionDialog.kt @@ -14,7 +14,6 @@ package eu.ibagroup.formainframe.tso.config.ui - import com.intellij.openapi.project.Project import com.intellij.openapi.ui.ValidationInfo import com.intellij.ui.CollectionComboBoxModel diff --git a/src/main/kotlin/eu/ibagroup/formainframe/vfs/MFVFileCreateEventDelegate.kt b/src/main/kotlin/eu/ibagroup/formainframe/vfs/MFVFileCreateEventDelegate.kt new file mode 100644 index 000000000..12795119e --- /dev/null +++ b/src/main/kotlin/eu/ibagroup/formainframe/vfs/MFVFileCreateEventDelegate.kt @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2024 IBA Group. + * + * This program and the accompanying materials are made available under the terms of the + * Eclipse Public License v2.0 which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-v20.html + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBA Group + * Zowe Community + */ + +package eu.ibagroup.formainframe.vfs + +import com.intellij.openapi.util.text.StringUtil +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.openapi.vfs.VirtualFileSystem +import eu.ibagroup.formainframe.vfs.MFVirtualFileSystem.Companion.MF_VFS_CHANGES_TOPIC + +/** + * MF virtual file create event. Carries info about the created MF virtual file. + * Use it together with [MF_VFS_CHANGES_TOPIC] + */ +class MFVFileCreateEventDelegate { + + private var createdFile: MFVirtualFile? = null + + fun equals( + origin: MFVFileCreateEvent, + isDirectory: Boolean, + childName: String, + parent: MFVirtualFile, + other: Any?, + otherIsDirectory: Boolean?, + otherChildName: String?, + otherParent: MFVirtualFile? + ): Boolean { + if (origin === other) return true + if (other == null || origin.javaClass != other.javaClass) return false + return isDirectory == otherIsDirectory + && childName == otherChildName + && parent == otherParent + } + + fun hashCode( + parent: VirtualFile, + isDirectory: Boolean, + childName: String + ): Int { + var result = parent.hashCode() + result = 31 * result + (if (isDirectory) 1 else 0) + result = 31 * result + childName.hashCode() + return result + } + + fun computePath(parent: MFVirtualFile, childName: String): String { + val parentPath = parent.path + return if (StringUtil.endsWithChar(parentPath, '/')) parentPath + childName else "$parentPath/$childName" + } + + fun getFile(parent: MFVirtualFile, childName: String): VirtualFile { + var createdFileNewValue = createdFile + if (createdFile == null && parent.isValid()) { + createdFile = parent.findChild(childName) + createdFileNewValue = createdFile + } + return createdFileNewValue ?: throw Exception("Created file is not found") + } + + fun getFileSystem(parent: MFVirtualFile): VirtualFileSystem { + return parent.fileSystem + } + + fun isValid(parent: MFVirtualFile, childName: String): Boolean { + return parent.isValid() && parent.findChild(childName) == null + } + +} diff --git a/src/main/kotlin/eu/ibagroup/formainframe/vfs/MFVirtualFileSystemModel.kt b/src/main/kotlin/eu/ibagroup/formainframe/vfs/MFVirtualFileSystemModel.kt index 446bf7dc4..8f191d3a1 100755 --- a/src/main/kotlin/eu/ibagroup/formainframe/vfs/MFVirtualFileSystemModel.kt +++ b/src/main/kotlin/eu/ibagroup/formainframe/vfs/MFVirtualFileSystemModel.kt @@ -396,8 +396,7 @@ class MFVirtualFileSystemModel { if (attributes.isSymLink) { throw IOException("Cannot create symlink without destination") } - @Suppress("UnstableApiUsage") - val event = listOf(VFileCreateEvent(requestor, vDir, name, attributes.isDirectory, attributes, null, false, null)) + val event = listOf(MFVFileCreateEvent(requestor, vDir, name, attributes.isDirectory, MFVFileCreateEventDelegate())) sendMFVfsChangesTopic().before(event) val file = vDir.validWriteLock { if (!vDir.isDirectory) { diff --git a/src/test/kotlin/eu/ibagroup/formainframe/config/ConfigTestSpec.kt b/src/test/kotlin/eu/ibagroup/formainframe/config/ConfigTestSpec.kt index 6b9844a8b..2c04cc3a1 100644 --- a/src/test/kotlin/eu/ibagroup/formainframe/config/ConfigTestSpec.kt +++ b/src/test/kotlin/eu/ibagroup/formainframe/config/ConfigTestSpec.kt @@ -14,21 +14,15 @@ package eu.ibagroup.formainframe.config +import com.intellij.openapi.application.EDT import com.intellij.openapi.progress.ProgressIndicator import com.intellij.openapi.ui.DialogPanel import com.intellij.openapi.ui.ValidationInfo import eu.ibagroup.formainframe.api.ZosmfApi -import eu.ibagroup.formainframe.config.connect.ConnectionConfig -import eu.ibagroup.formainframe.config.connect.Credentials -import eu.ibagroup.formainframe.config.connect.CredentialsConfigDeclaration -import eu.ibagroup.formainframe.config.connect.ZOSMFConnectionConfigDeclaration -import eu.ibagroup.formainframe.config.connect.getOwner -import eu.ibagroup.formainframe.config.connect.getUsername -import eu.ibagroup.formainframe.config.connect.tryToExtractOwnerFromConfig +import eu.ibagroup.formainframe.config.connect.* import eu.ibagroup.formainframe.config.connect.ui.zosmf.ConnectionDialogState import eu.ibagroup.formainframe.config.connect.ui.zosmf.ConnectionsTableModel import eu.ibagroup.formainframe.config.connect.ui.zosmf.initEmptyUuids -import eu.ibagroup.formainframe.config.connect.whoAmI import eu.ibagroup.formainframe.config.ws.FilesWorkingSetConfig import eu.ibagroup.formainframe.config.ws.JesWorkingSetConfig import eu.ibagroup.formainframe.config.ws.ui.AbstractWsDialog @@ -47,20 +41,11 @@ import eu.ibagroup.formainframe.utils.crudable.Crudable import io.kotest.assertions.assertSoftly import io.kotest.matchers.shouldBe import io.kotest.matchers.shouldNotBe -import io.mockk.clearAllMocks -import io.mockk.every -import io.mockk.mockk -import io.mockk.mockkConstructor -import io.mockk.mockkObject -import io.mockk.mockkStatic -import io.mockk.unmockkAll -import io.mockk.verify -import org.zowe.kotlinsdk.MessageType -import org.zowe.kotlinsdk.TsoApi -import org.zowe.kotlinsdk.TsoCmdResponse -import org.zowe.kotlinsdk.TsoCmdResult -import org.zowe.kotlinsdk.TsoData -import org.zowe.kotlinsdk.TsoResponse +import io.mockk.* +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.withContext +import org.zowe.kotlinsdk.* import org.zowe.kotlinsdk.annotations.ZVersion import retrofit2.Call import retrofit2.Response @@ -530,7 +515,11 @@ class ConfigTestSpec : WithApplicationShouldSpec({ // ui/AbstractWsDialog.init should("check that OK action is enabled if validation map is empty") { - val dialog = FilesWorkingSetDialog(crudableMockk, FilesWorkingSetDialogState()) + val dialog = runBlocking { + withContext(Dispatchers.EDT) { + FilesWorkingSetDialog(crudableMockk, FilesWorkingSetDialogState()) + } + } verify { anyConstructed().registerValidators(any(), any()) } assertSoftly { dialog.isOKActionEnabled shouldBe true } diff --git a/src/test/kotlin/eu/ibagroup/formainframe/dataops/DatasetFileFetchProviderTestSpec.kt b/src/test/kotlin/eu/ibagroup/formainframe/dataops/DatasetFileFetchProviderTestSpec.kt index 26bcd975c..b29814da6 100644 --- a/src/test/kotlin/eu/ibagroup/formainframe/dataops/DatasetFileFetchProviderTestSpec.kt +++ b/src/test/kotlin/eu/ibagroup/formainframe/dataops/DatasetFileFetchProviderTestSpec.kt @@ -14,60 +14,28 @@ package eu.ibagroup.formainframe.dataops -import com.intellij.openapi.components.service import com.intellij.openapi.progress.ProgressIndicator import com.intellij.openapi.vfs.VirtualFile -import com.intellij.testFramework.LightProjectDescriptor -import com.intellij.testFramework.fixtures.IdeaTestFixtureFactory -import com.intellij.testFramework.fixtures.impl.LightTempDirTestFixtureImpl import eu.ibagroup.formainframe.api.ZosmfApi import eu.ibagroup.formainframe.config.connect.ConnectionConfig import eu.ibagroup.formainframe.config.connect.authToken import eu.ibagroup.formainframe.config.ws.DSMask -import eu.ibagroup.formainframe.dataops.attributes.AttributesService -import eu.ibagroup.formainframe.dataops.attributes.FileAttributes -import eu.ibagroup.formainframe.dataops.attributes.MaskedRequester -import eu.ibagroup.formainframe.dataops.attributes.RemoteDatasetAttributes -import eu.ibagroup.formainframe.dataops.attributes.RemoteDatasetAttributesService +import eu.ibagroup.formainframe.dataops.attributes.* import eu.ibagroup.formainframe.dataops.fetch.DatasetFileFetchProvider +import eu.ibagroup.formainframe.testutils.WithApplicationShouldSpec import eu.ibagroup.formainframe.testutils.testServiceImpl.TestDataOpsManagerImpl import eu.ibagroup.formainframe.testutils.testServiceImpl.TestZosmfApiImpl import eu.ibagroup.formainframe.utils.cancelByIndicator import eu.ibagroup.formainframe.vfs.MFVirtualFile import io.kotest.assertions.assertSoftly -import io.kotest.core.spec.style.ShouldSpec import io.kotest.matchers.collections.shouldHaveSize import io.kotest.matchers.shouldBe -import io.mockk.Runs -import io.mockk.clearAllMocks -import io.mockk.every -import io.mockk.just -import io.mockk.mockk -import io.mockk.spyk -import io.mockk.unmockkAll -import org.zowe.kotlinsdk.DataAPI -import org.zowe.kotlinsdk.DataSetsList -import org.zowe.kotlinsdk.Dataset -import org.zowe.kotlinsdk.DatasetOrganization -import org.zowe.kotlinsdk.HasMigrated -import org.zowe.kotlinsdk.XIBMAttr +import io.mockk.* +import org.zowe.kotlinsdk.* import retrofit2.Call import retrofit2.Response -class DatasetFileFetchProviderTestSpec : ShouldSpec({ - - beforeSpec { - // FIXTURE SETUP TO HAVE ACCESS TO APPLICATION INSTANCE - val factory = IdeaTestFixtureFactory.getFixtureFactory() - val projectDescriptor = LightProjectDescriptor.EMPTY_PROJECT_DESCRIPTOR - val fixtureBuilder = factory.createLightFixtureBuilder(projectDescriptor, "for-mainframe") - val fixture = fixtureBuilder.fixture - val myFixture = IdeaTestFixtureFactory.getFixtureFactory().createCodeInsightFixture( - fixture, - LightTempDirTestFixtureImpl(true) - ) - myFixture.setUp() - } +class DatasetFileFetchProviderTestSpec : WithApplicationShouldSpec({ afterSpec { clearAllMocks() diff --git a/src/test/kotlin/eu/ibagroup/formainframe/dataops/JobFetchProviderTestSpec.kt b/src/test/kotlin/eu/ibagroup/formainframe/dataops/JobFetchProviderTestSpec.kt index e314742db..7bd782e7f 100644 --- a/src/test/kotlin/eu/ibagroup/formainframe/dataops/JobFetchProviderTestSpec.kt +++ b/src/test/kotlin/eu/ibagroup/formainframe/dataops/JobFetchProviderTestSpec.kt @@ -16,36 +16,23 @@ package eu.ibagroup.formainframe.dataops import com.intellij.openapi.progress.ProgressIndicator import com.intellij.openapi.vfs.VirtualFile -import com.intellij.testFramework.LightProjectDescriptor -import com.intellij.testFramework.fixtures.IdeaTestFixtureFactory -import com.intellij.testFramework.fixtures.impl.LightTempDirTestFixtureImpl import eu.ibagroup.formainframe.api.ZosmfApi import eu.ibagroup.formainframe.config.connect.ConnectionConfig import eu.ibagroup.formainframe.config.connect.authToken import eu.ibagroup.formainframe.config.ws.JobsFilter -import eu.ibagroup.formainframe.dataops.attributes.AttributesService -import eu.ibagroup.formainframe.dataops.attributes.FileAttributes -import eu.ibagroup.formainframe.dataops.attributes.JobsRequester -import eu.ibagroup.formainframe.dataops.attributes.RemoteJobAttributes -import eu.ibagroup.formainframe.dataops.attributes.RemoteJobAttributesService +import eu.ibagroup.formainframe.dataops.attributes.* import eu.ibagroup.formainframe.dataops.fetch.JobFetchProvider +import eu.ibagroup.formainframe.testutils.WithApplicationShouldSpec import eu.ibagroup.formainframe.testutils.testServiceImpl.TestDataOpsManagerImpl import eu.ibagroup.formainframe.testutils.testServiceImpl.TestZosmfApiImpl import eu.ibagroup.formainframe.utils.cancelByIndicator import eu.ibagroup.formainframe.vfs.MFVirtualFile import io.kotest.assertions.assertSoftly import io.kotest.assertions.throwables.shouldThrow -import io.kotest.core.spec.style.ShouldSpec import io.kotest.matchers.collections.shouldHaveSize import io.kotest.matchers.shouldBe import io.kotest.matchers.throwable.shouldHaveMessage -import io.mockk.Runs -import io.mockk.clearAllMocks -import io.mockk.every -import io.mockk.just -import io.mockk.mockk -import io.mockk.spyk -import io.mockk.unmockkAll +import io.mockk.* import org.zowe.kotlinsdk.ExecData import org.zowe.kotlinsdk.JESApi import org.zowe.kotlinsdk.Job @@ -53,20 +40,7 @@ import retrofit2.Call import retrofit2.Response import java.lang.reflect.InvocationTargetException -class JobFetchProviderTestSpec : ShouldSpec({ - - beforeSpec { - // FIXTURE SETUP TO HAVE ACCESS TO APPLICATION INSTANCE - val factory = IdeaTestFixtureFactory.getFixtureFactory() - val projectDescriptor = LightProjectDescriptor.EMPTY_PROJECT_DESCRIPTOR - val fixtureBuilder = factory.createLightFixtureBuilder(projectDescriptor, "for-mainframe") - val fixture = fixtureBuilder.fixture - val myFixture = IdeaTestFixtureFactory.getFixtureFactory().createCodeInsightFixture( - fixture, - LightTempDirTestFixtureImpl(true) - ) - myFixture.setUp() - } +class JobFetchProviderTestSpec : WithApplicationShouldSpec({ afterSpec { clearAllMocks() diff --git a/src/test/kotlin/eu/ibagroup/formainframe/explorer/actions/EditMaskActionTestSpec.kt b/src/test/kotlin/eu/ibagroup/formainframe/explorer/actions/EditMaskActionTestSpec.kt index 269005fba..9ddc14f24 100644 --- a/src/test/kotlin/eu/ibagroup/formainframe/explorer/actions/EditMaskActionTestSpec.kt +++ b/src/test/kotlin/eu/ibagroup/formainframe/explorer/actions/EditMaskActionTestSpec.kt @@ -15,26 +15,17 @@ package eu.ibagroup.formainframe.explorer.actions import com.intellij.openapi.actionSystem.AnActionEvent +import com.intellij.openapi.application.EDT import eu.ibagroup.formainframe.config.ConfigService import eu.ibagroup.formainframe.config.connect.ConnectionConfig import eu.ibagroup.formainframe.config.connect.ConnectionConfigBase import eu.ibagroup.formainframe.config.connect.CredentialService -import eu.ibagroup.formainframe.config.ws.DSMask -import eu.ibagroup.formainframe.config.ws.FilesWorkingSetConfig -import eu.ibagroup.formainframe.config.ws.MaskState -import eu.ibagroup.formainframe.config.ws.MaskStateWithWS -import eu.ibagroup.formainframe.config.ws.UssPath +import eu.ibagroup.formainframe.config.ws.* import eu.ibagroup.formainframe.explorer.Explorer import eu.ibagroup.formainframe.explorer.ExplorerContentProvider import eu.ibagroup.formainframe.explorer.FilesWorkingSet import eu.ibagroup.formainframe.explorer.UIComponentManager -import eu.ibagroup.formainframe.explorer.ui.AddOrEditMaskDialog -import eu.ibagroup.formainframe.explorer.ui.DSMaskNode -import eu.ibagroup.formainframe.explorer.ui.ExplorerTreeNode -import eu.ibagroup.formainframe.explorer.ui.FileExplorerView -import eu.ibagroup.formainframe.explorer.ui.NodeData -import eu.ibagroup.formainframe.explorer.ui.UssDirNode -import eu.ibagroup.formainframe.explorer.ui.getExplorerView +import eu.ibagroup.formainframe.explorer.ui.* import eu.ibagroup.formainframe.testutils.WithApplicationShouldSpec import eu.ibagroup.formainframe.testutils.testServiceImpl.TestConfigServiceImpl import eu.ibagroup.formainframe.testutils.testServiceImpl.TestCredentialsServiceImpl @@ -42,12 +33,10 @@ import eu.ibagroup.formainframe.testutils.testServiceImpl.TestUIComponentManager import eu.ibagroup.formainframe.utils.MaskType import io.kotest.assertions.assertSoftly import io.kotest.matchers.shouldBe -import io.mockk.clearAllMocks -import io.mockk.every -import io.mockk.mockk -import io.mockk.mockkConstructor -import io.mockk.mockkObject -import io.mockk.unmockkAll +import io.mockk.* +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.withContext import java.util.* class EditMaskActionTestSpec : WithApplicationShouldSpec({ @@ -137,14 +126,22 @@ class EditMaskActionTestSpec : WithApplicationShouldSpec({ should("not perform edit action if explorer view is null") { every { anActionEventMock.getExplorerView() } returns null - editMaskAction.actionPerformed(anActionEventMock) + runBlocking { + withContext(Dispatchers.EDT) { + editMaskAction.actionPerformed(anActionEventMock) + } + } assertSoftly { updated shouldBe false } } should("not perform edit action if selected node is not a DS or USS mask") { every { selectedNodeMock.node } returns mockk>() - editMaskAction.actionPerformed(anActionEventMock) + runBlocking { + withContext(Dispatchers.EDT) { + editMaskAction.actionPerformed(anActionEventMock) + } + } assertSoftly { updated shouldBe false } } @@ -161,7 +158,11 @@ class EditMaskActionTestSpec : WithApplicationShouldSpec({ every { selectedNodeMock.node } returns ussDirNode - editMaskAction.actionPerformed(anActionEventMock) + runBlocking { + withContext(Dispatchers.EDT) { + editMaskAction.actionPerformed(anActionEventMock) + } + } assertSoftly { updated shouldBe false } } @@ -199,7 +200,11 @@ class EditMaskActionTestSpec : WithApplicationShouldSpec({ anyConstructed().state } returns MaskStateWithWS(MaskState("test_passed", MaskType.USS), filesWorkingSetMock) - editMaskAction.actionPerformed(anActionEventMock) + runBlocking { + withContext(Dispatchers.EDT) { + editMaskAction.actionPerformed(anActionEventMock) + } + } assertSoftly { updated shouldBe true } assertSoftly { changed shouldBe true } @@ -223,7 +228,11 @@ class EditMaskActionTestSpec : WithApplicationShouldSpec({ anyConstructed().state } returns MaskStateWithWS(MaskState("test_passed", MaskType.ZOS), filesWorkingSetMock) - editMaskAction.actionPerformed(anActionEventMock) + runBlocking { + withContext(Dispatchers.EDT) { + editMaskAction.actionPerformed(anActionEventMock) + } + } assertSoftly { updated shouldBe true } assertSoftly { changed shouldBe true } @@ -231,7 +240,11 @@ class EditMaskActionTestSpec : WithApplicationShouldSpec({ should("not perform edit on USS mask if dialog is closed") { every { anyConstructed().showAndGet() } returns false - editMaskAction.actionPerformed(anActionEventMock) + runBlocking { + withContext(Dispatchers.EDT) { + editMaskAction.actionPerformed(anActionEventMock) + } + } assertSoftly { updated shouldBe false } } @@ -240,7 +253,11 @@ class EditMaskActionTestSpec : WithApplicationShouldSpec({ configService.crudable.getByUniqueKey(filesWorkingSetConfigMock::class.java, uuid) } returns Optional.ofNullable(null) - editMaskAction.actionPerformed(anActionEventMock) + runBlocking { + withContext(Dispatchers.EDT) { + editMaskAction.actionPerformed(anActionEventMock) + } + } assertSoftly { updated shouldBe false } } @@ -249,7 +266,11 @@ class EditMaskActionTestSpec : WithApplicationShouldSpec({ var throwable: Throwable? = null runCatching { - editMaskAction.actionPerformed(anActionEventMock) + runBlocking { + withContext(Dispatchers.EDT) { + editMaskAction.actionPerformed(anActionEventMock) + } + } }.onFailure { throwable = it } @@ -266,7 +287,11 @@ class EditMaskActionTestSpec : WithApplicationShouldSpec({ var throwable: Throwable? = null runCatching { - editMaskAction.actionPerformed(anActionEventMock) + runBlocking { + withContext(Dispatchers.EDT) { + editMaskAction.actionPerformed(anActionEventMock) + } + } }.onFailure { throwable = it } @@ -318,7 +343,11 @@ class EditMaskActionTestSpec : WithApplicationShouldSpec({ anyConstructed().state } returns MaskStateWithWS(MaskState("test_passed", MaskType.ZOS), filesWorkingSetMock) - editMaskAction.actionPerformed(anActionEventMock) + runBlocking { + withContext(Dispatchers.EDT) { + editMaskAction.actionPerformed(anActionEventMock) + } + } assertSoftly { updated shouldBe true } assertSoftly { changed shouldBe true } @@ -342,7 +371,11 @@ class EditMaskActionTestSpec : WithApplicationShouldSpec({ anyConstructed().state } returns MaskStateWithWS(MaskState("test_passed", MaskType.USS), filesWorkingSetMock) - editMaskAction.actionPerformed(anActionEventMock) + runBlocking { + withContext(Dispatchers.EDT) { + editMaskAction.actionPerformed(anActionEventMock) + } + } assertSoftly { updated shouldBe true } assertSoftly { changed shouldBe true } diff --git a/src/test/kotlin/eu/ibagroup/formainframe/explorer/actions/GoToJobActionTestSpec.kt b/src/test/kotlin/eu/ibagroup/formainframe/explorer/actions/GoToJobActionTestSpec.kt index 677345d06..75458d46f 100644 --- a/src/test/kotlin/eu/ibagroup/formainframe/explorer/actions/GoToJobActionTestSpec.kt +++ b/src/test/kotlin/eu/ibagroup/formainframe/explorer/actions/GoToJobActionTestSpec.kt @@ -18,6 +18,7 @@ import com.intellij.notification.NotificationType import com.intellij.openapi.actionSystem.ActionUpdateThread import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.actionSystem.Presentation +import com.intellij.openapi.application.EDT import com.intellij.openapi.project.Project import com.intellij.openapi.project.ProjectManager import com.intellij.openapi.wm.ToolWindow @@ -35,18 +36,10 @@ import eu.ibagroup.formainframe.config.ws.ui.jes.JesWsDialog import eu.ibagroup.formainframe.dataops.log.AbstractMFLoggerBase import eu.ibagroup.formainframe.dataops.log.JobLogFetcher import eu.ibagroup.formainframe.dataops.log.JobProcessInfo -import eu.ibagroup.formainframe.explorer.Explorer -import eu.ibagroup.formainframe.explorer.ExplorerContentProvider -import eu.ibagroup.formainframe.explorer.JesExplorerContentProvider -import eu.ibagroup.formainframe.explorer.JesWorkingSetImpl -import eu.ibagroup.formainframe.explorer.UIComponentManager +import eu.ibagroup.formainframe.explorer.* import eu.ibagroup.formainframe.explorer.actions.GoToJobAction.Companion.JOB_FILTER_CREATED_TITLE import eu.ibagroup.formainframe.explorer.actions.GoToJobAction.Companion.JOB_FILTER_NOT_CREATED_TITLE -import eu.ibagroup.formainframe.explorer.ui.AddJobsFilterDialog -import eu.ibagroup.formainframe.explorer.ui.CommonExplorerTreeStructure -import eu.ibagroup.formainframe.explorer.ui.JesExplorerView -import eu.ibagroup.formainframe.explorer.ui.JesFilterNode -import eu.ibagroup.formainframe.explorer.ui.JesWsNode +import eu.ibagroup.formainframe.explorer.ui.* import eu.ibagroup.formainframe.testutils.WithApplicationShouldSpec import eu.ibagroup.formainframe.testutils.testServiceImpl.TestConfigServiceImpl import eu.ibagroup.formainframe.testutils.testServiceImpl.TestUIComponentManager @@ -54,17 +47,10 @@ import eu.ibagroup.formainframe.ui.build.jobs.JOBS_LOG_VIEW import eu.ibagroup.formainframe.ui.build.jobs.JobBuildTreeView import io.kotest.assertions.assertSoftly import io.kotest.matchers.shouldBe -import io.mockk.Runs -import io.mockk.clearAllMocks -import io.mockk.clearMocks -import io.mockk.every -import io.mockk.just -import io.mockk.mockk -import io.mockk.mockkConstructor -import io.mockk.mockkObject -import io.mockk.spyk -import io.mockk.unmockkAll -import io.mockk.verify +import io.mockk.* +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.withContext import org.zowe.kotlinsdk.Job import java.util.* import java.util.stream.Stream @@ -160,7 +146,11 @@ class GoToJobActionTestSpec : WithApplicationShouldSpec({ every { anyConstructed().showAndGet() } returns true every { myFsTreeStructureMock.findByPredicate(any()) } returns jesWsNodesTest - classUnderTest.actionPerformed(actionEventMock) + runBlocking { + withContext(Dispatchers.EDT) { + classUnderTest.actionPerformed(actionEventMock) + } + } verify { jesExplorerMock.showNotification( @@ -205,7 +195,11 @@ class GoToJobActionTestSpec : WithApplicationShouldSpec({ mockkConstructor(AddJobsFilterDialog::class) every { anyConstructed().showAndGet() } returns true - classUnderTest.actionPerformed(actionEventMock) + runBlocking { + withContext(Dispatchers.EDT) { + classUnderTest.actionPerformed(actionEventMock) + } + } verify { jesWorkingSet.addMask(jobFilterToSaveExpected) } verify { @@ -242,7 +236,11 @@ class GoToJobActionTestSpec : WithApplicationShouldSpec({ every { myFsTreeStructureMock.findByPredicate(any()) } returns jesWsNodesTest - classUnderTest.actionPerformed(actionEventMock) + runBlocking { + withContext(Dispatchers.EDT) { + classUnderTest.actionPerformed(actionEventMock) + } + } verify { jesExplorerMock.showNotification( diff --git a/src/test/kotlin/eu/ibagroup/formainframe/explorer/actions/RenameActionTestSpec.kt b/src/test/kotlin/eu/ibagroup/formainframe/explorer/actions/RenameActionTestSpec.kt index 8407b0c59..0d3e564dc 100644 --- a/src/test/kotlin/eu/ibagroup/formainframe/explorer/actions/RenameActionTestSpec.kt +++ b/src/test/kotlin/eu/ibagroup/formainframe/explorer/actions/RenameActionTestSpec.kt @@ -16,6 +16,7 @@ package eu.ibagroup.formainframe.explorer.actions import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.application.ApplicationManager +import com.intellij.openapi.application.EDT import com.intellij.openapi.progress.ProgressIndicator import com.intellij.openapi.project.Project import com.intellij.openapi.vfs.VirtualFile @@ -37,6 +38,9 @@ import eu.ibagroup.formainframe.vfs.MFVirtualFile import io.kotest.assertions.assertSoftly import io.kotest.matchers.shouldBe import io.mockk.* +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.withContext import java.util.* class RenameActionTestSpec : WithApplicationShouldSpec({ @@ -148,28 +152,44 @@ class RenameActionTestSpec : WithApplicationShouldSpec({ should("perform rename on dataset") { every { anActionEventMock.getExplorerView() } returns fileExplorerViewMock - renameAction.actionPerformed(anActionEventMock) + runBlocking { + withContext(Dispatchers.EDT) { + renameAction.actionPerformed(anActionEventMock) + } + } assertSoftly { renamed shouldBe true } } should("not perform rename on dataset if dialog is closed") { every { anyConstructed().showAndGet() } returns false - renameAction.actionPerformed(anActionEventMock) + runBlocking { + withContext(Dispatchers.EDT) { + renameAction.actionPerformed(anActionEventMock) + } + } assertSoftly { renamed shouldBe false } } should("not perform rename on dataset if virtual file is null") { every { (libraryNodeMock as ExplorerTreeNode).virtualFile } returns null - renameAction.actionPerformed(anActionEventMock) + runBlocking { + withContext(Dispatchers.EDT) { + renameAction.actionPerformed(anActionEventMock) + } + } assertSoftly { renamed shouldBe false } } should("not perform rename on dataset if virtual file is syncing now") { every { checkFileForSync(any(), any(), any()) } returns true - renameAction.actionPerformed(anActionEventMock) + runBlocking { + withContext(Dispatchers.EDT) { + renameAction.actionPerformed(anActionEventMock) + } + } assertSoftly { renamed shouldBe false } } @@ -190,14 +210,22 @@ class RenameActionTestSpec : WithApplicationShouldSpec({ } should("perform rename on dataset member") { - renameAction.actionPerformed(anActionEventMock) + runBlocking { + withContext(Dispatchers.EDT) { + renameAction.actionPerformed(anActionEventMock) + } + } assertSoftly { renamed shouldBe true } } should("not perform rename on dataset member if attributes is null") { every { selectedNodeDataMock.attributes } returns null - renameAction.actionPerformed(anActionEventMock) + runBlocking { + withContext(Dispatchers.EDT) { + renameAction.actionPerformed(anActionEventMock) + } + } assertSoftly { renamed shouldBe false } } @@ -218,28 +246,44 @@ class RenameActionTestSpec : WithApplicationShouldSpec({ } should("perform rename on USS file") { - renameAction.actionPerformed(anActionEventMock) + runBlocking { + withContext(Dispatchers.EDT) { + renameAction.actionPerformed(anActionEventMock) + } + } assertSoftly { renamed shouldBe true } } should("perform rename on USS file but don't clean cache if parent node is null") { every { ussFileNodeMock.parent } returns null - renameAction.actionPerformed(anActionEventMock) + runBlocking { + withContext(Dispatchers.EDT) { + renameAction.actionPerformed(anActionEventMock) + } + } assertSoftly { renamed shouldBe true } } should("not perform rename on USS file if dialog is closed") { every { anyConstructed().showAndGet() } returns false - renameAction.actionPerformed(anActionEventMock) + runBlocking { + withContext(Dispatchers.EDT) { + renameAction.actionPerformed(anActionEventMock) + } + } assertSoftly { renamed shouldBe false } } should("not perform rename on USS file if virtual file is null") { every { selectedNodeDataMock.file } returns null - renameAction.actionPerformed(anActionEventMock) + runBlocking { + withContext(Dispatchers.EDT) { + renameAction.actionPerformed(anActionEventMock) + } + } assertSoftly { renamed shouldBe false } } @@ -247,12 +291,20 @@ class RenameActionTestSpec : WithApplicationShouldSpec({ should("not perform rename action if explorer view is null") { every { anActionEventMock.getExplorerView() } returns null - renameAction.actionPerformed(anActionEventMock) + runBlocking { + withContext(Dispatchers.EDT) { + renameAction.actionPerformed(anActionEventMock) + } + } assertSoftly { updated shouldBe false } } should("not perform rename action if selected node is not a DS mask, dataset, dataset member, USS mask, USS directory or USS file") { - renameAction.actionPerformed(anActionEventMock) + runBlocking { + withContext(Dispatchers.EDT) { + renameAction.actionPerformed(anActionEventMock) + } + } assertSoftly { updated shouldBe false } } diff --git a/src/test/kotlin/eu/ibagroup/formainframe/explorer/ui/ChangeEncodingDialogTestSpec.kt b/src/test/kotlin/eu/ibagroup/formainframe/explorer/ui/ChangeEncodingDialogTestSpec.kt index 6d1e0f08d..cb50928b0 100644 --- a/src/test/kotlin/eu/ibagroup/formainframe/explorer/ui/ChangeEncodingDialogTestSpec.kt +++ b/src/test/kotlin/eu/ibagroup/formainframe/explorer/ui/ChangeEncodingDialogTestSpec.kt @@ -16,6 +16,7 @@ package eu.ibagroup.formainframe.explorer.ui import com.intellij.icons.AllIcons import com.intellij.ide.IdeBundle +import com.intellij.openapi.application.EDT import com.intellij.openapi.editor.Document import com.intellij.openapi.project.Project import com.intellij.openapi.project.ProjectManager @@ -39,14 +40,10 @@ import eu.ibagroup.formainframe.utils.saveIn import eu.ibagroup.formainframe.utils.updateFileTag import io.kotest.assertions.assertSoftly import io.kotest.matchers.shouldBe -import io.mockk.clearAllMocks -import io.mockk.every -import io.mockk.mockk -import io.mockk.mockkConstructor -import io.mockk.mockkObject -import io.mockk.mockkStatic -import io.mockk.spyk -import io.mockk.unmockkAll +import io.mockk.* +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.withContext import java.awt.event.ActionEvent import java.nio.charset.Charset import javax.swing.Action @@ -129,16 +126,20 @@ class ChangeEncodingDialogTestSpec : WithApplicationShouldSpec({ every { projectManagerMock.openProjects } returns arrayOf(mockk()) - changeEncodingDialog = spyk( - ChangeEncodingDialog( - projectMock, - virtualFileMock, - attributesMock, - charsetMock, - safeToReload, - safeToConvert - ) - ) + changeEncodingDialog = runBlocking { + withContext(Dispatchers.EDT) { + spyk( + ChangeEncodingDialog( + projectMock, + virtualFileMock, + attributesMock, + charsetMock, + safeToReload, + safeToConvert + ) + ) + } + } every { Messages.showDialog(any(), any(), any>(), any(), any()) @@ -165,7 +166,11 @@ class ChangeEncodingDialogTestSpec : WithApplicationShouldSpec({ // ChangeEncodingDialog.createActions should("create actions when conversion is possible") { - val actions = createActionsRef.invoke(changeEncodingDialog) as Array<*> + val actions = runBlocking { + withContext(Dispatchers.EDT) { + createActionsRef.invoke(changeEncodingDialog) as Array<*> + } + } val expectedTitle = message("encoding.reload.or.convert.dialog.title", fileName, charsetName) val expectedMessage = message("encoding.reload.or.convert.dialog.message", fileName, charsetName) @@ -177,18 +182,26 @@ class ChangeEncodingDialogTestSpec : WithApplicationShouldSpec({ should("create actions when conversion is not possible") { every { attributesMock.isWritable } returns false - changeEncodingDialog = spyk( - ChangeEncodingDialog( - projectMock, - virtualFileMock, - attributesMock, - charsetMock, - safeToReload, - safeToConvert - ) - ) + changeEncodingDialog = runBlocking { + withContext(Dispatchers.EDT) { + spyk( + ChangeEncodingDialog( + projectMock, + virtualFileMock, + attributesMock, + charsetMock, + safeToReload, + safeToConvert + ) + ) + } + } - val actions = createActionsRef.invoke(changeEncodingDialog) as Array<*> + val actions = runBlocking { + withContext(Dispatchers.EDT) { + createActionsRef.invoke(changeEncodingDialog) as Array<*> + } + } val expectedTitle = message("encoding.reload.dialog.title", fileName, charsetName) val expectedMessage = message("encoding.reload.dialog.message", fileName, charsetName) @@ -200,18 +213,26 @@ class ChangeEncodingDialogTestSpec : WithApplicationShouldSpec({ should("create actions when conversion is disabled") { every { projectManagerMock.openProjects } returns arrayOf(mockk(), mockk()) - changeEncodingDialog = spyk( - ChangeEncodingDialog( - projectMock, - virtualFileMock, - attributesMock, - charsetMock, - safeToReload, - safeToConvert - ) - ) - - val actions = createActionsRef.invoke(changeEncodingDialog).castOrNull>() + changeEncodingDialog = runBlocking { + withContext(Dispatchers.EDT) { + spyk( + ChangeEncodingDialog( + projectMock, + virtualFileMock, + attributesMock, + charsetMock, + safeToReload, + safeToConvert + ) + ) + } + } + + val actions = runBlocking { + withContext(Dispatchers.EDT) { + createActionsRef.invoke(changeEncodingDialog).castOrNull>() + } + } val actualConvertAction = actions?.get(1) val expectedTooltip = message("encoding.convert.button.error.tooltip") @@ -226,18 +247,26 @@ class ChangeEncodingDialogTestSpec : WithApplicationShouldSpec({ safeToReload = Magic8.NO_WAY safeToConvert = Magic8.NO_WAY - changeEncodingDialog = spyk( - ChangeEncodingDialog( - projectMock, - virtualFileMock, - attributesMock, - charsetMock, - safeToReload, - safeToConvert - ) - ) - - val actions = createActionsRef.invoke(changeEncodingDialog).castOrNull>() + changeEncodingDialog = runBlocking { + withContext(Dispatchers.EDT) { + spyk( + ChangeEncodingDialog( + projectMock, + virtualFileMock, + attributesMock, + charsetMock, + safeToReload, + safeToConvert + ) + ) + } + } + + val actions = runBlocking { + withContext(Dispatchers.EDT) { + createActionsRef.invoke(changeEncodingDialog).castOrNull>() + } + } val icon1 = actions?.get(0)?.getValue(Action.SMALL_ICON) val icon2 = actions?.get(1)?.getValue(Action.SMALL_ICON) @@ -251,7 +280,11 @@ class ChangeEncodingDialogTestSpec : WithApplicationShouldSpec({ mockkStatic(::reloadIn) every { reloadIn(any(), virtualFileMock, charsetMock, any()) } returns Unit - val actions = createActionsRef.invoke(changeEncodingDialog).castOrNull>() + val actions = runBlocking { + withContext(Dispatchers.EDT) { + createActionsRef.invoke(changeEncodingDialog).castOrNull>() + } + } val reloadAction = actions?.first { it.getValue(Action.NAME) == IdeBundle.message("button.reload") } reloadAction?.actionPerformed(actionEventMock) @@ -268,7 +301,11 @@ class ChangeEncodingDialogTestSpec : WithApplicationShouldSpec({ configService.isAutoSyncEnabled = false - val actions = createActionsRef.invoke(changeEncodingDialog).castOrNull>() + val actions = runBlocking { + withContext(Dispatchers.EDT) { + createActionsRef.invoke(changeEncodingDialog).castOrNull>() + } + } val reloadAction = actions?.first { it.getValue(Action.NAME) == IdeBundle.message("button.reload") } reloadAction?.actionPerformed(actionEventMock) @@ -289,7 +326,11 @@ class ChangeEncodingDialogTestSpec : WithApplicationShouldSpec({ every { ask(any()) } returns false } - val actions = createActionsRef.invoke(changeEncodingDialog).castOrNull>() + val actions = runBlocking { + withContext(Dispatchers.EDT) { + createActionsRef.invoke(changeEncodingDialog).castOrNull>() + } + } val reloadAction = actions?.first { it.getValue(Action.NAME) == IdeBundle.message("button.reload") } reloadAction?.actionPerformed(actionEventMock) @@ -302,7 +343,11 @@ class ChangeEncodingDialogTestSpec : WithApplicationShouldSpec({ mockkStatic(::reloadIn) every { reloadIn(any(), virtualFileMock, charsetMock, any()) } returns Unit - val actions = createActionsRef.invoke(changeEncodingDialog).castOrNull>() + val actions = runBlocking { + withContext(Dispatchers.EDT) { + createActionsRef.invoke(changeEncodingDialog).castOrNull>() + } + } val reloadAction = actions?.first { it.getValue(Action.NAME) == IdeBundle.message("button.reload") } reloadAction?.actionPerformed(actionEventMock) @@ -326,7 +371,11 @@ class ChangeEncodingDialogTestSpec : WithApplicationShouldSpec({ this } - val actions = createActionsRef.invoke(changeEncodingDialog).castOrNull>() + val actions = runBlocking { + withContext(Dispatchers.EDT) { + createActionsRef.invoke(changeEncodingDialog).castOrNull>() + } + } val reloadAction = actions?.first { it.getValue(Action.NAME) == IdeBundle.message("button.reload") } reloadAction?.actionPerformed(actionEventMock) @@ -335,16 +384,20 @@ class ChangeEncodingDialogTestSpec : WithApplicationShouldSpec({ should("run reload action when encoding is incompatible but user reloads anyway") { safeToReload = Magic8.NO_WAY - changeEncodingDialog = spyk( - ChangeEncodingDialog( - projectMock, - virtualFileMock, - attributesMock, - charsetMock, - safeToReload, - safeToConvert - ) - ) + changeEncodingDialog = runBlocking { + withContext(Dispatchers.EDT) { + spyk( + ChangeEncodingDialog( + projectMock, + virtualFileMock, + attributesMock, + charsetMock, + safeToReload, + safeToConvert + ) + ) + } + } every { Messages.showDialog(any(), any(), any>(), any(), any()) @@ -358,7 +411,11 @@ class ChangeEncodingDialogTestSpec : WithApplicationShouldSpec({ this } - val actions = createActionsRef.invoke(changeEncodingDialog).castOrNull>() + val actions = runBlocking { + withContext(Dispatchers.EDT) { + createActionsRef.invoke(changeEncodingDialog).castOrNull>() + } + } val reloadAction = actions?.first { it.getValue(Action.NAME) == IdeBundle.message("button.reload") } reloadAction?.actionPerformed(actionEventMock) @@ -367,23 +424,31 @@ class ChangeEncodingDialogTestSpec : WithApplicationShouldSpec({ should("not run reload action when encoding is incompatible") { safeToReload = Magic8.NO_WAY - changeEncodingDialog = spyk( - ChangeEncodingDialog( - projectMock, - virtualFileMock, - attributesMock, - charsetMock, - safeToReload, - safeToConvert - ) - ) + changeEncodingDialog = runBlocking { + withContext(Dispatchers.EDT) { + spyk( + ChangeEncodingDialog( + projectMock, + virtualFileMock, + attributesMock, + charsetMock, + safeToReload, + safeToConvert + ) + ) + } + } every { changeEncodingDialog["close"](any()) } answers { expectedExitCode = firstArg() this } - val actions = createActionsRef.invoke(changeEncodingDialog).castOrNull>() + val actions = runBlocking { + withContext(Dispatchers.EDT) { + createActionsRef.invoke(changeEncodingDialog).castOrNull>() + } + } val reloadAction = actions?.first { it.getValue(Action.NAME) == IdeBundle.message("button.reload") } reloadAction?.actionPerformed(actionEventMock) @@ -394,7 +459,11 @@ class ChangeEncodingDialogTestSpec : WithApplicationShouldSpec({ mockkStatic(::saveIn) every { saveIn(any(), virtualFileMock, charsetMock) } returns Unit - val actions = createActionsRef.invoke(changeEncodingDialog).castOrNull>() + val actions = runBlocking { + withContext(Dispatchers.EDT) { + createActionsRef.invoke(changeEncodingDialog).castOrNull>() + } + } val convertAction = actions?.first { it.getValue(Action.NAME) == IdeBundle.message("button.convert") } convertAction?.actionPerformed(actionEventMock) @@ -403,16 +472,20 @@ class ChangeEncodingDialogTestSpec : WithApplicationShouldSpec({ should("run convert action when encoding is incompatible but user converts anyway") { safeToConvert = Magic8.NO_WAY - changeEncodingDialog = spyk( - ChangeEncodingDialog( - projectMock, - virtualFileMock, - attributesMock, - charsetMock, - safeToReload, - safeToConvert - ) - ) + changeEncodingDialog = runBlocking { + withContext(Dispatchers.EDT) { + spyk( + ChangeEncodingDialog( + projectMock, + virtualFileMock, + attributesMock, + charsetMock, + safeToReload, + safeToConvert + ) + ) + } + } every { Messages.showDialog(any(), any(), any>(), any(), any()) @@ -426,7 +499,11 @@ class ChangeEncodingDialogTestSpec : WithApplicationShouldSpec({ this } - val actions = createActionsRef.invoke(changeEncodingDialog).castOrNull>() + val actions = runBlocking { + withContext(Dispatchers.EDT) { + createActionsRef.invoke(changeEncodingDialog).castOrNull>() + } + } val convertAction = actions?.first { it.getValue(Action.NAME) == IdeBundle.message("button.convert") } convertAction?.actionPerformed(actionEventMock) @@ -435,23 +512,31 @@ class ChangeEncodingDialogTestSpec : WithApplicationShouldSpec({ should("not run convert action when encoding is incompatible") { safeToConvert = Magic8.NO_WAY - changeEncodingDialog = spyk( - ChangeEncodingDialog( - projectMock, - virtualFileMock, - attributesMock, - charsetMock, - safeToReload, - safeToConvert - ) - ) + changeEncodingDialog = runBlocking { + withContext(Dispatchers.EDT) { + spyk( + ChangeEncodingDialog( + projectMock, + virtualFileMock, + attributesMock, + charsetMock, + safeToReload, + safeToConvert + ) + ) + } + } every { changeEncodingDialog["close"](any()) } answers { expectedExitCode = firstArg() this } - val actions = createActionsRef.invoke(changeEncodingDialog).castOrNull>() + val actions = runBlocking { + withContext(Dispatchers.EDT) { + createActionsRef.invoke(changeEncodingDialog).castOrNull>() + } + } val convertAction = actions?.first { it.getValue(Action.NAME) == IdeBundle.message("button.convert") } convertAction?.actionPerformed(actionEventMock) diff --git a/src/test/kotlin/eu/ibagroup/formainframe/explorer/ui/ExplorerTreeViewTestSpec.kt b/src/test/kotlin/eu/ibagroup/formainframe/explorer/ui/ExplorerTreeViewTestSpec.kt index b4906511b..0dbe8e147 100644 --- a/src/test/kotlin/eu/ibagroup/formainframe/explorer/ui/ExplorerTreeViewTestSpec.kt +++ b/src/test/kotlin/eu/ibagroup/formainframe/explorer/ui/ExplorerTreeViewTestSpec.kt @@ -54,6 +54,8 @@ class ExplorerTreeViewTestSpec : WithApplicationShouldSpec({ val contentSynchronizerMock = mockk() every { contentSynchronizerMock.markAsNotNeededForSync(any()) } returns Unit + val fileEditorManager = mockk() + beforeEach { mockkConstructor(CommonExplorerTreeStructure::class) every { anyConstructed>().rootElement } returns Unit @@ -69,17 +71,14 @@ class ExplorerTreeViewTestSpec : WithApplicationShouldSpec({ ) closedFileSize = 0 - mockkStatic(FileEditorManager::getInstance) - every { FileEditorManager.getInstance(any()) } returns object : TestFileEditorManager() { - override fun getOpenFiles(): Array { - return openFilesMock - } - - override fun closeFile(file: VirtualFile) { - closedFileSize++ - } + every { fileEditorManager.openFiles } returns openFilesMock + every { fileEditorManager.closeFile(any()) } answers { + closedFileSize++ } + mockkStatic(FileEditorManager::getInstance) + every { FileEditorManager.getInstance(any()) } returns fileEditorManager + val isAncestorRef: (VirtualFile, VirtualFile, Boolean) -> Boolean = VfsUtilCore::isAncestor mockkStatic(isAncestorRef as KFunction<*>) every { VfsUtilCore.isAncestor(any(), any(), any()) } returns true diff --git a/src/test/kotlin/eu/ibagroup/formainframe/explorer/ui/SelectTSOSessionDialogTestSpec.kt b/src/test/kotlin/eu/ibagroup/formainframe/explorer/ui/SelectTSOSessionDialogTestSpec.kt index e721d2f15..98d9b83de 100644 --- a/src/test/kotlin/eu/ibagroup/formainframe/explorer/ui/SelectTSOSessionDialogTestSpec.kt +++ b/src/test/kotlin/eu/ibagroup/formainframe/explorer/ui/SelectTSOSessionDialogTestSpec.kt @@ -1,22 +1,26 @@ package eu.ibagroup.formainframe.explorer.ui +import com.intellij.openapi.application.EDT import com.intellij.openapi.ui.ComboBox import com.intellij.openapi.ui.DialogPanel import com.intellij.openapi.ui.DialogWrapper import com.intellij.ui.CollectionComboBoxModel +import eu.ibagroup.formainframe.testutils.WithApplicationShouldSpec import eu.ibagroup.formainframe.tso.config.TSOSessionConfig import eu.ibagroup.formainframe.utils.crudable.Crudable import eu.ibagroup.formainframe.utils.initialize import eu.ibagroup.formainframe.utils.validateTsoSessionSelection import io.kotest.assertions.assertSoftly -import io.kotest.core.spec.style.ShouldSpec import io.kotest.matchers.shouldNotBe import io.mockk.* +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.withContext import java.util.stream.Stream import javax.swing.JList import javax.swing.ListCellRenderer -class SelectTSOSessionDialogTestSpec: ShouldSpec({ +class SelectTSOSessionDialogTestSpec : WithApplicationShouldSpec({ afterSpec { clearAllMocks() @@ -40,7 +44,11 @@ class SelectTSOSessionDialogTestSpec: ShouldSpec({ mockkStatic(::initialize) every { initialize(any()) } returns Unit - dialog = SelectTSOSessionDialog(mockk(), crudableMock, state) + dialog = runBlocking { + withContext(Dispatchers.EDT) { + SelectTSOSessionDialog(mockk(), crudableMock, state) + } + } mockkStatic(::validateTsoSessionSelection) every { validateTsoSessionSelection(any(), any()) } returns null @@ -52,23 +60,36 @@ class SelectTSOSessionDialogTestSpec: ShouldSpec({ // createCenterPanel should("create panel") { - val panel = createCenterPanelMethod.invoke(dialog) as? DialogPanel + val panel = runBlocking { + withContext(Dispatchers.EDT) { + createCenterPanelMethod.invoke(dialog) as? DialogPanel + } + } assertSoftly { panel shouldNotBe null } } should("validate panel") { - val panel = createCenterPanelMethod.invoke(dialog) as? DialogPanel - panel?.registerValidators { } + val panel = runBlocking { + withContext(Dispatchers.EDT) { + createCenterPanelMethod.invoke(dialog) as? DialogPanel + } + } + panel?.registerValidators { } panel?.validateAll() verify { validateTsoSessionSelection(any(), any()) } } should("render TSO sessions combobox") { - val panel = createCenterPanelMethod.invoke(dialog) as? DialogPanel + val panel = runBlocking { + withContext(Dispatchers.EDT) { + createCenterPanelMethod.invoke(dialog) as? DialogPanel + } + } val comboBox = panel?.components?.filterIsInstance>()?.firstOrNull() + @Suppress("UNCHECKED_CAST") val renderer = comboBox?.renderer as? ListCellRenderer diff --git a/src/test/kotlin/eu/ibagroup/formainframe/explorer/ui/UssFileNodeTestSpec.kt b/src/test/kotlin/eu/ibagroup/formainframe/explorer/ui/UssFileNodeTestSpec.kt index 99dfbeb8c..a2f1191d2 100644 --- a/src/test/kotlin/eu/ibagroup/formainframe/explorer/ui/UssFileNodeTestSpec.kt +++ b/src/test/kotlin/eu/ibagroup/formainframe/explorer/ui/UssFileNodeTestSpec.kt @@ -18,10 +18,7 @@ import com.intellij.ide.projectView.PresentationData import com.intellij.ide.util.treeView.AbstractTreeNode import com.intellij.ide.util.treeView.TreeAnchorizer import com.intellij.openapi.application.ApplicationManager -import com.intellij.openapi.fileEditor.FileEditor import com.intellij.openapi.fileEditor.FileEditorManager -import com.intellij.openapi.fileEditor.FileNavigator -import com.intellij.openapi.fileEditor.OpenFileDescriptor import com.intellij.openapi.project.Project import com.intellij.openapi.ui.Messages import com.intellij.openapi.ui.showYesNoDialog @@ -34,32 +31,20 @@ import eu.ibagroup.formainframe.dataops.attributes.RemoteUssAttributes import eu.ibagroup.formainframe.dataops.content.synchronizer.ContentSynchronizer import eu.ibagroup.formainframe.dataops.content.synchronizer.SyncProvider import eu.ibagroup.formainframe.dataops.content.synchronizer.checkFileForSync -import eu.ibagroup.formainframe.explorer.Explorer -import eu.ibagroup.formainframe.explorer.ExplorerContentProvider -import eu.ibagroup.formainframe.explorer.ExplorerUnit -import eu.ibagroup.formainframe.explorer.FileExplorer -import eu.ibagroup.formainframe.explorer.FileExplorerContentProvider -import eu.ibagroup.formainframe.explorer.UIComponentManager -import eu.ibagroup.formainframe.explorer.WorkingSet +import eu.ibagroup.formainframe.explorer.* import eu.ibagroup.formainframe.telemetry.NotificationsService import eu.ibagroup.formainframe.testutils.WithApplicationShouldSpec import eu.ibagroup.formainframe.testutils.testServiceImpl.TestDataOpsManagerImpl import eu.ibagroup.formainframe.testutils.testServiceImpl.TestNotificationsServiceImpl import eu.ibagroup.formainframe.testutils.testServiceImpl.TestUIComponentManager import eu.ibagroup.formainframe.utils.isBeingEditingNow +import eu.ibagroup.formainframe.utils.runInEdtAndWait import eu.ibagroup.formainframe.vfs.MFVirtualFile import eu.ibagroup.formainframe.vfs.MFVirtualFileSystem import io.kotest.assertions.assertSoftly import io.kotest.matchers.shouldBe import io.kotest.matchers.string.shouldContain -import io.mockk.Runs -import io.mockk.clearAllMocks -import io.mockk.every -import io.mockk.just -import io.mockk.mockk -import io.mockk.mockkObject -import io.mockk.mockkStatic -import io.mockk.spyk +import io.mockk.* import javax.swing.Icon import javax.swing.tree.TreePath import kotlin.reflect.KFunction @@ -154,25 +139,13 @@ class UssFileNodeTestSpec : WithApplicationShouldSpec({ } var isOnSyncSuccessTriggered = false - var isNavigatePerformed = false - mockkStatic(FileNavigator::getInstance) - every { FileNavigator.getInstance() } answers { + mockkStatic(::runInEdtAndWait) + every { runInEdtAndWait(any()) } answers { isOnSyncSuccessTriggered = true - object : FileNavigator { - override fun navigate(descriptor: OpenFileDescriptor, requestFocus: Boolean) { - isNavigatePerformed = true - return - } - - override fun navigateInEditor(descriptor: OpenFileDescriptor, requestFocus: Boolean): Boolean { - return true - } - } } ussFileNode.navigate(requestFocus) assertSoftly { isSyncWithRemotePerformed shouldBe true } - assertSoftly { isNavigatePerformed shouldBe true } assertSoftly { isOnSyncSuccessTriggered shouldBe true } } should("perform navigate on file with failure due to permission denied") { @@ -247,18 +220,9 @@ class UssFileNodeTestSpec : WithApplicationShouldSpec({ } var isNavigateContinued = false - mockkStatic(FileNavigator::getInstance) - every { FileNavigator.getInstance() } answers { - object : FileNavigator { - override fun navigate(descriptor: OpenFileDescriptor, requestFocus: Boolean) { - isNavigateContinued = true - return - } - - override fun navigateInEditor(descriptor: OpenFileDescriptor, requestFocus: Boolean): Boolean { - return true - } - } + mockkStatic(::runInEdtAndWait) + every { runInEdtAndWait(any()) } answers { + isNavigateContinued = true } ussFileNode.navigate(requestFocus) @@ -268,18 +232,9 @@ class UssFileNodeTestSpec : WithApplicationShouldSpec({ every { fileMock.isDirectory } returns true var isNavigateContinued = false - mockkStatic(FileNavigator::getInstance) - every { FileNavigator.getInstance() } answers { - object : FileNavigator { - override fun navigate(descriptor: OpenFileDescriptor, requestFocus: Boolean) { - isNavigateContinued = true - return - } - - override fun navigateInEditor(descriptor: OpenFileDescriptor, requestFocus: Boolean): Boolean { - return true - } - } + mockkStatic(::runInEdtAndWait) + every { runInEdtAndWait(any()) } answers { + isNavigateContinued = true } ussFileNode.navigate(requestFocus) @@ -333,37 +288,23 @@ class UssFileNodeTestSpec : WithApplicationShouldSpec({ } var isOnSyncSuccessTriggered = false - var isNavigatePerformed = false - mockkStatic(FileNavigator::getInstance) - every { FileNavigator.getInstance() } answers { + mockkStatic(::runInEdtAndWait) + every { runInEdtAndWait(any()) } answers { isOnSyncSuccessTriggered = true - object : FileNavigator { - override fun navigate(descriptor: OpenFileDescriptor, requestFocus: Boolean) { - isNavigatePerformed = true - return - } - - override fun navigateInEditor(descriptor: OpenFileDescriptor, requestFocus: Boolean): Boolean { - return true - } - } } - every { fileMock.isBeingEditingNow() } returns true - mockkStatic(FileEditorManager::getInstance) var isOpenFileCalled = false - every { - FileEditorManager.getInstance(any()) - } returns object : TestFileEditorManager() { - override fun openFile(file: VirtualFile, focusEditor: Boolean): Array { - isOpenFileCalled = true - return arrayOf() - } + val fileEditorManager = mockk() + every { fileEditorManager.openFile(any(), any()) } answers { + isOpenFileCalled = true + arrayOf() } + every { fileMock.isBeingEditingNow() } returns true + mockkStatic(FileEditorManager::getInstance) + every { FileEditorManager.getInstance(any()) } returns fileEditorManager ussFileNode.navigate(requestFocus) assertSoftly { isSyncWithRemotePerformed shouldBe false } - assertSoftly { isNavigatePerformed shouldBe false } assertSoftly { isOnSyncSuccessTriggered shouldBe false } assertSoftly { isOpenFileCalled shouldBe true } } @@ -371,18 +312,9 @@ class UssFileNodeTestSpec : WithApplicationShouldSpec({ every { checkFileForSync(any(), any(), any()) } returns true var isNavigateContinued = false - mockkStatic(FileNavigator::getInstance) - every { FileNavigator.getInstance() } answers { - object : FileNavigator { - override fun navigate(descriptor: OpenFileDescriptor, requestFocus: Boolean) { - isNavigateContinued = true - return - } - - override fun navigateInEditor(descriptor: OpenFileDescriptor, requestFocus: Boolean): Boolean { - return true - } - } + mockkStatic(::runInEdtAndWait) + every { runInEdtAndWait(any()) } answers { + isNavigateContinued = true } ussFileNode.navigate(requestFocus) diff --git a/src/test/kotlin/eu/ibagroup/formainframe/explorer/ui/dummyClasses.kt b/src/test/kotlin/eu/ibagroup/formainframe/explorer/ui/dummyClasses.kt deleted file mode 100644 index be39e9a21..000000000 --- a/src/test/kotlin/eu/ibagroup/formainframe/explorer/ui/dummyClasses.kt +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (c) 2020-2024 IBA Group. - * - * This program and the accompanying materials are made available under the terms of the - * Eclipse Public License v2.0 which accompanies this distribution, and is available at - * https://www.eclipse.org/legal/epl-v20.html - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * IBA Group - * Zowe Community - */ - -package eu.ibagroup.formainframe.explorer.ui - -import com.intellij.openapi.Disposable -import com.intellij.openapi.editor.Caret -import com.intellij.openapi.editor.Editor -import com.intellij.openapi.fileEditor.EditorDataProvider -import com.intellij.openapi.fileEditor.FileEditor -import com.intellij.openapi.fileEditor.FileEditorComposite -import com.intellij.openapi.fileEditor.FileEditorManager -import com.intellij.openapi.fileEditor.FileEditorNavigatable -import com.intellij.openapi.fileEditor.OpenFileDescriptor -import com.intellij.openapi.project.Project -import com.intellij.openapi.vfs.VirtualFile -import javax.swing.JComponent - -open class TestFileEditorManager : FileEditorManager() { - override fun getComposite(file: VirtualFile): FileEditorComposite? { - TODO("Not yet implemented") - } - - override fun openFile(file: VirtualFile, focusEditor: Boolean): Array { - TODO("Not yet implemented") - } - - override fun openFile(file: VirtualFile): MutableList { - TODO("Not yet implemented") - } - - override fun closeFile(file: VirtualFile) { - TODO("Not yet implemented") - } - - override fun openTextEditor(descriptor: OpenFileDescriptor, focusEditor: Boolean): Editor? { - TODO("Not yet implemented") - } - - override fun getSelectedTextEditor(): Editor? { - TODO("Not yet implemented") - } - - override fun isFileOpen(file: VirtualFile): Boolean { - TODO("Not yet implemented") - } - - override fun getOpenFiles(): Array { - TODO("Not yet implemented") - } - - override fun getOpenFilesWithRemotes(): MutableList { - TODO("Not yet implemented") - } - - override fun getSelectedFiles(): Array { - TODO("Not yet implemented") - } - - override fun getSelectedEditors(): Array { - TODO("Not yet implemented") - } - - override fun getSelectedEditor(file: VirtualFile): FileEditor? { - TODO("Not yet implemented") - } - - override fun getEditors(file: VirtualFile): Array { - TODO("Not yet implemented") - } - - override fun getAllEditors(file: VirtualFile): Array { - TODO("Not yet implemented") - } - - override fun getAllEditors(): Array { - TODO("Not yet implemented") - } - - override fun addTopComponent(editor: FileEditor, component: JComponent) { - TODO("Not yet implemented") - } - - override fun removeTopComponent(editor: FileEditor, component: JComponent) { - TODO("Not yet implemented") - } - - override fun addBottomComponent(editor: FileEditor, component: JComponent) { - TODO("Not yet implemented") - } - - override fun removeBottomComponent(editor: FileEditor, component: JComponent) { - TODO("Not yet implemented") - } - - override fun openFileEditor(descriptor: FileEditorNavigatable, focusEditor: Boolean): MutableList { - TODO("Not yet implemented") - } - - override fun getProject(): Project { - TODO("Not yet implemented") - } - - override fun registerExtraEditorDataProvider(provider: EditorDataProvider, parentDisposable: Disposable?) { - TODO("Not yet implemented") - } - - override fun getData(dataId: String, editor: Editor, caret: Caret): Any? { - TODO("Not yet implemented") - } - - override fun setSelectedEditor(file: VirtualFile, fileEditorProviderId: String) { - TODO("Not yet implemented") - } - - override fun runWhenLoaded(editor: Editor, runnable: Runnable) { - TODO("Not yet implemented") - } - -} diff --git a/src/test/kotlin/eu/ibagroup/formainframe/testutils/WithApplicationShouldSpec.kt b/src/test/kotlin/eu/ibagroup/formainframe/testutils/WithApplicationShouldSpec.kt index 9cd53e4e9..d3c153a45 100644 --- a/src/test/kotlin/eu/ibagroup/formainframe/testutils/WithApplicationShouldSpec.kt +++ b/src/test/kotlin/eu/ibagroup/formainframe/testutils/WithApplicationShouldSpec.kt @@ -15,8 +15,9 @@ package eu.ibagroup.formainframe.testutils import com.intellij.openapi.application.Application -import com.intellij.testFramework.fixtures.IdeaProjectTestFixture +import com.intellij.testFramework.fixtures.CodeInsightTestFixture import com.intellij.testFramework.fixtures.IdeaTestFixtureFactory +import com.intellij.testFramework.fixtures.impl.LightTempDirTestFixtureImpl import eu.ibagroup.formainframe.analytics.AnalyticsService import eu.ibagroup.formainframe.api.ZosmfApi import eu.ibagroup.formainframe.config.ConfigSandbox @@ -25,34 +26,31 @@ import eu.ibagroup.formainframe.config.connect.CredentialService import eu.ibagroup.formainframe.dataops.DataOpsManager import eu.ibagroup.formainframe.dataops.content.service.SyncProcessService import eu.ibagroup.formainframe.telemetry.NotificationsService -import eu.ibagroup.formainframe.testutils.testServiceImpl.TestAnalyticsServiceImpl -import eu.ibagroup.formainframe.testutils.testServiceImpl.TestConfigSandboxImpl -import eu.ibagroup.formainframe.testutils.testServiceImpl.TestConfigServiceImpl -import eu.ibagroup.formainframe.testutils.testServiceImpl.TestCredentialsServiceImpl -import eu.ibagroup.formainframe.testutils.testServiceImpl.TestDataOpsManagerImpl -import eu.ibagroup.formainframe.testutils.testServiceImpl.TestNotificationsServiceImpl -import eu.ibagroup.formainframe.testutils.testServiceImpl.TestSyncProcessServiceImpl -import eu.ibagroup.formainframe.testutils.testServiceImpl.TestZosmfApiImpl +import eu.ibagroup.formainframe.testutils.testServiceImpl.* import io.kotest.core.spec.Spec import io.kotest.core.spec.style.ShouldSpec import io.mockk.clearMocks +private var appFixture: CodeInsightTestFixture? = null + /** * [ShouldSpec] wrapper that provides implemented beforeSpec, initializing an [Application] * instance to be able to use and mock services for tests */ abstract class WithApplicationShouldSpec(body: ShouldSpec.() -> Unit = {}) : ShouldSpec() { - private lateinit var appFixture: IdeaProjectTestFixture /** * Fixture setup to have access to the [Application] instance */ override suspend fun beforeSpec(spec: Spec) { super.beforeSpec(spec) - val factory = IdeaTestFixtureFactory.getFixtureFactory() - val lightFixture = factory.createLightFixtureBuilder("for-mainframe").fixture - appFixture = factory.createCodeInsightFixture(lightFixture) - appFixture.setUp() + if (appFixture == null) { + val factory = IdeaTestFixtureFactory.getFixtureFactory() + val lightFixture = factory.createLightFixtureBuilder("for-mainframe").fixture + appFixture = factory + .createCodeInsightFixture(lightFixture, LightTempDirTestFixtureImpl(true)) + appFixture?.setUp() ?: throw Exception("Fixture setup is failed") + } (AnalyticsService.getService() as TestAnalyticsServiceImpl).testInstance = TestAnalyticsServiceImpl() (ConfigSandbox.getService() as TestConfigSandboxImpl).testInstance = TestConfigSandboxImpl() diff --git a/src/test/kotlin/eu/ibagroup/formainframe/testutils/misc.kt b/src/test/kotlin/eu/ibagroup/formainframe/testutils/misc.kt index 71690e9da..cef236a0c 100644 --- a/src/test/kotlin/eu/ibagroup/formainframe/testutils/misc.kt +++ b/src/test/kotlin/eu/ibagroup/formainframe/testutils/misc.kt @@ -23,7 +23,7 @@ import java.lang.reflect.Modifier * @param fieldName the field name to mock * @param mockValue the mock value to set for the field */ -fun setPrivateFieldValue(sourceObj: Any, classWithTheField: Class<*>, fieldName: String, mockValue: Any) { +fun setPrivateFieldValue(sourceObj: Any, classWithTheField: Class<*>, fieldName: String, mockValue: Any?) { return classWithTheField .declaredFields .filter { it.modifiers.and(Modifier.PRIVATE) > 0 || it.modifiers.and(Modifier.PROTECTED) > 0 } diff --git a/src/test/kotlin/eu/ibagroup/formainframe/tso/config/TSOSessionConfigTestSpec.kt b/src/test/kotlin/eu/ibagroup/formainframe/tso/config/TSOSessionConfigTestSpec.kt index 573b3d916..96b81d5fb 100644 --- a/src/test/kotlin/eu/ibagroup/formainframe/tso/config/TSOSessionConfigTestSpec.kt +++ b/src/test/kotlin/eu/ibagroup/formainframe/tso/config/TSOSessionConfigTestSpec.kt @@ -14,6 +14,7 @@ package eu.ibagroup.formainframe.tso.config +import com.intellij.openapi.application.EDT import com.intellij.openapi.ui.DialogPanel import com.intellij.openapi.ui.DialogWrapper import com.intellij.openapi.ui.ValidationInfo @@ -31,27 +32,16 @@ import eu.ibagroup.formainframe.tso.config.ui.TSOSessionConfigurable import eu.ibagroup.formainframe.tso.config.ui.TSOSessionDialog import eu.ibagroup.formainframe.tso.config.ui.TSOSessionDialogState import eu.ibagroup.formainframe.tso.config.ui.table.TSOSessionTableModel +import eu.ibagroup.formainframe.utils.* import eu.ibagroup.formainframe.utils.crudable.Crudable import eu.ibagroup.formainframe.utils.crudable.MergedCollections -import eu.ibagroup.formainframe.utils.initialize -import eu.ibagroup.formainframe.utils.sendTopic -import eu.ibagroup.formainframe.utils.validateConnectionSelection -import eu.ibagroup.formainframe.utils.validateForBlank -import eu.ibagroup.formainframe.utils.validateForPositiveInteger -import eu.ibagroup.formainframe.utils.validateForPositiveLong -import eu.ibagroup.formainframe.utils.validateTsoSessionName import io.kotest.assertions.assertSoftly import io.kotest.matchers.shouldBe import io.kotest.matchers.shouldNotBe -import io.mockk.clearAllMocks -import io.mockk.clearMocks -import io.mockk.every -import io.mockk.mockk -import io.mockk.mockkConstructor -import io.mockk.mockkStatic -import io.mockk.spyk -import io.mockk.unmockkAll -import io.mockk.verify +import io.mockk.* +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.withContext import org.zowe.kotlinsdk.TsoCodePage import java.awt.event.MouseAdapter import java.awt.event.MouseEvent @@ -245,7 +235,11 @@ class TSOSessionConfigTestSpec : WithApplicationShouldSpec({ } // addSession should("add session when 'Ok' button is pressed") { - addSessionMethod.invoke(configurable) + runBlocking { + withContext(Dispatchers.EDT) { + addSessionMethod.invoke(configurable) + } + } assertSoftly { rowAdded shouldBe true @@ -254,7 +248,11 @@ class TSOSessionConfigTestSpec : WithApplicationShouldSpec({ should("do not add session when 'Cancel' button is pressed") { every { anyConstructed().showAndGet() } returns false - addSessionMethod.invoke(configurable) + runBlocking { + withContext(Dispatchers.EDT) { + addSessionMethod.invoke(configurable) + } + } assertSoftly { rowAdded shouldBe false @@ -262,7 +260,11 @@ class TSOSessionConfigTestSpec : WithApplicationShouldSpec({ } // editSession should("edit session when 'Ok' button is pressed") { - editSessionMethod.invoke(configurable) + runBlocking { + withContext(Dispatchers.EDT) { + editSessionMethod.invoke(configurable) + } + } assertSoftly { rowEdited shouldBe true @@ -271,7 +273,11 @@ class TSOSessionConfigTestSpec : WithApplicationShouldSpec({ should("do not edit session when 'Cancel' button is pressed") { every { anyConstructed().showAndGet() } returns false - editSessionMethod.invoke(configurable) + runBlocking { + withContext(Dispatchers.EDT) { + editSessionMethod.invoke(configurable) + } + } assertSoftly { rowEdited shouldBe false @@ -281,7 +287,11 @@ class TSOSessionConfigTestSpec : WithApplicationShouldSpec({ every { tableMock.selectedObject } returns null tableField.set(configurable, tableMock) - editSessionMethod.invoke(configurable) + runBlocking { + withContext(Dispatchers.EDT) { + editSessionMethod.invoke(configurable) + } + } assertSoftly { rowEdited shouldBe false @@ -335,21 +345,6 @@ class TSOSessionConfigTestSpec : WithApplicationShouldSpec({ tableModelReinitialized shouldBe false } } - should("catch reload call and do not reinitialize because table model is null") { - tableModelField.set(configurable, null) - var exceptionCaught = false - - try { - sendTopic(SandboxListener.TOPIC).reload(TSOSessionConfig::class.java) - } catch (e: Exception) { - exceptionCaught = true - } - - assertSoftly { - exceptionCaught shouldBe true - tableModelReinitialized shouldBe false - } - } } context("table/TSOSessionTableModel") { @@ -500,7 +495,11 @@ class TSOSessionConfigTestSpec : WithApplicationShouldSpec({ mockkStatic(::initialize) every { initialize(any()) } returns Unit - dialog = TSOSessionDialog(crudableMock, TSOSessionDialogState()) + dialog = runBlocking { + withContext(Dispatchers.EDT) { + TSOSessionDialog(crudableMock, TSOSessionDialogState()) + } + } mockkStatic("eu.ibagroup.formainframe.utils.ValidationFunctionsKt") every { validateForBlank(any()) } returns null @@ -567,7 +566,11 @@ class TSOSessionConfigTestSpec : WithApplicationShouldSpec({ } should("validate panel if session name is not empty") { val state = TSOSessionDialogState(name = "sessionName") - dialog = TSOSessionDialog(crudableMock, state) + dialog = runBlocking { + withContext(Dispatchers.EDT) { + TSOSessionDialog(crudableMock, state) + } + } val result = doValidateMethod.invoke(dialog) @@ -581,7 +584,11 @@ class TSOSessionConfigTestSpec : WithApplicationShouldSpec({ val defaultLogonProc = "DBSPROCC" val state = TSOSessionDialogState(name = expectedSessionName, logonProcedure = "logonProc") - dialog = TSOSessionDialog(crudableMock, state) + dialog = runBlocking { + withContext(Dispatchers.EDT) { + TSOSessionDialog(crudableMock, state) + } + } createCenterPanelMethod.invoke(dialog) resetToDefaultMethod.invoke(dialog) @@ -611,7 +618,11 @@ class TSOSessionConfigTestSpec : WithApplicationShouldSpec({ mockkStatic(::panel) every { panel(any()) } returns mainPanel - dialog = TSOSessionDialog(crudableMock, TSOSessionDialogState()) + dialog = runBlocking { + withContext(Dispatchers.EDT) { + TSOSessionDialog(crudableMock, TSOSessionDialogState()) + } + } createCenterPanelMethod.invoke(dialog) diff --git a/src/test/kotlin/eu/ibagroup/formainframe/utils/EncodingUtilsTestSpec.kt b/src/test/kotlin/eu/ibagroup/formainframe/utils/EncodingUtilsTestSpec.kt index 9e0fabae8..cff4d06d5 100644 --- a/src/test/kotlin/eu/ibagroup/formainframe/utils/EncodingUtilsTestSpec.kt +++ b/src/test/kotlin/eu/ibagroup/formainframe/utils/EncodingUtilsTestSpec.kt @@ -20,6 +20,7 @@ import com.intellij.codeInspection.InspectionManager import com.intellij.codeInspection.ProblemDescriptor import com.intellij.codeInspection.ex.InspectionProfileImpl import com.intellij.codeInspection.ex.InspectionToolWrapper +import com.intellij.openapi.application.EDT import com.intellij.openapi.editor.Document import com.intellij.openapi.fileEditor.FileDocumentManager import com.intellij.openapi.project.Project @@ -39,12 +40,10 @@ import eu.ibagroup.formainframe.testutils.WithApplicationShouldSpec import eu.ibagroup.formainframe.testutils.testServiceImpl.TestDataOpsManagerImpl import io.kotest.assertions.assertSoftly import io.kotest.matchers.shouldBe -import io.mockk.every -import io.mockk.mockk -import io.mockk.mockkConstructor -import io.mockk.mockkObject -import io.mockk.mockkStatic -import io.mockk.unmockkAll +import io.mockk.* +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.withContext import java.nio.ByteBuffer import java.nio.CharBuffer import java.nio.charset.Charset @@ -289,7 +288,11 @@ class EncodingUtilsTestSpec : WithApplicationShouldSpec({ every { anyConstructed().exitCode } returns ChangeEncodingDialog.RELOAD_EXIT_CODE - val actual = changeFileEncodingAction(projectMock, virtualFileMock, attributesMock, charsetMock) + val actual = runBlocking { + withContext(Dispatchers.EDT) { + changeFileEncodingAction(projectMock, virtualFileMock, attributesMock, charsetMock) + } + } assertSoftly { actual shouldBe true } } @@ -299,7 +302,11 @@ class EncodingUtilsTestSpec : WithApplicationShouldSpec({ every { anyConstructed().exitCode } returns ChangeEncodingDialog.CONVERT_EXIT_CODE - val actual = changeFileEncodingAction(projectMock, virtualFileMock, attributesMock, charsetMock) + val actual = runBlocking { + withContext(Dispatchers.EDT) { + changeFileEncodingAction(projectMock, virtualFileMock, attributesMock, charsetMock) + } + } assertSoftly { actual shouldBe true } } @@ -309,7 +316,11 @@ class EncodingUtilsTestSpec : WithApplicationShouldSpec({ every { anyConstructed().exitCode } returns 1 - val actual = changeFileEncodingAction(projectMock, virtualFileMock, attributesMock, charsetMock) + val actual = runBlocking { + withContext(Dispatchers.EDT) { + changeFileEncodingAction(projectMock, virtualFileMock, attributesMock, charsetMock) + } + } assertSoftly { actual shouldBe false } }