diff --git a/grails-cli/src/main/java/org/grails/forge/cli/command/CreateServiceCommand.java b/grails-cli/src/main/java/org/grails/forge/cli/command/CreateServiceCommand.java new file mode 100644 index 00000000..c6e73359 --- /dev/null +++ b/grails-cli/src/main/java/org/grails/forge/cli/command/CreateServiceCommand.java @@ -0,0 +1,85 @@ +/* + * Copyright 2017-2020 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.grails.forge.cli.command; + +import io.micronaut.context.annotation.Parameter; +import io.micronaut.core.annotation.ReflectiveAccess; +import io.micronaut.core.util.functional.ThrowingSupplier; +import jakarta.inject.Inject; +import org.grails.forge.application.Project; +import org.grails.forge.cli.CodeGenConfig; +import org.grails.forge.cli.command.templates.service; +import org.grails.forge.cli.command.templates.serviceSpec; +import org.grails.forge.io.ConsoleOutput; +import org.grails.forge.io.OutputHandler; +import org.grails.forge.template.RenderResult; +import org.grails.forge.template.RockerTemplate; +import org.grails.forge.template.TemplateRenderer; +import picocli.CommandLine; + +import java.io.IOException; + +@CommandLine.Command(name = CreateServiceCommand.NAME, description = "Creates a Service Class") +public class CreateServiceCommand extends CodeGenCommand { + + public static final String NAME = "create-service"; + + @ReflectiveAccess + @CommandLine.Parameters(paramLabel = "SERVICE-NAME", description = "The name of the service to create") + String serviceName; + + @Inject + public CreateServiceCommand(@Parameter CodeGenConfig config) { + super(config); + } + + public CreateServiceCommand(CodeGenConfig config, + ThrowingSupplier outputHandlerSupplier, + ConsoleOutput consoleOutput) { + super(config, outputHandlerSupplier, consoleOutput); + } + + @Override + public boolean applies() { + return true; + } + + @Override + public Integer call() throws Exception { + final Project project = getProject(serviceName); + final TemplateRenderer templateRenderer = getTemplateRenderer(project); + final RenderResult renderResult = templateRenderer.render(new RockerTemplate("grails-app/services/{packagePath}/{className}Service.groovy", service.template(project)), overwrite); + final RenderResult specRenderResult = templateRenderer.render(new RockerTemplate("src/test/groovy/{packagePath}/{className}ServiceSpec.groovy", serviceSpec.template(project)), overwrite); + if (renderResult != null && specRenderResult != null) { + logRenderResult(renderResult); + logRenderResult(specRenderResult); + } + + return 0; + } + + private void logRenderResult(RenderResult result) throws Exception { + if (result != null) { + if (result.isSuccess()) { + out("@|blue ||@ Rendered service class to " + result.getPath()); + } else if (result.isSkipped()) { + warning("Rendering skipped for " + result.getPath() + " because it already exists. Run again with -f to overwrite."); + } else if (result.getError() != null) { + throw result.getError(); + } + } + } +} diff --git a/grails-cli/src/main/java/org/grails/forge/cli/command/templates/service.rocker.raw b/grails-cli/src/main/java/org/grails/forge/cli/command/templates/service.rocker.raw new file mode 100644 index 00000000..da490245 --- /dev/null +++ b/grails-cli/src/main/java/org/grails/forge/cli/command/templates/service.rocker.raw @@ -0,0 +1,20 @@ +@import org.grails.forge.application.Project + +@args ( + Project project +) + +@if(project.getPackageName() != null) { +package @project.getPackageName() + +} + +import groovy.transform.CompileStatic + +@@CompileStatic +class @project.getClassName()Service { + + def doSomething() { + + } +} \ No newline at end of file diff --git a/grails-cli/src/main/java/org/grails/forge/cli/command/templates/serviceSpec.rocker.raw b/grails-cli/src/main/java/org/grails/forge/cli/command/templates/serviceSpec.rocker.raw new file mode 100644 index 00000000..4c66b0ce --- /dev/null +++ b/grails-cli/src/main/java/org/grails/forge/cli/command/templates/serviceSpec.rocker.raw @@ -0,0 +1,21 @@ +@import org.grails.forge.application.Project + +@args ( + Project project +) + +@if(project.getPackageName() != null) { +package @project.getPackageName() + +} + +import grails.testing.services.ServiceUnitTest +import spock.lang.Specification + +class @project.getClassName()ServiceSpec extends Specification implements ServiceUnitTest<@project.getClassName()Service> { + + void "test something"() { + expect: + service.doSomething() + } +} diff --git a/grails-cli/src/test/groovy/org/grails/forge/cli/command/CreateServiceCommandSpec.groovy b/grails-cli/src/test/groovy/org/grails/forge/cli/command/CreateServiceCommandSpec.groovy new file mode 100644 index 00000000..eb982662 --- /dev/null +++ b/grails-cli/src/test/groovy/org/grails/forge/cli/command/CreateServiceCommandSpec.groovy @@ -0,0 +1,71 @@ +package org.grails.forge.cli.command + +import io.micronaut.context.ApplicationContext +import org.grails.forge.application.ApplicationType +import org.grails.forge.cli.CodeGenConfig +import org.grails.forge.cli.CommandFixture +import org.grails.forge.cli.CommandSpec +import org.grails.forge.io.ConsoleOutput +import spock.lang.AutoCleanup +import spock.lang.Shared + +class CreateServiceCommandSpec extends CommandSpec implements CommandFixture { + + @Shared + @AutoCleanup + ApplicationContext beanContext = ApplicationContext.run() + + + void "test creating a service"() { + + setup: + generateProject(ApplicationType.WEB) + CodeGenConfig codeGenConfig = CodeGenConfig.load(beanContext, dir, ConsoleOutput.NOOP) + ConsoleOutput consoleOutput = Mock(ConsoleOutput) + CreateServiceCommand command = new CreateServiceCommand(codeGenConfig, getOutputHandler(consoleOutput), consoleOutput) + command.serviceName = "test" + + when: + Integer exitCode = command.call() + File output = new File(dir, "grails-app/services/example/grails/TestService.groovy") + File specOutput = new File(dir, "src/test/groovy/example/grails/TestServiceSpec.groovy") + + then: + exitCode == 0 + output.exists() + specOutput.exists() + 2 * consoleOutput.out({ it.contains("Rendered service") }) + } + + void "test app with service"() { + setup: + generateProject(ApplicationType.WEB) + CodeGenConfig codeGenConfig = CodeGenConfig.load(beanContext, dir, ConsoleOutput.NOOP) + ConsoleOutput consoleOutput = Mock(ConsoleOutput) + CreateServiceCommand command = new CreateServiceCommand(codeGenConfig, getOutputHandler(consoleOutput), consoleOutput) + + when: + command.serviceName = 'test' + Integer exitCode = command.call() + executeGradleCommand("test") + + then: + exitCode == 0 + testOutputContains("TestServiceSpec > test something FAILED") + + when: + new File(dir, "grails-app/services/example/grails/TestService.groovy").text = '''package example.grails + +class TestService { + + String doSomething() { + "something" + } +}''' + + executeGradleCommand("test") + + then: + testOutputContains("BUILD SUCCESSFUL") + } +} diff --git a/test-core/src/test/groovy/org/grails/forge/cli/command/CreateServiceSpec.groovy b/test-core/src/test/groovy/org/grails/forge/cli/command/CreateServiceSpec.groovy new file mode 100644 index 00000000..9b91e01a --- /dev/null +++ b/test-core/src/test/groovy/org/grails/forge/cli/command/CreateServiceSpec.groovy @@ -0,0 +1,31 @@ +package org.grails.forge.cli.command + +import io.micronaut.configuration.picocli.PicocliRunner +import org.grails.forge.cli.CodeGenConfig +import org.grails.forge.utils.CommandSpec +import spock.lang.Ignore + +class CreateServiceSpec extends CommandSpec { + + @Ignore + void "test create-service command"() { + when: + generateProjectWithDefaults() + applicationContext.createBean(CodeGenConfig.class, new CodeGenConfig()) + + then: + applicationContext.getBean(CodeGenConfig.class) + + when: + PicocliRunner.run(CreateServiceCommand.class, applicationContext, "Test") + + then: + new File(dir, "grails-app/controllers/example/grails/TestService.groovy").exists() + + } + + @Override + String getTempDirectoryPrefix() { + return "test-app" + } +}