diff --git a/components/ide/ide-workspace/src/main/java/org/eclipse/dirigible/components/ide/workspace/service/ActionsService.java b/components/ide/ide-workspace/src/main/java/org/eclipse/dirigible/components/ide/workspace/service/ActionsService.java index 0afbd394b71..de2dfdf02a9 100644 --- a/components/ide/ide-workspace/src/main/java/org/eclipse/dirigible/components/ide/workspace/service/ActionsService.java +++ b/components/ide/ide-workspace/src/main/java/org/eclipse/dirigible/components/ide/workspace/service/ActionsService.java @@ -68,7 +68,7 @@ public int executeAction(String workspace, String project, String action) { ProjectMetadata projectJson = GsonHelper.fromJson(new String(fileObject.getContent()), ProjectMetadata.class); List actions = projectJson.getActions(); if (actions == null) { - logger.error("Actions section not found in the project descriptor file: " + project); + logger.debug("No actions section in the project descriptor file of project [{}]", project); } else { ProjectAction projectAction = actions.stream() .filter(a -> a.getName() @@ -196,7 +196,6 @@ public List listRegisteredActions(String workspace, String projec ProjectMetadata projectJson = GsonHelper.fromJson(new String(fileObject.getContent()), ProjectMetadata.class); List actions = projectJson.getActions(); if (actions == null) { - logger.error("Actions section not found in the project descriptor file: " + project); return new ArrayList(); } return actions; diff --git a/components/ide/ide-workspace/src/test/java/org/eclipse/dirigible/components/ide/workspace/service/ActionsServiceTest.java b/components/ide/ide-workspace/src/test/java/org/eclipse/dirigible/components/ide/workspace/service/ActionsServiceTest.java index 33edab12668..7b876fa5f15 100644 --- a/components/ide/ide-workspace/src/test/java/org/eclipse/dirigible/components/ide/workspace/service/ActionsServiceTest.java +++ b/components/ide/ide-workspace/src/test/java/org/eclipse/dirigible/components/ide/workspace/service/ActionsServiceTest.java @@ -11,12 +11,16 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; import org.apache.commons.lang3.SystemUtils; import org.eclipse.dirigible.commons.config.Configuration; import org.eclipse.dirigible.components.ide.workspace.domain.File; import org.eclipse.dirigible.components.ide.workspace.domain.Project; import org.eclipse.dirigible.components.ide.workspace.domain.Workspace; +import org.eclipse.dirigible.components.project.ProjectAction; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -27,6 +31,14 @@ import org.springframework.context.annotation.ComponentScan; import org.springframework.security.test.context.support.WithMockUser; import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.slf4j.LoggerFactory; + +import java.util.List; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.read.ListAppender; /** * The Class WorkspacesCoreServiceTest. @@ -48,6 +60,12 @@ public class ActionsServiceTest { @Autowired private WorkspaceService workspaceService; + /** Captures what the service logs while a test runs. */ + private ListAppender appender; + + /** The logger of the service under test. */ + private Logger serviceLogger; + /** The project json content. */ private static final String PROJECT_JSON_CONTENT = """ { @@ -69,6 +87,34 @@ public class ActionsServiceTest { } """; + /** A descriptor without an actions section - what a project that declares none looks like. */ + private static final String PROJECT_JSON_WITHOUT_ACTIONS = """ + { + "guid": "TestProject2" + } + """; + + /** + * Attaches the log appender. Spring re-initializes logback while the application context starts, so + * the appender is attached per test rather than in a field initializer. + */ + @BeforeEach + public void attachLogAppender() { + appender = new ListAppender<>(); + appender.start(); + serviceLogger = (Logger) LoggerFactory.getLogger(ActionsService.class); + serviceLogger.addAppender(appender); + } + + /** + * Detaches the log appender. + */ + @AfterEach + public void detachLogAppender() { + serviceLogger.detachAppender(appender); + appender.stop(); + } + /** * Publish with action test. @@ -127,6 +173,42 @@ public void publishWithoutActionTest() { } } + /** + * A project descriptor without an actions section is the normal case - it yields no actions and + * must not be reported as an error. + */ + @Test + public void projectWithoutActionsSectionIsNotAnError() { + workspaceService.createWorkspace("TestWorkspace2"); + workspaceService.createProject("TestWorkspace2", "TestProject2"); + workspaceService.createFile("TestWorkspace2", "TestProject2", "project.json", PROJECT_JSON_WITHOUT_ACTIONS.getBytes(), + "application/json"); + try { + List actions = actionsService.listRegisteredActions("TestWorkspace2", "TestProject2"); + assertTrue(actions.isEmpty()); + + int result = actionsService.executeAction("TestWorkspace2", "TestProject2", "MyAction"); + assertEquals(-1, result); + + List errors = loggedErrors(); + assertTrue(errors.isEmpty(), "unexpected error logged: " + errors); + } finally { + workspaceService.deleteWorkspace("TestWorkspace2"); + } + } + + /** + * Logged errors. + * + * @return the messages the service under test logged at ERROR + */ + private List loggedErrors() { + return appender.list.stream() + .filter(event -> event.getLevel() == Level.ERROR) + .map(ILoggingEvent::getFormattedMessage) + .toList(); + } + /** * The Class TestConfiguration. */