diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index d45798b..ed289f2 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -3,9 +3,6 @@ on:
pull_request:
branches:
- main
- push:
- branches:
- - codeMigration
jobs:
@@ -36,7 +33,16 @@ jobs:
run: |
Xvfb -ac :99 -screen 0 1920x1080x16 &
mvn verify -Dtest.includes="**/ui/*.java"
-
+ - name: Upload Coverage Report
+ uses: actions/upload-artifact@v4
+ with:
+ name: jacoco-coverage-report-ui
+ path: checkmarx-ast-eclipse-plugin-tests/target/site/jacoco-aggregate
+ - name: Generate JaCoCo Badge
+ uses: cicirello/jacoco-badge-generator@f33476a5a3fd5a4f77cb5eef2ebe728c1dd5b921
+ with:
+ jacoco-csv-file: checkmarx-ast-eclipse-plugin-tests/target/site/jacoco-aggregate/jacoco.csv
+ generate-summary: true
integration-tests:
runs-on: ubuntu-latest
steps:
@@ -64,5 +70,50 @@ jobs:
run: |
Xvfb -ac :99 -screen 0 1920x1080x16 &
mvn verify -Dtest.includes="**/integration/*Test.java"
-
-
+ - name: Upload Coverage Report
+ uses: actions/upload-artifact@v4
+ with:
+ name: jacoco-coverage-report-integration
+ path: checkmarx-ast-eclipse-plugin-tests/target/site/jacoco-aggregate
+ - name: Generate JaCoCo Badge
+ uses: cicirello/jacoco-badge-generator@f33476a5a3fd5a4f77cb5eef2ebe728c1dd5b921
+ with:
+ jacoco-csv-file: checkmarx-ast-eclipse-plugin-tests/target/site/jacoco-aggregate/jacoco.csv
+ generate-summary: true
+ unit-tests:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v3.5.2
+ with:
+ lfs: true
+ - name: Checkout LFS objects
+ run: git lfs checkout
+ - uses: actions/setup-java@v4
+ with:
+ distribution: temurin
+ java-version: 17
+ - uses: actions/cache@v3
+ with:
+ path: ~/.m2/repository
+ key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
+ restore-keys: ${{ runner.os }}-maven-
+ - name: Run Unit Tests with Coverage
+ env:
+ CX_BASE_URI: ${{ secrets.CX_BASE_URI }}
+ CX_TENANT: ${{ secrets.CX_TENANT }}
+ CX_APIKEY: ${{ secrets.CX_APIKEY }}
+ CX_TEST_SCAN: ${{ secrets.CX_TEST_SCAN }}
+ DISPLAY: :99.0
+ run: |
+ Xvfb -ac :99 -screen 0 1920x1080x16 &
+ mvn clean verify -Dtest.includes="**/unit/**/*Test.java"
+ - name: Upload Coverage Report
+ uses: actions/upload-artifact@v4
+ with:
+ name: jacoco-coverage-report-unit
+ path: checkmarx-ast-eclipse-plugin-tests/target/site/jacoco-aggregate
+ - name: Generate JaCoCo Badge
+ uses: cicirello/jacoco-badge-generator@f33476a5a3fd5a4f77cb5eef2ebe728c1dd5b921
+ with:
+ jacoco-csv-file: checkmarx-ast-eclipse-plugin-tests/target/site/jacoco-aggregate/jacoco.csv
+ generate-summary: true
\ No newline at end of file
diff --git a/checkmarx-ast-eclipse-plugin-tests/.classpath b/checkmarx-ast-eclipse-plugin-tests/.classpath
index 6f671e1..98ee5fe 100644
--- a/checkmarx-ast-eclipse-plugin-tests/.classpath
+++ b/checkmarx-ast-eclipse-plugin-tests/.classpath
@@ -14,16 +14,7 @@
-
-
-
-
-
-
-
-
-
diff --git a/checkmarx-ast-eclipse-plugin-tests/META-INF/MANIFEST.MF b/checkmarx-ast-eclipse-plugin-tests/META-INF/MANIFEST.MF
index 91cb193..8bf051b 100644
--- a/checkmarx-ast-eclipse-plugin-tests/META-INF/MANIFEST.MF
+++ b/checkmarx-ast-eclipse-plugin-tests/META-INF/MANIFEST.MF
@@ -12,5 +12,5 @@ Require-Bundle:
org.eclipse.jdt.junit5.runtime,
junit-jupiter-api
Bundle-RequiredExecutionEnvironment: JavaSE-17
-Bundle-ClassPath: .,lib/mockito-core-5.14.2.jar,lib/powermock-core-*.jar
+Bundle-ClassPath: .,lib/mockito-core-5.14.2.jar,lib/powermock-core-*.jar, lib/byte-buddy-1.17.8.jar, lib/byte-buddy-agent-1.17.8.jar
Automatic-Module-Name: com.checkmarx.ast.eclipse.tests
diff --git a/checkmarx-ast-eclipse-plugin-tests/lib/byte-buddy-1.17.8.jar b/checkmarx-ast-eclipse-plugin-tests/lib/byte-buddy-1.17.8.jar
new file mode 100644
index 0000000..7cca201
Binary files /dev/null and b/checkmarx-ast-eclipse-plugin-tests/lib/byte-buddy-1.17.8.jar differ
diff --git a/checkmarx-ast-eclipse-plugin-tests/lib/byte-buddy-agent-1.17.8.jar b/checkmarx-ast-eclipse-plugin-tests/lib/byte-buddy-agent-1.17.8.jar
new file mode 100644
index 0000000..a47ea2f
Binary files /dev/null and b/checkmarx-ast-eclipse-plugin-tests/lib/byte-buddy-agent-1.17.8.jar differ
diff --git a/checkmarx-ast-eclipse-plugin-tests/pom.xml b/checkmarx-ast-eclipse-plugin-tests/pom.xml
index 2a6a04b..e3161ba 100644
--- a/checkmarx-ast-eclipse-plugin-tests/pom.xml
+++ b/checkmarx-ast-eclipse-plugin-tests/pom.xml
@@ -4,7 +4,8 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
- **/Test*.java,**/*Test.java,**/*Tests.java,**/*TestCase.java
+
+ **/Test*.java,**/*Test.java,**/*Tests.java,**/*TestCase.java
com.checkmarx.ast.eclipse.tests
com.checkmarx.ast.eclipse.tests
@@ -17,6 +18,36 @@
+
+ org.jacoco
+ jacoco-maven-plugin
+ 0.8.11
+
+
+ prepare-agent
+
+ prepare-agent
+
+
+ tycho.testArgLine
+ ${project.build.directory}/jacoco.exec
+
+
+
+ report
+ verify
+
+ report
+
+
+
+ XML
+ CSV
+
+
+
+
+
org.eclipse.tycho
tycho-surefire-plugin
@@ -26,11 +57,13 @@
false
junit5
true
+ ${tycho.testArgLine}
${test.includes}
+
\ No newline at end of file
diff --git a/checkmarx-ast-eclipse-plugin-tests/src/test/java/checkmarx/ast/eclipse/plugin/tests/ui/BaseUITest.java b/checkmarx-ast-eclipse-plugin-tests/src/test/java/checkmarx/ast/eclipse/plugin/tests/ui/BaseUITest.java
index 54af1ca..2211c71 100644
--- a/checkmarx-ast-eclipse-plugin-tests/src/test/java/checkmarx/ast/eclipse/plugin/tests/ui/BaseUITest.java
+++ b/checkmarx-ast-eclipse-plugin-tests/src/test/java/checkmarx/ast/eclipse/plugin/tests/ui/BaseUITest.java
@@ -17,6 +17,7 @@
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotTree;
+import org.eclipse.swt.widgets.Decorations;
import org.eclipse.swt.widgets.Tree;
import com.checkmarx.eclipse.utils.PluginConstants;
@@ -302,18 +303,48 @@ protected static void waitUntilBranchComboIsEnabled() throws TimeoutException {
* Wait for connection response
*/
protected static void waitForConnectionResponse() throws TimeoutException {
- int retryIdx = 0;
- while (!_bot.text(3).getText().equals(INFO_SUCCESSFUL_CONNECTION)) {
- if (retryIdx == 10) {
- break;
- }
- _bot.sleep(1000);
- retryIdx++;
- }
-
- if (retryIdx == 10) {
- throw new TimeoutException("Connection validation timeout after 10000ms.");
- }
+ int retryIdx = 0;
+ while (retryIdx < 10) {
+ boolean found = false;
+ int index = 0;
+ // Search text widgets
+ while (true) {
+ try {
+ String textValue = _bot.text(index).getText();
+ System.out.println("[waitForConnectionResponse] text[" + index + "]: '" + textValue + "'");
+ if (textValue.contains(INFO_SUCCESSFUL_CONNECTION)) {
+ found = true;
+ break;
+ }
+ index++;
+ } catch (Exception e) {
+ break;
+ }
+ }
+ // Search label widgets if not found
+ if (!found) {
+ index = 0;
+ while (true) {
+ try {
+ String labelValue = _bot.label(index).getText();
+ System.out.println("[waitForConnectionResponse] label[" + index + "]: '" + labelValue + "'");
+ if (labelValue.contains(INFO_SUCCESSFUL_CONNECTION)) {
+ found = true;
+ break;
+ }
+ index++;
+ } catch (Exception e) {
+ break;
+ }
+ }
+ }
+ if (found) {
+ return;
+ }
+ _bot.sleep(1000);
+ retryIdx++;
+ }
+ throw new TimeoutException("Connection validation timeout after 10000ms. See logs for widget contents.");
}
/**
@@ -381,4 +412,4 @@ protected SWTBotTree getResultsTree() {
return _bot.tree(0);
}
}
-}
\ No newline at end of file
+}
diff --git a/checkmarx-ast-eclipse-plugin-tests/src/test/java/checkmarx/ast/eclipse/plugin/tests/unit/runner/AuthenticatorTest.java b/checkmarx-ast-eclipse-plugin-tests/src/test/java/checkmarx/ast/eclipse/plugin/tests/unit/runner/AuthenticatorTest.java
new file mode 100644
index 0000000..740e12a
--- /dev/null
+++ b/checkmarx-ast-eclipse-plugin-tests/src/test/java/checkmarx/ast/eclipse/plugin/tests/unit/runner/AuthenticatorTest.java
@@ -0,0 +1,108 @@
+package checkmarx.ast.eclipse.plugin.tests.unit.runner;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+import java.io.IOException;
+
+import org.junit.jupiter.api.Test;
+import org.mockito.MockedConstruction;
+import org.mockito.Mockito;
+import org.slf4j.Logger;
+
+import com.checkmarx.ast.wrapper.CxException;
+import com.checkmarx.ast.wrapper.CxWrapper;
+import com.checkmarx.eclipse.runner.Authenticator;
+import com.checkmarx.eclipse.utils.PluginConstants;
+
+class AuthenticatorTest {
+
+ @Test
+ void testDoAuthenticationSuccess() throws Exception {
+
+ Logger mockLogger = mock(Logger.class);
+
+ try (MockedConstruction mocked =
+ Mockito.mockConstruction(CxWrapper.class,
+ (mock, context) -> when(mock.authValidate()).thenReturn("SUCCESS"))) {
+
+ Authenticator authenticator = new Authenticator(mockLogger);
+
+ String result = authenticator.doAuthentication("dummyKey", "--param");
+
+ assertEquals("SUCCESS", result);
+ verify(mockLogger).info("Authentication Status: SUCCESS");
+ }
+ }
+
+ @Test
+ void testDoAuthenticationIOException() throws Exception {
+
+ Logger mockLogger = mock(Logger.class);
+
+ try (MockedConstruction mocked =
+ Mockito.mockConstruction(CxWrapper.class,
+ (mock, context) -> when(mock.authValidate())
+ .thenThrow(new IOException("IO error")))) {
+
+ Authenticator authenticator = new Authenticator(mockLogger);
+
+ String result = authenticator.doAuthentication("dummyKey", "--param");
+
+ assertEquals("IO error", result);
+ verify(mockLogger).error(
+ eq(String.format(PluginConstants.ERROR_AUTHENTICATING_AST, "IO error")),
+ any(IOException.class)
+ );
+ }
+ }
+
+ @Test
+ void testDoAuthenticationInterruptedException() throws Exception {
+
+ Logger mockLogger = mock(Logger.class);
+
+ try (MockedConstruction mocked =
+ Mockito.mockConstruction(CxWrapper.class,
+ (mock, context) -> when(mock.authValidate())
+ .thenThrow(new InterruptedException("Interrupted")))) {
+
+ Authenticator authenticator = new Authenticator(mockLogger);
+
+ String result = authenticator.doAuthentication("dummyKey", "--param");
+
+ assertEquals("Interrupted", result);
+ verify(mockLogger).error(
+ eq(String.format(PluginConstants.ERROR_AUTHENTICATING_AST, "Interrupted")),
+ any(InterruptedException.class)
+ );
+ }
+ }
+
+ @Test
+ void testDoAuthenticationCxException() throws Exception {
+
+ Logger mockLogger = mock(Logger.class);
+
+ try (MockedConstruction mocked =
+ Mockito.mockConstruction(CxWrapper.class,
+ (mock, context) -> when(mock.authValidate())
+ .thenThrow(new CxException(1, "Cx error")))) {
+
+ Authenticator authenticator = new Authenticator(mockLogger);
+
+ String result = authenticator.doAuthentication("dummyKey", "--param");
+
+ assertEquals("Cx error", result);
+ verify(mockLogger).error(
+ eq(String.format(PluginConstants.ERROR_AUTHENTICATING_AST, "Cx error")),
+ any(CxException.class)
+ );
+ }
+ }
+
+ @Test
+ void testSingletonInstanceNotNull() {
+ assertNotNull(Authenticator.INSTANCE);
+ }
+}
diff --git a/checkmarx-ast-eclipse-plugin-tests/src/test/java/checkmarx/ast/eclipse/plugin/tests/unit/utils/PluginUtilsTest.java b/checkmarx-ast-eclipse-plugin-tests/src/test/java/checkmarx/ast/eclipse/plugin/tests/unit/utils/PluginUtilsTest.java
new file mode 100644
index 0000000..022ce3c
--- /dev/null
+++ b/checkmarx-ast-eclipse-plugin-tests/src/test/java/checkmarx/ast/eclipse/plugin/tests/unit/utils/PluginUtilsTest.java
@@ -0,0 +1,269 @@
+package checkmarx.ast.eclipse.plugin.tests.unit.utils;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.resources.IWorkspaceRoot;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceProxyVisitor;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.e4.core.services.events.IEventBroker;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.viewers.ComboViewer;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.swt.widgets.Combo;
+import org.junit.jupiter.api.Test;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+import org.mockito.stubbing.Answer;
+
+import com.checkmarx.ast.results.result.Data;
+import com.checkmarx.ast.results.result.Node;
+import com.checkmarx.ast.results.result.Result;
+import com.checkmarx.eclipse.enums.Severity;
+import com.checkmarx.eclipse.properties.Preferences;
+import com.checkmarx.eclipse.utils.PluginConstants;
+import com.checkmarx.eclipse.utils.PluginUtils;
+import com.checkmarx.eclipse.views.DataProvider;
+import com.checkmarx.eclipse.views.DisplayModel;
+import com.checkmarx.eclipse.views.filters.FilterState;
+import org.eclipse.core.runtime.IStatus;
+
+public class PluginUtilsTest {
+
+ @Test
+ void testConvertStringTimeStampValid() {
+ String input = "2024-01-01T10:00:00Z";
+
+ String result = PluginUtils.convertStringTimeStamp(input);
+
+ assertNotNull(result);
+ assertTrue(result.contains("2024"));
+ }
+
+ @Test
+ void testConvertStringTimeStampInvalid() {
+ String input = "invalid-date";
+
+ String result = PluginUtils.convertStringTimeStamp(input);
+
+ assertEquals(input, result);
+ }
+
+ @Test
+ void testValidateScanIdFormatValid() {
+ String scanId = "d61aaad4-38fb-406c-bf54-b9b8475f81a5";
+
+ boolean result = PluginUtils.validateScanIdFormat(scanId);
+
+ assertTrue(result);
+ }
+
+ @Test
+ void testValidateScanIdFormatInvalid() {
+ String scanId = "invalid-scan-id";
+
+ boolean result = PluginUtils.validateScanIdFormat(scanId);
+
+ assertFalse(result);
+ }
+
+ @Test
+ void testEnableComboViewer() {
+ ComboViewer viewer = mock(ComboViewer.class);
+ Combo combo = mock(Combo.class);
+
+ when(viewer.getCombo()).thenReturn(combo);
+
+ PluginUtils.enableComboViewer(viewer, true);
+
+ verify(combo).setEnabled(true);
+ }
+
+ @Test
+ void testSetTextForComboViewer() {
+ ComboViewer viewer = mock(ComboViewer.class);
+ Combo combo = mock(Combo.class);
+
+ when(viewer.getCombo()).thenReturn(combo);
+
+ PluginUtils.setTextForComboViewer(viewer, "TestText");
+
+ verify(combo).setText("TestText");
+ verify(combo).update();
+ }
+
+ @Test
+ void testUpdateFiltersEnabledAndCheckedState() {
+
+ Action action = mock(Action.class);
+ when(action.getId()).thenReturn("LOW");
+
+ List actions = new ArrayList<>();
+ actions.add(action);
+
+ try (MockedStatic dp = Mockito.mockStatic(DataProvider.class);
+ MockedStatic fs = Mockito.mockStatic(FilterState.class)) {
+
+ DataProvider provider = mock(DataProvider.class);
+ dp.when(DataProvider::getInstance).thenReturn(provider);
+ when(provider.containsResults()).thenReturn(true);
+
+ fs.when(() -> FilterState.isSeverityEnabled("LOW")).thenReturn(true);
+
+ PluginUtils.updateFiltersEnabledAndCheckedState(actions);
+
+ verify(action).setEnabled(true);
+ verify(action).setChecked(true);
+ }
+ }
+
+ @Test
+ void testMessageCreation() {
+ DisplayModel model = PluginUtils.message("Hello");
+
+ assertNotNull(model);
+ }
+
+ @Test
+ void testShowMessage() {
+ DisplayModel root = new DisplayModel.DisplayModelBuilder("root").build();
+ TreeViewer viewer = mock(TreeViewer.class);
+
+ PluginUtils.showMessage(root, viewer, "Test message");
+
+ assertEquals(1, root.children.size());
+ verify(viewer).refresh();
+ }
+
+ @Test
+ void testClearMessage() {
+
+ DisplayModel root = new DisplayModel.DisplayModelBuilder("root").build();
+ root.children.add(new DisplayModel.DisplayModelBuilder("child").build());
+
+ TreeViewer viewer = mock(TreeViewer.class);
+
+ PluginUtils.clearMessage(root, viewer);
+
+ assertEquals(0, root.children.size());
+ verify(viewer).refresh();
+ }
+
+ @Test
+ void testAreCredentialsDefinedTrue() {
+
+ try (MockedStatic prefs = Mockito.mockStatic(Preferences.class)) {
+
+ prefs.when(Preferences::getApiKey).thenReturn("apikey");
+
+ boolean result = PluginUtils.areCredentialsDefined();
+
+ assertTrue(result);
+ }
+ }
+
+ @Test
+ void testAreCredentialsDefinedFalse() {
+
+ try (MockedStatic prefs = Mockito.mockStatic(Preferences.class)) {
+
+ prefs.when(Preferences::getApiKey).thenReturn("");
+
+ boolean result = PluginUtils.areCredentialsDefined();
+
+ assertFalse(result);
+ }
+ }
+
+ @Test
+ void testGetEventBroker() {
+ IEventBroker mockBroker = mock(IEventBroker.class);
+ IWorkbench mockWorkbench = mock(IWorkbench.class);
+ try (MockedStatic platformUI = Mockito.mockStatic(PlatformUI.class)) {
+ platformUI.when(PlatformUI::getWorkbench).thenReturn(mockWorkbench);
+ when(mockWorkbench.getService(IEventBroker.class)).thenReturn(mockBroker);
+ IEventBroker result = PluginUtils.getEventBroker();
+ assertSame(mockBroker, result);
+ }
+ }
+
+ @Test
+ void testFindFileInWorkspace_normal() throws Exception {
+ IFile mockFile = mock(IFile.class);
+ IWorkspaceRoot root = mock(IWorkspaceRoot.class);
+ IWorkspace workspace = mock(IWorkspace.class);
+ IResourceProxyVisitor[] visitorHolder = new IResourceProxyVisitor[1];
+ try (MockedStatic rp = Mockito.mockStatic(ResourcesPlugin.class)) {
+ rp.when(ResourcesPlugin::getWorkspace).thenReturn(workspace);
+ when(workspace.getRoot()).thenReturn(root);
+ doAnswer((Answer) invocation -> {
+ visitorHolder[0] = invocation.getArgument(0);
+ // Simulate visit
+ return null;
+ }).when(root).accept(any(IResourceProxyVisitor.class), anyInt());
+ List files = PluginUtils.findFileInWorkspace("file.java");
+ assertNotNull(files);
+ }
+ }
+
+ @Test
+ void testFindFileInWorkspace_exception() throws Exception {
+ IWorkspaceRoot root = mock(IWorkspaceRoot.class);
+ IWorkspace workspace = mock(IWorkspace.class);
+ try (MockedStatic rp = Mockito.mockStatic(ResourcesPlugin.class)) {
+ rp.when(ResourcesPlugin::getWorkspace).thenReturn(workspace);
+ when(workspace.getRoot()).thenReturn(root);
+ doThrow(new RuntimeException("fail")).when(root).accept(any(IResourceProxyVisitor.class), anyInt());
+ List files = PluginUtils.findFileInWorkspace("file.java");
+ assertNotNull(files);
+ assertTrue(files.isEmpty());
+ }
+ }
+
+ @Test
+ void testClearVulnerabilitiesFromProblemsView_normal() throws Exception {
+ IWorkspace workspace = mock(IWorkspace.class);
+ IWorkspaceRoot resource = mock(IWorkspaceRoot.class);
+ IMarker marker1 = mock(IMarker.class);
+ IMarker marker2 = mock(IMarker.class);
+ when(workspace.getRoot()).thenReturn(resource);
+ when(resource.findMarkers(IMarker.MARKER, true, IResource.DEPTH_INFINITE)).thenReturn(new IMarker[]{marker1, marker2});
+ when(marker1.getAttribute(IMarker.SOURCE_ID)).thenReturn(PluginConstants.PROBLEM_SOURCE_ID);
+ when(marker2.getAttribute(IMarker.SOURCE_ID)).thenReturn("other");
+ try (MockedStatic rp = Mockito.mockStatic(ResourcesPlugin.class)) {
+ rp.when(ResourcesPlugin::getWorkspace).thenReturn(workspace);
+ PluginUtils.clearVulnerabilitiesFromProblemsView();
+ verify(marker1).delete();
+ verify(marker2, never()).delete();
+ }
+ }
+
+ @Test
+ void testClearVulnerabilitiesFromProblemsView_coreException() throws Exception {
+ IWorkspace workspace = mock(IWorkspace.class);
+ IWorkspaceRoot resource = mock(IWorkspaceRoot.class);
+ IMarker marker1 = mock(IMarker.class);
+ when(workspace.getRoot()).thenReturn(resource);
+ when(resource.findMarkers(IMarker.MARKER, true, IResource.DEPTH_INFINITE)).thenReturn(new IMarker[]{marker1});
+ when(marker1.getAttribute(IMarker.SOURCE_ID)).thenReturn(PluginConstants.PROBLEM_SOURCE_ID);
+ IStatus status = mock(IStatus.class);
+ when(status.getMessage()).thenReturn("error");
+ doThrow(new CoreException(status)).when(marker1).delete();
+ try (MockedStatic rp = Mockito.mockStatic(ResourcesPlugin.class)) {
+ rp.when(ResourcesPlugin::getWorkspace).thenReturn(workspace);
+ PluginUtils.clearVulnerabilitiesFromProblemsView();
+ // Should not throw
+ }
+ }
+}
\ No newline at end of file
diff --git a/checkmarx-ast-eclipse-plugin-tests/src/test/java/checkmarx/ast/eclipse/plugin/tests/unit/views/CheckmarxViewTest.java b/checkmarx-ast-eclipse-plugin-tests/src/test/java/checkmarx/ast/eclipse/plugin/tests/unit/views/CheckmarxViewTest.java
new file mode 100644
index 0000000..05978ac
--- /dev/null
+++ b/checkmarx-ast-eclipse-plugin-tests/src/test/java/checkmarx/ast/eclipse/plugin/tests/unit/views/CheckmarxViewTest.java
@@ -0,0 +1,374 @@
+package checkmarx.ast.eclipse.plugin.tests.unit.views;
+
+import com.checkmarx.eclipse.views.CheckmarxView;
+import com.checkmarx.eclipse.views.DataProvider;
+import com.checkmarx.eclipse.views.actions.ToolBarActions;
+import com.checkmarx.eclipse.properties.Preferences;
+import com.checkmarx.eclipse.utils.PluginUtils;
+import com.checkmarx.ast.project.Project;
+import com.checkmarx.ast.scan.Scan;
+import com.checkmarx.eclipse.Activator;
+
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.swt.graphics.Image;
+
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchWindow;
+
+import org.eclipse.e4.core.services.events.IEventBroker;
+import java.util.Map;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+
+import org.osgi.service.event.Event;
+
+import org.junit.jupiter.api.*;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class CheckmarxViewTest {
+
+ private static Display display;
+
+ private static MockedStatic activatorStaticMock;
+ private static MockedStatic imageDescriptorStaticMock;
+
+ private MockedStatic platformUIMock;
+ private MockedStatic pluginUtilsMock;
+
+ private CheckmarxView checkmarxView;
+ private Shell shell;
+ private Composite parent;
+
+ @BeforeAll
+ static void beforeAll() {
+
+ display = Display.getDefault();
+
+ activatorStaticMock = Mockito.mockStatic(Activator.class);
+ imageDescriptorStaticMock = Mockito.mockStatic(ImageDescriptor.class, Mockito.CALLS_REAL_METHODS);
+
+ ImageDescriptor descriptor = Mockito.mock(ImageDescriptor.class);
+ Image image = Mockito.mock(Image.class);
+
+ activatorStaticMock
+ .when(() -> Activator.getImageDescriptor(Mockito.anyString()))
+ .thenReturn(descriptor);
+
+ Mockito.when(descriptor.createImage()).thenReturn(image);
+ }
+
+ @AfterAll
+ static void afterAll() {
+ activatorStaticMock.close();
+ imageDescriptorStaticMock.close();
+ }
+
+ @BeforeEach
+ void setUp() throws Exception {
+
+ platformUIMock = Mockito.mockStatic(PlatformUI.class);
+ pluginUtilsMock = Mockito.mockStatic(PluginUtils.class);
+
+ IWorkbench workbench = Mockito.mock(IWorkbench.class);
+ IWorkbenchWindow window = Mockito.mock(IWorkbenchWindow.class);
+
+ display.syncExec(() -> {
+ shell = new Shell(display);
+ parent = new Composite(shell, 0);
+ });
+
+ Mockito.when(window.getShell()).thenReturn(shell);
+ Mockito.when(workbench.getActiveWorkbenchWindow()).thenReturn(window);
+ Mockito.when(workbench.getDisplay()).thenReturn(display);
+
+ platformUIMock.when(PlatformUI::getWorkbench).thenReturn(workbench);
+
+ IEventBroker broker = Mockito.mock(IEventBroker.class);
+ Mockito.when(broker.subscribe(Mockito.anyString(), Mockito.any())).thenReturn(true);
+
+ pluginUtilsMock.when(PluginUtils::getEventBroker).thenReturn(broker);
+
+ checkmarxView = new CheckmarxView();
+
+ injectDependencies();
+ }
+
+ @AfterEach
+ void tearDown() {
+
+ platformUIMock.close();
+ pluginUtilsMock.close();
+
+ if (shell != null && !shell.isDisposed()) {
+ display.syncExec(() -> shell.dispose());
+ }
+ }
+
+ @Test
+ void testConstructorInitializesFields() {
+ assertNotNull(checkmarxView);
+ }
+
+ @Test
+ void testDisposeDoesNotThrow() {
+ assertDoesNotThrow(() -> checkmarxView.dispose());
+ }
+
+ @Test
+ void testSetFocusDoesNotThrow() {
+ assertDoesNotThrow(() -> checkmarxView.setFocus());
+ }
+
+ @Test
+ void testHandleEventWithEmptyApiKey() throws Exception {
+
+ Event event = new Event("test/topic", new HashMap());
+
+ try (MockedStatic prefMock =
+ Mockito.mockStatic(Preferences.class, Mockito.CALLS_REAL_METHODS)) {
+
+ prefMock.when(Preferences::getApiKey).thenReturn("");
+
+ assertDoesNotThrow(() ->
+ Display.getDefault().syncExec(() -> checkmarxView.handleEvent(event))
+ );
+ }
+ }
+
+ @Test
+ void testHandleEventWithNonEmptyApiKey() {
+
+ org.osgi.service.event.Event event =
+ new org.osgi.service.event.Event("test/topic", new HashMap<>());
+
+ try (MockedStatic prefMock =
+ Mockito.mockStatic(Preferences.class, Mockito.CALLS_REAL_METHODS)) {
+
+ prefMock.when(Preferences::getApiKey).thenReturn("dummyApiKey");
+
+ assertDoesNotThrow(() ->
+ Display.getDefault().syncExec(() -> checkmarxView.handleEvent(event))
+ );
+ }
+ }
+
+ @Test
+ void testStaticFieldsNotNull() {
+
+ assertNotNull(CheckmarxView.ID);
+ assertNotNull(CheckmarxView.CHECKMARX_OPEN_SETTINGS_LOGO);
+ assertNotNull(CheckmarxView.CRITICAL_SEVERITY);
+ assertNotNull(CheckmarxView.HIGH_SEVERITY);
+ assertNotNull(CheckmarxView.MEDIUM_SEVERITY);
+ assertNotNull(CheckmarxView.LOW_SEVERITY);
+ assertNotNull(CheckmarxView.INFO_SEVERITY);
+ assertNotNull(CheckmarxView.USER);
+ assertNotNull(CheckmarxView.CREATED_AT_IMAGE);
+ assertNotNull(CheckmarxView.COMMENT);
+ assertNotNull(CheckmarxView.STATE);
+ assertNotNull(CheckmarxView.BFL);
+ }
+
+ @Test
+ void testRemoveCount() throws Exception {
+ Method method = CheckmarxView.class.getDeclaredMethod("removeCount", String.class);
+ method.setAccessible(true);
+
+ String result = (String) method.invoke(null, "High (5)");
+
+ assertEquals("High", result);
+ }
+
+ @Test
+ void testGetLatestScanFromScanList() throws Exception {
+
+ Scan scan1 = Mockito.mock(Scan.class);
+ Scan scan2 = Mockito.mock(Scan.class);
+
+ List scans = Arrays.asList(scan1, scan2);
+
+ Method method = CheckmarxView.class.getDeclaredMethod("getLatestScanFromScanList", List.class);
+ method.setAccessible(true);
+
+ Scan result = (Scan) method.invoke(checkmarxView, scans);
+
+ assertEquals(scan1, result);
+ }
+
+ @Test
+ void testGetProjectFromIdFound() throws Exception {
+
+ Project project = Mockito.mock(Project.class);
+ Mockito.when(project.getId()).thenReturn("123");
+ Mockito.when(project.getName()).thenReturn("DemoProject");
+
+ List projects = List.of(project);
+
+ Method method = CheckmarxView.class.getDeclaredMethod(
+ "getProjectFromId", List.class, String.class);
+ method.setAccessible(true);
+
+ String result = (String) method.invoke(checkmarxView, projects, "123");
+
+ assertEquals("DemoProject", result);
+ }
+
+ @Test
+ void testGetProjectFromIdNotFound() throws Exception {
+
+ Project project = Mockito.mock(Project.class);
+ Mockito.when(project.getId()).thenReturn("123");
+
+ List projects = List.of(project);
+
+ Method method = CheckmarxView.class.getDeclaredMethod(
+ "getProjectFromId", List.class, String.class);
+ method.setAccessible(true);
+
+ String result = (String) method.invoke(checkmarxView, projects, "999");
+
+ assertEquals("Select a project", result);
+ }
+
+ @Test
+ void testGetProjectFromIdEmptyList() throws Exception {
+
+ Method method = CheckmarxView.class.getDeclaredMethod(
+ "getProjectFromId", List.class, String.class);
+ method.setAccessible(true);
+
+ String result = (String) method.invoke(checkmarxView, Collections.emptyList(), "123");
+
+ assertEquals("No projects available.", result);
+ }
+
+ @Test
+ void testFormatScanLabelNormal() throws Exception {
+
+ Scan scan = Mockito.mock(Scan.class);
+
+ Mockito.when(scan.getId()).thenReturn("scan123");
+ Mockito.when(scan.getUpdatedAt()).thenReturn("2024-01-01T10:00:00Z");
+
+ Field latestScanField = CheckmarxView.class.getDeclaredField("latestScanId");
+ latestScanField.setAccessible(true);
+ latestScanField.set(checkmarxView, "otherScan");
+
+ Method method = CheckmarxView.class.getDeclaredMethod("formatScanLabel", Scan.class);
+ method.setAccessible(true);
+
+ String label = (String) method.invoke(checkmarxView, scan);
+
+ assertTrue(label.contains("scan123"));
+ }
+
+ @Test
+ void testFormatScanLabelLatest() throws Exception {
+
+ Scan scan = Mockito.mock(Scan.class);
+
+ Mockito.when(scan.getId()).thenReturn("scan999");
+ Mockito.when(scan.getUpdatedAt()).thenReturn("2024-01-01T10:00:00Z");
+
+ Field latestScanField = CheckmarxView.class.getDeclaredField("latestScanId");
+ latestScanField.setAccessible(true);
+ latestScanField.set(checkmarxView, "scan999");
+
+ Method method = CheckmarxView.class.getDeclaredMethod("formatScanLabel", Scan.class);
+ method.setAccessible(true);
+
+ String label = (String) method.invoke(checkmarxView, scan);
+
+ assertTrue(label.contains("latest"));
+ }
+
+ @Test
+ void testGetProjectsSuccess() throws Exception {
+
+ List projects = List.of(Mockito.mock(Project.class));
+
+ DataProvider provider = Mockito.mock(DataProvider.class);
+ Mockito.when(provider.getProjects()).thenReturn(projects);
+
+ try (MockedStatic mocked = Mockito.mockStatic(DataProvider.class)) {
+
+ mocked.when(DataProvider::getInstance).thenReturn(provider);
+
+ Method method = CheckmarxView.class.getDeclaredMethod("getProjects");
+ method.setAccessible(true);
+
+ List result = (List) method.invoke(checkmarxView);
+
+ assertEquals(1, result.size());
+ }
+ }
+
+ @Test
+ void testGetProjectsException() throws Exception {
+
+ DataProvider provider = Mockito.mock(DataProvider.class);
+
+ Mockito.when(provider.getProjects()).thenThrow(new RuntimeException("error"));
+
+ try (MockedStatic mocked = Mockito.mockStatic(DataProvider.class)) {
+
+ mocked.when(DataProvider::getInstance).thenReturn(provider);
+
+ Method method = CheckmarxView.class.getDeclaredMethod("getProjects");
+ method.setAccessible(true);
+
+ List result = (List) method.invoke(checkmarxView);
+
+ assertNotNull(result);
+ }
+ }
+
+ @Test
+ void testUpdateStartScanButtonEnabled() throws Exception {
+
+ ToolBarActions toolBarActions = Mockito.mock(ToolBarActions.class);
+ Action startAction = Mockito.mock(Action.class);
+
+ Mockito.when(toolBarActions.getStartScanAction()).thenReturn(startAction);
+
+ Field field = CheckmarxView.class.getDeclaredField("toolBarActions");
+ field.setAccessible(true);
+ field.set(checkmarxView, toolBarActions);
+
+ Method method = CheckmarxView.class.getDeclaredMethod("updateStartScanButton", boolean.class);
+ method.setAccessible(true);
+
+ method.invoke(checkmarxView, true);
+
+ Mockito.verify(startAction).setEnabled(Mockito.anyBoolean());
+ }
+
+ private void injectDependencies() throws Exception {
+
+ ToolBarActions toolbar = Mockito.mock(ToolBarActions.class);
+ Action action = Mockito.mock(Action.class);
+
+ Mockito.when(toolbar.getStartScanAction()).thenReturn(action);
+
+ Field toolbarField = CheckmarxView.class.getDeclaredField("toolBarActions");
+ toolbarField.setAccessible(true);
+ toolbarField.set(checkmarxView, toolbar);
+
+ Field parentField = CheckmarxView.class.getDeclaredField("parent");
+ parentField.setAccessible(true);
+ parentField.set(checkmarxView, parent);
+ }
+}
\ No newline at end of file
diff --git a/checkmarx-ast-eclipse-plugin-tests/src/test/java/checkmarx/ast/eclipse/plugin/tests/unit/views/DataProviderTest.java b/checkmarx-ast-eclipse-plugin-tests/src/test/java/checkmarx/ast/eclipse/plugin/tests/unit/views/DataProviderTest.java
new file mode 100644
index 0000000..05ca480
--- /dev/null
+++ b/checkmarx-ast-eclipse-plugin-tests/src/test/java/checkmarx/ast/eclipse/plugin/tests/unit/views/DataProviderTest.java
@@ -0,0 +1,206 @@
+package checkmarx.ast.eclipse.plugin.tests.unit.views;
+
+import com.checkmarx.eclipse.views.DataProvider;
+
+import checkmarx.ast.eclipse.plugin.tests.common.Environment;
+
+import com.checkmarx.ast.results.Results;
+import com.checkmarx.ast.project.Project;
+import com.checkmarx.ast.scan.Scan;
+import com.checkmarx.ast.wrapper.CxWrapper;
+import com.checkmarx.ast.predicate.Predicate;
+import org.junit.jupiter.api.*;
+import org.mockito.MockedConstruction;
+
+import java.util.*;
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+class DataProviderTest {
+
+ protected static final String SCAN_ID = Environment.SCAN_ID;
+ private static final String TEST_PROJECT = "pedrompflopes/WebGoat";
+
+
+
+ DataProvider dataProvider;
+
+ @BeforeEach
+ void setUp() {
+ dataProvider = DataProvider.getInstance();
+ dataProvider.setCurrentResults(null);
+ dataProvider.setCurrentScanId(null);
+ }
+
+ @Test
+ void testSingletonInstance() {
+ DataProvider instance1 = DataProvider.getInstance();
+ DataProvider instance2 = DataProvider.getInstance();
+ assertSame(instance1, instance2, "DataProvider should be singleton");
+ }
+
+ @Test
+ void testSetAndGetCurrentScanId() {
+ String scanId = "scan-123";
+ dataProvider.setCurrentScanId(scanId);
+ assertEquals(scanId, dataProvider.getCurrentScanId());
+ }
+
+ @Test
+ void testSetAndGetCurrentResults() {
+ Results mockResults = mock(Results.class);
+ dataProvider.setCurrentResults(mockResults);
+ assertEquals(mockResults, dataProvider.getCurrentResults());
+ }
+
+ @Test
+ void testGetProjectsReturnsList() throws Exception {
+ List projects = dataProvider.getProjects();
+ assertNotNull(projects);
+ }
+
+ @Test
+ void testGetProjectsByNameReturnsList() throws Exception {
+ List projects = dataProvider.getProjects(TEST_PROJECT);
+ assertNotNull(projects);
+ }
+
+ @Test
+ void testGetBranchesForProjectReturnsList() {
+ List branches = dataProvider.getBranchesForProject("e7478063-976c-4c79-b762-93074dabad24");
+ assertNotNull(branches);
+ }
+
+ @Test
+ void testGetScansForProjectReturnsList() {
+ List scans = dataProvider.getScansForProject("main");
+ assertNotNull(scans);
+ }
+
+ @Test
+ void testGetResultsForScanIdReturnsList() {
+ List> results = dataProvider.getResultsForScanId(SCAN_ID);
+ assertNotNull(results);
+ }
+
+ @Test
+ void testSortResultsReturnsList() {
+ List> sorted = dataProvider.sortResults();
+ assertNotNull(sorted);
+ }
+
+ @Test
+ void testContainsResults() {
+ dataProvider.setCurrentResults(null);
+ assertFalse(dataProvider.containsResults());
+ }
+
+ @Test
+ void testGetTriageShowReturnsList() throws Exception {
+ List triage = dataProvider.getTriageShow(UUID.randomUUID(), "simId", "SAST");
+ assertNotNull(triage);
+ }
+
+ @Test
+ void testTriageUpdateDoesNotThrow() throws Exception {
+
+ UUID projectId = UUID.randomUUID();
+ String similarityId = "-930213981328";
+
+ try (MockedConstruction mocked = mockConstruction(
+ CxWrapper.class,
+ (mock, context) -> {
+ doNothing().when(mock).triageUpdate(
+ any(UUID.class),
+ anyString(),
+ anyString(),
+ anyString(),
+ anyString(),
+ anyString()
+ );
+ })) {
+ DataProvider provider = DataProvider.getInstance();
+ assertDoesNotThrow(() ->
+ provider.triageUpdate(
+ projectId,
+ similarityId,
+ "SAST",
+ "TO_VERIFY",
+ "comment",
+ "HIGH"
+ )
+ );
+ }
+ }
+
+ @Test
+ void testContainsResultsTrue() {
+
+ Results results = mock(Results.class);
+
+ List list = new ArrayList<>();
+ list.add(mock(com.checkmarx.ast.results.result.Result.class));
+
+ when(results.getResults()).thenReturn(list);
+
+ dataProvider.setCurrentResults(results);
+
+ assertTrue(dataProvider.containsResults());
+ }
+
+ @Test
+ void testGetStatesForEngineSAST() {
+
+ List states = dataProvider.getStatesForEngine("SAST");
+
+ assertNotNull(states);
+ }
+
+ @Test
+ void testGetStatesForEngineOther() {
+
+ List states = dataProvider.getStatesForEngine("SCA");
+
+ assertNotNull(states);
+ }
+
+ @Test
+ void testGetCustomStates() {
+
+ List states = dataProvider.getCustomStates();
+
+ assertNotNull(states);
+ }
+
+ @Test
+ void testGetResultsForScanIdInvalid() {
+
+ List> results = dataProvider.getResultsForScanId("invalid-uuid");
+
+ assertNotNull(results);
+ }
+
+ @Test
+ void testGetBranchesForProjectEmpty() {
+
+ List branches = dataProvider.getBranchesForProject("");
+
+ assertNotNull(branches);
+ }
+
+ @Test
+ void testGetScansForProjectNullBranch() {
+
+ List scans = dataProvider.getScansForProject(null);
+
+ assertNotNull(scans);
+ }
+
+ @Test
+ void testGetScanInformationException() {
+
+ assertThrows(Exception.class, () -> {
+ dataProvider.getScanInformation("invalid-scan");
+ });
+ }
+}
\ No newline at end of file
diff --git a/checkmarx-ast-eclipse-plugin-tests/src/test/java/checkmarx/ast/eclipse/plugin/tests/unit/views/GlobalSettingsTest.java b/checkmarx-ast-eclipse-plugin-tests/src/test/java/checkmarx/ast/eclipse/plugin/tests/unit/views/GlobalSettingsTest.java
new file mode 100644
index 0000000..d6e28e6
--- /dev/null
+++ b/checkmarx-ast-eclipse-plugin-tests/src/test/java/checkmarx/ast/eclipse/plugin/tests/unit/views/GlobalSettingsTest.java
@@ -0,0 +1,74 @@
+package checkmarx.ast.eclipse.plugin.tests.unit.views;
+
+import static org.junit.jupiter.api.Assertions.*;
+import org.junit.jupiter.api.Test;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+import com.checkmarx.eclipse.views.GlobalSettings;
+import com.checkmarx.eclipse.views.filters.FilterState;
+
+class GlobalSettingsTest {
+
+ @Test
+ void testSetAndGetProjectId() {
+
+ GlobalSettings settings = new GlobalSettings();
+
+ settings.setProjectId("project1");
+
+ assertEquals("project1", settings.getProjectId());
+ }
+
+ @Test
+ void testSetAndGetBranch() {
+
+ GlobalSettings settings = new GlobalSettings();
+
+ settings.setBranch("main");
+
+ assertEquals("main", settings.getBranch());
+ }
+
+ @Test
+ void testSetAndGetScanId() {
+
+ GlobalSettings settings = new GlobalSettings();
+
+ settings.setScanId("scan123");
+
+ assertEquals("scan123", settings.getScanId());
+ }
+
+ @Test
+ void testStoreInPreferencesDoesNotThrow() {
+
+ assertDoesNotThrow(() ->
+ GlobalSettings.storeInPreferences("test-key", "test-value")
+ );
+ }
+
+ @Test
+ void testGetFromPreferencesReturnsValue() {
+
+ String value = GlobalSettings.getFromPreferences("non-existing", "default");
+
+ assertNotNull(value);
+ }
+
+ @Test
+ void testLoadSettings() {
+
+ GlobalSettings settings = new GlobalSettings();
+
+ try (MockedStatic filterMock = Mockito.mockStatic(FilterState.class)) {
+
+ settings.loadSettings();
+
+ filterMock.verify(FilterState::loadFiltersFromSettings);
+ }
+
+ assertNotNull(settings.getProjectId());
+ assertNotNull(settings.getBranch());
+ assertNotNull(settings.getScanId());
+ }
+}
\ No newline at end of file
diff --git a/checkmarx-ast-eclipse-plugin-tests/src/test/java/checkmarx/ast/eclipse/plugin/tests/unit/views/actions/ToolBarActionsTest.java b/checkmarx-ast-eclipse-plugin-tests/src/test/java/checkmarx/ast/eclipse/plugin/tests/unit/views/actions/ToolBarActionsTest.java
new file mode 100644
index 0000000..baa719a
--- /dev/null
+++ b/checkmarx-ast-eclipse-plugin-tests/src/test/java/checkmarx/ast/eclipse/plugin/tests/unit/views/actions/ToolBarActionsTest.java
@@ -0,0 +1,177 @@
+package checkmarx.ast.eclipse.plugin.tests.unit.views.actions;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.jface.viewers.ComboViewer;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.ui.IActionBars;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+
+import com.checkmarx.eclipse.enums.PluginListenerType;
+import com.checkmarx.eclipse.views.DisplayModel;
+import com.checkmarx.eclipse.views.PluginListenerDefinition;
+import com.checkmarx.eclipse.views.actions.ToolBarActions;
+import com.checkmarx.eclipse.views.filters.FilterState;
+import com.google.common.eventbus.EventBus;
+
+class ToolBarActionsTest {
+
+ private IActionBars actionBars;
+ private IToolBarManager toolBarManager;
+ private IMenuManager menuManager;
+
+ private TreeViewer resultsTree;
+ private ComboViewer projectCombo;
+ private ComboViewer branchCombo;
+ private ComboViewer scanCombo;
+
+ private EventBus eventBus;
+ private DisplayModel rootModel;
+
+ private ToolBarActions toolBarActions;
+
+ @BeforeEach
+ void setup() {
+
+ actionBars = mock(IActionBars.class);
+ toolBarManager = mock(IToolBarManager.class);
+ menuManager = mock(IMenuManager.class);
+
+ resultsTree = mock(TreeViewer.class);
+ projectCombo = mock(ComboViewer.class);
+ branchCombo = mock(ComboViewer.class);
+ scanCombo = mock(ComboViewer.class);
+
+ rootModel = mock(DisplayModel.class);
+ eventBus = new EventBus();
+
+ when(actionBars.getToolBarManager()).thenReturn(toolBarManager);
+ when(actionBars.getMenuManager()).thenReturn(menuManager);
+
+ toolBarActions =
+ new ToolBarActions.ToolBarActionsBuilder()
+ .actionBars(actionBars)
+ .rootModel(rootModel)
+ .resultsTree(resultsTree)
+ .pluginEventBus(eventBus)
+ .projectsCombo(projectCombo)
+ .branchesCombo(branchCombo)
+ .scansCombo(scanCombo)
+ .build();
+ }
+
+ @Test
+ void testBuilderCreatesInstance() {
+ assertNotNull(toolBarActions);
+ }
+
+ @Test
+ void testGetToolBarActions() {
+ List actions = toolBarActions.getToolBarActions();
+ assertNotNull(actions);
+ }
+
+ @Test
+ void testGetFilterActions() {
+ List filters = toolBarActions.getFilterActions();
+ assertNotNull(filters);
+ }
+
+ @Test
+ void testGetStartScanAction() {
+ Action action = toolBarActions.getStartScanAction();
+ assertNotNull(action);
+ }
+
+ @Test
+ void testGetCancelScanAction() {
+ Action action = toolBarActions.getCancelScanAction();
+ assertNotNull(action);
+ }
+
+ @Test
+ void testGetStateFilterAction() {
+ Action action = toolBarActions.getStateFilterAction();
+ assertNotNull(action);
+ }
+
+ @Test
+ void testDisposeToolbarRemovesAll() {
+
+ toolBarActions.disposeToolbar();
+
+ verify(toolBarManager).removeAll();
+ verify(menuManager).removeAll();
+ }
+
+ @Test
+ void testRefreshToolbarRecreatesActions() {
+
+ toolBarActions.refreshToolbar();
+
+ verify(toolBarManager).removeAll();
+ verify(menuManager).removeAll();
+ }
+
+ @Test
+ void testGroupBySeverityAction() {
+
+ List actions = toolBarActions.getFilterActions();
+
+ for (Action action : actions) {
+ if ("GROUP_BY_SEVERITY".equals(action.getId())) {
+ action.run();
+ break;
+ }
+ }
+
+ assertTrue(FilterState.groupBySeverity);
+ }
+
+ @Test
+ void testEventBusPostCleanRefresh() {
+
+ assertDoesNotThrow(() -> {
+ eventBus.post(
+ new PluginListenerDefinition(
+ PluginListenerType.CLEAN_AND_REFRESH,
+ Collections.emptyList()));
+ });
+ }
+
+ @Test
+ void testBuilderSetsComboViewers() {
+
+ ToolBarActions actions =
+ new ToolBarActions.ToolBarActionsBuilder()
+ .actionBars(actionBars)
+ .rootModel(rootModel)
+ .resultsTree(resultsTree)
+ .pluginEventBus(eventBus)
+ .projectsCombo(projectCombo)
+ .branchesCombo(branchCombo)
+ .scansCombo(scanCombo)
+ .build();
+
+ assertNotNull(actions);
+ }
+
+ @Test
+ void testToolBarActionsListNotEmpty() {
+
+ List actions = toolBarActions.getToolBarActions();
+
+ assertNotNull(actions);
+ assertTrue(actions.size() >= 0);
+ }
+
+}
\ No newline at end of file
diff --git a/checkmarx-ast-eclipse-plugin-tests/src/test/java/checkmarx/ast/eclipse/plugin/tests/unit/views/filters/ActionFiltersTest.java b/checkmarx-ast-eclipse-plugin-tests/src/test/java/checkmarx/ast/eclipse/plugin/tests/unit/views/filters/ActionFiltersTest.java
new file mode 100644
index 0000000..2f1ed8e
--- /dev/null
+++ b/checkmarx-ast-eclipse-plugin-tests/src/test/java/checkmarx/ast/eclipse/plugin/tests/unit/views/filters/ActionFiltersTest.java
@@ -0,0 +1,104 @@
+package checkmarx.ast.eclipse.plugin.tests.unit.views.filters;
+
+import com.checkmarx.eclipse.views.filters.ActionFilters;
+import com.checkmarx.eclipse.enums.ActionName;
+import com.checkmarx.eclipse.enums.PluginListenerType;
+import com.checkmarx.eclipse.enums.Severity;
+import com.checkmarx.eclipse.views.DataProvider;
+import com.checkmarx.eclipse.views.PluginListenerDefinition;
+import com.google.common.eventbus.EventBus;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+class ActionFiltersTest {
+ private EventBus mockEventBus;
+ private ActionFilters actionFilters;
+
+ @BeforeEach
+ void setUp() {
+ mockEventBus = mock(EventBus.class);
+ actionFilters = new ActionFilters(mockEventBus);
+ }
+
+ @Test
+ void testCreateFilterActions_propertiesAndState() {
+ try (MockedStatic dp = Mockito.mockStatic(DataProvider.class);
+ MockedStatic fs = Mockito.mockStatic(com.checkmarx.eclipse.views.filters.FilterState.class);
+ MockedStatic activator = Mockito.mockStatic(com.checkmarx.eclipse.Activator.class)) {
+
+ DataProvider provider = mock(DataProvider.class);
+ dp.when(DataProvider::getInstance).thenReturn(provider);
+ when(provider.containsResults()).thenReturn(true);
+ fs.when(() -> com.checkmarx.eclipse.views.filters.FilterState.isSeverityEnabled(anyString())).thenReturn(true);
+ activator.when(() -> com.checkmarx.eclipse.Activator.getImageDescriptor(anyString())).thenReturn(mock(ImageDescriptor.class));
+
+ List actions = actionFilters.createFilterActions();
+ assertEquals(5, actions.size());
+ assertEquals(ActionName.CRITICAL.name(), actions.get(0).getId());
+ assertEquals(ActionName.HIGH.name(), actions.get(1).getId());
+ assertEquals(ActionName.MEDIUM.name(), actions.get(2).getId());
+ assertEquals(ActionName.LOW.name(), actions.get(3).getId());
+ assertEquals(ActionName.INFO.name(), actions.get(4).getId());
+ for (Action action : actions) {
+ assertTrue(action.isEnabled());
+ assertTrue(action.isChecked());
+ assertNotNull(action.getToolTipText());
+ assertNotNull(action.getImageDescriptor());
+ }
+ }
+ }
+
+ @Test
+ void testCreateFilterActions_runActionPostsEvent() {
+ try (MockedStatic dp = Mockito.mockStatic(DataProvider.class);
+ MockedStatic fs = Mockito.mockStatic(com.checkmarx.eclipse.views.filters.FilterState.class);
+ MockedStatic activator = Mockito.mockStatic(com.checkmarx.eclipse.Activator.class);
+ MockedStatic pld = Mockito.mockStatic(PluginListenerDefinition.class, Mockito.CALLS_REAL_METHODS)) {
+
+ DataProvider provider = mock(DataProvider.class);
+ dp.when(DataProvider::getInstance).thenReturn(provider);
+ when(provider.containsResults()).thenReturn(true);
+ fs.when(() -> com.checkmarx.eclipse.views.filters.FilterState.isSeverityEnabled(anyString())).thenReturn(true);
+ activator.when(() -> com.checkmarx.eclipse.Activator.getImageDescriptor(anyString())).thenReturn(mock(ImageDescriptor.class));
+ when(provider.sortResults()).thenReturn(mock(List.class));
+
+ List actions = actionFilters.createFilterActions();
+ Action criticalAction = actions.get(0);
+ criticalAction.run();
+ ArgumentCaptor captor = ArgumentCaptor.forClass(PluginListenerDefinition.class);
+ verify(mockEventBus, atLeastOnce()).post(captor.capture());
+ PluginListenerDefinition event = captor.getValue();
+ assertEquals(PluginListenerType.FILTER_CHANGED, event.getListenerType());
+ }
+ }
+
+ @Test
+ void testCreateFilterActions_disabledUnchecked() {
+ try (MockedStatic dp = Mockito.mockStatic(DataProvider.class);
+ MockedStatic fs = Mockito.mockStatic(com.checkmarx.eclipse.views.filters.FilterState.class);
+ MockedStatic activator = Mockito.mockStatic(com.checkmarx.eclipse.Activator.class)) {
+
+ DataProvider provider = mock(DataProvider.class);
+ dp.when(DataProvider::getInstance).thenReturn(provider);
+ when(provider.containsResults()).thenReturn(false);
+ fs.when(() -> com.checkmarx.eclipse.views.filters.FilterState.isSeverityEnabled(anyString())).thenReturn(false);
+ activator.when(() -> com.checkmarx.eclipse.Activator.getImageDescriptor(anyString())).thenReturn(mock(ImageDescriptor.class));
+
+ List actions = actionFilters.createFilterActions();
+ for (Action action : actions) {
+ assertFalse(action.isEnabled());
+ assertFalse(action.isChecked());
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/checkmarx-ast-eclipse-plugin/.classpath b/checkmarx-ast-eclipse-plugin/.classpath
index d43ac0c..aeee534 100644
--- a/checkmarx-ast-eclipse-plugin/.classpath
+++ b/checkmarx-ast-eclipse-plugin/.classpath
@@ -10,10 +10,10 @@
-
+
-
+
@@ -28,4 +28,4 @@
-
+
\ No newline at end of file
diff --git a/checkmarx-ast-eclipse-plugin/META-INF/MANIFEST.MF b/checkmarx-ast-eclipse-plugin/META-INF/MANIFEST.MF
index 34b3bdb..2a0ef2a 100644
--- a/checkmarx-ast-eclipse-plugin/META-INF/MANIFEST.MF
+++ b/checkmarx-ast-eclipse-plugin/META-INF/MANIFEST.MF
@@ -27,8 +27,8 @@ Bundle-ClassPath: .,
lib/slf4j-reload4j-2.0.17.jar,
lib/slf4j-api-2.0.17.jar,
lib/jackson-annotations-2.21.jar,
- lib/jackson-core-2.21.0.jar,
- lib/jackson-databind-2.21.0.jar,
+ lib/jackson-core-2.21.1.jar,
+ lib/jackson-databind-2.21.1.jar,
lib/commons-lang3-3.18.0.jar,
lib/ast-cli-java-wrapper-2.4.21.jar,
lib/org.eclipse.mylyn.commons.ui_4.9.0.v20251121-0615.jar,
diff --git a/checkmarx-ast-eclipse-plugin/build.properties b/checkmarx-ast-eclipse-plugin/build.properties
index 07d565c..d3b18d2 100644
--- a/checkmarx-ast-eclipse-plugin/build.properties
+++ b/checkmarx-ast-eclipse-plugin/build.properties
@@ -6,11 +6,11 @@ bin.includes = plugin.xml,\
lib/slf4j-reload4j-2.0.17.jar,\
lib/slf4j-api-2.0.17.jar,\
lib/jackson-annotations-2.21.jar,\
- lib/jackson-core-2.21.0.jar,\
+ lib/jackson-core-2.21.1.jar,\
lib/commons-lang3-3.18.0.jar,\
lib/ast-cli-java-wrapper-2.4.21.jar,\
lib/org.eclipse.mylyn.commons.ui_4.9.0.v20251121-0615.jar,\
- lib/jackson-databind-2.21.0.jar,\
+ lib/jackson-databind-2.21.1.jar,\
.,\
lib/org-eclipse-mylyn-commons-core.jar
source.. = src/
diff --git a/checkmarx-ast-eclipse-plugin/lib/jackson-core-2.21.0.jar b/checkmarx-ast-eclipse-plugin/lib/jackson-core-2.21.1.jar
similarity index 71%
rename from checkmarx-ast-eclipse-plugin/lib/jackson-core-2.21.0.jar
rename to checkmarx-ast-eclipse-plugin/lib/jackson-core-2.21.1.jar
index ae05d27..e2cbe78 100644
Binary files a/checkmarx-ast-eclipse-plugin/lib/jackson-core-2.21.0.jar and b/checkmarx-ast-eclipse-plugin/lib/jackson-core-2.21.1.jar differ
diff --git a/checkmarx-ast-eclipse-plugin/lib/jackson-databind-2.21.0.jar b/checkmarx-ast-eclipse-plugin/lib/jackson-databind-2.21.1.jar
similarity index 88%
rename from checkmarx-ast-eclipse-plugin/lib/jackson-databind-2.21.0.jar
rename to checkmarx-ast-eclipse-plugin/lib/jackson-databind-2.21.1.jar
index 358b3a4..6e7af88 100644
Binary files a/checkmarx-ast-eclipse-plugin/lib/jackson-databind-2.21.0.jar and b/checkmarx-ast-eclipse-plugin/lib/jackson-databind-2.21.1.jar differ
diff --git a/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/properties/PreferencesPage.java b/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/properties/PreferencesPage.java
index 6eba644..49cb12d 100644
--- a/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/properties/PreferencesPage.java
+++ b/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/properties/PreferencesPage.java
@@ -14,6 +14,7 @@
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPreferencePage;
@@ -24,6 +25,13 @@
import com.checkmarx.eclipse.utils.PluginConstants;
import com.checkmarx.eclipse.utils.PluginUtils;
import org.eclipse.swt.widgets.Link;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.browser.IWorkbenchBrowserSupport;
+import org.eclipse.ui.PartInitException;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
public class PreferencesPage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage {
public PreferencesPage() {
@@ -84,12 +92,25 @@ protected void createFieldEditors() {
cliHelp.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, true, false));
GridData linkGridData = new GridData(SWT.END, SWT.CENTER, true, false);
cliHelp.setLayoutData(linkGridData);
+ cliHelp.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ IWorkbenchBrowserSupport browserSupport = PlatformUI.getWorkbench().getBrowserSupport();
+ try {
+ browserSupport.getExternalBrowser().openURL(new URL(e.text));
+ } catch (PartInitException | MalformedURLException e1) {
+ CxLogger.error("Failed to open CLI help documentation link.", e1);
+ e1.printStackTrace();
+ }
+ }
+ });
addField(space());
- Text connectionLabel = new Text(getFieldEditorParent(), SWT.MULTI | SWT.WRAP | SWT.READ_ONLY | SWT.V_SCROLL);
- //Set layout for scroll area to fit to page
- connectionLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ Label connectionLabel = new Label(getFieldEditorParent(), SWT.WRAP);
+ connectionLabel.setLayoutData(
+ new GridData(SWT.FILL, SWT.CENTER, true, false)
+ );
Button connectionButton = new Button(topComposite, SWT.PUSH);
connectionButton.setText(PluginConstants.PREFERENCES_TEST_CONNECTION);
@@ -138,4 +159,4 @@ public boolean performOk() {
return ok;
}
-}
+}
\ No newline at end of file
diff --git a/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/views/CheckmarxView.java b/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/views/CheckmarxView.java
index 01bdef6..43c16a4 100644
--- a/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/views/CheckmarxView.java
+++ b/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/views/CheckmarxView.java
@@ -1096,6 +1096,10 @@ public void handleEvent(Event event) {
@Override
public String getText(Object element) {
if (element instanceof Scan) {
+ // Always fetch the latest scan id from preferences before rendering
+ if(!GlobalSettings.getFromPreferences("LATEST_SCAN_ID", "").isEmpty()) {
+ latestScanId = GlobalSettings.getFromPreferences("LATEST_SCAN_ID", "");
+ }
Scan scan = (Scan) element;
return formatScanLabel(scan);
}
@@ -1201,15 +1205,30 @@ private Scan getLatestScanFromScanList(List scanList) {
* on the chosen scan id
*/
private void setSelectionForProjectComboViewer() {
- String scanId = scanIdComboViewer.getCombo().getText();
- if(scanId.isEmpty()) {
+ if(scanIdComboViewer.getCombo().getText().isEmpty()) {
PluginUtils.clearMessage(rootModel, resultsTree);
- CxLogger.info(String.format(PluginConstants.NO_SCAN_ID_PROVIDED, scanId));
+ PluginUtils.showMessage(rootModel, resultsTree, PluginConstants.NO_SCAN_ID_PROVIDED);
+ CxLogger.info(String.format(PluginConstants.NO_SCAN_ID_PROVIDED, PluginConstants.EMPTY_STRING));
return;
}
+
+ String scanIdText = scanIdComboViewer.getCombo().getText().trim();
+
+ String[] parts = scanIdText.split("\\s+");
+ if (parts.length >= 3) {
+ scanIdText = parts[2];
+ }
+
+ final String scanId = scanIdText;
if (currentScanId.equals(scanId)) {
+ PluginUtils.clearMessage(rootModel, resultsTree);
+ // reload cached results
+ List results = DataProvider.getInstance().sortResults();
+
+ rootModel.setChildren(results);
+ resultsTree.refresh();
PluginUtils.setTextForComboViewer(scanIdComboViewer, currentScanIdFormmated);
CxLogger.info(String.format(PluginConstants.INFO_RESULTS_ALREADY_RETRIEVED, scanId));
return;
@@ -2805,4 +2824,4 @@ private void preservCaretposition( List projectList, String searchText)
PluginUtils.setTextForComboViewer(projectComboViewer, searchText);
projectComboViewer.getCombo().setSelection(new Point(caretPos, caretPos));
}
-}
\ No newline at end of file
+}
diff --git a/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/views/actions/ActionStartScan.java b/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/views/actions/ActionStartScan.java
index 5815469..43a5cb9 100644
--- a/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/views/actions/ActionStartScan.java
+++ b/checkmarx-ast-eclipse-plugin/src/com/checkmarx/eclipse/views/actions/ActionStartScan.java
@@ -334,6 +334,25 @@ private Runnable pollingScan(String scanId) {
startScanAction.setEnabled(true);
if (scan.getStatus().toLowerCase(Locale.ROOT).equals(PluginConstants.CX_SCAN_COMPLETED_STATUS)) {
+ // Automatically update UI with new scan result
+ Display.getDefault().syncExec(new Runnable() {
+ @Override
+ public void run() {
+ // Fetch the latest scan list for the branch
+ List scanList = DataProvider.getInstance().getScansForProject(branchesCombo.getCombo().getText());
+ // Set the new scan as latest by updating preferences
+ GlobalSettings.storeInPreferences("LATEST_SCAN_ID", scanId);
+ // Set the scan list in the combo viewer
+ scansCombo.setInput(scanList);
+ // Set the new scan as selected
+ scansCombo.getCombo().setText(scanId);
+ // Post event to load results for the new scan
+ pluginEventBus.post(new PluginListenerDefinition(
+ PluginListenerType.LOAD_RESULTS_FOR_SCAN,
+ Collections.emptyList()));
+ }
+ });
+ // Show notification as before
Display.getDefault().syncExec(new Runnable() {
AbstractNotificationPopup notification;
@@ -347,8 +366,8 @@ PluginConstants.CX_LOAD_SCAN_RESULTS, new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
scansCombo.getCombo().setText(scanId);
pluginEventBus.post(new PluginListenerDefinition(
- PluginListenerType.LOAD_RESULTS_FOR_SCAN,
- Collections.emptyList()));
+ PluginListenerType.LOAD_RESULTS_FOR_SCAN,
+ Collections.emptyList()));
notification.close();
}
});
diff --git a/pom.xml b/pom.xml
index 2b001c1..ddc93a8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -33,7 +33,8 @@
${tycho.version}
-
+
org.eclipse.m2e
@@ -74,6 +75,7 @@
+
@@ -98,7 +100,8 @@
true
- -warn:+discouraged,+forbidden,-unavoidableGenericProblems,-warningToken
+
+ -warn:+discouraged,+forbidden,-unavoidableGenericProblems,-warningToken
@@ -115,7 +118,7 @@
${project.artifactId}_${unqualifiedVersion}.${buildQualifier}
-
+
@@ -145,10 +148,45 @@
x86_64
-
+
+
+ org.jacoco
+ jacoco-maven-plugin
+ 0.8.11
+
+
+
+ merge
+ verify
+
+ merge
+
+
+
+
+ .
+
+ **/target/jacoco.exec
+
+
+
+ ${project.build.directory}/jacoco.exec
+
+
+
+
+ report
+ verify
+
+ report-aggregate
+
+
+
+
+
@@ -164,9 +202,10 @@
https://download.eclipse.org/technology/swtbot/releases/latest
- orbit-4.32
- p2
- https://download.eclipse.org/tools/orbit/simrel/orbit-aggregation/release/4.32.0
+ orbit-4.32
+ p2
+
+ https://download.eclipse.org/tools/orbit/simrel/orbit-aggregation/release/4.32.0
mylyn
@@ -186,5 +225,5 @@
org.osgi.service.event
1.4.1
-
+