From 9f58a5027c8188e12422c4e1815d6aa8754fda81 Mon Sep 17 00:00:00 2001 From: Uladzislau Date: Wed, 13 Mar 2024 18:34:03 +0100 Subject: [PATCH 1/5] Dependencies versions bump Signed-off-by: Uladzislau --- build.gradle.kts | 51 +++++++++++++++++++++++------------------------- 1 file changed, 24 insertions(+), 27 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 12b107baf..bf7449002 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -13,7 +13,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { id("org.jetbrains.intellij") version "1.14.2" - kotlin("jvm") version "1.8.10" + kotlin("jvm") version "1.8.20" java id("org.jetbrains.kotlinx.kover") version "0.6.1" } @@ -23,9 +23,9 @@ apply(plugin = "org.jetbrains.intellij") group = "eu.ibagroup" version = "1.2.0-221" -val remoteRobotVersion = "0.11.21" +val remoteRobotVersion = "0.11.22" val okHttp3Version = "4.12.0" -val kotestVersion = "5.6.2" +val kotestVersion = "5.8.1" repositories { mavenCentral() @@ -55,23 +55,22 @@ dependencies { implementation("com.squareup.retrofit2:converter-gson:2.9.0") implementation("com.squareup.retrofit2:converter-scalars:2.9.0") implementation("com.squareup.okhttp3:okhttp:$okHttp3Version") - implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.6.20") - implementation("org.jetbrains.kotlin:kotlin-reflect:1.6.20") - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4") - implementation("org.jgrapht:jgrapht-core:1.5.1") + implementation("org.jetbrains.kotlin:kotlin-reflect:1.8.20") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0") + implementation("org.jgrapht:jgrapht-core:1.5.2") implementation("org.zowe.sdk:zowe-kotlin-sdk:0.4.0") - implementation("com.segment.analytics.java:analytics:3.3.1") + implementation("com.segment.analytics.java:analytics:3.5.0") implementation("com.ibm.mq:com.ibm.mq.allclient:9.3.4.1") - testImplementation("io.mockk:mockk:1.13.5") - testImplementation("org.junit.jupiter:junit-jupiter-api:5.9.2") + testImplementation("io.mockk:mockk:1.13.9") + testImplementation("org.junit.jupiter:junit-jupiter-api:5.10.1") testImplementation("io.kotest:kotest-assertions-core:$kotestVersion") testImplementation("io.kotest:kotest-runner-junit5:$kotestVersion") testImplementation("com.intellij.remoterobot:remote-robot:$remoteRobotVersion") testImplementation("com.intellij.remoterobot:remote-fixtures:$remoteRobotVersion") testImplementation("com.squareup.okhttp3:mockwebserver:$okHttp3Version") testImplementation("com.squareup.okhttp3:okhttp-tls:$okHttp3Version") - testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.9.2") - testRuntimeOnly("org.junit.vintage:junit-vintage-engine:5.9.2") + testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.10.1") + testRuntimeOnly("org.junit.vintage:junit-vintage-engine:5.10.1") } intellij { @@ -86,6 +85,10 @@ tasks { } } + withType { + duplicatesStrategy = DuplicatesStrategy.EXCLUDE + } + patchPluginXml { sinceBuild.set("221.5080") untilBuild.set("222.*") @@ -155,6 +158,15 @@ tasks { dependsOn(createOpenApiSourceJar) from(createOpenApiSourceJar) { into("lib/src") } } + + downloadRobotServerPlugin { + version.set(remoteRobotVersion) + } + + runIdeForUiTests { + systemProperty("idea.trust.all.projects", "true") + systemProperty("ide.show.tips.on.startup.default.value", "false") + } } /** @@ -244,18 +256,3 @@ val SmokeUiTest = task("smokeUiTest") { isDisabled.set(true) } } - -tasks { - withType { - duplicatesStrategy = DuplicatesStrategy.EXCLUDE - } -} - -tasks.downloadRobotServerPlugin { - version.set(remoteRobotVersion) -} - -tasks.runIdeForUiTests { - systemProperty("idea.trust.all.projects", "true") - systemProperty("ide.show.tips.on.startup.default.value", "false") -} From aa41f3e1e443d392d8664aea62ce780d833b877b Mon Sep 17 00:00:00 2001 From: Uladzislau Date: Wed, 13 Mar 2024 19:10:18 +0100 Subject: [PATCH 2/5] Removed as much unnecessary dependencies as possible, another versions upgrade Signed-off-by: Uladzislau --- build.gradle.kts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index bf7449002..346896049 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -12,8 +12,8 @@ import kotlinx.kover.api.KoverTaskExtension import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { - id("org.jetbrains.intellij") version "1.14.2" - kotlin("jvm") version "1.8.20" + id("org.jetbrains.intellij") version "1.17.2" + kotlin("jvm") version "1.9.22" java id("org.jetbrains.kotlinx.kover") version "0.6.1" } @@ -55,8 +55,6 @@ dependencies { implementation("com.squareup.retrofit2:converter-gson:2.9.0") implementation("com.squareup.retrofit2:converter-scalars:2.9.0") implementation("com.squareup.okhttp3:okhttp:$okHttp3Version") - implementation("org.jetbrains.kotlin:kotlin-reflect:1.8.20") - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0") implementation("org.jgrapht:jgrapht-core:1.5.2") implementation("org.zowe.sdk:zowe-kotlin-sdk:0.4.0") implementation("com.segment.analytics.java:analytics:3.5.0") From 52661c0b143464a53aed3147c5ca88042d5d1c1d Mon Sep 17 00:00:00 2001 From: Uladzislau Date: Wed, 13 Mar 2024 20:17:14 +0100 Subject: [PATCH 3/5] CHANGELOG.md updates Signed-off-by: Uladzislau --- CHANGELOG.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f58394010..70785043c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,28 @@ All notable changes to the Zowe IntelliJ Plugin will be documented in this file. +## `1.2.0 (2024-xx-yy)` + +* Feature: TSO CLI PA1 button functionality added ([48834cac](https://github.com/zowe/zowe-explorer-intellij/commit/48834cac)) +* Feature: Allocation units clarification added ([1ff218e4](https://github.com/zowe/zowe-explorer-intellij/commit/1ff218e4)) +* Feature: Now after allocating a dataset, a notification is shown instead of a dialog window ([20343651](https://github.com/zowe/zowe-explorer-intellij/commit/20343651)) +* Feature: VFS_CHANGES topic rework for encoding purposes ([3adaded3](https://github.com/zowe/zowe-explorer-intellij/commit/3adaded3)) +* Feature: Close all files in editor, related to the file/folder/dataset/member being deleted ([8a0d9980](https://github.com/zowe/zowe-explorer-intellij/commit/8a0d9980)) + + +* Bugfix: GitHub issue #159: Zowe config detection doesn't work correctly ([c73226f6](https://github.com/zowe/zowe-explorer-intellij/commit/c73226f6)) +* Bugfix: Warning during working set creation without masks/job filters is missing ([4fd0b22c](https://github.com/zowe/zowe-explorer-intellij/commit/4fd0b22c)) +* Bugfix: When opened file tabs bar is full, opening any dataset or USS file preserves only last 2 items Explorer items in the bar ([3a822fbb](https://github.com/zowe/zowe-explorer-intellij/commit/3a822fbb)) +* Bugfix: Unclear error message for list datasets/jobs when password is expired ([74fe5e86](https://github.com/zowe/zowe-explorer-intellij/commit/74fe5e86)) +* Bugfix: In dataset allocation dialog window, dataset name is reset when an error is received ([218f5a3a](https://github.com/zowe/zowe-explorer-intellij/commit/218f5a3a)) +* Bugfix: Issue creating member with the same name as the existing one ([6ebae1a0](https://github.com/zowe/zowe-explorer-intellij/commit/6ebae1a0)) +* Bugfix: "Overwrite for All" causes caches conflicts when dataset member is being copied to a USS with rewrite ([90b9ce17](https://github.com/zowe/zowe-explorer-intellij/commit/90b9ce17)) +* Bugfix: "Cut/Paste" doesn't work when moving a sequential dataset to a partitioned dataset ([f1cf4a9d](https://github.com/zowe/zowe-explorer-intellij/commit/f1cf4a9d)) +* Bugfix: Incorrect warning message when uploading a local file to a PDS ([6d9e5de3](https://github.com/zowe/zowe-explorer-intellij/commit/6d9e5de3)) +* Bugfix: It is possible to create a dataset when a connection is removed or invalid ([3df02fde](https://github.com/zowe/zowe-explorer-intellij/commit/3df02fde)) +* Bugfix: TSO EXEC command without operands causes the CLI to hang ([d071960a](https://github.com/zowe/zowe-explorer-intellij/commit/d071960a)) +* Bugfix: Connection is not fully reset to the last successful state and it causes errors ([f6d5a72e](https://github.com/zowe/zowe-explorer-intellij/commit/f6d5a72e)) + ## `1.1.2 (2024-01-22)` * Bugfix: Sync action does not work after file download ([bfb125d7](https://github.com/zowe/zowe-explorer-intellij/commit/bfb125d7)) From a49093187d264dc7465416afb0e2a1fc5f8e79b1 Mon Sep 17 00:00:00 2001 From: Arseni Tsikhamirau Date: Thu, 14 Mar 2024 19:02:53 +0100 Subject: [PATCH 4/5] IJMP-1556-Fix-Unit-tests-in-release-branch --- .../explorer/ui/ExplorerPasteProviderTestSpec.kt | 10 +++------- .../formainframe/explorer/ui/UssFileNodeTestSpec.kt | 2 -- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/test/kotlin/eu/ibagroup/formainframe/explorer/ui/ExplorerPasteProviderTestSpec.kt b/src/test/kotlin/eu/ibagroup/formainframe/explorer/ui/ExplorerPasteProviderTestSpec.kt index 369d8124e..4c9fb9698 100644 --- a/src/test/kotlin/eu/ibagroup/formainframe/explorer/ui/ExplorerPasteProviderTestSpec.kt +++ b/src/test/kotlin/eu/ibagroup/formainframe/explorer/ui/ExplorerPasteProviderTestSpec.kt @@ -13,7 +13,7 @@ package eu.ibagroup.formainframe.explorer.ui import com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode import com.intellij.openapi.actionSystem.CommonDataKeys import com.intellij.openapi.actionSystem.DataContext -import com.intellij.openapi.application.ApplicationManager +import com.intellij.openapi.components.service import com.intellij.openapi.progress.ProgressIndicator import com.intellij.openapi.project.Project import com.intellij.openapi.ui.DialogWrapper @@ -40,7 +40,6 @@ import eu.ibagroup.formainframe.explorer.FilesWorkingSet import eu.ibagroup.formainframe.testutils.WithApplicationShouldSpec import eu.ibagroup.formainframe.testutils.testServiceImpl.TestDataOpsManagerImpl import eu.ibagroup.formainframe.utils.castOrNull -import eu.ibagroup.formainframe.utils.service import eu.ibagroup.formainframe.vfs.MFVirtualFile import io.kotest.assertions.assertSoftly import io.kotest.matchers.shouldBe @@ -76,9 +75,7 @@ class ExplorerPasteProviderTestSpec : WithApplicationShouldSpec({ ExplorerPasteProvider(), recordPrivateCalls = true ) - var dataOpsManagerService = - ApplicationManager.getApplication().service() as TestDataOpsManagerImpl - every { mockedFileExplorer.componentManager } returns ApplicationManager.getApplication() + var dataOpsManagerService = service() as TestDataOpsManagerImpl dataOpsManagerService.testInstance = object : TestDataOpsManagerImpl(mockedFileExplorer.componentManager) { override fun tryToGetAttributes(file: VirtualFile): FileAttributes { return mockk() @@ -1000,8 +997,7 @@ class ExplorerPasteProviderTestSpec : WithApplicationShouldSpec({ true } - dataOpsManagerService = ApplicationManager.getApplication().service() as TestDataOpsManagerImpl - every { mockedFileExplorer.componentManager } returns ApplicationManager.getApplication() + dataOpsManagerService = service() as TestDataOpsManagerImpl dataOpsManagerService.testInstance = object : TestDataOpsManagerImpl(mockedFileExplorer.componentManager) { override fun performOperation(operation: Operation, progressIndicator: ProgressIndicator): R { throw IllegalStateException("Test Error") 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 eb364abf1..47da622fe 100644 --- a/src/test/kotlin/eu/ibagroup/formainframe/explorer/ui/UssFileNodeTestSpec.kt +++ b/src/test/kotlin/eu/ibagroup/formainframe/explorer/ui/UssFileNodeTestSpec.kt @@ -401,7 +401,6 @@ class UssFileNodeTestSpec : WithApplicationShouldSpec({ context("ExplorerTreeNode.updateNodeTitleUsingCutBuffer") { every { virtualFileMock.presentableName } returns "test" every { virtualFileMock.isValid } returns false - every { explorer.nullableProject } returns mockedProject should("perform an update of the node if virtual file in the cut buffer and navigate is true") { every { explorerContentProviderMock.isFileInCutBuffer(virtualFileMock) } returns true @@ -455,7 +454,6 @@ class UssFileNodeTestSpec : WithApplicationShouldSpec({ updatePerformed = true true } - every { explorerToTest.nullableProject } returns mockedProject every { ussFileMockToSpyTest.virtualFile } returns virtualFileMock every { ussFileMockToSpyTest.value } returns virtualFileMock ussFileMockToSpyTest.update() From 60c14575a15aab4d983824f32b14957d7aba6fe7 Mon Sep 17 00:00:00 2001 From: Dzianis Lisiankou Date: Fri, 15 Mar 2024 11:10:09 +0100 Subject: [PATCH 5/5] IJMP-1537: move tasks from 2.0.0 to 1.2.0 --- .../common/SettingsPropertyManager.kt | 31 ++ .../dataops/operations/TsoOperationRunner.kt | 57 ++- .../explorer/actions/AllocateActionBase.kt | 69 ++-- .../explorer/ui/AllocationDialog.kt | 5 + .../ui/build/TerminalCommandReceiver.kt | 37 +- .../ui/build/tso/TSOWindowFactory.kt | 2 +- .../ui/build/tso/ui/TSOConsoleView.kt | 55 ++- .../resources/messages/FMBundle.properties | 4 +- src/main/resources/settings.properties | 1 + .../formainframe/common/CommonTestSpec.kt | 52 ++- .../formainframe/editor/EditorTestSpec.kt | 19 +- .../actions/AllocateDatasetActionTestSpec.kt | 336 ++++-------------- .../actions/AllocateLikeActionTestSpec.kt | 204 +++-------- .../ui/ChangeEncodingDialogTestSpec.kt | 7 +- .../utils/EncodingUtilsTestSpec.kt | 7 +- 15 files changed, 398 insertions(+), 488 deletions(-) create mode 100644 src/main/kotlin/eu/ibagroup/formainframe/common/SettingsPropertyManager.kt create mode 100644 src/main/resources/settings.properties diff --git a/src/main/kotlin/eu/ibagroup/formainframe/common/SettingsPropertyManager.kt b/src/main/kotlin/eu/ibagroup/formainframe/common/SettingsPropertyManager.kt new file mode 100644 index 000000000..9aced3e81 --- /dev/null +++ b/src/main/kotlin/eu/ibagroup/formainframe/common/SettingsPropertyManager.kt @@ -0,0 +1,31 @@ +/* + * 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 + * + * Copyright IBA Group 2020 + */ + +package eu.ibagroup.formainframe.common + +import java.util.* + +class SettingsPropertyManager + +/** + * Properties from the settings.properties file + */ +internal val settingsProperties by lazy { + Properties().apply { + load(SettingsPropertyManager::class.java.classLoader.getResourceAsStream("settings.properties")) + } +} + +/** + * Check if the debug mode is enabled + */ +fun isDebugModeEnabled(): Boolean { + return settingsProperties.getProperty("debug.mode")?.toBoolean() ?: false +} \ No newline at end of file diff --git a/src/main/kotlin/eu/ibagroup/formainframe/dataops/operations/TsoOperationRunner.kt b/src/main/kotlin/eu/ibagroup/formainframe/dataops/operations/TsoOperationRunner.kt index 8c5c64edd..b6a7d8803 100644 --- a/src/main/kotlin/eu/ibagroup/formainframe/dataops/operations/TsoOperationRunner.kt +++ b/src/main/kotlin/eu/ibagroup/formainframe/dataops/operations/TsoOperationRunner.kt @@ -19,14 +19,13 @@ import eu.ibagroup.formainframe.ui.build.tso.config.TSOConfigWrapper import eu.ibagroup.formainframe.ui.build.tso.ui.TSOSessionParams import eu.ibagroup.formainframe.utils.cancelByIndicator import eu.ibagroup.formainframe.utils.log +import eu.ibagroup.formainframe.dataops.operations.MessageType as MessageTypeEnum import org.zowe.kotlinsdk.MessageType import org.zowe.kotlinsdk.TsoApi import org.zowe.kotlinsdk.TsoData import org.zowe.kotlinsdk.TsoResponse import io.ktor.util.* import retrofit2.Response -import java.nio.charset.Charset -import java.util.* /** * Factory class which represents a TSO operation runner. Defined in plugin.xml @@ -85,12 +84,7 @@ class TsoOperationRunner : OperationRunner { response = api(state.getConnectionConfig()) .sendMessageToTso( state.getConnectionConfig().authToken, - body = TsoData( - tsoResponse = MessageType( - version = "0100", - data = operation.message - ) - ), + body = createTsoData(operation), servletKey = servletKey ) .cancelByIndicator(progressIndicator) @@ -140,4 +134,51 @@ class TsoOperationRunner : OperationRunner { return response?.body() ?: throw Exception("Cannot retrieve response from server.") } + /** + * Create TsoData object depending on the specified message type + * @throws Exception if message type not specified + */ + private fun createTsoData(operation: TsoOperation): TsoData { + return when (operation.messageType) { + MessageTypeEnum.TSO_MESSAGE -> TsoData( + tsoMessage = createMessageType(operation) + ) + + MessageTypeEnum.TSO_PROMPT -> TsoData( + tsoPrompt = createMessageType(operation) + ) + + MessageTypeEnum.TSO_RESPONSE -> TsoData( + tsoResponse = createMessageType(operation) + ) + + null -> throw Exception("Message type not specified") + } + } + + /** + * Create MessageType object depending on the specified message data + * @throws Exception if message data not specified + */ + private fun createMessageType(operation: TsoOperation): MessageType { + return when (operation.messageData) { + MessageData.DATA_DATA -> MessageType( + version = "0100", + data = operation.message + ) + + MessageData.DATA_HIDDEN -> MessageType( + version = "0100", + hidden = operation.message + ) + + MessageData.DATA_ACTION -> MessageType( + version = "0100", + action = operation.message + ) + + null -> throw Exception("Message data not specified") + } + } + } diff --git a/src/main/kotlin/eu/ibagroup/formainframe/explorer/actions/AllocateActionBase.kt b/src/main/kotlin/eu/ibagroup/formainframe/explorer/actions/AllocateActionBase.kt index 79fd503c7..5697ecf3c 100644 --- a/src/main/kotlin/eu/ibagroup/formainframe/explorer/actions/AllocateActionBase.kt +++ b/src/main/kotlin/eu/ibagroup/formainframe/explorer/actions/AllocateActionBase.kt @@ -10,12 +10,14 @@ package eu.ibagroup.formainframe.explorer.actions +import com.intellij.notification.Notification +import com.intellij.notification.NotificationAction +import com.intellij.notification.NotificationType +import com.intellij.notification.Notifications import com.intellij.openapi.actionSystem.AnAction import com.intellij.openapi.actionSystem.AnActionEvent -import com.intellij.openapi.application.runInEdt import com.intellij.openapi.components.service import com.intellij.openapi.progress.runModalTask -import com.intellij.openapi.ui.showOkNoDialog import eu.ibagroup.formainframe.analytics.AnalyticsService import eu.ibagroup.formainframe.analytics.events.FileAction import eu.ibagroup.formainframe.analytics.events.FileEvent @@ -28,6 +30,7 @@ import eu.ibagroup.formainframe.config.ws.FilesWorkingSetConfig import eu.ibagroup.formainframe.dataops.DataOpsManager import eu.ibagroup.formainframe.dataops.operations.DatasetAllocationOperation import eu.ibagroup.formainframe.dataops.operations.DatasetAllocationParams +import eu.ibagroup.formainframe.explorer.ExplorerUnit import eu.ibagroup.formainframe.explorer.FilesWorkingSet import eu.ibagroup.formainframe.explorer.ui.AllocationDialog import eu.ibagroup.formainframe.explorer.ui.DSMaskNode @@ -44,6 +47,8 @@ import org.zowe.kotlinsdk.Dataset import org.zowe.kotlinsdk.DatasetOrganization import org.zowe.kotlinsdk.DsnameType +const val ALLOCATE_ACTION_NOTIFICATION_GROUP_ID = "eu.ibagroup.formainframe.explorer.AllocateActionNotificationGroup" + abstract class AllocateActionBase : AnAction() { /** @@ -140,34 +145,10 @@ abstract class AllocateActionBase : AnAction() { } val nodeToClean = parentProbablyDSMaskNode?.castOrNull>() nodeToClean?.let { cleanInvalidateOnExpand(nodeToClean, view) } - - var nodeCleaned = false - runInEdt { - if ( - showOkNoDialog( - title = "Dataset ${state.datasetName} Has Been Created", - message = "Would you like to add mask \"${state.datasetName}\" to ${workingSet.name}", - project = e.project, - okText = "Yes", - noText = "No" - ) - ) { - val filesWorkingSetConfig = - configCrudable.getByUniqueKey(workingSet.uuid)?.clone() - if (filesWorkingSetConfig != null) { - nodeToClean?.cleanCache(recursively = false, cleanBatchedQuery = true, sendTopic = false) - nodeCleaned = true - - filesWorkingSetConfig.dsMasks.add(DSMask().apply { mask = state.datasetName }) - configCrudable.update(filesWorkingSetConfig) - } - } - - if (!nodeCleaned) { - nodeToClean?.cleanCache(recursively = false, cleanBatchedQuery = true) - } - } + nodeToClean?.cleanCache(recursively = false, cleanBatchedQuery = true) initialState.errorMessage = "" + + showNotification(state, workingSet) } .onFailure { t -> explorer.reportThrowable(t, e.project) @@ -187,4 +168,34 @@ abstract class AllocateActionBase : AnAction() { override fun isDumbAware(): Boolean { return true } + + /** + * Shows a notification about successful allocation and suggest adding a mask to the working set + */ + private fun showNotification( + state: DatasetAllocationParams, + workingSet: ExplorerUnit<*> + ) { + val notification = Notification( + ALLOCATE_ACTION_NOTIFICATION_GROUP_ID, + "Dataset ${state.datasetName} has been created", + "Would you like to add mask \"${state.datasetName}\" to ${workingSet.name}?", + NotificationType.INFORMATION + ) + notification.addActions( + setOf( + NotificationAction.createSimpleExpiring("Add mask") { + val filesWorkingSetConfig = + configCrudable.getByUniqueKey(workingSet.uuid)?.clone() + if (filesWorkingSetConfig != null) { + filesWorkingSetConfig.dsMasks.add(DSMask().apply { mask = state.datasetName }) + configCrudable.update(filesWorkingSetConfig) + } + }, + NotificationAction.createSimpleExpiring("Skip") { } + ) + ) + notification.setSuggestionType(true) + Notifications.Bus.notify(notification) + } } diff --git a/src/main/kotlin/eu/ibagroup/formainframe/explorer/ui/AllocationDialog.kt b/src/main/kotlin/eu/ibagroup/formainframe/explorer/ui/AllocationDialog.kt index 48d428048..052d3e028 100644 --- a/src/main/kotlin/eu/ibagroup/formainframe/explorer/ui/AllocationDialog.kt +++ b/src/main/kotlin/eu/ibagroup/formainframe/explorer/ui/AllocationDialog.kt @@ -22,6 +22,7 @@ import com.intellij.ui.dsl.builder.panel import com.intellij.ui.dsl.builder.toNullableProperty import com.intellij.ui.dsl.gridLayout.HorizontalAlign import com.intellij.ui.layout.selectedValueMatches +import eu.ibagroup.formainframe.common.message import eu.ibagroup.formainframe.common.ui.StatefulDialog import eu.ibagroup.formainframe.config.connect.ConnectionConfig import eu.ibagroup.formainframe.config.connect.getUsername @@ -133,6 +134,10 @@ class AllocationDialog(project: Project?, config: ConnectionConfig, override var .bindItem(state.allocationParameters::allocationUnit.toNullableProperty()) .also { spaceUnitBox = it.component } .widthGroup(sameWidthComboBoxGroup) + contextHelp( + description = message("allocation.dialog.unit.size.hint.description"), + title = message("allocation.dialog.unit.size.hint.title") + ) } row { label("Primary allocation: ") diff --git a/src/main/kotlin/eu/ibagroup/formainframe/ui/build/TerminalCommandReceiver.kt b/src/main/kotlin/eu/ibagroup/formainframe/ui/build/TerminalCommandReceiver.kt index 3d44aea58..de07b5b9d 100644 --- a/src/main/kotlin/eu/ibagroup/formainframe/ui/build/TerminalCommandReceiver.kt +++ b/src/main/kotlin/eu/ibagroup/formainframe/ui/build/TerminalCommandReceiver.kt @@ -13,6 +13,7 @@ package eu.ibagroup.formainframe.ui.build import com.intellij.execution.process.NopProcessHandler import com.intellij.execution.process.ProcessHandler import com.intellij.execution.process.ProcessOutputType +import com.intellij.openapi.util.Key import com.intellij.terminal.TerminalExecutionConsole import com.jediterm.terminal.TerminalKeyEncoder import eu.ibagroup.formainframe.ui.build.tso.utils.InputRecognizer @@ -33,6 +34,7 @@ class TerminalCommandReceiver(terminalConsole: TerminalExecutionConsole) { private var needToWaitForCommandInput = false private var commandsInQueue: Queue = LinkedList() private var expectParameters = false + private var prevCommandEndsWithReady = false var initialized = false private var onCommandEntered: (String) -> Unit = {} @@ -146,15 +148,34 @@ class TerminalCommandReceiver(terminalConsole: TerminalExecutionConsole) { override fun getProcessInput(): OutputStream { return this@TerminalCommandReceiver.processInput } + + /** + * Override notifyTextAvailable() method to check what the command ends with + */ + override fun notifyTextAvailable(text: String, outputType: Key<*>) { + if (text != "\n" && text.endsWith("\n")) { + prevCommandEndsWithReady = isTextEndsWithReady(text) + } + super.notifyTextAvailable(text, outputType) + } } terminalConsole.withConvertLfToCrlfForNonPtyProcess(true) terminalConsole.attachToProcess(processHandler) } + /** + * Check if the text ends with "READY" - successful completion of TSO command + */ + private fun isTextEndsWithReady(text: String): Boolean { + val successfulEnding = "READY" + val trimmedText = text.trimEnd() + return trimmedText.endsWith(successfulEnding, true) + } + /** * Called when command is submitted. Clean up the entered command for follow up user input */ - private fun cleanCommand() { + fun cleanCommand() { this.typedCommand = "" this.textAfterCursor = "" this.cursorPosition = 0 @@ -193,6 +214,20 @@ class TerminalCommandReceiver(terminalConsole: TerminalExecutionConsole) { } } + /** + * Return true if console is waiting for command input or else otherwise + */ + fun isNeedToWaitForCommandInput(): Boolean { + return needToWaitForCommandInput + } + + /** + * Return true if previous command ends with "READY" or else otherwise + */ + fun isPrevCommandEndsWithReady(): Boolean { + return prevCommandEndsWithReady + } + /** * Called when user finished typing the command and pressed Enter */ diff --git a/src/main/kotlin/eu/ibagroup/formainframe/ui/build/tso/TSOWindowFactory.kt b/src/main/kotlin/eu/ibagroup/formainframe/ui/build/tso/TSOWindowFactory.kt index d7d07aea6..18aa36a9b 100644 --- a/src/main/kotlin/eu/ibagroup/formainframe/ui/build/tso/TSOWindowFactory.kt +++ b/src/main/kotlin/eu/ibagroup/formainframe/ui/build/tso/TSOWindowFactory.kt @@ -350,7 +350,7 @@ class TSOWindowFactory : ToolWindowFactory { try { sendTopic(SESSION_RECONNECT_TOPIC, project).reconnect(project, console, session) processHandler.notifyTextAvailable( - "Successfully reconnected to the TSO session.\n", + "Successfully reconnected to the TSO session.\nREADY\n", ProcessOutputType.STDOUT ) } catch (e: Exception) { diff --git a/src/main/kotlin/eu/ibagroup/formainframe/ui/build/tso/ui/TSOConsoleView.kt b/src/main/kotlin/eu/ibagroup/formainframe/ui/build/tso/ui/TSOConsoleView.kt index 8a6818105..3bbdd5b79 100644 --- a/src/main/kotlin/eu/ibagroup/formainframe/ui/build/tso/ui/TSOConsoleView.kt +++ b/src/main/kotlin/eu/ibagroup/formainframe/ui/build/tso/ui/TSOConsoleView.kt @@ -11,15 +11,21 @@ package eu.ibagroup.formainframe.ui.build.tso.ui //import com.intellij.ui.layout.cellPanel +import com.intellij.execution.process.ProcessEvent import com.intellij.execution.process.ProcessHandler +import com.intellij.execution.process.ProcessListener import com.intellij.execution.ui.ExecutionConsole import com.intellij.openapi.project.Project +import com.intellij.openapi.ui.ComboBox import com.intellij.openapi.util.Disposer +import com.intellij.openapi.util.Key import com.intellij.terminal.TerminalExecutionConsole import com.intellij.ui.CollectionComboBoxModel import com.intellij.ui.SimpleListCellRenderer import com.intellij.ui.components.JBPanel import com.intellij.ui.dsl.builder.panel +import com.intellij.util.ui.JBEmptyBorder +import eu.ibagroup.formainframe.common.isDebugModeEnabled import eu.ibagroup.formainframe.dataops.operations.MessageData import eu.ibagroup.formainframe.dataops.operations.MessageType import eu.ibagroup.formainframe.ui.build.TerminalCommandReceiver @@ -29,7 +35,7 @@ import eu.ibagroup.formainframe.ui.build.tso.utils.InputRecognizer import eu.ibagroup.formainframe.utils.log import eu.ibagroup.formainframe.utils.sendTopic import java.awt.BorderLayout -import javax.swing.JComboBox +import javax.swing.JButton import javax.swing.JComponent /** @@ -42,12 +48,13 @@ class TSOConsoleView( private var tsoSession: TSOConfigWrapper ) : ExecutionConsole, JBPanel() { - private lateinit var tsoMessageType: JComboBox - private lateinit var tsoDataType: JComboBox + private lateinit var tsoMessageTypeBox: ComboBox + private lateinit var tsoDataTypeBox: ComboBox + private lateinit var cancelCommandButton: JButton private val tsoWidthGroup: String = "TSO_WIDTH_GROUP" private val tsoMessageTypes: List = - listOf(MessageType.TSO_MESSAGE, MessageType.TSO_PROMPT, MessageType.TSO_RESPONSE) + listOf(MessageType.TSO_RESPONSE, MessageType.TSO_MESSAGE, MessageType.TSO_PROMPT) private val tsoDataTypes: List = listOf(MessageData.DATA_DATA, MessageData.DATA_HIDDEN, MessageData.DATA_ACTION) @@ -61,6 +68,8 @@ class TSOConsoleView( private val log = log() + private val debugMode = isDebugModeEnabled() + /** * UI panel which contains 2 combo boxes of TSO message type and message data type */ @@ -73,18 +82,35 @@ class TSOConsoleView( model = tsoMessageTypeComboBoxModel, renderer = SimpleListCellRenderer.create("") { it.type } ).also { - tsoMessageType = it.component + tsoMessageTypeBox = it.component } - } + }.visible(debugMode) row { label("TSO data type").widthGroup(tsoWidthGroup) comboBox( model = tsoDataTypeComboBoxModel, renderer = SimpleListCellRenderer.create("") { it.data } ).also { - tsoDataType = it.component + tsoDataTypeBox = it.component + } + }.visible(debugMode) + row { + button("Cancel Command (PA1)") { + log.info("CANCEL COMMAND (PA1)") + val prevTsoMessageType = tsoMessageTypeBox.item + val prevTsoDataType = tsoDataTypeBox.item + tsoMessageTypeBox.item = MessageType.TSO_RESPONSE + tsoDataTypeBox.item = MessageData.DATA_ACTION + terminalCommandReceiver.cleanCommand() + processHandler.processInput?.write(("\r").toByteArray()) + tsoMessageTypeBox.item = prevTsoMessageType + tsoDataTypeBox.item = prevTsoDataType + }.also { + cancelCommandButton = it.component } } + }.also { + it.border = JBEmptyBorder(10, 15, 10, 15) } } @@ -102,8 +128,8 @@ class TSOConsoleView( this, tsoSession, enteredCommand.trim(), - tsoMessageType.selectedItem as MessageType, - tsoDataType.selectedItem as MessageData, + tsoMessageTypeBox.item, + tsoDataTypeBox.item, processHandler ) terminalCommandReceiver.waitForCommandInput() @@ -111,6 +137,17 @@ class TSOConsoleView( terminalCommandReceiver.initialized = true + processHandler.addProcessListener(object : ProcessListener { + override fun startNotified(event: ProcessEvent) {} + + override fun processTerminated(event: ProcessEvent) {} + + override fun onTextAvailable(event: ProcessEvent, outputType: Key<*>) { + cancelCommandButton.isEnabled = + !terminalCommandReceiver.isPrevCommandEndsWithReady() && terminalCommandReceiver.isNeedToWaitForCommandInput() + } + }) + Disposer.register(this, consoleView) layout = BorderLayout() add(this.component, BorderLayout.WEST) diff --git a/src/main/resources/messages/FMBundle.properties b/src/main/resources/messages/FMBundle.properties index 521c2c349..85709ae3e 100755 --- a/src/main/resources/messages/FMBundle.properties +++ b/src/main/resources/messages/FMBundle.properties @@ -25,4 +25,6 @@ encoding.reload.or.convert.dialog.title={0}: Reload or Convert to {1} encoding.reload.or.convert.dialog.message=The encoding you'''ve chosen ('{1}') may change the contents of '{0}'.
Do you want to
1. Reload the file from remote in the new encoding '{1}' and overwrite contents (may not display correctly) or
2. Convert the text and overwrite file in the new encoding?
encoding.reload.dialog.title={0}: Reload to {1} encoding.reload.dialog.message=The encoding you'''ve chosen ('{1}') may change the contents of '{0}'.
Do you want to Reload the file from remote in the new encoding '{1}' and overwrite contents (may not display correctly).
-encoding.convert.button.error.tooltip=Encoding conversion is not available because more than one project is open \ No newline at end of file +encoding.convert.button.error.tooltip=Encoding conversion is not available because more than one project is open +allocation.dialog.unit.size.hint.description=For IBM 3390 direct access storage device:
1 CYLINDER = 15 TRACKS
1 TRACK = 56664 BYTES +allocation.dialog.unit.size.hint.title=Allocation unit Size \ No newline at end of file diff --git a/src/main/resources/settings.properties b/src/main/resources/settings.properties new file mode 100644 index 000000000..ccee7c8ba --- /dev/null +++ b/src/main/resources/settings.properties @@ -0,0 +1 @@ +debug.mode=false \ No newline at end of file diff --git a/src/test/kotlin/eu/ibagroup/formainframe/common/CommonTestSpec.kt b/src/test/kotlin/eu/ibagroup/formainframe/common/CommonTestSpec.kt index 07b14dc46..5985c97ec 100644 --- a/src/test/kotlin/eu/ibagroup/formainframe/common/CommonTestSpec.kt +++ b/src/test/kotlin/eu/ibagroup/formainframe/common/CommonTestSpec.kt @@ -10,9 +10,16 @@ package eu.ibagroup.formainframe.common -import io.kotest.core.spec.style.ShouldSpec +import eu.ibagroup.formainframe.testutils.WithApplicationShouldSpec +import io.kotest.assertions.assertSoftly +import io.kotest.matchers.shouldBe +import io.mockk.* +import java.util.Properties -class CommonTestSpec : ShouldSpec({ +class CommonTestSpec : WithApplicationShouldSpec({ + afterSpec { + clearAllMocks() + } context("common module: ui") { // ValidatingCellRenderer.getTableCellRendererComponent should("get table cell renderer") {} @@ -26,4 +33,45 @@ class CommonTestSpec : ShouldSpec({ // StatefulDialog.showUntilDone should("show dialog until it is fulfilled") {} } + context("common module: SettingsPropertyManager") { + val propertyName = "debug.mode" + + mockkConstructor(Properties::class) + + // isDebugModeEnabled + should("debug mode enabled") { + every { anyConstructed().getProperty(propertyName) } returns "true" + val debugMode = isDebugModeEnabled() + + assertSoftly { + debugMode shouldBe true + } + } + should("debug mode disabled") { + every { anyConstructed().getProperty(propertyName) } returns "false" + val debugMode = isDebugModeEnabled() + + assertSoftly { + debugMode shouldBe false + } + } + should("debug mode property not found") { + every { anyConstructed().getProperty(propertyName) } returns null + val debugMode = isDebugModeEnabled() + + assertSoftly { + debugMode shouldBe false + } + } + should("debug mode property contains a non-boolean value") { + every { anyConstructed().getProperty(propertyName) } returns "123" + val debugMode = isDebugModeEnabled() + + assertSoftly { + debugMode shouldBe false + } + } + + unmockkAll() + } }) diff --git a/src/test/kotlin/eu/ibagroup/formainframe/editor/EditorTestSpec.kt b/src/test/kotlin/eu/ibagroup/formainframe/editor/EditorTestSpec.kt index ea57efb22..e149e5120 100644 --- a/src/test/kotlin/eu/ibagroup/formainframe/editor/EditorTestSpec.kt +++ b/src/test/kotlin/eu/ibagroup/formainframe/editor/EditorTestSpec.kt @@ -75,7 +75,6 @@ import java.nio.charset.CoderResult import javax.swing.JComponent import javax.swing.SwingUtilities import kotlin.reflect.KFunction -import kotlin.reflect.full.declaredFunctions class EditorTestSpec : WithApplicationShouldSpec({ afterSpec { @@ -300,10 +299,8 @@ class EditorTestSpec : WithApplicationShouldSpec({ val decoderResultMock = mockk() every { decoderResultMock.length() } returns 1 - val getLastItemRef = ContainerUtil::class.declaredFunctions - .filter { it.name == "getLastItem" } - .first { it.parameters.size == 2 } - mockkStatic(getLastItemRef) + val getLastItemRef: (MutableList) -> Any = ContainerUtil::getLastItem + mockkStatic(getLastItemRef as KFunction<*>) every { ContainerUtil.getLastItem(any>()) } answers { val descriptors = firstArg>() if (descriptors.isNotEmpty()) descriptors.last() else null @@ -502,10 +499,8 @@ class EditorTestSpec : WithApplicationShouldSpec({ decoderResultMock } - val commonPrefixLengthRef = StringUtil::class.declaredFunctions - .filter { it.name == "commonPrefixLength" } - .first { it.parameters.size == 2 } - mockkStatic(commonPrefixLengthRef) + val commonPrefixLengthRef: (CharSequence, CharSequence) -> Int = StringUtil::commonPrefixLength + mockkStatic(commonPrefixLengthRef as KFunction<*>) every { StringUtil.commonPrefixLength(any(), any()) } returns text.length val descriptors = lossyEncodingInspection.checkFile(psiFileMock, inspectionManagerMock, isOnTheFly) @@ -621,10 +616,8 @@ class EditorTestSpec : WithApplicationShouldSpec({ decoderResultMock } - val commonPrefixLengthRef = StringUtil::class.declaredFunctions - .filter { it.name == "commonPrefixLength" } - .first { it.parameters.size == 2 } - mockkStatic(commonPrefixLengthRef) + val commonPrefixLengthRef: (CharSequence, CharSequence) -> Int = StringUtil::commonPrefixLength + mockkStatic(commonPrefixLengthRef as KFunction<*>) every { StringUtil.commonPrefixLength(any(), any()) } returns text.length - 1 val descriptors = lossyEncodingInspection.checkFile(psiFileMock, inspectionManagerMock, isOnTheFly) diff --git a/src/test/kotlin/eu/ibagroup/formainframe/explorer/actions/AllocateDatasetActionTestSpec.kt b/src/test/kotlin/eu/ibagroup/formainframe/explorer/actions/AllocateDatasetActionTestSpec.kt index 061d4a19b..0504a7335 100644 --- a/src/test/kotlin/eu/ibagroup/formainframe/explorer/actions/AllocateDatasetActionTestSpec.kt +++ b/src/test/kotlin/eu/ibagroup/formainframe/explorer/actions/AllocateDatasetActionTestSpec.kt @@ -10,13 +10,15 @@ package eu.ibagroup.formainframe.explorer.actions +import com.intellij.notification.Notification +import com.intellij.notification.Notifications +import com.intellij.openapi.actionSystem.AnAction import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.actionSystem.Presentation import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.components.ComponentManager import com.intellij.openapi.progress.ProgressIndicator import com.intellij.openapi.project.Project -import com.intellij.openapi.ui.showOkNoDialog import eu.ibagroup.formainframe.analytics.AnalyticsService import eu.ibagroup.formainframe.analytics.events.AnalyticsEvent import eu.ibagroup.formainframe.common.ui.StatefulDialog @@ -44,12 +46,10 @@ import io.mockk.mockk import io.mockk.mockkObject import io.mockk.mockkStatic import io.mockk.unmockkAll -import org.junit.jupiter.api.fail import org.zowe.kotlinsdk.DatasetOrganization import org.zowe.kotlinsdk.DsnameType import java.util.* import javax.swing.Icon -import javax.swing.SwingUtilities import kotlin.reflect.KFunction class AllocateDatasetActionTestSpec : WithApplicationShouldSpec({ @@ -69,6 +69,7 @@ class AllocateDatasetActionTestSpec : WithApplicationShouldSpec({ val dataOpsManagerMock = mockk() val componentManagerMock = mockk() val explorerMock = mockk>() + lateinit var addMaskActionInst: AnAction val analyticsService = ApplicationManager.getApplication().service() as TestAnalyticsServiceImpl @@ -109,6 +110,15 @@ class AllocateDatasetActionTestSpec : WithApplicationShouldSpec({ } answers { isCleanInvalidateOnExpandTriggered = true } + + val notifyRef: (Notification) -> Unit = Notifications.Bus::notify + mockkStatic(notifyRef as KFunction<*>) + mockkStatic(Notification::get) + every { Notifications.Bus.notify(any()) } answers { + val notification = firstArg() + every { Notification.get(any()) } returns notification + addMaskActionInst = notification.actions.first { it.templateText == "Add mask" } + } } afterEach { @@ -124,7 +134,6 @@ class AllocateDatasetActionTestSpec : WithApplicationShouldSpec({ val dsMaskNodeMock = mockk() lateinit var initState: DatasetAllocationParams var isOperationPerformed = false - var isCleanCacheTriggered = false var isUpdateOnConfigCrudableCalled = false var isShowUntilDoneSucceeded = false @@ -153,15 +162,7 @@ class AllocateDatasetActionTestSpec : WithApplicationShouldSpec({ configCrudable.getByUniqueKey(any(), any()) } returns Optional.of(filesWorkingSetConfigMock) - every { - dsMaskNodeMock.cleanCache(any(), any(), any(), any()) - } answers { - isCleanCacheTriggered = true - val isSendTopic = lastArg() - if (isSendTopic) { - fail("cleanCache should not send topic in this testcase") - } - } + every { dsMaskNodeMock.cleanCache(any(), any(), any(), any()) } returns Unit every { nodeMock.parent } returns dsMaskNodeMock every { nodeMock.hint(FilesWorkingSet::class).unit } returns workingSetMock every { viewMock.mySelectedNodesData } returns selectedNodesData @@ -180,34 +181,17 @@ class AllocateDatasetActionTestSpec : WithApplicationShouldSpec({ Optional.of(mockk()) } - val showOkNoDialogMock: ( - String, - String, - Project?, - String, - String, - Icon? - ) -> Boolean = ::showOkNoDialog - mockkStatic(showOkNoDialogMock as KFunction<*>) - every { - hint(Boolean::class) - showOkNoDialogMock(any(), any(), any(), any(), any(), any()) - } answers { - true - } - allocateDsActionInst.actionPerformed(anActionEventMock) + addMaskActionInst.actionPerformed(anActionEventMock) - // Pause to wait until all EDT events are finished - SwingUtilities.invokeAndWait { - assertSoftly { isCleanInvalidateOnExpandTriggered shouldBe true } - assertSoftly { isShowUntilDoneSucceeded shouldBe true } - assertSoftly { isAnalitycsTracked shouldBe true } - assertSoftly { isOperationPerformed shouldBe true } - assertSoftly { isCleanCacheTriggered shouldBe true } - assertSoftly { isUpdateOnConfigCrudableCalled shouldBe true } - assertSoftly { isThrowableReported shouldBe false } - assertSoftly { initState.errorMessage shouldBe "" } + assertSoftly { + isCleanInvalidateOnExpandTriggered shouldBe true + isShowUntilDoneSucceeded shouldBe true + isAnalitycsTracked shouldBe true + isOperationPerformed shouldBe true + isUpdateOnConfigCrudableCalled shouldBe true + isThrowableReported shouldBe false + initState.errorMessage shouldBe "" } } should("perform allocate PS dataset action creating a new dataset mask") { @@ -218,7 +202,6 @@ class AllocateDatasetActionTestSpec : WithApplicationShouldSpec({ val dsMaskNodeMock = mockk() lateinit var initState: DatasetAllocationParams var isOperationPerformed = false - var isCleanCacheTriggered = false var isUpdateOnConfigCrudableCalled = false var isShowUntilDoneSucceeded = false @@ -254,15 +237,7 @@ class AllocateDatasetActionTestSpec : WithApplicationShouldSpec({ configCrudable.getByUniqueKey(any(), any()) } returns Optional.of(filesWorkingSetConfigMock) - every { - dsMaskNodeMock.cleanCache(any(), any(), any(), any()) - } answers { - isCleanCacheTriggered = true - val isSendTopic = lastArg() - if (isSendTopic) { - fail("cleanCache should not send topic in this testcase") - } - } + every { dsMaskNodeMock.cleanCache(any(), any(), any(), any()) } returns Unit every { nodeMock.parent } returns dsMaskNodeMock every { nodeMock.hint(FilesWorkingSet::class).unit } returns workingSetMock every { viewMock.mySelectedNodesData } returns selectedNodesData @@ -281,35 +256,18 @@ class AllocateDatasetActionTestSpec : WithApplicationShouldSpec({ Optional.of(mockk()) } - val showOkNoDialogMock: ( - String, - String, - Project?, - String, - String, - Icon? - ) -> Boolean = ::showOkNoDialog - mockkStatic(showOkNoDialogMock as KFunction<*>) - every { - hint(Boolean::class) - showOkNoDialogMock(any(), any(), any(), any(), any(), any()) - } answers { - true - } - allocateDsActionInst.actionPerformed(anActionEventMock) + addMaskActionInst.actionPerformed(anActionEventMock) - // Pause to wait until all EDT events are finished - SwingUtilities.invokeAndWait { - assertSoftly { isCleanInvalidateOnExpandTriggered shouldBe true } - assertSoftly { isShowUntilDoneSucceeded shouldBe true } - assertSoftly { isAnalitycsTracked shouldBe true } - assertSoftly { isOperationPerformed shouldBe true } - assertSoftly { isCleanCacheTriggered shouldBe true } - assertSoftly { isUpdateOnConfigCrudableCalled shouldBe true } - assertSoftly { isThrowableReported shouldBe false } - assertSoftly { initState.errorMessage shouldBe "" } - assertSoftly { initState.allocationParameters.directoryBlocks shouldBe null } + assertSoftly { + isCleanInvalidateOnExpandTriggered shouldBe true + isShowUntilDoneSucceeded shouldBe true + isAnalitycsTracked shouldBe true + isOperationPerformed shouldBe true + isUpdateOnConfigCrudableCalled shouldBe true + isThrowableReported shouldBe false + initState.errorMessage shouldBe "" + initState.allocationParameters.directoryBlocks shouldBe null } } should("perform allocate PO-E dataset action creating a new dataset mask") { @@ -320,7 +278,6 @@ class AllocateDatasetActionTestSpec : WithApplicationShouldSpec({ val dsMaskNodeMock = mockk() lateinit var initState: DatasetAllocationParams var isOperationPerformed = false - var isCleanCacheTriggered = false var isUpdateOnConfigCrudableCalled = false var isShowUntilDoneSucceeded = false @@ -353,15 +310,7 @@ class AllocateDatasetActionTestSpec : WithApplicationShouldSpec({ configCrudable.getByUniqueKey(any(), any()) } returns Optional.of(filesWorkingSetConfigMock) - every { - dsMaskNodeMock.cleanCache(any(), any(), any(), any()) - } answers { - isCleanCacheTriggered = true - val isSendTopic = lastArg() - if (isSendTopic) { - fail("cleanCache should not send topic in this testcase") - } - } + every { dsMaskNodeMock.cleanCache(any(), any(), any(), any()) } returns Unit every { nodeMock.parent } returns dsMaskNodeMock every { nodeMock.hint(FilesWorkingSet::class).unit } returns workingSetMock every { viewMock.mySelectedNodesData } returns selectedNodesData @@ -380,36 +329,19 @@ class AllocateDatasetActionTestSpec : WithApplicationShouldSpec({ Optional.of(mockk()) } - val showOkNoDialogMock: ( - String, - String, - Project?, - String, - String, - Icon? - ) -> Boolean = ::showOkNoDialog - mockkStatic(showOkNoDialogMock as KFunction<*>) - every { - hint(Boolean::class) - showOkNoDialogMock(any(), any(), any(), any(), any(), any()) - } answers { - true - } - allocateDsActionInst.actionPerformed(anActionEventMock) + addMaskActionInst.actionPerformed(anActionEventMock) - // Pause to wait until all EDT events are finished - SwingUtilities.invokeAndWait { - assertSoftly { isCleanInvalidateOnExpandTriggered shouldBe true } - assertSoftly { isShowUntilDoneSucceeded shouldBe true } - assertSoftly { isAnalitycsTracked shouldBe true } - assertSoftly { isOperationPerformed shouldBe true } - assertSoftly { isCleanCacheTriggered shouldBe true } - assertSoftly { isUpdateOnConfigCrudableCalled shouldBe true } - assertSoftly { isThrowableReported shouldBe false } - assertSoftly { initState.errorMessage shouldBe "" } - assertSoftly { initState.allocationParameters.datasetOrganization shouldBe DatasetOrganization.PO } - assertSoftly { initState.allocationParameters.dsnType shouldBe DsnameType.LIBRARY } + assertSoftly { + isCleanInvalidateOnExpandTriggered shouldBe true + isShowUntilDoneSucceeded shouldBe true + isAnalitycsTracked shouldBe true + isOperationPerformed shouldBe true + isUpdateOnConfigCrudableCalled shouldBe true + isThrowableReported shouldBe false + initState.errorMessage shouldBe "" + initState.allocationParameters.datasetOrganization shouldBe DatasetOrganization.PO + initState.allocationParameters.dsnType shouldBe DsnameType.LIBRARY } } should("perform allocate dataset action without creating a new dataset mask") { @@ -420,7 +352,6 @@ class AllocateDatasetActionTestSpec : WithApplicationShouldSpec({ val dsMaskNodeMock = mockk() lateinit var initState: DatasetAllocationParams var isOperationPerformed = false - var isCleanCacheTriggered = false var isUpdateOnConfigCrudableCalled = false var isShowUntilDoneSucceeded = false @@ -449,15 +380,7 @@ class AllocateDatasetActionTestSpec : WithApplicationShouldSpec({ configCrudable.getByUniqueKey(any(), any()) } returns Optional.of(filesWorkingSetConfigMock) - every { - dsMaskNodeMock.cleanCache(any(), any(), any(), any()) - } answers { - isCleanCacheTriggered = true - val isSendTopic = lastArg() - if (!isSendTopic) { - fail("cleanCache should send topic in this testcase") - } - } + every { dsMaskNodeMock.cleanCache(any(), any(), any(), any()) } returns Unit every { nodeMock.parent } returns dsMaskNodeMock every { nodeMock.hint(FilesWorkingSet::class).unit } returns workingSetMock every { viewMock.mySelectedNodesData } returns selectedNodesData @@ -476,119 +399,19 @@ class AllocateDatasetActionTestSpec : WithApplicationShouldSpec({ Optional.of(mockk()) } - val showOkNoDialogMock: ( - String, - String, - Project?, - String, - String, - Icon? - ) -> Boolean = ::showOkNoDialog - mockkStatic(showOkNoDialogMock as KFunction<*>) - every { - hint(Boolean::class) - showOkNoDialogMock(any(), any(), any(), any(), any(), any()) - } answers { - false - } - allocateDsActionInst.actionPerformed(anActionEventMock) - // Pause to wait until all EDT events are finished - SwingUtilities.invokeAndWait { - assertSoftly { isCleanInvalidateOnExpandTriggered shouldBe true } - assertSoftly { isShowUntilDoneSucceeded shouldBe true } - assertSoftly { isAnalitycsTracked shouldBe true } - assertSoftly { isOperationPerformed shouldBe true } - assertSoftly { isCleanCacheTriggered shouldBe true } - assertSoftly { isUpdateOnConfigCrudableCalled shouldBe false } - assertSoftly { isThrowableReported shouldBe false } - assertSoftly { initState.errorMessage shouldBe "" } - } - } - should("perform allocate dataset action without refreshing dataset mask as the selected node is a working set") { - val workingSetMock = mockk() - val nodeMock = mockk() - val nodeDataMock = NodeData(nodeMock, null, null) - val selectedNodesData = listOf(nodeDataMock) - lateinit var initState: DatasetAllocationParams - var isOperationPerformed = false - var isUpdateOnConfigCrudableCalled = false - var isShowUntilDoneSucceeded = false - - val showUntilDoneMockk: ( - DatasetAllocationParams, - (DatasetAllocationParams) -> StatefulDialog, - (DatasetAllocationParams) -> Boolean - ) -> DatasetAllocationParams? = ::showUntilDone - mockkStatic(showUntilDoneMockk as KFunction<*>) - every { - hint(DatasetAllocationParams::class) - showUntilDoneMockk( - any(), - any<(DatasetAllocationParams) -> StatefulDialog>(), - any<(DatasetAllocationParams) -> Boolean>() - ) - } answers { - initState = firstArg() - val thirdBlockResult = thirdArg<(DatasetAllocationParams) -> Boolean>() - isShowUntilDoneSucceeded = thirdBlockResult(initState) - initState - } - - mockkObject(configCrudable) - every { - configCrudable.getByUniqueKey(any(), any()) - } returns Optional.of(filesWorkingSetConfigMock) - - every { nodeMock.parent } returns null - every { nodeMock.hint(FilesWorkingSet::class).unit } returns workingSetMock - every { viewMock.mySelectedNodesData } returns selectedNodesData - every { workingSetMock.name } returns "test" - every { workingSetMock.uuid } returns "test" - every { workingSetMock.hint(ConnectionConfig::class).connectionConfig } returns mockk() - every { - dataOpsManagerMock.hint(Boolean::class).performOperation(any>(), any()) - } answers { - isOperationPerformed = true - true - } - every { workingSetMock.explorer } returns explorerMock - every { configCrudable.update(any(), any()) } answers { - isUpdateOnConfigCrudableCalled = true - Optional.of(mockk()) - } - - val showOkNoDialogMock: ( - String, - String, - Project?, - String, - String, - Icon? - ) -> Boolean = ::showOkNoDialog - mockkStatic(showOkNoDialogMock as KFunction<*>) - every { - hint(Boolean::class) - showOkNoDialogMock(any(), any(), any(), any(), any(), any()) - } answers { - true - } - - allocateDsActionInst.actionPerformed(anActionEventMock) - - // Pause to wait until all EDT events are finished - SwingUtilities.invokeAndWait { - assertSoftly { isCleanInvalidateOnExpandTriggered shouldBe false } - assertSoftly { isShowUntilDoneSucceeded shouldBe true } - assertSoftly { isAnalitycsTracked shouldBe true } - assertSoftly { isOperationPerformed shouldBe true } - assertSoftly { isUpdateOnConfigCrudableCalled shouldBe true } - assertSoftly { isThrowableReported shouldBe false } - assertSoftly { initState.errorMessage shouldBe "" } + assertSoftly { + isCleanInvalidateOnExpandTriggered shouldBe true + isShowUntilDoneSucceeded shouldBe true + isAnalitycsTracked shouldBe true + isOperationPerformed shouldBe true + isUpdateOnConfigCrudableCalled shouldBe false + isThrowableReported shouldBe false + initState.errorMessage shouldBe "" } } - should("perform allocate dataset action creating new dataset mask without refreshing the existing on as the connection config is not found") { + should("perform allocate dataset action creating new dataset mask without adding as the connection config is not found") { val workingSetMock = mockk() val nodeMock = mockk() val nodeDataMock = NodeData(nodeMock, null, null) @@ -641,33 +464,17 @@ class AllocateDatasetActionTestSpec : WithApplicationShouldSpec({ Optional.of(mockk()) } - val showOkNoDialogMock: ( - String, - String, - Project?, - String, - String, - Icon? - ) -> Boolean = ::showOkNoDialog - mockkStatic(showOkNoDialogMock as KFunction<*>) - every { - hint(Boolean::class) - showOkNoDialogMock(any(), any(), any(), any(), any(), any()) - } answers { - true - } - allocateDsActionInst.actionPerformed(anActionEventMock) + addMaskActionInst.actionPerformed(anActionEventMock) - // Pause to wait until all EDT events are finished - SwingUtilities.invokeAndWait { - assertSoftly { isCleanInvalidateOnExpandTriggered shouldBe false } - assertSoftly { isShowUntilDoneSucceeded shouldBe true } - assertSoftly { isAnalitycsTracked shouldBe true } - assertSoftly { isOperationPerformed shouldBe true } - assertSoftly { isUpdateOnConfigCrudableCalled shouldBe false } - assertSoftly { isThrowableReported shouldBe false } - assertSoftly { initState.errorMessage shouldBe "" } + assertSoftly { + isCleanInvalidateOnExpandTriggered shouldBe false + isShowUntilDoneSucceeded shouldBe true + isAnalitycsTracked shouldBe true + isOperationPerformed shouldBe true + isUpdateOnConfigCrudableCalled shouldBe false + isThrowableReported shouldBe false + initState.errorMessage shouldBe "" } } should("perform allocate dataset action with failure on operation performing") { @@ -711,13 +518,12 @@ class AllocateDatasetActionTestSpec : WithApplicationShouldSpec({ allocateDsActionInst.actionPerformed(anActionEventMock) - // Pause to wait until all EDT events are finished - SwingUtilities.invokeAndWait { - assertSoftly { isCleanInvalidateOnExpandTriggered shouldBe false } - assertSoftly { isShowUntilDoneSucceeded shouldBe false } - assertSoftly { isAnalitycsTracked shouldBe true } - assertSoftly { isThrowableReported shouldBe true } - assertSoftly { initState.errorMessage shouldBe exceptionMsg } + assertSoftly { + isCleanInvalidateOnExpandTriggered shouldBe false + isShowUntilDoneSucceeded shouldBe false + isAnalitycsTracked shouldBe true + isThrowableReported shouldBe true + initState.errorMessage shouldBe exceptionMsg } } } diff --git a/src/test/kotlin/eu/ibagroup/formainframe/explorer/actions/AllocateLikeActionTestSpec.kt b/src/test/kotlin/eu/ibagroup/formainframe/explorer/actions/AllocateLikeActionTestSpec.kt index a92bb88d5..c0bc04312 100644 --- a/src/test/kotlin/eu/ibagroup/formainframe/explorer/actions/AllocateLikeActionTestSpec.kt +++ b/src/test/kotlin/eu/ibagroup/formainframe/explorer/actions/AllocateLikeActionTestSpec.kt @@ -10,6 +10,9 @@ package eu.ibagroup.formainframe.explorer.actions +import com.intellij.notification.Notification +import com.intellij.notification.Notifications +import com.intellij.openapi.actionSystem.AnAction import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.actionSystem.Presentation import com.intellij.openapi.application.ApplicationManager @@ -17,7 +20,6 @@ import com.intellij.openapi.components.ComponentManager import com.intellij.openapi.progress.ProgressIndicator import com.intellij.openapi.project.Project import com.intellij.openapi.ui.Messages.showWarningDialog -import com.intellij.openapi.ui.showOkNoDialog import eu.ibagroup.formainframe.analytics.AnalyticsService import eu.ibagroup.formainframe.analytics.events.AnalyticsEvent import eu.ibagroup.formainframe.common.ui.StatefulDialog @@ -54,14 +56,12 @@ import io.mockk.mockk import io.mockk.mockkObject import io.mockk.mockkStatic import io.mockk.unmockkAll -import org.junit.jupiter.api.fail import org.zowe.kotlinsdk.Dataset import org.zowe.kotlinsdk.DatasetOrganization import org.zowe.kotlinsdk.RecordFormat import org.zowe.kotlinsdk.SpaceUnits import java.util.* import javax.swing.Icon -import javax.swing.SwingUtilities import kotlin.reflect.KFunction class AllocateLikeActionTestSpec : WithApplicationShouldSpec({ @@ -80,6 +80,7 @@ class AllocateLikeActionTestSpec : WithApplicationShouldSpec({ val dataOpsManagerMock = mockk() val componentManagerMock = mockk() val explorerMock = mockk>() + lateinit var addMaskActionInst: AnAction val analyticsService = ApplicationManager.getApplication().service() as TestAnalyticsServiceImpl @@ -119,6 +120,15 @@ class AllocateLikeActionTestSpec : WithApplicationShouldSpec({ } answers { isCleanInvalidateOnExpandTriggered = true } + + val notifyRef: (Notification) -> Unit = Notifications.Bus::notify + mockkStatic(notifyRef as KFunction<*>) + mockkStatic(Notification::get) + every { Notifications.Bus.notify(any()) } answers { + val notification = firstArg() + every { Notification.get(any()) } returns notification + addMaskActionInst = notification.actions.first { it.templateText == "Add mask" } + } } afterEach { @@ -137,7 +147,6 @@ class AllocateLikeActionTestSpec : WithApplicationShouldSpec({ val dsMaskNodeMock = mockk() lateinit var initState: DatasetAllocationParams var isOperationPerformed = false - var isCleanCacheTriggered = false var isShowUntilDoneSucceeded = false every { anActionEventMock.getExplorerView() } returns viewMock @@ -168,15 +177,7 @@ class AllocateLikeActionTestSpec : WithApplicationShouldSpec({ configCrudable.getByUniqueKey(any(), any()) } returns Optional.of(filesWorkingSetConfigMock) - every { - dsMaskNodeMock.cleanCache(any(), any(), any(), any()) - } answers { - isCleanCacheTriggered = true - val isSendTopic = lastArg() - if (!isSendTopic) { - fail("cleanCache should send topic in this testcase") - } - } + every { dsMaskNodeMock.cleanCache(any(), any(), any(), any()) } returns Unit every { nodeMock.parent } returns dsMaskNodeMock every { nodeMock.hint(FilesWorkingSet::class).unit } returns workingSetMock every { viewMock.mySelectedNodesData } returns selectedNodesData @@ -191,33 +192,16 @@ class AllocateLikeActionTestSpec : WithApplicationShouldSpec({ } every { workingSetMock.explorer } returns explorerMock - val showOkNoDialogMock: ( - String, - String, - Project?, - String, - String, - Icon? - ) -> Boolean = ::showOkNoDialog - mockkStatic(showOkNoDialogMock as KFunction<*>) - every { - hint(Boolean::class) - showOkNoDialogMock(any(), any(), any(), any(), any(), any()) - } answers { - false - } - allocateDsActionInst.actionPerformed(anActionEventMock) - - // Pause to wait until all EDT events are finished - SwingUtilities.invokeAndWait { - assertSoftly { isCleanInvalidateOnExpandTriggered shouldBe true } - assertSoftly { isShowUntilDoneSucceeded shouldBe true } - assertSoftly { isAnalitycsTracked shouldBe true } - assertSoftly { isOperationPerformed shouldBe true } - assertSoftly { isCleanCacheTriggered shouldBe true } - assertSoftly { isThrowableReported shouldBe false } - assertSoftly { initState.errorMessage shouldBe "" } + addMaskActionInst.actionPerformed(anActionEventMock) + + assertSoftly { + isCleanInvalidateOnExpandTriggered shouldBe true + isShowUntilDoneSucceeded shouldBe true + isAnalitycsTracked shouldBe true + isOperationPerformed shouldBe true + isThrowableReported shouldBe false + initState.errorMessage shouldBe "" } } should("perform allocate PDS dataset with TRACKS action without creating a new dataset mask") { @@ -236,7 +220,6 @@ class AllocateLikeActionTestSpec : WithApplicationShouldSpec({ val dsMaskNodeMock = mockk() lateinit var initState: DatasetAllocationParams var isOperationPerformed = false - var isCleanCacheTriggered = false var isShowUntilDoneSucceeded = false every { anActionEventMock.getExplorerView() } returns viewMock @@ -267,15 +250,7 @@ class AllocateLikeActionTestSpec : WithApplicationShouldSpec({ configCrudable.getByUniqueKey(any(), any()) } returns Optional.of(filesWorkingSetConfigMock) - every { - dsMaskNodeMock.cleanCache(any(), any(), any(), any()) - } answers { - isCleanCacheTriggered = true - val isSendTopic = lastArg() - if (!isSendTopic) { - fail("cleanCache should send topic in this testcase") - } - } + every { dsMaskNodeMock.cleanCache(any(), any(), any(), any()) } returns Unit every { nodeMock.parent } returns dsMaskNodeMock every { nodeMock.hint(FilesWorkingSet::class).unit } returns workingSetMock every { viewMock.mySelectedNodesData } returns selectedNodesData @@ -290,33 +265,15 @@ class AllocateLikeActionTestSpec : WithApplicationShouldSpec({ } every { workingSetMock.explorer } returns explorerMock - val showOkNoDialogMock: ( - String, - String, - Project?, - String, - String, - Icon? - ) -> Boolean = ::showOkNoDialog - mockkStatic(showOkNoDialogMock as KFunction<*>) - every { - hint(Boolean::class) - showOkNoDialogMock(any(), any(), any(), any(), any(), any()) - } answers { - false - } - allocateDsActionInst.actionPerformed(anActionEventMock) - // Pause to wait until all EDT events are finished - SwingUtilities.invokeAndWait { - assertSoftly { isCleanInvalidateOnExpandTriggered shouldBe true } - assertSoftly { isShowUntilDoneSucceeded shouldBe true } - assertSoftly { isAnalitycsTracked shouldBe true } - assertSoftly { isOperationPerformed shouldBe true } - assertSoftly { isCleanCacheTriggered shouldBe true } - assertSoftly { isThrowableReported shouldBe false } - assertSoftly { initState.errorMessage shouldBe "" } + assertSoftly { + isCleanInvalidateOnExpandTriggered shouldBe true + isShowUntilDoneSucceeded shouldBe true + isAnalitycsTracked shouldBe true + isOperationPerformed shouldBe true + isThrowableReported shouldBe false + initState.errorMessage shouldBe "" } } should("perform allocate PDS/E dataset with CYLINDERS action without creating a new dataset mask") { @@ -335,7 +292,6 @@ class AllocateLikeActionTestSpec : WithApplicationShouldSpec({ val dsMaskNodeMock = mockk() lateinit var initState: DatasetAllocationParams var isOperationPerformed = false - var isCleanCacheTriggered = false var isShowUntilDoneSucceeded = false every { anActionEventMock.getExplorerView() } returns viewMock @@ -366,15 +322,7 @@ class AllocateLikeActionTestSpec : WithApplicationShouldSpec({ configCrudable.getByUniqueKey(any(), any()) } returns Optional.of(filesWorkingSetConfigMock) - every { - dsMaskNodeMock.cleanCache(any(), any(), any(), any()) - } answers { - isCleanCacheTriggered = true - val isSendTopic = lastArg() - if (!isSendTopic) { - fail("cleanCache should send topic in this testcase") - } - } + every { dsMaskNodeMock.cleanCache(any(), any(), any(), any()) } returns Unit every { nodeMock.parent } returns dsMaskNodeMock every { nodeMock.hint(FilesWorkingSet::class).unit } returns workingSetMock every { viewMock.mySelectedNodesData } returns selectedNodesData @@ -389,33 +337,15 @@ class AllocateLikeActionTestSpec : WithApplicationShouldSpec({ } every { workingSetMock.explorer } returns explorerMock - val showOkNoDialogMock: ( - String, - String, - Project?, - String, - String, - Icon? - ) -> Boolean = ::showOkNoDialog - mockkStatic(showOkNoDialogMock as KFunction<*>) - every { - hint(Boolean::class) - showOkNoDialogMock(any(), any(), any(), any(), any(), any()) - } answers { - false - } - allocateDsActionInst.actionPerformed(anActionEventMock) - // Pause to wait until all EDT events are finished - SwingUtilities.invokeAndWait { - assertSoftly { isCleanInvalidateOnExpandTriggered shouldBe true } - assertSoftly { isShowUntilDoneSucceeded shouldBe true } - assertSoftly { isAnalitycsTracked shouldBe true } - assertSoftly { isOperationPerformed shouldBe true } - assertSoftly { isCleanCacheTriggered shouldBe true } - assertSoftly { isThrowableReported shouldBe false } - assertSoftly { initState.errorMessage shouldBe "" } + assertSoftly { + isCleanInvalidateOnExpandTriggered shouldBe true + isShowUntilDoneSucceeded shouldBe true + isAnalitycsTracked shouldBe true + isOperationPerformed shouldBe true + isThrowableReported shouldBe false + initState.errorMessage shouldBe "" } } should("perform allocate PS dataset with BLOCKS action without creating a new dataset mask, changing BLOCKS to TRACKS") { @@ -429,7 +359,6 @@ class AllocateLikeActionTestSpec : WithApplicationShouldSpec({ val dsMaskNodeMock = mockk() lateinit var initState: DatasetAllocationParams var isOperationPerformed = false - var isCleanCacheTriggered = false var isShowUntilDoneSucceeded = false var isBlocksChangedToTracks = false @@ -470,15 +399,7 @@ class AllocateLikeActionTestSpec : WithApplicationShouldSpec({ configCrudable.getByUniqueKey(any(), any()) } returns Optional.of(filesWorkingSetConfigMock) - every { - dsMaskNodeMock.cleanCache(any(), any(), any(), any()) - } answers { - isCleanCacheTriggered = true - val isSendTopic = lastArg() - if (!isSendTopic) { - fail("cleanCache should send topic in this testcase") - } - } + every { dsMaskNodeMock.cleanCache(any(), any(), any(), any()) } returns Unit every { nodeMock.parent } returns dsMaskNodeMock every { nodeMock.hint(FilesWorkingSet::class).unit } returns workingSetMock every { viewMock.mySelectedNodesData } returns selectedNodesData @@ -493,34 +414,16 @@ class AllocateLikeActionTestSpec : WithApplicationShouldSpec({ } every { workingSetMock.explorer } returns explorerMock - val showOkNoDialogMock: ( - String, - String, - Project?, - String, - String, - Icon? - ) -> Boolean = ::showOkNoDialog - mockkStatic(showOkNoDialogMock as KFunction<*>) - every { - hint(Boolean::class) - showOkNoDialogMock(any(), any(), any(), any(), any(), any()) - } answers { - false - } - allocateDsActionInst.actionPerformed(anActionEventMock) - // Pause to wait until all EDT events are finished - SwingUtilities.invokeAndWait { - assertSoftly { isCleanInvalidateOnExpandTriggered shouldBe true } - assertSoftly { isShowUntilDoneSucceeded shouldBe true } - assertSoftly { isAnalitycsTracked shouldBe true } - assertSoftly { isOperationPerformed shouldBe true } - assertSoftly { isCleanCacheTriggered shouldBe true } - assertSoftly { isBlocksChangedToTracks shouldBe true } - assertSoftly { isThrowableReported shouldBe false } - assertSoftly { initState.errorMessage shouldBe "" } + assertSoftly { + isCleanInvalidateOnExpandTriggered shouldBe true + isShowUntilDoneSucceeded shouldBe true + isAnalitycsTracked shouldBe true + isOperationPerformed shouldBe true + isBlocksChangedToTracks shouldBe true + isThrowableReported shouldBe false + initState.errorMessage shouldBe "" } } should("not perform 'allocate like' action as the file explorer view is not found") { @@ -537,12 +440,11 @@ class AllocateLikeActionTestSpec : WithApplicationShouldSpec({ allocateDsActionInst.actionPerformed(anActionEventMock) - // Pause to wait until all EDT events are finished - SwingUtilities.invokeAndWait { - assertSoftly { isCleanInvalidateOnExpandTriggered shouldBe false } - assertSoftly { isAnalitycsTracked shouldBe false } - assertSoftly { isOperationPerformed shouldBe false } - assertSoftly { isThrowableReported shouldBe false } + assertSoftly { + isCleanInvalidateOnExpandTriggered shouldBe false + isAnalitycsTracked shouldBe false + isOperationPerformed shouldBe false + isThrowableReported 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 1989d4ca1..91c27687f 100644 --- a/src/test/kotlin/eu/ibagroup/formainframe/explorer/ui/ChangeEncodingDialogTestSpec.kt +++ b/src/test/kotlin/eu/ibagroup/formainframe/explorer/ui/ChangeEncodingDialogTestSpec.kt @@ -49,7 +49,7 @@ import java.awt.event.ActionEvent import java.nio.charset.Charset import javax.swing.Action import javax.swing.Icon -import kotlin.reflect.full.declaredFunctions +import kotlin.reflect.KFunction class ChangeEncodingDialogTestSpec : WithApplicationShouldSpec({ afterSpec { @@ -95,9 +95,8 @@ class ChangeEncodingDialogTestSpec : WithApplicationShouldSpec({ val actionEventMock = mockk() - val showDialogRef = Messages::class.declaredFunctions - .first { it.name == "showDialog" && it.parameters.size == 5 } - mockkStatic(showDialogRef) + val showDialogRef: (String, String, Array, Int, Icon) -> Int = Messages::showDialog + mockkStatic(showDialogRef as KFunction<*>) every { contentSynchronizerMock.synchronizeWithRemote(any()) } returns Unit diff --git a/src/test/kotlin/eu/ibagroup/formainframe/utils/EncodingUtilsTestSpec.kt b/src/test/kotlin/eu/ibagroup/formainframe/utils/EncodingUtilsTestSpec.kt index 0a2131b37..5f86f3397 100644 --- a/src/test/kotlin/eu/ibagroup/formainframe/utils/EncodingUtilsTestSpec.kt +++ b/src/test/kotlin/eu/ibagroup/formainframe/utils/EncodingUtilsTestSpec.kt @@ -52,7 +52,7 @@ import java.nio.charset.CharsetDecoder import java.nio.charset.CharsetEncoder import java.nio.charset.UnsupportedCharsetException import javax.swing.Icon -import kotlin.reflect.full.declaredFunctions +import kotlin.reflect.KFunction class EncodingUtilsTestSpec : WithApplicationShouldSpec({ context("utils module: encodingUtils") { @@ -139,9 +139,8 @@ class EncodingUtilsTestSpec : WithApplicationShouldSpec({ mockkStatic(InspectionEngine::runInspectionOnFile) - val showDialogRef = Messages::class.declaredFunctions - .first { it.name == "showDialog" && it.parameters.size == 5 } - mockkStatic(showDialogRef) + val showDialogRef: (String, String, Array, Int, Icon) -> Int = Messages::showDialog + mockkStatic(showDialogRef as KFunction<*>) beforeEach { dataOpsManagerService.testInstance = object : TestDataOpsManagerImpl(explorerMock.componentManager) {