From b2e50fa8e486305b4d2b7f83bbfe29c6ef8f29f6 Mon Sep 17 00:00:00 2001 From: Puneet Behl Date: Mon, 25 Sep 2023 13:36:20 +0530 Subject: [PATCH] Add command create-interceptor --- .../cli/command/CreateInterceptorCommand.java | 85 ++++++++++++ .../command/templates/interceptor.rocker.raw | 22 +++ .../templates/interceptorSpec.rocker.raw | 24 ++++ .../CreateInterceptorCommandSpec.groovy | 127 ++++++++++++++++++ .../cli/command/CreateInterceptorSpec.groovy | 32 +++++ 5 files changed, 290 insertions(+) create mode 100644 grails-cli/src/main/java/org/grails/forge/cli/command/CreateInterceptorCommand.java create mode 100644 grails-cli/src/main/java/org/grails/forge/cli/command/templates/interceptor.rocker.raw create mode 100644 grails-cli/src/main/java/org/grails/forge/cli/command/templates/interceptorSpec.rocker.raw create mode 100644 grails-cli/src/test/groovy/org/grails/forge/cli/command/CreateInterceptorCommandSpec.groovy create mode 100644 test-core/src/test/groovy/org/grails/forge/cli/command/CreateInterceptorSpec.groovy diff --git a/grails-cli/src/main/java/org/grails/forge/cli/command/CreateInterceptorCommand.java b/grails-cli/src/main/java/org/grails/forge/cli/command/CreateInterceptorCommand.java new file mode 100644 index 00000000..4457a413 --- /dev/null +++ b/grails-cli/src/main/java/org/grails/forge/cli/command/CreateInterceptorCommand.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.interceptor; +import org.grails.forge.cli.command.templates.interceptorSpec; +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 = CreateInterceptorCommand.NAME, description = "Creates a Interceptor Class") +public class CreateInterceptorCommand extends CodeGenCommand { + + public static final String NAME = "create-interceptor"; + + @ReflectiveAccess + @CommandLine.Parameters(paramLabel = "INTERCEPTOR-NAME", description = "The name of the interceptor to create") + String interceptorName; + + @Inject + public CreateInterceptorCommand(@Parameter CodeGenConfig config) { + super(config); + } + + public CreateInterceptorCommand(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(interceptorName); + final TemplateRenderer templateRenderer = getTemplateRenderer(project); + final RenderResult renderResult = templateRenderer.render(new RockerTemplate("grails-app/controllers/{packagePath}/{className}Interceptor.groovy", interceptor.template(project)), overwrite); + final RenderResult specRenderResult = templateRenderer.render(new RockerTemplate("src/test/groovy/{packagePath}/{className}InterceptorSpec.groovy", interceptorSpec.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 interceptor 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/interceptor.rocker.raw b/grails-cli/src/main/java/org/grails/forge/cli/command/templates/interceptor.rocker.raw new file mode 100644 index 00000000..81e4e7d8 --- /dev/null +++ b/grails-cli/src/main/java/org/grails/forge/cli/command/templates/interceptor.rocker.raw @@ -0,0 +1,22 @@ +@import org.grails.forge.application.Project + +@args ( + Project project +) + +@if(project.getPackageName() != null) { +package @project.getPackageName() + +} + +class @project.getClassName()Interceptor { + + boolean before() { true } + + boolean after() { true } + + void afterView() { + // no-op + } + +} \ No newline at end of file diff --git a/grails-cli/src/main/java/org/grails/forge/cli/command/templates/interceptorSpec.rocker.raw b/grails-cli/src/main/java/org/grails/forge/cli/command/templates/interceptorSpec.rocker.raw new file mode 100644 index 00000000..2e032aa1 --- /dev/null +++ b/grails-cli/src/main/java/org/grails/forge/cli/command/templates/interceptorSpec.rocker.raw @@ -0,0 +1,24 @@ +@import org.grails.forge.application.Project + +@args ( + Project project +) + +@if(project.getPackageName() != null) { +package @project.getPackageName() + +} + +import grails.testing.web.interceptor.InterceptorUnitTest +import spock.lang.Specification + +class @project.getClassName()InterceptorSpec extends Specification implements InterceptorUnitTest<@project.getClassName()Interceptor> { + + void "test interceptor matching"() { + when: + withRequest(controller: "@project.getClassName().toLowerCase()") + + then: + interceptor.doesMatch() + } +} diff --git a/grails-cli/src/test/groovy/org/grails/forge/cli/command/CreateInterceptorCommandSpec.groovy b/grails-cli/src/test/groovy/org/grails/forge/cli/command/CreateInterceptorCommandSpec.groovy new file mode 100644 index 00000000..83b34d9e --- /dev/null +++ b/grails-cli/src/test/groovy/org/grails/forge/cli/command/CreateInterceptorCommandSpec.groovy @@ -0,0 +1,127 @@ +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 CreateInterceptorCommandSpec 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) + CreateInterceptorCommand command = new CreateInterceptorCommand(codeGenConfig, getOutputHandler(consoleOutput), consoleOutput) + command.interceptorName = "test" + + when: + Integer exitCode = command.call() + File output = new File(dir, "grails-app/controllers/example/grails/TestInterceptor.groovy") + File specOutput = new File(dir, "src/test/groovy/example/grails/TestInterceptorSpec.groovy") + + then: + exitCode == 0 + output.exists() + specOutput.exists() + 2 * consoleOutput.out({ it.contains("Rendered interceptor") }) + } + + void "test app with interceptor"() { + setup: + generateProject(ApplicationType.WEB) + CodeGenConfig codeGenConfig = CodeGenConfig.load(beanContext, dir, ConsoleOutput.NOOP) + ConsoleOutput consoleOutput = Mock(ConsoleOutput) + CreateInterceptorCommand command = new CreateInterceptorCommand(codeGenConfig, getOutputHandler(consoleOutput), consoleOutput) + + new File(dir, "grails-app/controllers/example/grails/TestController.groovy").text = '''package example.grails + +class TestController { + + def index() { + render request.getAttribute('foo') + } + +}''' + + + when: + command.interceptorName = 'test' + Integer exitCode = command.call() + executeGradleCommand("test") + + then: + exitCode == 0 + testOutputContains("BUILD SUCCESSFUL") + + when: + new File(dir, "src/test/groovy/example/grails/TestInterceptorSpec.groovy").text = '''package example.grails + +import grails.testing.web.interceptor.InterceptorUnitTest +import spock.lang.Specification + +class TestInterceptorSpec extends Specification implements InterceptorUnitTest { + + void "test interceptor matching"() { + when: + withRequest(controller: "test") + + then: + interceptor.doesMatch() + + when: + withRequest(controller: "person") + + then: + !interceptor.doesMatch() + } + + void "test controller execution with interceptors"() { + given: + def controller = (TestController)mockController(TestController) + + when: + withInterceptors([controller: "test"]) { + controller.renderAttribute() + } + + then: + response.text == "Foo is Bar" + } +}''' + executeGradleCommand("test") + + then: + testOutputContains("TestInterceptorSpec > test controller execution with interceptors FAILED") + + when: + new File(dir, "grails-app/controllers/example/grails/TestInterceptor.groovy").text = '''package example.grails + +class TestInterceptor { + + TestInterceptor() { + match(controller: "test") + } + + boolean before() { + request.setAttribute('foo', 'Foo is Bar') + true + } +}''' + + executeGradleCommand("test") + + then: + testOutputContains("BUILD SUCCESSFUL") + } +} diff --git a/test-core/src/test/groovy/org/grails/forge/cli/command/CreateInterceptorSpec.groovy b/test-core/src/test/groovy/org/grails/forge/cli/command/CreateInterceptorSpec.groovy new file mode 100644 index 00000000..cddd897f --- /dev/null +++ b/test-core/src/test/groovy/org/grails/forge/cli/command/CreateInterceptorSpec.groovy @@ -0,0 +1,32 @@ +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 CreateInterceptorSpec extends CommandSpec { + + @Ignore + void "test create-interceptor command"() { + when: + generateProjectWithDefaults() + applicationContext.createBean(CodeGenConfig.class, new CodeGenConfig()) + + then: + applicationContext.getBean(CodeGenConfig.class) + + when: + PicocliRunner.run(CreateInterceptorCommand.class, applicationContext, "test") + + then: + new File(dir, "grails-app/controllers/example/grails/TestInterceptor.groovy").exists() + new File(dir, "src/tests/example/grails/TestInterceptorSpec.groovy").exists() + + } + + @Override + String getTempDirectoryPrefix() { + return "test-app" + } +}