T lookup(Parent root, String selector) {
+
+ return (T) root.lookup(selector);
+ }
+
+
}
diff --git a/gui/src/test/java/com/devonfw/ide/gui/FakeProjectFolderStructureHelper.java b/gui/src/test/java/com/devonfw/ide/gui/FakeProjectFolderStructureHelper.java
new file mode 100644
index 0000000000..d6850e22c3
--- /dev/null
+++ b/gui/src/test/java/com/devonfw/ide/gui/FakeProjectFolderStructureHelper.java
@@ -0,0 +1,40 @@
+package com.devonfw.ide.gui;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+/**
+ * This class helps to create a fake project folder structure for testing. The projects are named in the format "project-{i}" and the workspaces are named
+ * "main".
+ *
+ * This class is supposed to be replaced by enabling ide-cli test dependencies allowing to mock a IdeContext
+ */
+public class FakeProjectFolderStructureHelper {
+
+ /**
+ * @param rootPath root path where fake structure should be created
+ * @return the rootPath
+ */
+ public static Path createFakeProjectFolderStructure(Path rootPath) throws IOException {
+
+ for (int i = 0; i <= 5; i++) {
+ String projectFolderName = "project-" + i;
+ assertThat(Files.createDirectory(rootPath.resolve(projectFolderName)))
+ .as("Unable to create mock project directory for mock project " + i)
+ .isNotNull();
+ assertThat(Files.createDirectory(rootPath.resolve(projectFolderName).resolve("workspaces")))
+ .as("Unable to create mock workspaces directory for mock project " + i)
+ .isNotNull();
+ assertThat(Files.createDirectory(rootPath.resolve(projectFolderName).resolve("workspaces").resolve("main")))
+ .as(
+ "Unable to create mock main workspace directory for mock project " + i)
+ .isNotNull();
+ }
+
+ return rootPath;
+ }
+
+}
diff --git a/gui/src/test/java/com/devonfw/ide/gui/HeadlessApplicationTest.java b/gui/src/test/java/com/devonfw/ide/gui/HeadlessApplicationTest.java
index 2e7298caac..3b51b66787 100644
--- a/gui/src/test/java/com/devonfw/ide/gui/HeadlessApplicationTest.java
+++ b/gui/src/test/java/com/devonfw/ide/gui/HeadlessApplicationTest.java
@@ -15,10 +15,11 @@ public abstract class HeadlessApplicationTest extends ApplicationTest {
System.setProperty("testfx.robot", "glass");
System.setProperty("testfx.headless", "true");
- System.setProperty("glass.platform", "Monocle");
System.setProperty("prism.order", "sw");
System.setProperty("prism.text", "t2k");
- System.setProperty("testfx.setup.timeout", "10000"); // increased timeout for testing on server-side CIs
System.setProperty("java.awt.headless", "true");
+ System.setProperty("glass.platform", "Monocle");
+ System.setProperty("monocle.platform", "Headless");
+ System.setProperty("testfx.setup.timeout", "10000"); // increased timeout for testing on server-side CIs
}
}
diff --git a/gui/src/test/java/com/devonfw/ide/gui/IdeGuiMockRootTest.java b/gui/src/test/java/com/devonfw/ide/gui/IdeGuiMockRootTest.java
new file mode 100644
index 0000000000..c650f7bf39
--- /dev/null
+++ b/gui/src/test/java/com/devonfw/ide/gui/IdeGuiMockRootTest.java
@@ -0,0 +1,24 @@
+package com.devonfw.ide.gui;
+
+import java.nio.file.Path;
+
+import org.junit.jupiter.api.io.CleanupMode;
+import org.junit.jupiter.api.io.TempDir;
+import org.testfx.framework.junit5.ApplicationTest;
+
+/**
+ * Provides the handling of mocking the IDE_ROOT directory to subclasses.
+ */
+public class IdeGuiMockRootTest extends ApplicationTest {
+
+ @TempDir(cleanup = CleanupMode.ON_SUCCESS)
+ private static Path mockIdeRoot;
+
+ /**
+ * @return a mock {@link Path} to a temporary IDE_ROOT directory.
+ */
+ public static Path getMockIdeRoot() {
+
+ return mockIdeRoot;
+ }
+}
diff --git a/gui/src/test/java/com/devonfw/ide/gui/context/IdeGuiStateManagerTest.java b/gui/src/test/java/com/devonfw/ide/gui/context/IdeGuiStateManagerTest.java
new file mode 100644
index 0000000000..c92f12e56f
--- /dev/null
+++ b/gui/src/test/java/com/devonfw/ide/gui/context/IdeGuiStateManagerTest.java
@@ -0,0 +1,114 @@
+package com.devonfw.ide.gui.context;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.stream.Stream;
+
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.devonfw.tools.ide.context.AbstractIdeContextTest;
+import com.devonfw.tools.ide.context.IdeTestContext;
+
+/**
+ * Tests for {@link IdeGuiStateManager}.
+ */
+public class IdeGuiStateManagerTest extends AbstractIdeContextTest {
+
+ private static final Logger LOG = LoggerFactory.getLogger(IdeGuiStateManagerTest.class);
+
+ private static IdeTestContext context;
+
+ private static IdeGuiStateManager guiStateManager;
+ private static ProjectManager projectManager;
+
+ @BeforeAll
+ static void setup() {
+
+ context = newContext("testProject", "project-0");
+ LOG.debug("root: {}", context.getIdeRoot());
+
+ guiStateManager = IdeGuiStateManager.getInstanceOverrideRootDir(context.getIdeRoot().toString());
+ projectManager = guiStateManager.getProjectManager();
+ }
+
+ @BeforeEach
+ void reset() {
+ IdeGuiStateManager.getInstanceOverrideRootDir(context.getIdeRoot().toString());
+ }
+
+ @Test
+ void testThrowsIfIdeRootNull() {
+
+ try {
+ IdeGuiStateManager.getInstanceOverrideRootDir(null);
+ } catch (IllegalArgumentException e) {
+ assertThat(e.getMessage()).contains("ideRoot must not be null!");
+ }
+ }
+
+ @Test
+ void testThrowsIfIdeRootDoesNotExist() {
+
+ try {
+ IdeGuiStateManager.getInstanceOverrideRootDir("nonExistingIdeRoot");
+ } catch (IllegalArgumentException e) {
+ assertThat(e.getMessage()).contains("Root directory does not exist");
+ }
+ }
+
+ @Test
+ void testGetContext() throws FileNotFoundException {
+
+ IdeGuiContext context = guiStateManager.switchContext(projectManager.getProjectNames().getFirst(), "main");
+ assertThat(context).isNotNull().as("context was null after switchContext was called"); // When switching to a project, the context should be set.
+ }
+
+ @Test
+ void testSwitchContext() {
+
+ projectManager.getProjectNames().forEach((projectName) -> {
+ try {
+ guiStateManager.switchContext(projectName, "main");
+ } catch (FileNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ });
+ }
+
+ @Test
+ void testThrowsIfNonExistentProjectSelected() {
+
+ Path fakeProject = context.getIdeRoot().resolve("nonExistingProject");
+
+ try {
+ guiStateManager.switchContext(fakeProject.getFileName().toString(), "main");
+ } catch (FileNotFoundException e) {
+ assertThat(e.getMessage()).contains("Project " + fakeProject + " does not exist!")
+ .as("GuiStateManager.switchContext should throw an exception, if a non-existent project is selected");
+ }
+ }
+
+ @Test
+ void testThrowsIfNonExistentWorkspaceSelected() throws IOException {
+
+ try (Stream stream = Files.list(context.getIdeRoot())) {
+ stream.forEach((projectPath) -> {
+ Path fakeWorkspacePath = projectPath.resolve("workspaces").resolve("nonExistingWorkspace");
+
+ try {
+ guiStateManager.switchContext(projectPath.getFileName().toString(), fakeWorkspacePath.getFileName().toString());
+ } catch (FileNotFoundException e) {
+ assertThat(e.getMessage()).contains("Workspace " + fakeWorkspacePath + " does not exist!")
+ .as("GuiStateManager.switchContext should throw an exception, if a non-existent workspace is selected");
+ }
+ });
+ }
+ }
+
+}
diff --git a/gui/src/test/java/com/devonfw/ide/gui/context/ProjectManagerTest.java b/gui/src/test/java/com/devonfw/ide/gui/context/ProjectManagerTest.java
new file mode 100644
index 0000000000..888c7aa308
--- /dev/null
+++ b/gui/src/test/java/com/devonfw/ide/gui/context/ProjectManagerTest.java
@@ -0,0 +1,132 @@
+package com.devonfw.ide.gui.context;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.NotDirectoryException;
+import java.nio.file.Path;
+
+import org.apache.commons.io.FileUtils;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import com.devonfw.tools.ide.context.AbstractIdeContextTest;
+import com.devonfw.tools.ide.context.IdeTestContext;
+
+/**
+ * Tests for the ProjectManager class.
+ */
+public class ProjectManagerTest extends AbstractIdeContextTest {
+
+ private static ProjectManager projectManager;
+
+ private static IdeTestContext context;
+ private static Path ideRoot;
+
+ @BeforeEach
+ void resetContext() {
+
+ context = newContext("testProject", "project-0");
+ ideRoot = context.getIdeRoot();
+ }
+
+ @Test
+ void testProjectManagerFull() throws NotDirectoryException {
+
+ projectManager = new ProjectManager(ideRoot);
+
+ assertThat(projectManager).isNotNull();
+ assertThat(projectManager.getProjectNames()).containsExactlyInAnyOrder("project-0", "project-1", "project-2", "project-3", "project-4", "project-5");
+ for (String projectName : projectManager.getProjectNames()) {
+ assertThat(projectManager.getWorkspaceNames(projectName)).containsExactlyInAnyOrder("foo-test", "main");
+ }
+ }
+
+ @Test
+ void testConstructorWithNullDirectory() {
+
+ try {
+ projectManager = new ProjectManager(null);
+ fail("IllegalArgumentException expected");
+ } catch (IllegalArgumentException e) {
+ assertThat(e.getMessage()).contains("Root directory is null");
+ }
+ }
+
+ @Test
+ void testConstructorWithNonExistentDirectory() {
+
+ try {
+
+ projectManager = new ProjectManager(ideRoot.resolve("nonExistent"));
+ fail("IllegalArgumentException expected");
+ } catch (IllegalArgumentException e) {
+ assertThat(e.getMessage()).contains("Root directory does not exist");
+ }
+ }
+
+ @Test
+ void testConstructorWithFile() throws IOException {
+
+ try {
+ File testFile = ideRoot.resolve("testFile").toFile();
+ boolean success = testFile.createNewFile();
+ if (!success) {
+ throw new RuntimeException("Unable to create test file");
+ }
+
+ projectManager = new ProjectManager(ideRoot.resolve("testFile"));
+ fail("IllegalArgumentException expected");
+ } catch (IllegalArgumentException e) {
+ assertThat(e.getMessage()).contains("Root directory is not a directory");
+ } finally {
+ Files.deleteIfExists(ideRoot.resolve("testFile"));
+ }
+ }
+
+ @Test
+ void testRefreshProjects() throws IOException {
+
+ projectManager = new ProjectManager(ideRoot);
+ assertThat(projectManager.getProjectNames()).containsExactlyInAnyOrder("project-0", "project-1", "project-2", "project-3", "project-4", "project-5");
+
+ Path project0 = ideRoot.resolve("project-0");
+ Path project6 = ideRoot.resolve("project-6");
+ FileUtils.copyDirectory(project0.toFile(), project6.toFile());
+
+ // Verify that project-6 is now recognized
+ assertThat(projectManager.getProjectNames()).containsExactlyInAnyOrder("project-0", "project-1", "project-2", "project-3", "project-4", "project-5",
+ "project-6");
+ assertThat(projectManager.getWorkspaceNames("project-6")).containsExactlyInAnyOrder("foo-test", "main");
+
+ // Cleanup
+ FileUtils.deleteDirectory(project0.toFile());
+ }
+
+ @Test
+ void testReadProjectsExcludesFoldersWithoutWorkspaces() throws IOException {
+
+ // Create a project folder without a workspaces subdirectory
+ Path testProject = ideRoot.resolve("test-project-no-workspaces");
+ Files.createDirectory(testProject);
+
+ projectManager = new ProjectManager(ideRoot);
+
+ // Verify that test-project-no-workspaces is not recognized
+ assertThat(projectManager.getProjectNames()).doesNotContain("test-project-no-workspaces");
+ assertThat(projectManager.getProjectNames()).containsExactlyInAnyOrder("project-0", "project-1", "project-2", "project-3", "project-4", "project-5");
+
+ // Cleanup
+ FileUtils.deleteDirectory(testProject.toFile());
+ }
+
+ @Test
+ void testReadProjectsExcludesUnderscorePrefixedFolders() {
+
+ projectManager = new ProjectManager(ideRoot);
+
+ // Verify that _ide folder is not in the project names
+ assertThat(projectManager.getProjectNames()).doesNotContain("_ide");
+ assertThat(projectManager.getProjectNames()).containsExactlyInAnyOrder("project-0", "project-1", "project-2", "project-3", "project-4", "project-5");
+ }
+}
diff --git a/gui/src/test/java/com/devonfw/ide/gui/i18n/I18nServiceTest.java b/gui/src/test/java/com/devonfw/ide/gui/i18n/I18nServiceTest.java
new file mode 100644
index 0000000000..d4549d9bf3
--- /dev/null
+++ b/gui/src/test/java/com/devonfw/ide/gui/i18n/I18nServiceTest.java
@@ -0,0 +1,114 @@
+package com.devonfw.ide.gui.i18n;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.ResourceBundle;
+import java.util.Set;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests for {@link I18nService} - verifies locale switching, bundle loading, and fallback behavior.
+ */
+public class I18nServiceTest {
+
+ private Set englishKeys;
+
+ @BeforeEach
+ public void setUp() {
+
+ // Reset the singleton instance before each test
+ I18nService.resetInstance();
+ // Preload English bundle keys used by bundle-completion tests
+ ResourceBundle englishBundle = ResourceBundle.getBundle("i18n.messages", Locale.ENGLISH);
+ this.englishKeys = extractKeys(englishBundle);
+ }
+
+ @Test
+ public void testGetInstanceWithLocale() {
+
+ Locale englishLocale = Locale.ENGLISH;
+ I18nService service = I18nService.getInstance(englishLocale);
+
+ assertThat(service.getLocale()).isEqualTo(englishLocale);
+ assertThat(service.getResourceBundle()).isNotNull();
+ }
+
+ @Test
+ public void testGetInstanceSingleton() {
+
+ I18nService service1 = I18nService.getInstance(Locale.ENGLISH);
+ I18nService service2 = I18nService.getInstance();
+
+ assertThat(service1).isSameAs(service2);
+ }
+
+ @Test
+ public void testSetLocale() {
+
+ I18nService service = I18nService.getInstance(Locale.ENGLISH);
+ service.setLocale(Locale.GERMAN);
+
+ assertThat(service.getLocale().getLanguage()).isEqualTo("de");
+ assertThat(service.getResourceBundle()).isNotNull();
+ }
+
+
+ @Test
+ public void testGetMissingKeyReturnsFallback() {
+
+ I18nService service = I18nService.getInstance(Locale.ENGLISH);
+ String value = service.get("non.existent.key");
+
+ assertThat(value).isEqualTo("!non.existent.key!");
+ }
+
+
+ @Test
+ public void testGermanBundleCompleteWithAllEnglishKeys() {
+
+ ResourceBundle germanBundle = ResourceBundle.getBundle("i18n.messages", Locale.GERMAN);
+ Set germanKeys = extractKeys(germanBundle);
+
+ assertThat(germanKeys).as("German bundle must contain all keys from English bundle").containsAll(this.englishKeys);
+ }
+
+ @Test
+ public void testGermanBundleDoesNotHaveExtraKeys() {
+
+ ResourceBundle germanBundle = ResourceBundle.getBundle("i18n.messages", Locale.GERMAN);
+ Set germanKeys = extractKeys(germanBundle);
+
+ assertThat(this.englishKeys).as("German bundle should not have extra keys beyond the English bundle").containsAll(germanKeys);
+ }
+
+ @Test
+ public void testNoEmptyTranslations() {
+
+ ResourceBundle englishBundle = ResourceBundle.getBundle("i18n.messages", Locale.ENGLISH);
+ for (String key : this.englishKeys) {
+ String value = englishBundle.getString(key);
+ assertThat(value).isNotBlank()
+ .as("Translation for key '%s' should not be empty", key);
+ }
+ }
+
+ private Set extractKeys(ResourceBundle bundle) {
+
+ Set keys = new HashSet<>();
+ Enumeration enumeration = bundle.getKeys();
+ while (enumeration.hasMoreElements()) {
+ keys.add(enumeration.nextElement());
+ }
+ return keys;
+ }
+
+
+}
+
+
+
diff --git a/gui/src/test/resources/ide-projects/testProject/_ide/placeholder b/gui/src/test/resources/ide-projects/testProject/_ide/placeholder
new file mode 100644
index 0000000000..aefe683d65
--- /dev/null
+++ b/gui/src/test/resources/ide-projects/testProject/_ide/placeholder
@@ -0,0 +1 @@
+placeholder so _ide gets read correctly
diff --git a/gui/src/test/resources/ide-projects/testProject/project-0/settings/ide.properties b/gui/src/test/resources/ide-projects/testProject/project-0/settings/ide.properties
new file mode 100644
index 0000000000..71b1d7cd74
--- /dev/null
+++ b/gui/src/test/resources/ide-projects/testProject/project-0/settings/ide.properties
@@ -0,0 +1,4 @@
+#********************************************************************************
+# This file contains project specific environment variables.
+# THIS IS ONLY A PLACEHOLDER FILE FOR TESTING; Tests will fail if not provided.
+#********************************************************************************
diff --git a/gui/src/test/resources/ide-projects/testProject/project-0/workspaces/foo-test/placeholder b/gui/src/test/resources/ide-projects/testProject/project-0/workspaces/foo-test/placeholder
new file mode 100644
index 0000000000..53a33fa0c2
--- /dev/null
+++ b/gui/src/test/resources/ide-projects/testProject/project-0/workspaces/foo-test/placeholder
@@ -0,0 +1 @@
+this is the foo-bar workspace
diff --git a/gui/src/test/resources/ide-projects/testProject/project-0/workspaces/main/placeholder b/gui/src/test/resources/ide-projects/testProject/project-0/workspaces/main/placeholder
new file mode 100644
index 0000000000..c0a75dc8ee
--- /dev/null
+++ b/gui/src/test/resources/ide-projects/testProject/project-0/workspaces/main/placeholder
@@ -0,0 +1 @@
+this is the main workspace
diff --git a/gui/src/test/resources/ide-projects/testProject/project-1/settings/ide.properties b/gui/src/test/resources/ide-projects/testProject/project-1/settings/ide.properties
new file mode 100644
index 0000000000..71b1d7cd74
--- /dev/null
+++ b/gui/src/test/resources/ide-projects/testProject/project-1/settings/ide.properties
@@ -0,0 +1,4 @@
+#********************************************************************************
+# This file contains project specific environment variables.
+# THIS IS ONLY A PLACEHOLDER FILE FOR TESTING; Tests will fail if not provided.
+#********************************************************************************
diff --git a/gui/src/test/resources/ide-projects/testProject/project-1/workspaces/foo-test/placeholder b/gui/src/test/resources/ide-projects/testProject/project-1/workspaces/foo-test/placeholder
new file mode 100644
index 0000000000..53a33fa0c2
--- /dev/null
+++ b/gui/src/test/resources/ide-projects/testProject/project-1/workspaces/foo-test/placeholder
@@ -0,0 +1 @@
+this is the foo-bar workspace
diff --git a/gui/src/test/resources/ide-projects/testProject/project-1/workspaces/main/placeholder b/gui/src/test/resources/ide-projects/testProject/project-1/workspaces/main/placeholder
new file mode 100644
index 0000000000..c0a75dc8ee
--- /dev/null
+++ b/gui/src/test/resources/ide-projects/testProject/project-1/workspaces/main/placeholder
@@ -0,0 +1 @@
+this is the main workspace
diff --git a/gui/src/test/resources/ide-projects/testProject/project-2/settings/ide.properties b/gui/src/test/resources/ide-projects/testProject/project-2/settings/ide.properties
new file mode 100644
index 0000000000..71b1d7cd74
--- /dev/null
+++ b/gui/src/test/resources/ide-projects/testProject/project-2/settings/ide.properties
@@ -0,0 +1,4 @@
+#********************************************************************************
+# This file contains project specific environment variables.
+# THIS IS ONLY A PLACEHOLDER FILE FOR TESTING; Tests will fail if not provided.
+#********************************************************************************
diff --git a/gui/src/test/resources/ide-projects/testProject/project-2/workspaces/foo-test/placeholder b/gui/src/test/resources/ide-projects/testProject/project-2/workspaces/foo-test/placeholder
new file mode 100644
index 0000000000..53a33fa0c2
--- /dev/null
+++ b/gui/src/test/resources/ide-projects/testProject/project-2/workspaces/foo-test/placeholder
@@ -0,0 +1 @@
+this is the foo-bar workspace
diff --git a/gui/src/test/resources/ide-projects/testProject/project-2/workspaces/main/placeholder b/gui/src/test/resources/ide-projects/testProject/project-2/workspaces/main/placeholder
new file mode 100644
index 0000000000..c0a75dc8ee
--- /dev/null
+++ b/gui/src/test/resources/ide-projects/testProject/project-2/workspaces/main/placeholder
@@ -0,0 +1 @@
+this is the main workspace
diff --git a/gui/src/test/resources/ide-projects/testProject/project-3/settings/ide.properties b/gui/src/test/resources/ide-projects/testProject/project-3/settings/ide.properties
new file mode 100644
index 0000000000..71b1d7cd74
--- /dev/null
+++ b/gui/src/test/resources/ide-projects/testProject/project-3/settings/ide.properties
@@ -0,0 +1,4 @@
+#********************************************************************************
+# This file contains project specific environment variables.
+# THIS IS ONLY A PLACEHOLDER FILE FOR TESTING; Tests will fail if not provided.
+#********************************************************************************
diff --git a/gui/src/test/resources/ide-projects/testProject/project-3/workspaces/foo-test/placeholder b/gui/src/test/resources/ide-projects/testProject/project-3/workspaces/foo-test/placeholder
new file mode 100644
index 0000000000..53a33fa0c2
--- /dev/null
+++ b/gui/src/test/resources/ide-projects/testProject/project-3/workspaces/foo-test/placeholder
@@ -0,0 +1 @@
+this is the foo-bar workspace
diff --git a/gui/src/test/resources/ide-projects/testProject/project-3/workspaces/main/placeholder b/gui/src/test/resources/ide-projects/testProject/project-3/workspaces/main/placeholder
new file mode 100644
index 0000000000..c0a75dc8ee
--- /dev/null
+++ b/gui/src/test/resources/ide-projects/testProject/project-3/workspaces/main/placeholder
@@ -0,0 +1 @@
+this is the main workspace
diff --git a/gui/src/test/resources/ide-projects/testProject/project-4/settings/ide.properties b/gui/src/test/resources/ide-projects/testProject/project-4/settings/ide.properties
new file mode 100644
index 0000000000..71b1d7cd74
--- /dev/null
+++ b/gui/src/test/resources/ide-projects/testProject/project-4/settings/ide.properties
@@ -0,0 +1,4 @@
+#********************************************************************************
+# This file contains project specific environment variables.
+# THIS IS ONLY A PLACEHOLDER FILE FOR TESTING; Tests will fail if not provided.
+#********************************************************************************
diff --git a/gui/src/test/resources/ide-projects/testProject/project-4/workspaces/foo-test/placeholder b/gui/src/test/resources/ide-projects/testProject/project-4/workspaces/foo-test/placeholder
new file mode 100644
index 0000000000..53a33fa0c2
--- /dev/null
+++ b/gui/src/test/resources/ide-projects/testProject/project-4/workspaces/foo-test/placeholder
@@ -0,0 +1 @@
+this is the foo-bar workspace
diff --git a/gui/src/test/resources/ide-projects/testProject/project-4/workspaces/main/placeholder b/gui/src/test/resources/ide-projects/testProject/project-4/workspaces/main/placeholder
new file mode 100644
index 0000000000..c0a75dc8ee
--- /dev/null
+++ b/gui/src/test/resources/ide-projects/testProject/project-4/workspaces/main/placeholder
@@ -0,0 +1 @@
+this is the main workspace
diff --git a/gui/src/test/resources/ide-projects/testProject/project-5/settings/ide.properties b/gui/src/test/resources/ide-projects/testProject/project-5/settings/ide.properties
new file mode 100644
index 0000000000..71b1d7cd74
--- /dev/null
+++ b/gui/src/test/resources/ide-projects/testProject/project-5/settings/ide.properties
@@ -0,0 +1,4 @@
+#********************************************************************************
+# This file contains project specific environment variables.
+# THIS IS ONLY A PLACEHOLDER FILE FOR TESTING; Tests will fail if not provided.
+#********************************************************************************
diff --git a/gui/src/test/resources/ide-projects/testProject/project-5/workspaces/foo-test/placeholder b/gui/src/test/resources/ide-projects/testProject/project-5/workspaces/foo-test/placeholder
new file mode 100644
index 0000000000..53a33fa0c2
--- /dev/null
+++ b/gui/src/test/resources/ide-projects/testProject/project-5/workspaces/foo-test/placeholder
@@ -0,0 +1 @@
+this is the foo-bar workspace
diff --git a/gui/src/test/resources/ide-projects/testProject/project-5/workspaces/main/placeholder b/gui/src/test/resources/ide-projects/testProject/project-5/workspaces/main/placeholder
new file mode 100644
index 0000000000..c0a75dc8ee
--- /dev/null
+++ b/gui/src/test/resources/ide-projects/testProject/project-5/workspaces/main/placeholder
@@ -0,0 +1 @@
+this is the main workspace