From f51194e0fcb62832c1a12fcb71e1cb45af39970b Mon Sep 17 00:00:00 2001 From: James Daugherty Date: Sun, 29 Jun 2025 22:21:51 -0400 Subject: [PATCH 01/26] test: #14193 add test case for changes after forward --- grails-test-examples/app1/build.gradle | 4 +++ .../ForwardingController.groovy | 15 +++++++++++ .../views/forwarding/forwardedView.gsp | 26 +++++++++++++++++++ .../functionaltests/ForwardingSpec.groovy | 10 +++++++ 4 files changed, 55 insertions(+) create mode 100644 grails-test-examples/app1/grails-app/views/forwarding/forwardedView.gsp diff --git a/grails-test-examples/app1/build.gradle b/grails-test-examples/app1/build.gradle index fef740daf90..4d2746c70fa 100644 --- a/grails-test-examples/app1/build.gradle +++ b/grails-test-examples/app1/build.gradle @@ -78,6 +78,10 @@ test { //compileGroovy.groovyOptions.fork = true //compileGroovy.groovyOptions.forkOptions.jvmArgs = ['-Xdebug', '-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005'] +//bootRun { +// jvmArgs("-Xdebug", "-Xnoagent", "-Djava.compiler=NONE", "-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005") +//} + apply { from rootProject.layout.projectDirectory.file('gradle/functional-test-config.gradle') from rootProject.layout.projectDirectory.file('gradle/java-config.gradle') diff --git a/grails-test-examples/app1/grails-app/controllers/functionaltests/ForwardingController.groovy b/grails-test-examples/app1/grails-app/controllers/functionaltests/ForwardingController.groovy index a102938f601..eba12783d40 100644 --- a/grails-test-examples/app1/grails-app/controllers/functionaltests/ForwardingController.groovy +++ b/grails-test-examples/app1/grails-app/controllers/functionaltests/ForwardingController.groovy @@ -19,6 +19,8 @@ package functionaltests +import org.springframework.http.HttpStatus + class ForwardingController { def one() { @@ -41,6 +43,19 @@ class ForwardingController { forward action: 'list' } + def forwardWithRender(String anArgument) { + if(!anArgument) { + forward action: 'renderedView' + return + } + + render text: 'did not forward', status: HttpStatus.OK + } + + def renderedView() { + render view: 'forwardedView' + } + def list() { [people: ['Jeff', 'Jake', 'Zack', 'Betsy']] } diff --git a/grails-test-examples/app1/grails-app/views/forwarding/forwardedView.gsp b/grails-test-examples/app1/grails-app/views/forwarding/forwardedView.gsp new file mode 100644 index 00000000000..a3daf829c0d --- /dev/null +++ b/grails-test-examples/app1/grails-app/views/forwarding/forwardedView.gsp @@ -0,0 +1,26 @@ +<%-- + ~ Licensed to the Apache Software Foundation (ASF) under one + ~ or more contributor license agreements. See the NOTICE file + ~ distributed with this work for additional information + ~ regarding copyright ownership. The ASF licenses this file + ~ to you 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. + --%> + + + + + +

Hello from a forwarded view

+ + diff --git a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/ForwardingSpec.groovy b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/ForwardingSpec.groovy index 3425de1a150..fe112994bb6 100644 --- a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/ForwardingSpec.groovy +++ b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/ForwardingSpec.groovy @@ -22,6 +22,7 @@ package functionaltests import grails.gorm.transactions.Rollback import grails.plugin.geb.ContainerGebSpec import grails.testing.mixin.integration.Integration +import spock.lang.PendingFeature /** */ @@ -96,4 +97,13 @@ class ForwardingSpec extends ContainerGebSpec { then: 'the flash message has been cleared' $('div', id: 'message').text() == 'flash.message is []' } + + @PendingFeature + void "forwarding to a view"() { + when: "A forward is issued to a view" + go '/forwarding/forwardWithRender' + + then: "The view is rendered correctly" + $('p', id: 'message').text() == 'Hello from a forwarded view' + } } From e49e1785a61068e3bf0b6ec2fe32a04ef118c370 Mon Sep 17 00:00:00 2001 From: James Daugherty Date: Mon, 30 Jun 2025 09:24:43 -0400 Subject: [PATCH 02/26] test: add back sitemesh tests that were removed & rename tests to gsp-layout --- .../{gsp-sitemesh3 => gsp-layout}/README.md | 0 .../build.gradle | 2 +- .../assets/images/advancedgrails.svg | 0 .../assets/images/apple-touch-icon-retina.png | Bin .../assets/images/apple-touch-icon.png | Bin .../assets/images/documentation.svg | 0 .../grails-app/assets/images/favicon.ico | Bin .../images/grails-cupsonly-logo-white.svg | 0 .../grails-app/assets/images/grails.svg | 0 .../assets/images/skin/database_add.png | Bin .../assets/images/skin/database_delete.png | Bin .../assets/images/skin/database_edit.png | Bin .../assets/images/skin/database_save.png | Bin .../assets/images/skin/database_table.png | Bin .../assets/images/skin/exclamation.png | Bin .../grails-app/assets/images/skin/house.png | Bin .../assets/images/skin/information.png | Bin .../assets/images/skin/sorted_asc.gif | Bin .../assets/images/skin/sorted_desc.gif | Bin .../grails-app/assets/images/slack.svg | 0 .../grails-app/assets/images/spinner.gif | Bin .../assets/javascripts/application.js | 0 .../assets/stylesheets/application.css | 0 .../grails-app/assets/stylesheets/errors.css | 0 .../grails-app/assets/stylesheets/grails.css | 0 .../grails-app/assets/stylesheets/main.css | 0 .../grails-app/assets/stylesheets/mobile.css | 0 .../grails-app/conf/application.yml | 0 .../grails-app/conf/logback-spring.xml | 0 .../grails/layout}/DemoController.groovy | 2 +- .../grails/layout/EndToEndController.groovy | 48 ++++++++++ .../example/grails/layout}/UrlMappings.groovy | 2 +- .../grails-app/i18n/messages.properties | 0 .../grails-app/i18n/messages_cs.properties | 0 .../grails-app/i18n/messages_da.properties | 0 .../grails-app/i18n/messages_de.properties | 0 .../grails-app/i18n/messages_es.properties | 0 .../grails-app/i18n/messages_fr.properties | 0 .../grails-app/i18n/messages_it.properties | 0 .../grails-app/i18n/messages_ja.properties | 0 .../grails-app/i18n/messages_nb.properties | 0 .../grails-app/i18n/messages_nl.properties | 0 .../grails-app/i18n/messages_pl.properties | 0 .../grails-app/i18n/messages_pt_BR.properties | 0 .../grails-app/i18n/messages_pt_PT.properties | 0 .../grails-app/i18n/messages_ru.properties | 0 .../grails-app/i18n/messages_sk.properties | 0 .../grails-app/i18n/messages_sv.properties | 0 .../grails-app/i18n/messages_th.properties | 0 .../grails-app/i18n/messages_zh_CN.properties | 0 .../example/grails/layout}/Application.groovy | 2 +- .../grails-app/views/demo/chaining.gsp | 0 .../grails-app/views/demo/index.gsp | 0 .../grails-app/views/demo/viewException.gsp | 0 .../grails-app/views/endToEnd/_title.gsp | 19 ++++ .../views/endToEnd/multilineTitle.gsp | 25 ++++++ .../endToEnd/multipleLevelsOfLayouts.gsp | 24 +++++ .../grails-app/views/endToEnd/parameters.gsp | 25 ++++++ .../views/endToEnd/parametersWithLogic.gsp | 25 ++++++ .../grails-app/views/endToEnd/simple.gsp | 22 +++++ .../views/endToEnd/titleInSubtemplate.gsp | 22 +++++ .../grails-app/views/error.gsp | 0 .../grails-app/views/index.gsp | 0 .../grails-app/views/layouts/base.gsp | 22 +++++ .../grails-app/views/layouts/bootstrap5.gsp | 4 +- .../grails-app/views/layouts/dialog.gsp | 22 +++++ .../grails-app/views/layouts/main.gsp | 0 .../grails-app/views/layouts/modal.gsp | 0 .../views/layouts/parameterLogic.gsp | 19 ++++ .../grails-app/views/layouts/parameters.gsp | 19 ++++ .../grails-app/views/layouts/simple.gsp | 22 +++++ .../grails-app/views/notFound.gsp | 0 .../grails-forge-cli.yml | 2 +- .../groovy/EndToEndSpec.groovy | 85 ++++++++++++++++++ .../groovy/GrailsLayoutSpec.groovy} | 2 +- .../WEB-INF/grails-app/views/demo/hello.jsp | 0 settings.gradle | 4 +- 77 files changed, 409 insertions(+), 10 deletions(-) rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/README.md (100%) rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/build.gradle (98%) rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-app/assets/images/advancedgrails.svg (100%) rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-app/assets/images/apple-touch-icon-retina.png (100%) rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-app/assets/images/apple-touch-icon.png (100%) rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-app/assets/images/documentation.svg (100%) rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-app/assets/images/favicon.ico (100%) rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-app/assets/images/grails-cupsonly-logo-white.svg (100%) rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-app/assets/images/grails.svg (100%) rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-app/assets/images/skin/database_add.png (100%) rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-app/assets/images/skin/database_delete.png (100%) rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-app/assets/images/skin/database_edit.png (100%) rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-app/assets/images/skin/database_save.png (100%) rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-app/assets/images/skin/database_table.png (100%) rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-app/assets/images/skin/exclamation.png (100%) rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-app/assets/images/skin/house.png (100%) rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-app/assets/images/skin/information.png (100%) rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-app/assets/images/skin/sorted_asc.gif (100%) rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-app/assets/images/skin/sorted_desc.gif (100%) rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-app/assets/images/slack.svg (100%) rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-app/assets/images/spinner.gif (100%) rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-app/assets/javascripts/application.js (100%) rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-app/assets/stylesheets/application.css (100%) rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-app/assets/stylesheets/errors.css (100%) rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-app/assets/stylesheets/grails.css (100%) rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-app/assets/stylesheets/main.css (100%) rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-app/assets/stylesheets/mobile.css (100%) rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-app/conf/application.yml (100%) rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-app/conf/logback-spring.xml (100%) rename grails-test-examples/{gsp-sitemesh3/grails-app/controllers/org/sitemesh/grails/plugins/sitemesh3 => gsp-layout/grails-app/controllers/org/example/grails/layout}/DemoController.groovy (97%) create mode 100644 grails-test-examples/gsp-layout/grails-app/controllers/org/example/grails/layout/EndToEndController.groovy rename grails-test-examples/{gsp-sitemesh3/grails-app/controllers/org/sitemesh/grails/plugins/sitemesh3 => gsp-layout/grails-app/controllers/org/example/grails/layout}/UrlMappings.groovy (96%) rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-app/i18n/messages.properties (100%) rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-app/i18n/messages_cs.properties (100%) rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-app/i18n/messages_da.properties (100%) rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-app/i18n/messages_de.properties (100%) rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-app/i18n/messages_es.properties (100%) rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-app/i18n/messages_fr.properties (100%) rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-app/i18n/messages_it.properties (100%) rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-app/i18n/messages_ja.properties (100%) rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-app/i18n/messages_nb.properties (100%) rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-app/i18n/messages_nl.properties (100%) rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-app/i18n/messages_pl.properties (100%) rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-app/i18n/messages_pt_BR.properties (100%) rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-app/i18n/messages_pt_PT.properties (100%) rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-app/i18n/messages_ru.properties (100%) rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-app/i18n/messages_sk.properties (100%) rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-app/i18n/messages_sv.properties (100%) rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-app/i18n/messages_th.properties (100%) rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-app/i18n/messages_zh_CN.properties (100%) rename grails-test-examples/{gsp-sitemesh3/grails-app/init/org/sitemesh/grails/plugins/sitemesh3 => gsp-layout/grails-app/init/org/example/grails/layout}/Application.groovy (95%) rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-app/views/demo/chaining.gsp (100%) rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-app/views/demo/index.gsp (100%) rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-app/views/demo/viewException.gsp (100%) create mode 100644 grails-test-examples/gsp-layout/grails-app/views/endToEnd/_title.gsp create mode 100644 grails-test-examples/gsp-layout/grails-app/views/endToEnd/multilineTitle.gsp create mode 100644 grails-test-examples/gsp-layout/grails-app/views/endToEnd/multipleLevelsOfLayouts.gsp create mode 100644 grails-test-examples/gsp-layout/grails-app/views/endToEnd/parameters.gsp create mode 100644 grails-test-examples/gsp-layout/grails-app/views/endToEnd/parametersWithLogic.gsp create mode 100644 grails-test-examples/gsp-layout/grails-app/views/endToEnd/simple.gsp create mode 100644 grails-test-examples/gsp-layout/grails-app/views/endToEnd/titleInSubtemplate.gsp rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-app/views/error.gsp (100%) rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-app/views/index.gsp (100%) create mode 100644 grails-test-examples/gsp-layout/grails-app/views/layouts/base.gsp rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-app/views/layouts/bootstrap5.gsp (97%) create mode 100644 grails-test-examples/gsp-layout/grails-app/views/layouts/dialog.gsp rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-app/views/layouts/main.gsp (100%) rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-app/views/layouts/modal.gsp (100%) create mode 100644 grails-test-examples/gsp-layout/grails-app/views/layouts/parameterLogic.gsp create mode 100644 grails-test-examples/gsp-layout/grails-app/views/layouts/parameters.gsp create mode 100644 grails-test-examples/gsp-layout/grails-app/views/layouts/simple.gsp rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-app/views/notFound.gsp (100%) rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/grails-forge-cli.yml (96%) create mode 100644 grails-test-examples/gsp-layout/src/integration-test/groovy/EndToEndSpec.groovy rename grails-test-examples/{gsp-sitemesh3/src/integration-test/groovy/SitemeshSpec.groovy => gsp-layout/src/integration-test/groovy/GrailsLayoutSpec.groovy} (97%) rename grails-test-examples/{gsp-sitemesh3 => gsp-layout}/src/main/webapp/WEB-INF/grails-app/views/demo/hello.jsp (100%) diff --git a/grails-test-examples/gsp-sitemesh3/README.md b/grails-test-examples/gsp-layout/README.md similarity index 100% rename from grails-test-examples/gsp-sitemesh3/README.md rename to grails-test-examples/gsp-layout/README.md diff --git a/grails-test-examples/gsp-sitemesh3/build.gradle b/grails-test-examples/gsp-layout/build.gradle similarity index 98% rename from grails-test-examples/gsp-sitemesh3/build.gradle rename to grails-test-examples/gsp-layout/build.gradle index 91552292a75..0cea1a38211 100644 --- a/grails-test-examples/gsp-sitemesh3/build.gradle +++ b/grails-test-examples/gsp-layout/build.gradle @@ -18,7 +18,7 @@ */ version = '0.0.1' -group = 'org.sitemesh.grails.plugins.sitemesh3' +group = 'org.example.grails.layout' apply plugin: 'org.apache.grails.gradle.grails-web' apply plugin: 'org.apache.grails.gradle.grails-gsp' diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/assets/images/advancedgrails.svg b/grails-test-examples/gsp-layout/grails-app/assets/images/advancedgrails.svg similarity index 100% rename from grails-test-examples/gsp-sitemesh3/grails-app/assets/images/advancedgrails.svg rename to grails-test-examples/gsp-layout/grails-app/assets/images/advancedgrails.svg diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/assets/images/apple-touch-icon-retina.png b/grails-test-examples/gsp-layout/grails-app/assets/images/apple-touch-icon-retina.png similarity index 100% rename from grails-test-examples/gsp-sitemesh3/grails-app/assets/images/apple-touch-icon-retina.png rename to grails-test-examples/gsp-layout/grails-app/assets/images/apple-touch-icon-retina.png diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/assets/images/apple-touch-icon.png b/grails-test-examples/gsp-layout/grails-app/assets/images/apple-touch-icon.png similarity index 100% rename from grails-test-examples/gsp-sitemesh3/grails-app/assets/images/apple-touch-icon.png rename to grails-test-examples/gsp-layout/grails-app/assets/images/apple-touch-icon.png diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/assets/images/documentation.svg b/grails-test-examples/gsp-layout/grails-app/assets/images/documentation.svg similarity index 100% rename from grails-test-examples/gsp-sitemesh3/grails-app/assets/images/documentation.svg rename to grails-test-examples/gsp-layout/grails-app/assets/images/documentation.svg diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/assets/images/favicon.ico b/grails-test-examples/gsp-layout/grails-app/assets/images/favicon.ico similarity index 100% rename from grails-test-examples/gsp-sitemesh3/grails-app/assets/images/favicon.ico rename to grails-test-examples/gsp-layout/grails-app/assets/images/favicon.ico diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/assets/images/grails-cupsonly-logo-white.svg b/grails-test-examples/gsp-layout/grails-app/assets/images/grails-cupsonly-logo-white.svg similarity index 100% rename from grails-test-examples/gsp-sitemesh3/grails-app/assets/images/grails-cupsonly-logo-white.svg rename to grails-test-examples/gsp-layout/grails-app/assets/images/grails-cupsonly-logo-white.svg diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/assets/images/grails.svg b/grails-test-examples/gsp-layout/grails-app/assets/images/grails.svg similarity index 100% rename from grails-test-examples/gsp-sitemesh3/grails-app/assets/images/grails.svg rename to grails-test-examples/gsp-layout/grails-app/assets/images/grails.svg diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/assets/images/skin/database_add.png b/grails-test-examples/gsp-layout/grails-app/assets/images/skin/database_add.png similarity index 100% rename from grails-test-examples/gsp-sitemesh3/grails-app/assets/images/skin/database_add.png rename to grails-test-examples/gsp-layout/grails-app/assets/images/skin/database_add.png diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/assets/images/skin/database_delete.png b/grails-test-examples/gsp-layout/grails-app/assets/images/skin/database_delete.png similarity index 100% rename from grails-test-examples/gsp-sitemesh3/grails-app/assets/images/skin/database_delete.png rename to grails-test-examples/gsp-layout/grails-app/assets/images/skin/database_delete.png diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/assets/images/skin/database_edit.png b/grails-test-examples/gsp-layout/grails-app/assets/images/skin/database_edit.png similarity index 100% rename from grails-test-examples/gsp-sitemesh3/grails-app/assets/images/skin/database_edit.png rename to grails-test-examples/gsp-layout/grails-app/assets/images/skin/database_edit.png diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/assets/images/skin/database_save.png b/grails-test-examples/gsp-layout/grails-app/assets/images/skin/database_save.png similarity index 100% rename from grails-test-examples/gsp-sitemesh3/grails-app/assets/images/skin/database_save.png rename to grails-test-examples/gsp-layout/grails-app/assets/images/skin/database_save.png diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/assets/images/skin/database_table.png b/grails-test-examples/gsp-layout/grails-app/assets/images/skin/database_table.png similarity index 100% rename from grails-test-examples/gsp-sitemesh3/grails-app/assets/images/skin/database_table.png rename to grails-test-examples/gsp-layout/grails-app/assets/images/skin/database_table.png diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/assets/images/skin/exclamation.png b/grails-test-examples/gsp-layout/grails-app/assets/images/skin/exclamation.png similarity index 100% rename from grails-test-examples/gsp-sitemesh3/grails-app/assets/images/skin/exclamation.png rename to grails-test-examples/gsp-layout/grails-app/assets/images/skin/exclamation.png diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/assets/images/skin/house.png b/grails-test-examples/gsp-layout/grails-app/assets/images/skin/house.png similarity index 100% rename from grails-test-examples/gsp-sitemesh3/grails-app/assets/images/skin/house.png rename to grails-test-examples/gsp-layout/grails-app/assets/images/skin/house.png diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/assets/images/skin/information.png b/grails-test-examples/gsp-layout/grails-app/assets/images/skin/information.png similarity index 100% rename from grails-test-examples/gsp-sitemesh3/grails-app/assets/images/skin/information.png rename to grails-test-examples/gsp-layout/grails-app/assets/images/skin/information.png diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/assets/images/skin/sorted_asc.gif b/grails-test-examples/gsp-layout/grails-app/assets/images/skin/sorted_asc.gif similarity index 100% rename from grails-test-examples/gsp-sitemesh3/grails-app/assets/images/skin/sorted_asc.gif rename to grails-test-examples/gsp-layout/grails-app/assets/images/skin/sorted_asc.gif diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/assets/images/skin/sorted_desc.gif b/grails-test-examples/gsp-layout/grails-app/assets/images/skin/sorted_desc.gif similarity index 100% rename from grails-test-examples/gsp-sitemesh3/grails-app/assets/images/skin/sorted_desc.gif rename to grails-test-examples/gsp-layout/grails-app/assets/images/skin/sorted_desc.gif diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/assets/images/slack.svg b/grails-test-examples/gsp-layout/grails-app/assets/images/slack.svg similarity index 100% rename from grails-test-examples/gsp-sitemesh3/grails-app/assets/images/slack.svg rename to grails-test-examples/gsp-layout/grails-app/assets/images/slack.svg diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/assets/images/spinner.gif b/grails-test-examples/gsp-layout/grails-app/assets/images/spinner.gif similarity index 100% rename from grails-test-examples/gsp-sitemesh3/grails-app/assets/images/spinner.gif rename to grails-test-examples/gsp-layout/grails-app/assets/images/spinner.gif diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/assets/javascripts/application.js b/grails-test-examples/gsp-layout/grails-app/assets/javascripts/application.js similarity index 100% rename from grails-test-examples/gsp-sitemesh3/grails-app/assets/javascripts/application.js rename to grails-test-examples/gsp-layout/grails-app/assets/javascripts/application.js diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/assets/stylesheets/application.css b/grails-test-examples/gsp-layout/grails-app/assets/stylesheets/application.css similarity index 100% rename from grails-test-examples/gsp-sitemesh3/grails-app/assets/stylesheets/application.css rename to grails-test-examples/gsp-layout/grails-app/assets/stylesheets/application.css diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/assets/stylesheets/errors.css b/grails-test-examples/gsp-layout/grails-app/assets/stylesheets/errors.css similarity index 100% rename from grails-test-examples/gsp-sitemesh3/grails-app/assets/stylesheets/errors.css rename to grails-test-examples/gsp-layout/grails-app/assets/stylesheets/errors.css diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/assets/stylesheets/grails.css b/grails-test-examples/gsp-layout/grails-app/assets/stylesheets/grails.css similarity index 100% rename from grails-test-examples/gsp-sitemesh3/grails-app/assets/stylesheets/grails.css rename to grails-test-examples/gsp-layout/grails-app/assets/stylesheets/grails.css diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/assets/stylesheets/main.css b/grails-test-examples/gsp-layout/grails-app/assets/stylesheets/main.css similarity index 100% rename from grails-test-examples/gsp-sitemesh3/grails-app/assets/stylesheets/main.css rename to grails-test-examples/gsp-layout/grails-app/assets/stylesheets/main.css diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/assets/stylesheets/mobile.css b/grails-test-examples/gsp-layout/grails-app/assets/stylesheets/mobile.css similarity index 100% rename from grails-test-examples/gsp-sitemesh3/grails-app/assets/stylesheets/mobile.css rename to grails-test-examples/gsp-layout/grails-app/assets/stylesheets/mobile.css diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/conf/application.yml b/grails-test-examples/gsp-layout/grails-app/conf/application.yml similarity index 100% rename from grails-test-examples/gsp-sitemesh3/grails-app/conf/application.yml rename to grails-test-examples/gsp-layout/grails-app/conf/application.yml diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/conf/logback-spring.xml b/grails-test-examples/gsp-layout/grails-app/conf/logback-spring.xml similarity index 100% rename from grails-test-examples/gsp-sitemesh3/grails-app/conf/logback-spring.xml rename to grails-test-examples/gsp-layout/grails-app/conf/logback-spring.xml diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/controllers/org/sitemesh/grails/plugins/sitemesh3/DemoController.groovy b/grails-test-examples/gsp-layout/grails-app/controllers/org/example/grails/layout/DemoController.groovy similarity index 97% rename from grails-test-examples/gsp-sitemesh3/grails-app/controllers/org/sitemesh/grails/plugins/sitemesh3/DemoController.groovy rename to grails-test-examples/gsp-layout/grails-app/controllers/org/example/grails/layout/DemoController.groovy index de19b8ccbc6..ed4e61e3423 100644 --- a/grails-test-examples/gsp-sitemesh3/grails-app/controllers/org/sitemesh/grails/plugins/sitemesh3/DemoController.groovy +++ b/grails-test-examples/gsp-layout/grails-app/controllers/org/example/grails/layout/DemoController.groovy @@ -17,7 +17,7 @@ * under the License. */ -package org.sitemesh.grails.plugins.sitemesh3 +package org.example.grails.layout class DemoController { diff --git a/grails-test-examples/gsp-layout/grails-app/controllers/org/example/grails/layout/EndToEndController.groovy b/grails-test-examples/gsp-layout/grails-app/controllers/org/example/grails/layout/EndToEndController.groovy new file mode 100644 index 00000000000..1c1320acf44 --- /dev/null +++ b/grails-test-examples/gsp-layout/grails-app/controllers/org/example/grails/layout/EndToEndController.groovy @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.example.grails.layout + +class EndToEndController { + + def simpleLayout() { + render view: 'simple', layout: 'simple' + } + + def titleInSubtemplate() { + render view: 'titleInSubtemplate', layout: 'simple' + } + + def multipleLevelsOfLayouts() { + render view: 'multipleLevelsOfLayouts', layout: 'simple' + } + + def parameters() { + render view: 'parameters', layout: 'parameters' + } + + def parametersWithLogic() { + render view: 'parametersWithLogic', layout: 'parameterLogic' + } + + // GRAILS-11484 + def multilineTitle() { + render view: 'multilineTitle', layout: 'simple' + } +} diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/controllers/org/sitemesh/grails/plugins/sitemesh3/UrlMappings.groovy b/grails-test-examples/gsp-layout/grails-app/controllers/org/example/grails/layout/UrlMappings.groovy similarity index 96% rename from grails-test-examples/gsp-sitemesh3/grails-app/controllers/org/sitemesh/grails/plugins/sitemesh3/UrlMappings.groovy rename to grails-test-examples/gsp-layout/grails-app/controllers/org/example/grails/layout/UrlMappings.groovy index c9228648c75..927f0094314 100644 --- a/grails-test-examples/gsp-sitemesh3/grails-app/controllers/org/sitemesh/grails/plugins/sitemesh3/UrlMappings.groovy +++ b/grails-test-examples/gsp-layout/grails-app/controllers/org/example/grails/layout/UrlMappings.groovy @@ -17,7 +17,7 @@ * under the License. */ -package org.sitemesh.grails.plugins.sitemesh3 +package org.example.grails.layout class UrlMappings { static mappings = { diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/i18n/messages.properties b/grails-test-examples/gsp-layout/grails-app/i18n/messages.properties similarity index 100% rename from grails-test-examples/gsp-sitemesh3/grails-app/i18n/messages.properties rename to grails-test-examples/gsp-layout/grails-app/i18n/messages.properties diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/i18n/messages_cs.properties b/grails-test-examples/gsp-layout/grails-app/i18n/messages_cs.properties similarity index 100% rename from grails-test-examples/gsp-sitemesh3/grails-app/i18n/messages_cs.properties rename to grails-test-examples/gsp-layout/grails-app/i18n/messages_cs.properties diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/i18n/messages_da.properties b/grails-test-examples/gsp-layout/grails-app/i18n/messages_da.properties similarity index 100% rename from grails-test-examples/gsp-sitemesh3/grails-app/i18n/messages_da.properties rename to grails-test-examples/gsp-layout/grails-app/i18n/messages_da.properties diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/i18n/messages_de.properties b/grails-test-examples/gsp-layout/grails-app/i18n/messages_de.properties similarity index 100% rename from grails-test-examples/gsp-sitemesh3/grails-app/i18n/messages_de.properties rename to grails-test-examples/gsp-layout/grails-app/i18n/messages_de.properties diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/i18n/messages_es.properties b/grails-test-examples/gsp-layout/grails-app/i18n/messages_es.properties similarity index 100% rename from grails-test-examples/gsp-sitemesh3/grails-app/i18n/messages_es.properties rename to grails-test-examples/gsp-layout/grails-app/i18n/messages_es.properties diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/i18n/messages_fr.properties b/grails-test-examples/gsp-layout/grails-app/i18n/messages_fr.properties similarity index 100% rename from grails-test-examples/gsp-sitemesh3/grails-app/i18n/messages_fr.properties rename to grails-test-examples/gsp-layout/grails-app/i18n/messages_fr.properties diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/i18n/messages_it.properties b/grails-test-examples/gsp-layout/grails-app/i18n/messages_it.properties similarity index 100% rename from grails-test-examples/gsp-sitemesh3/grails-app/i18n/messages_it.properties rename to grails-test-examples/gsp-layout/grails-app/i18n/messages_it.properties diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/i18n/messages_ja.properties b/grails-test-examples/gsp-layout/grails-app/i18n/messages_ja.properties similarity index 100% rename from grails-test-examples/gsp-sitemesh3/grails-app/i18n/messages_ja.properties rename to grails-test-examples/gsp-layout/grails-app/i18n/messages_ja.properties diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/i18n/messages_nb.properties b/grails-test-examples/gsp-layout/grails-app/i18n/messages_nb.properties similarity index 100% rename from grails-test-examples/gsp-sitemesh3/grails-app/i18n/messages_nb.properties rename to grails-test-examples/gsp-layout/grails-app/i18n/messages_nb.properties diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/i18n/messages_nl.properties b/grails-test-examples/gsp-layout/grails-app/i18n/messages_nl.properties similarity index 100% rename from grails-test-examples/gsp-sitemesh3/grails-app/i18n/messages_nl.properties rename to grails-test-examples/gsp-layout/grails-app/i18n/messages_nl.properties diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/i18n/messages_pl.properties b/grails-test-examples/gsp-layout/grails-app/i18n/messages_pl.properties similarity index 100% rename from grails-test-examples/gsp-sitemesh3/grails-app/i18n/messages_pl.properties rename to grails-test-examples/gsp-layout/grails-app/i18n/messages_pl.properties diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/i18n/messages_pt_BR.properties b/grails-test-examples/gsp-layout/grails-app/i18n/messages_pt_BR.properties similarity index 100% rename from grails-test-examples/gsp-sitemesh3/grails-app/i18n/messages_pt_BR.properties rename to grails-test-examples/gsp-layout/grails-app/i18n/messages_pt_BR.properties diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/i18n/messages_pt_PT.properties b/grails-test-examples/gsp-layout/grails-app/i18n/messages_pt_PT.properties similarity index 100% rename from grails-test-examples/gsp-sitemesh3/grails-app/i18n/messages_pt_PT.properties rename to grails-test-examples/gsp-layout/grails-app/i18n/messages_pt_PT.properties diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/i18n/messages_ru.properties b/grails-test-examples/gsp-layout/grails-app/i18n/messages_ru.properties similarity index 100% rename from grails-test-examples/gsp-sitemesh3/grails-app/i18n/messages_ru.properties rename to grails-test-examples/gsp-layout/grails-app/i18n/messages_ru.properties diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/i18n/messages_sk.properties b/grails-test-examples/gsp-layout/grails-app/i18n/messages_sk.properties similarity index 100% rename from grails-test-examples/gsp-sitemesh3/grails-app/i18n/messages_sk.properties rename to grails-test-examples/gsp-layout/grails-app/i18n/messages_sk.properties diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/i18n/messages_sv.properties b/grails-test-examples/gsp-layout/grails-app/i18n/messages_sv.properties similarity index 100% rename from grails-test-examples/gsp-sitemesh3/grails-app/i18n/messages_sv.properties rename to grails-test-examples/gsp-layout/grails-app/i18n/messages_sv.properties diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/i18n/messages_th.properties b/grails-test-examples/gsp-layout/grails-app/i18n/messages_th.properties similarity index 100% rename from grails-test-examples/gsp-sitemesh3/grails-app/i18n/messages_th.properties rename to grails-test-examples/gsp-layout/grails-app/i18n/messages_th.properties diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/i18n/messages_zh_CN.properties b/grails-test-examples/gsp-layout/grails-app/i18n/messages_zh_CN.properties similarity index 100% rename from grails-test-examples/gsp-sitemesh3/grails-app/i18n/messages_zh_CN.properties rename to grails-test-examples/gsp-layout/grails-app/i18n/messages_zh_CN.properties diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/init/org/sitemesh/grails/plugins/sitemesh3/Application.groovy b/grails-test-examples/gsp-layout/grails-app/init/org/example/grails/layout/Application.groovy similarity index 95% rename from grails-test-examples/gsp-sitemesh3/grails-app/init/org/sitemesh/grails/plugins/sitemesh3/Application.groovy rename to grails-test-examples/gsp-layout/grails-app/init/org/example/grails/layout/Application.groovy index 9dcaa9e70d9..5199ae162ce 100644 --- a/grails-test-examples/gsp-sitemesh3/grails-app/init/org/sitemesh/grails/plugins/sitemesh3/Application.groovy +++ b/grails-test-examples/gsp-layout/grails-app/init/org/example/grails/layout/Application.groovy @@ -17,7 +17,7 @@ * under the License. */ -package org.sitemesh.grails.plugins.sitemesh3 +package org.example.grails.layout import grails.boot.GrailsApp import grails.boot.config.GrailsAutoConfiguration diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/views/demo/chaining.gsp b/grails-test-examples/gsp-layout/grails-app/views/demo/chaining.gsp similarity index 100% rename from grails-test-examples/gsp-sitemesh3/grails-app/views/demo/chaining.gsp rename to grails-test-examples/gsp-layout/grails-app/views/demo/chaining.gsp diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/views/demo/index.gsp b/grails-test-examples/gsp-layout/grails-app/views/demo/index.gsp similarity index 100% rename from grails-test-examples/gsp-sitemesh3/grails-app/views/demo/index.gsp rename to grails-test-examples/gsp-layout/grails-app/views/demo/index.gsp diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/views/demo/viewException.gsp b/grails-test-examples/gsp-layout/grails-app/views/demo/viewException.gsp similarity index 100% rename from grails-test-examples/gsp-sitemesh3/grails-app/views/demo/viewException.gsp rename to grails-test-examples/gsp-layout/grails-app/views/demo/viewException.gsp diff --git a/grails-test-examples/gsp-layout/grails-app/views/endToEnd/_title.gsp b/grails-test-examples/gsp-layout/grails-app/views/endToEnd/_title.gsp new file mode 100644 index 00000000000..090f8c929ed --- /dev/null +++ b/grails-test-examples/gsp-layout/grails-app/views/endToEnd/_title.gsp @@ -0,0 +1,19 @@ +<%-- + ~ Licensed to the Apache Software Foundation (ASF) under one + ~ or more contributor license agreements. See the NOTICE file + ~ distributed with this work for additional information + ~ regarding copyright ownership. The ASF licenses this file + ~ to you 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. + --%> +This is the title \ No newline at end of file diff --git a/grails-test-examples/gsp-layout/grails-app/views/endToEnd/multilineTitle.gsp b/grails-test-examples/gsp-layout/grails-app/views/endToEnd/multilineTitle.gsp new file mode 100644 index 00000000000..1a89d6f7eb6 --- /dev/null +++ b/grails-test-examples/gsp-layout/grails-app/views/endToEnd/multilineTitle.gsp @@ -0,0 +1,25 @@ +<%-- + ~ Licensed to the Apache Software Foundation (ASF) under one + ~ or more contributor license agreements. See the NOTICE file + ~ distributed with this work for additional information + ~ regarding copyright ownership. The ASF licenses this file + ~ to you 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. + --%> + + + + This is the title + +body text + \ No newline at end of file diff --git a/grails-test-examples/gsp-layout/grails-app/views/endToEnd/multipleLevelsOfLayouts.gsp b/grails-test-examples/gsp-layout/grails-app/views/endToEnd/multipleLevelsOfLayouts.gsp new file mode 100644 index 00000000000..70de6408c1c --- /dev/null +++ b/grails-test-examples/gsp-layout/grails-app/views/endToEnd/multipleLevelsOfLayouts.gsp @@ -0,0 +1,24 @@ +<%-- + ~ Licensed to the Apache Software Foundation (ASF) under one + ~ or more contributor license agreements. See the NOTICE file + ~ distributed with this work for additional information + ~ regarding copyright ownership. The ASF licenses this file + ~ to you 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. + --%> + + + This is the title + body text + + \ No newline at end of file diff --git a/grails-test-examples/gsp-layout/grails-app/views/endToEnd/parameters.gsp b/grails-test-examples/gsp-layout/grails-app/views/endToEnd/parameters.gsp new file mode 100644 index 00000000000..31aff49a096 --- /dev/null +++ b/grails-test-examples/gsp-layout/grails-app/views/endToEnd/parameters.gsp @@ -0,0 +1,25 @@ +<%-- + ~ Licensed to the Apache Software Foundation (ASF) under one + ~ or more contributor license agreements. See the NOTICE file + ~ distributed with this work for additional information + ~ regarding copyright ownership. The ASF licenses this file + ~ to you 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. + --%> + + + Simple GSP page + + +Place your content here + \ No newline at end of file diff --git a/grails-test-examples/gsp-layout/grails-app/views/endToEnd/parametersWithLogic.gsp b/grails-test-examples/gsp-layout/grails-app/views/endToEnd/parametersWithLogic.gsp new file mode 100644 index 00000000000..f0c44091bcb --- /dev/null +++ b/grails-test-examples/gsp-layout/grails-app/views/endToEnd/parametersWithLogic.gsp @@ -0,0 +1,25 @@ +<%-- + ~ Licensed to the Apache Software Foundation (ASF) under one + ~ or more contributor license agreements. See the NOTICE file + ~ distributed with this work for additional information + ~ regarding copyright ownership. The ASF licenses this file + ~ to you 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. + --%> + + + Simple GSP page + + +Place your content here + \ No newline at end of file diff --git a/grails-test-examples/gsp-layout/grails-app/views/endToEnd/simple.gsp b/grails-test-examples/gsp-layout/grails-app/views/endToEnd/simple.gsp new file mode 100644 index 00000000000..bcaceb825e7 --- /dev/null +++ b/grails-test-examples/gsp-layout/grails-app/views/endToEnd/simple.gsp @@ -0,0 +1,22 @@ +<%-- + ~ Licensed to the Apache Software Foundation (ASF) under one + ~ or more contributor license agreements. See the NOTICE file + ~ distributed with this work for additional information + ~ regarding copyright ownership. The ASF licenses this file + ~ to you 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. + --%> + +This is the title +body text + \ No newline at end of file diff --git a/grails-test-examples/gsp-layout/grails-app/views/endToEnd/titleInSubtemplate.gsp b/grails-test-examples/gsp-layout/grails-app/views/endToEnd/titleInSubtemplate.gsp new file mode 100644 index 00000000000..7975937b7d1 --- /dev/null +++ b/grails-test-examples/gsp-layout/grails-app/views/endToEnd/titleInSubtemplate.gsp @@ -0,0 +1,22 @@ +<%-- + ~ Licensed to the Apache Software Foundation (ASF) under one + ~ or more contributor license agreements. See the NOTICE file + ~ distributed with this work for additional information + ~ regarding copyright ownership. The ASF licenses this file + ~ to you 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. + --%> + + +body text + \ No newline at end of file diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/views/error.gsp b/grails-test-examples/gsp-layout/grails-app/views/error.gsp similarity index 100% rename from grails-test-examples/gsp-sitemesh3/grails-app/views/error.gsp rename to grails-test-examples/gsp-layout/grails-app/views/error.gsp diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/views/index.gsp b/grails-test-examples/gsp-layout/grails-app/views/index.gsp similarity index 100% rename from grails-test-examples/gsp-sitemesh3/grails-app/views/index.gsp rename to grails-test-examples/gsp-layout/grails-app/views/index.gsp diff --git a/grails-test-examples/gsp-layout/grails-app/views/layouts/base.gsp b/grails-test-examples/gsp-layout/grails-app/views/layouts/base.gsp new file mode 100644 index 00000000000..fc775c85793 --- /dev/null +++ b/grails-test-examples/gsp-layout/grails-app/views/layouts/base.gsp @@ -0,0 +1,22 @@ +<%-- + ~ Licensed to the Apache Software Foundation (ASF) under one + ~ or more contributor license agreements. See the NOTICE file + ~ distributed with this work for additional information + ~ regarding copyright ownership. The ASF licenses this file + ~ to you 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. + --%> + +Base - <g:layoutTitle /> +
+ \ No newline at end of file diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/views/layouts/bootstrap5.gsp b/grails-test-examples/gsp-layout/grails-app/views/layouts/bootstrap5.gsp similarity index 97% rename from grails-test-examples/gsp-sitemesh3/grails-app/views/layouts/bootstrap5.gsp rename to grails-test-examples/gsp-layout/grails-app/views/layouts/bootstrap5.gsp index 0a7f2d63a19..8d3f542c2f6 100644 --- a/grails-test-examples/gsp-sitemesh3/grails-app/views/layouts/bootstrap5.gsp +++ b/grails-test-examples/gsp-layout/grails-app/views/layouts/bootstrap5.gsp @@ -47,7 +47,7 @@
-

SiteMesh Example Site:

+

Grails Layout Example Site:

Note: this demo requires an internet connection for BootStrap to show up.
diff --git a/grails-test-examples/gsp-layout/grails-app/views/layouts/dialog.gsp b/grails-test-examples/gsp-layout/grails-app/views/layouts/dialog.gsp new file mode 100644 index 00000000000..31ca8df0794 --- /dev/null +++ b/grails-test-examples/gsp-layout/grails-app/views/layouts/dialog.gsp @@ -0,0 +1,22 @@ +<%-- + ~ Licensed to the Apache Software Foundation (ASF) under one + ~ or more contributor license agreements. See the NOTICE file + ~ distributed with this work for additional information + ~ regarding copyright ownership. The ASF licenses this file + ~ to you 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. + --%> + +Dialog - <g:layoutTitle /> +
+ \ No newline at end of file diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/views/layouts/main.gsp b/grails-test-examples/gsp-layout/grails-app/views/layouts/main.gsp similarity index 100% rename from grails-test-examples/gsp-sitemesh3/grails-app/views/layouts/main.gsp rename to grails-test-examples/gsp-layout/grails-app/views/layouts/main.gsp diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/views/layouts/modal.gsp b/grails-test-examples/gsp-layout/grails-app/views/layouts/modal.gsp similarity index 100% rename from grails-test-examples/gsp-sitemesh3/grails-app/views/layouts/modal.gsp rename to grails-test-examples/gsp-layout/grails-app/views/layouts/modal.gsp diff --git a/grails-test-examples/gsp-layout/grails-app/views/layouts/parameterLogic.gsp b/grails-test-examples/gsp-layout/grails-app/views/layouts/parameterLogic.gsp new file mode 100644 index 00000000000..09d47e32633 --- /dev/null +++ b/grails-test-examples/gsp-layout/grails-app/views/layouts/parameterLogic.gsp @@ -0,0 +1,19 @@ +<%-- + ~ Licensed to the Apache Software Foundation (ASF) under one + ~ or more contributor license agreements. See the NOTICE file + ~ distributed with this work for additional information + ~ regarding copyright ownership. The ASF licenses this file + ~ to you 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. + --%> +good \ No newline at end of file diff --git a/grails-test-examples/gsp-layout/grails-app/views/layouts/parameters.gsp b/grails-test-examples/gsp-layout/grails-app/views/layouts/parameters.gsp new file mode 100644 index 00000000000..57bb7855aaa --- /dev/null +++ b/grails-test-examples/gsp-layout/grails-app/views/layouts/parameters.gsp @@ -0,0 +1,19 @@ +<%-- + ~ Licensed to the Apache Software Foundation (ASF) under one + ~ or more contributor license agreements. See the NOTICE file + ~ distributed with this work for additional information + ~ regarding copyright ownership. The ASF licenses this file + ~ to you 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. + --%> +

pageProperty: ${pageProperty(name: 'page.navigation')}

\ No newline at end of file diff --git a/grails-test-examples/gsp-layout/grails-app/views/layouts/simple.gsp b/grails-test-examples/gsp-layout/grails-app/views/layouts/simple.gsp new file mode 100644 index 00000000000..b3c61b7a21e --- /dev/null +++ b/grails-test-examples/gsp-layout/grails-app/views/layouts/simple.gsp @@ -0,0 +1,22 @@ +<%-- + ~ Licensed to the Apache Software Foundation (ASF) under one + ~ or more contributor license agreements. See the NOTICE file + ~ distributed with this work for additional information + ~ regarding copyright ownership. The ASF licenses this file + ~ to you 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. + --%> + +Decorated <g:layoutTitle /> +

Hello

+ \ No newline at end of file diff --git a/grails-test-examples/gsp-sitemesh3/grails-app/views/notFound.gsp b/grails-test-examples/gsp-layout/grails-app/views/notFound.gsp similarity index 100% rename from grails-test-examples/gsp-sitemesh3/grails-app/views/notFound.gsp rename to grails-test-examples/gsp-layout/grails-app/views/notFound.gsp diff --git a/grails-test-examples/gsp-sitemesh3/grails-forge-cli.yml b/grails-test-examples/gsp-layout/grails-forge-cli.yml similarity index 96% rename from grails-test-examples/gsp-sitemesh3/grails-forge-cli.yml rename to grails-test-examples/gsp-layout/grails-forge-cli.yml index c9191ade049..ec46d6bb743 100644 --- a/grails-test-examples/gsp-sitemesh3/grails-forge-cli.yml +++ b/grails-test-examples/gsp-layout/grails-forge-cli.yml @@ -14,7 +14,7 @@ # limitations under the License. applicationType: web_plugin -defaultPackage: org.sitemesh.grails.plugins.sitemesh3 +defaultPackage: org.example.grails.layout testFramework: spock sourceLanguage: groovy buildTool: gradle diff --git a/grails-test-examples/gsp-layout/src/integration-test/groovy/EndToEndSpec.groovy b/grails-test-examples/gsp-layout/src/integration-test/groovy/EndToEndSpec.groovy new file mode 100644 index 00000000000..5e1259a2078 --- /dev/null +++ b/grails-test-examples/gsp-layout/src/integration-test/groovy/EndToEndSpec.groovy @@ -0,0 +1,85 @@ +import grails.plugin.geb.ContainerGebSpec +import grails.testing.mixin.integration.Integration +import spock.lang.PendingFeature + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +@Integration +class EndToEndSpec extends ContainerGebSpec { + def "simple layout"() { + when: + browser.go 'endToEnd/simpleLayout' + + then: + browser.driver.pageSource == """Decorated This is the title +

Hello

body text +""" + } + + def "title in subtemplate"() { + when: + browser.go 'endToEnd/titleInSubtemplate' + + then: + browser.driver.pageSource == """Decorated This is the title + +

Hello

body text +""" + } + + @PendingFeature + def "multiple levels of layouts"() { + when: + browser.go 'endToEnd/multipleLevelsOfLayouts' + + then: + browser.driver.pageSource == """Decorated Base - Dialog - This is the title +

Hello

body text
+""" + } + + def "parameters"() { + when: + browser.go 'endToEnd/parameters' + + then: + browser.driver.pageSource == """

pageProperty: here!

""" + } + + def "parameters with logic"() { + when: + browser.go 'endToEnd/parametersWithLogic' + + then: + browser.driver.pageSource == "good" + } + + def "multiline title"() { + when: + browser.go 'endToEnd/multilineTitle' + + then: + browser.driver.pageSource == """Decorated + This is the title + + +

Hello

body text +""" + } +} diff --git a/grails-test-examples/gsp-sitemesh3/src/integration-test/groovy/SitemeshSpec.groovy b/grails-test-examples/gsp-layout/src/integration-test/groovy/GrailsLayoutSpec.groovy similarity index 97% rename from grails-test-examples/gsp-sitemesh3/src/integration-test/groovy/SitemeshSpec.groovy rename to grails-test-examples/gsp-layout/src/integration-test/groovy/GrailsLayoutSpec.groovy index 0f33f5921c5..87921443c60 100644 --- a/grails-test-examples/gsp-sitemesh3/src/integration-test/groovy/SitemeshSpec.groovy +++ b/grails-test-examples/gsp-layout/src/integration-test/groovy/GrailsLayoutSpec.groovy @@ -21,7 +21,7 @@ import grails.plugin.geb.ContainerGebSpec import grails.testing.mixin.integration.Integration @Integration -class SitemeshSpec extends ContainerGebSpec { +class GrailsLayoutSpec extends ContainerGebSpec { void "forced layout"() { when: diff --git a/grails-test-examples/gsp-sitemesh3/src/main/webapp/WEB-INF/grails-app/views/demo/hello.jsp b/grails-test-examples/gsp-layout/src/main/webapp/WEB-INF/grails-app/views/demo/hello.jsp similarity index 100% rename from grails-test-examples/gsp-sitemesh3/src/main/webapp/WEB-INF/grails-app/views/demo/hello.jsp rename to grails-test-examples/gsp-layout/src/main/webapp/WEB-INF/grails-app/views/demo/hello.jsp diff --git a/settings.gradle b/settings.gradle index 8e3f09256f6..b44e9ba5679 100644 --- a/settings.gradle +++ b/settings.gradle @@ -340,7 +340,7 @@ include( 'grails-test-examples-namespaces', 'grails-test-examples-geb', 'grails-test-examples-gorm', - 'grails-test-examples-gsp-sitemesh3', + 'grails-test-examples-gsp-layout', 'grails-test-examples-gsp-spring-boot', 'grails-test-examples-issue-698-domain-save-npe', 'grails-test-examples-hyphenated', @@ -367,7 +367,7 @@ project(':grails-test-examples-datasources').projectDir = file('grails-test-exam project(':grails-test-examples-geb').projectDir = file('grails-test-examples/geb') project(':grails-test-examples-namespaces').projectDir = file('grails-test-examples/namespaces') project(':grails-test-examples-gorm').projectDir = file('grails-test-examples/gorm') -project(':grails-test-examples-gsp-sitemesh3').projectDir = file('grails-test-examples/gsp-sitemesh3') +project(':grails-test-examples-gsp-layout').projectDir = file('grails-test-examples/gsp-layout') project(':grails-test-examples-gsp-spring-boot').projectDir = file('grails-test-examples/gsp-spring-boot/app') project(':grails-test-examples-issue-698-domain-save-npe').projectDir = file('grails-test-examples/issue-698-domain-save-npe') project(':grails-test-examples-hyphenated').projectDir = file('grails-test-examples/hyphenated') From 75fe50610e245f12c4cda21f105807de2a2289d4 Mon Sep 17 00:00:00 2001 From: James Daugherty Date: Mon, 30 Jun 2025 21:27:16 -0400 Subject: [PATCH 03/26] test: add wait to fix randomly failing test --- .../groovy/functionaltests/UploadControllerSpec.groovy | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/UploadControllerSpec.groovy b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/UploadControllerSpec.groovy index ff9ad1fd9ac..fe7a2dd9d0f 100644 --- a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/UploadControllerSpec.groovy +++ b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/UploadControllerSpec.groovy @@ -39,7 +39,9 @@ class UploadControllerSpec extends ContainerGebSpec { $('#input1').click() then:"The file is uploaded" - $('p').text() == 'Test upload' + waitFor { + $('p').text() == 'Test upload' + } } void "Test file upload parameters"() { @@ -53,7 +55,8 @@ class UploadControllerSpec extends ContainerGebSpec { $('#input2').click() then:"The file is uploaded" - $('p').text() == 'ok' - + waitFor { + $('p').text() == 'ok' + } } } From e48c0267a8867d1fdd221a4233b58a3316ca2598 Mon Sep 17 00:00:00 2001 From: James Daugherty Date: Tue, 1 Jul 2025 07:36:19 -0400 Subject: [PATCH 04/26] test: add script to assist in finding test pollution --- etc/bin/test-bisect.groovy | 247 +++++++++++++++++++++++++++++++++++++ gradle/test-config.gradle | 33 ++++- 2 files changed, 278 insertions(+), 2 deletions(-) create mode 100644 etc/bin/test-bisect.groovy diff --git a/etc/bin/test-bisect.groovy b/etc/bin/test-bisect.groovy new file mode 100644 index 00000000000..bf32d25f272 --- /dev/null +++ b/etc/bin/test-bisect.groovy @@ -0,0 +1,247 @@ +#!/usr/bin/env groovy +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +import java.nio.file.Path +import java.nio.file.Paths +import groovy.cli.commons.CliBuilder + +/** + * This script finds the test class that's causing test pollution in other tests. + * To use it, gradle must be configured to run sequentially, without retries, and output a specific line + * so the script knows the test order. The script will pass the property `testBisect` for gradle to detect when being called + * by this script. For example: + * + * if(hasProperty('testBisect')) { + * tasks.withType(Test).configureEach { + * maxParallelForks = 1 + * forkEvery = 0 + * develocity { + * testDistribution { + * enabled.set(false) + * retryInSameJvm.set(true) + * } + * testRetry { + * maxRetries = 1 + * maxFailures = 1 + * failOnPassedAfterRetry = true + * } + * } + * beforeTest { testDescriptor -> + * logger.info "STARTED TEST: ${testDescriptor.className} > ${testDescriptor.name}" + * } + * afterSuite { desc, result -> + * if (!desc.parent) { + * logger.info("FINISHED - ${result.failedTestCount == 0 && result.testCount > 1} ? 'PASSED' : 'FAILED'} - ${result.testCount} tests executed, ${result.failedTestCount} failed") + * } + * } + * } + * } + */ +class TestPollution { + + File gradleCommandDirectory + String taskPath + String testName + + Path scriptDir = Paths.get(getClass() + .protectionDomain + .codeSource + .location + .toURI()) + .toAbsolutePath() + .parent + + TestPollution(args) { + parseArgs(args) + } + + def parseArgs(args) { + def cli = new CliBuilder(usage: "test-bisect.groovy -p :grails-gsp:test -n org.grails.web.taglib.FormTagLibTests") + + cli.with { + p longOpt: 'taskPath', args: 1, argName: 'taskPath', 'The path to the gradle test task from the root of the project directory, e.g. grails-gsp:test' + n longOpt: 'testName', args: 1, argName: 'testName', 'The test class name that passes when run by itself but fails when the other tests are run' + } + + def options = cli.parse(args) + + if (options.'taskPath') { + taskPath = options.'taskPath' + } + + if (options.'testName') { + testName = options.'testName' + } + + if (!taskPath || !testName) { + cli.usage() + System.exit(-1) + } + + gradleCommandDirectory = scriptDir.resolve('../..').toFile().canonicalFile + if (!gradleCommandDirectory.exists()) { + println "Unable to find gradle rootProject for the given path: $gradleCommandDirectory.toString()" + cli.usage() + System.exit(-1) + } + } + + Collection findTestRunOrder() { + LinkedHashSet tests = [] + + def pattern = ~/.*STARTED TEST: ([a-z0-9A-Z.]+) >.*/ + runCommand('test-run-order', "./gradlew ${taskPath} --rerun-tasks -PtestBisect --info --no-daemon --no-parallel") { String line -> + pattern.matcher(line).each { matcher -> + if (matcher.size() > 1) { + String testName = matcher[1] + if (testName && !tests.contains(testName)) { + tests << testName + } + } + } + } + + tests + } + + void bisectTests() { + if (!testsPass("solo", [testName])) { + println "The test ($testName) fails when run by itself. Pollution cannot be determined." + println "Run the command yourself: ${createCommand(withPollutedTest([]))}" + return + } + + List testList = (findTestRunOrder() - testName).toList() + if (!testList) { + println "No other tests were found. Cannot bisect." + System.exit(1) + } + + bisectTests(testList) + } + + List bisectTests(List testList) { + + // if the test list size is > 1, split into left and right hand sides + if (testList.size() > 1) { + List lhs = leftHandSide(testList) + List rhs = rightHandSide(testList) + + if (!testsPass("left", withPollutedTest(lhs))) { + return bisectTests(lhs) + } + + if (!testsPass("right", withPollutedTest(rhs))) { + return bisectTests(rhs) + } + + if (testsPass("full", withPollutedTest(testList))) { + println "Unable to find any failing tests with this list, running them all appears to run without issue: \n${testList.join(" ")}" + return null + } + + println "Unable to find just one test that's causing problems. Running just with the left hand or right hand side of this narrowed list passes, but the full list fails" + println "full list (fails): ${testList.join(" ")}" + println "left hand side (passes): ${lhs.join(" ")}" + println "right hand side (passes): ${rhs.join(" ")}" + } else if (!testsPass("suspected", withPollutedTest(testList))) { + println "The test that's causing pollution: ${testList.join(" ")}" // should only be 1 + println "Here's the command to execute to see if you've fixed things:\n ${createCommand(withPollutedTest(testList))}" + return testList + } + + println "Not sure what's happening, got to this list of tests, but everything passes with this list: \n${testList.join(" ")}" + [] + } + + List leftHandSide(List testList) { + return testList[0..(testList.size() / 2 - 1)] + } + + List rightHandSide(List testList) { + return testList[(testList.size() / 2)..-1] + } + + List withPollutedTest(List testList) { + return [testList, testName].flatten() + } + + Boolean testsPass(String runName, List testList) { + String command = createCommand(testList) + return runCommand(runName, command) + } + + String createCommand(List testList) { + def testArgs = testList.collect { "--tests ${it}" } + "./gradlew ${taskPath} --rerun-tasks -PtestBisect --no-daemon --no-parallel --info ${testArgs.join(' ')}" + } + + def out(prefix, message) { + println("${prefix.padLeft(16, ' ')}: $message") + } + + boolean runCommand(runName, command, Closure outputParser = null) { + out runName, command + String completedLine = '' + + String knownExecutor = null + def executorPattern = ~/.*Gradle Test Executor ([0-9]+) .*/ + def finishPattern = ~/.*FINISHED - (PASSED|FAILED) - .*/ + def exitValue = command.execute(null, gradleCommandDirectory).with { proc -> + proc.in.eachLine { String line -> + // uncomment for real time output of the gradle commands + // out(runName, line) + def completedMatcher = finishPattern.matcher(line) + if (completedMatcher.matches()) { + completedLine = line + } + + + def execMatcher = executorPattern.matcher(line) + if (execMatcher.matches()) { + if (execMatcher.size() > 1) { + def foundExecutor = execMatcher[1] + if (!knownExecutor && foundExecutor) { + knownExecutor = foundExecutor + } else if (knownExecutor != foundExecutor) { + throw new Exception("WARNING: Found multiple Gradle Test Executors: ${knownExecutor} and ${foundExecutor}. Test pollution detection cannot work if tests are run in parallel.") + } + } + } + + if (outputParser) { + outputParser.call(line) + } + } + proc.waitFor() + proc.exitValue() + } + + if(!completedLine) { + throw new IllegalStateException("Could not locate the completed line in the output.") + } + boolean failures = completedLine.contains('FAILED') + + out(runName, "exitValue=${exitValue}, failures=${failures}, testExecutor=${knownExecutor}, completedLine=${completedLine}") + !failures && exitValue == 0 + } +} + +new TestPollution(args).bisectTests() diff --git a/gradle/test-config.gradle b/gradle/test-config.gradle index 25647cdb259..c30db8a7462 100644 --- a/gradle/test-config.gradle +++ b/gradle/test-config.gradle @@ -48,7 +48,7 @@ tasks.withType(Test).configureEach { jvmArgs += java17moduleReflectionCompatibilityArguments develocity { testRetry { - maxRetries = 2 + maxRetries = configuredTestParallel == 1 ? 1 : 2 maxFailures = 20 failOnPassedAfterRetry = true } @@ -63,7 +63,7 @@ tasks.withType(Test).configureEach { excludes = ['**/*TestCase.class', '**/*$*.class'] maxParallelForks = configuredTestParallel maxHeapSize = isCiBuild ? '768m' : '1024m' - forkEvery = isCiBuild ? 20 : 100 + forkEvery = hasProperty('forkEveryUnitTest') ? getProperty('forkEveryUnitTest') as long : (isCiBuild ? 20 : 100) if (System.getProperty('debug.tests')) { jvmArgs += debugArguments } @@ -73,3 +73,32 @@ tasks.withType(Test).configureEach { } } +if (hasProperty('testBisect')) { + tasks.withType(Test).configureEach { + maxParallelForks = 1 + forkEvery = 0 + + develocity { + testDistribution { + enabled = false + retryInSameJvm = true + } + testRetry { + maxRetries = 1 + maxFailures = 1 + failOnPassedAfterRetry = true + } + } + + beforeTest { testDescriptor -> + logger.info('STARTED TEST: {} > {}', testDescriptor.className, testDescriptor.name) + } + + afterSuite { desc, result -> + if (!desc.parent) { + def testStatus = result.failedTestCount == 0 && result.testCount > 1 ? 'PASSED' : 'FAILED' + logger.info('FINISHED - {} - {} tests executed, {} failed', testStatus, result.testCount, result.failedTestCount) + } + } + } +} \ No newline at end of file From cab0304500e7a90f334c7b360a2e425bb3a1eebb Mon Sep 17 00:00:00 2001 From: James Daugherty Date: Tue, 1 Jul 2025 10:51:06 -0400 Subject: [PATCH 05/26] fix: do not recreate the grails application while trying to clear it --- .../groovy/org/grails/testing/GrailsUnitTest.groovy | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/grails-testing-support-core/src/main/groovy/org/grails/testing/GrailsUnitTest.groovy b/grails-testing-support-core/src/main/groovy/org/grails/testing/GrailsUnitTest.groovy index dab55e42c37..56df2348ba6 100644 --- a/grails-testing-support-core/src/main/groovy/org/grails/testing/GrailsUnitTest.groovy +++ b/grails-testing-support-core/src/main/groovy/org/grails/testing/GrailsUnitTest.groovy @@ -139,17 +139,16 @@ trait GrailsUnitTest { } void cleanupGrailsApplication() { - if (_grailsApplication != null) { + if (_grailsApplication != null) { if (_grailsApplication instanceof DefaultGrailsApplication) { ((DefaultGrailsApplication)_grailsApplication).clear() } - ApplicationContext applicationContext = grailsApplication.getParentContext() - + ApplicationContext applicationContext = _grailsApplication.getParentContext() if (applicationContext instanceof ConfigurableApplicationContext) { if (((ConfigurableApplicationContext) applicationContext).isActive()) { - if(grailsApplication.mainContext instanceof Closeable) { - ((Closeable)grailsApplication.mainContext).close() + if(_grailsApplication.mainContext instanceof Closeable) { + ((Closeable)_grailsApplication.mainContext).close() } if (applicationContext instanceof Closeable) { ((Closeable)applicationContext).close() @@ -161,6 +160,8 @@ trait GrailsUnitTest { DeferredBindingActions.clear() this._grailsApplication = null + this._servletContext = null + cleanupPromiseFactory() Holders.clear() } From 1f9db1c2eb99cdc44326a33f043934c8b6cbc8b2 Mon Sep 17 00:00:00 2001 From: James Daugherty Date: Tue, 1 Jul 2025 10:51:40 -0400 Subject: [PATCH 06/26] test: fix test pollution with taglibs --- .../RestfulReverseUrlRenderingTests.groovy | 16 ++-- .../grails/web/taglib/FormTagLibTests.groovy | 86 ++++++------------- .../spock/CleanupContextInterceptor.groovy | 8 +- .../testing/web/GrailsWebUnitTest.groovy | 7 ++ .../testing/web/taglib/TagLibUnitTest.groovy | 4 + .../runtime/support/LazyTagLibraryLookup.java | 9 ++ .../spock/WebCleanupSpecInterceptor.groovy | 23 ++++- .../spock/WebSetupSpecInterceptor.groovy | 5 +- 8 files changed, 84 insertions(+), 74 deletions(-) diff --git a/grails-gsp/plugin/src/test/groovy/org/grails/web/mapping/RestfulReverseUrlRenderingTests.groovy b/grails-gsp/plugin/src/test/groovy/org/grails/web/mapping/RestfulReverseUrlRenderingTests.groovy index 518c419e98a..a40869e5ec9 100644 --- a/grails-gsp/plugin/src/test/groovy/org/grails/web/mapping/RestfulReverseUrlRenderingTests.groovy +++ b/grails-gsp/plugin/src/test/groovy/org/grails/web/mapping/RestfulReverseUrlRenderingTests.groovy @@ -32,42 +32,42 @@ class RestfulReverseUrlRenderingTests extends Specification implements UrlMappin def testLinkTagRendering() { when: - def template = 'create' + def template = 'create' String output = applyTemplate(template) then: - output == 'create' + output == 'create' } def testFormTagRendering() { when: - def template = 'save' + def template = 'save' String output = applyTemplate(template) then: - output == '
save
' + output == '
save
' } def testFormTagRenderGETRequest() { when: - def template = 'create' + def template = 'create' String output = applyTemplate(template) then: - output == '
create
' + output == '
create
' } } @Artefact("UrlMappings") class RestfulReverseUrlMappings { static mappings = { - "/book" (controller: "restfulBook", action: [GET: "create", POST: "save"]) + "/car" (controller: "restfulCar", action: [GET: "create", POST: "save"]) } } @Artefact("Controller") -class RestfulBookController { +class RestfulCarController { def create = {} def save = {} } diff --git a/grails-gsp/plugin/src/test/groovy/org/grails/web/taglib/FormTagLibTests.groovy b/grails-gsp/plugin/src/test/groovy/org/grails/web/taglib/FormTagLibTests.groovy index b72109ea9d8..714131e0dfd 100644 --- a/grails-gsp/plugin/src/test/groovy/org/grails/web/taglib/FormTagLibTests.groovy +++ b/grails-gsp/plugin/src/test/groovy/org/grails/web/taglib/FormTagLibTests.groovy @@ -18,15 +18,16 @@ */ package org.grails.web.taglib -import grails.core.GrailsUrlMappingsClass +import grails.artefact.Artefact import grails.testing.web.taglib.TagLibUnitTest import grails.util.MockRequestDataValueProcessor import org.grails.buffer.FastStringWriter -import org.grails.core.AbstractGrailsClass import org.grails.core.artefact.UrlMappingsArtefactHandler +import org.grails.plugins.web.taglib.ApplicationTagLib import org.grails.plugins.web.taglib.FormTagLib +import org.grails.plugins.web.taglib.UrlMappingTagLib +import org.grails.web.mapping.UrlMappingsHolderFactoryBean import spock.lang.Issue -import spock.lang.PendingFeatureIf import spock.lang.Rollup import spock.lang.Specification @@ -41,33 +42,25 @@ import spock.lang.Specification * @author rvanderwerf */ class FormTagLibTests extends Specification implements TagLibUnitTest { + def setupSpec() { + // Test pollution causes these to be cached on the LazyTagLibraryLookup + [ApplicationTagLib, FormTagLib, UrlMappingTagLib].each { + GroovySystem.metaClassRegistry.removeMetaClass(it) + } + } def setup() { tagLib.requestDataValueProcessor = new MockRequestDataValueProcessor() - } - def setupSpec() { - def mappingsClosure = { - '/admin/books'(controller: 'books', namespace: 'admin') - '/books'(controller: 'books') + grailsApplication.addArtefact(UrlMappingsArtefactHandler.TYPE, FormTagLibUrlMappings) + + defineBeans { + grailsUrlMappingsHolder(UrlMappingsHolderFactoryBean) { + getDelegate().grailsApplication = grailsApplication + } } - grailsApplication.addArtefact(UrlMappingsArtefactHandler.TYPE, new MockGrailsUrlMappingsClass(mappingsClosure)) - } - - @PendingFeatureIf({ - System.getenv().containsKey('CI') - /* - FOR SOME REASON FAILS (ONLY) IN CI WITH: - output == '
\n
' - | | - | false - | 6 differences (95% similarity) - |
\n
- |
\n
-
-
- */ - }) + } + def testFormNoNamespace() { expect: applyTemplate('') == @@ -291,27 +284,14 @@ class FormTagLibTests extends Specification implements TagLibUnitTest\n' } - @PendingFeatureIf({ - System.getenv().containsKey('CI') - /* - FOR SOME REASON FAILS (ONLY) IN CI WITH: - tagLib.formActionSubmit([ controller: 'con', id: 'formElementId', value: 'Submit' ]).toString() == '' - | | | | - | | false - | | 4 differences (94% similarity) - | | - | | - | - */ - }) def testFormActionSubmitWithController() { expect: tagLib.formActionSubmit([ - controller: 'con', + controller: 'books', id: 'formElementId', value: 'Submit' ]).toString() == - '' + '' } def testFormActionSubmitWithControllerAndAction() { @@ -582,24 +562,12 @@ class FormTagLibTests extends Specification implements TagLibUnitTest groovyPages = [:] GrailsWebRequest webRequest + /** + * When mocking tag libs, the LazyTagLibraryLookup will not be cleared by default. True forces it to be cleared. + */ + boolean getPurgeTagLibMetaClass() { + false + } + GrailsMockHttpServletRequest getRequest() { return (GrailsMockHttpServletRequest) getWebRequest().getCurrentRequest() } diff --git a/grails-testing-support-web/src/main/groovy/grails/testing/web/taglib/TagLibUnitTest.groovy b/grails-testing-support-web/src/main/groovy/grails/testing/web/taglib/TagLibUnitTest.groovy index b8856a7b37c..678ad527025 100644 --- a/grails-testing-support-web/src/main/groovy/grails/testing/web/taglib/TagLibUnitTest.groovy +++ b/grails-testing-support-web/src/main/groovy/grails/testing/web/taglib/TagLibUnitTest.groovy @@ -29,6 +29,10 @@ trait TagLibUnitTest implements ParameterizedGrailsUnitTest, GrailsWebUnit private boolean hasBeenMocked = false + boolean getPurgeTagLibMetaClass() { + true + } + /** * Renders a template for the given contents and model * diff --git a/grails-testing-support-web/src/main/groovy/org/grails/testing/runtime/support/LazyTagLibraryLookup.java b/grails-testing-support-web/src/main/groovy/org/grails/testing/runtime/support/LazyTagLibraryLookup.java index 06a041e178f..d0b71c6720f 100644 --- a/grails-testing-support-web/src/main/groovy/org/grails/testing/runtime/support/LazyTagLibraryLookup.java +++ b/grails-testing-support-web/src/main/groovy/org/grails/testing/runtime/support/LazyTagLibraryLookup.java @@ -21,6 +21,8 @@ import grails.core.gsp.GrailsTagLibClass; import groovy.lang.GroovyObject; +import groovy.lang.GroovySystem; +import groovy.lang.MetaClassRegistry; import org.grails.plugins.web.GroovyPagesGrailsPlugin; import org.grails.taglib.TagLibraryLookup; import org.springframework.beans.factory.support.AbstractBeanDefinition; @@ -48,6 +50,13 @@ protected void registerTagLibraries() { } } + public void cleanTagLibsMetaClass() { + MetaClassRegistry registry = GroovySystem.getMetaClassRegistry(); + for (Class clazz : tagLibClasses) { + registry.removeMetaClass(clazz); + } + } + public void registerLazyLoadableTagLibClass(Class tagLibClass) { Class defaultTagLibClass = null; GrailsTagLibClass grailsTagLibClass = null; diff --git a/grails-testing-support-web/src/main/groovy/org/grails/testing/spock/WebCleanupSpecInterceptor.groovy b/grails-testing-support-web/src/main/groovy/org/grails/testing/spock/WebCleanupSpecInterceptor.groovy index 5fef109626b..a5d45b55501 100644 --- a/grails-testing-support-web/src/main/groovy/org/grails/testing/spock/WebCleanupSpecInterceptor.groovy +++ b/grails-testing-support-web/src/main/groovy/org/grails/testing/spock/WebCleanupSpecInterceptor.groovy @@ -19,7 +19,9 @@ package org.grails.testing.spock +import grails.testing.web.GrailsWebUnitTest import groovy.transform.CompileStatic +import org.grails.testing.runtime.support.LazyTagLibraryLookup import org.grails.web.converters.configuration.ConvertersConfigurationHolder import org.spockframework.runtime.extension.IMethodInterceptor import org.spockframework.runtime.extension.IMethodInvocation @@ -29,7 +31,24 @@ class WebCleanupSpecInterceptor implements IMethodInterceptor { @Override void intercept(IMethodInvocation invocation) throws Throwable { - ConvertersConfigurationHolder.clear() - invocation.proceed() + try { + invocation.proceed() + } + finally { + ConvertersConfigurationHolder.clear() + + GrailsWebUnitTest test = (GrailsWebUnitTest) invocation.instance + if (test.purgeTagLibMetaClass) { + try { + def lookup = test.grailsApplication.mainContext.getBean(LazyTagLibraryLookup) + if (lookup) { + lookup.cleanTagLibsMetaClass() + } + } + catch (ignored) { + // may not exist + } + } + } } } diff --git a/grails-testing-support-web/src/main/groovy/org/grails/testing/spock/WebSetupSpecInterceptor.groovy b/grails-testing-support-web/src/main/groovy/org/grails/testing/spock/WebSetupSpecInterceptor.groovy index 449f34a3346..89d7cb39aed 100644 --- a/grails-testing-support-web/src/main/groovy/org/grails/testing/spock/WebSetupSpecInterceptor.groovy +++ b/grails-testing-support-web/src/main/groovy/org/grails/testing/spock/WebSetupSpecInterceptor.groovy @@ -97,6 +97,8 @@ class WebSetupSpecInterceptor implements IMethodInterceptor { String urlConverterType = config.getProperty(Settings.WEB_URL_CONVERTER) "${grails.web.UrlConverter.BEAN_NAME}"('hyphenated' == urlConverterType ? HyphenatedUrlConverter : CamelCaseUrlConverter) + grailsUrlMappingsHolder(UrlMappingsHolderFactoryBean) + grailsLinkGenerator(DefaultLinkGenerator, config?.grails?.serverURL ?: "http://localhost:8080") if (ClassUtils.isPresent("UrlMappings", classLoader)) { @@ -115,9 +117,6 @@ class WebSetupSpecInterceptor implements IMethodInterceptor { localeResolver(SessionLocaleResolver) multipartResolver(StandardServletMultipartResolver) - grailsUrlMappingsHolder(UrlMappingsHolderFactoryBean) { - grailsApplication = grailsApplication - } "${CompositeViewResolver.BEAN_NAME}"(CompositeViewResolver) From ea62cf85b9a31fb2ca7567748f1b64607591197e Mon Sep 17 00:00:00 2001 From: James Daugherty Date: Fri, 4 Jul 2025 05:28:03 -0400 Subject: [PATCH 07/26] feedback: cleanup --- .../codecs/Base64CodecExtensionMethods.groovy | 6 +- .../grails/plugins/codecs/DigestUtils.groovy | 3 +- .../codecs/HexCodecExtensionMethods.groovy | 4 +- ...alGrailsClassInjectorTransformation.groovy | 5 +- .../org/grails/core/io/MockFileResource.java | 3 +- .../core/io/MockStringResourceLoader.java | 8 +- .../orm/hibernate/cfg/GrailsDomainBinder.java | 9 +- .../testing/OutputCaptureExtension.groovy | 4 +- .../taglib/EmbeddedPropertiesSpec.groovy | 64 +++--- .../groovy/grails/doc/DocPublisher.groovy | 8 +- .../main/groovy/grails/doc/PdfBuilder.groovy | 6 +- .../doc/macros/GspTagSourceMacro.groovy | 3 +- .../grails/gsp/GroovyPagesTemplateEngine.java | 3 +- .../grails/gsp/compiler/GroovyPageParser.java | 195 ++++++++---------- .../web/gsp/GroovyPagesTemplateRenderer.java | 3 +- .../grails/web/pages/GSPResponseWriter.java | 1 + .../grails/web/pages/GroovyPagesServlet.java | 36 ++-- .../compiler/tags/GroovyEachParseTests.groovy | 12 +- .../RestfulReverseUrlRenderingTests.groovy | 2 +- .../web/mapping/ReverseUrlMappingTests.groovy | 2 +- ...verseUrlMappingToDefaultActionTests.groovy | 2 +- .../web/mapping/RootUrlMappingTests.groovy | 2 +- .../org/grails/web/pages/ParseTests.java | 139 ++++++------- .../web/taglib/AbstractGrailsTagTests.groovy | 61 +++--- .../web/taglib/FormTagLibResourceTests.groovy | 2 +- .../grails/web/taglib/FormTagLibTests.groovy | 4 +- .../taglib/LinkRenderingTagLibTests.groovy | 2 +- .../taglib/NamespacedTagLibMethodTests.groovy | 4 +- .../web/taglib/RenderTagLibTests.groovy | 52 ++--- .../templates/TemplateRendererImpl.groovy | 4 +- .../cli/profile/steps/RenderStep.groovy | 4 +- .../GrailsMockHttpServletRequest.groovy | 12 +- .../support/MockApplicationContext.java | 3 +- .../GrailsMockHttpServletRequestTests.groovy | 4 +- .../grails/web/util/StreamByteBufferTest.java | 7 +- .../grails/testing/gorm/DataTest.groovy | 6 +- .../testing/web/UrlMappingsUnitTest.groovy | 2 +- .../view/JsonViewTemplateEngineSpec.groovy | 4 +- .../web/util/IncludeResponseWrapper.java | 3 +- ...HalJsonDataBindingSourceCreatorSpec.groovy | 6 +- .../JsonDataBindingSourceCreatorSpec.groovy | 8 +- ...JsonApiDataBindingSourceCreatorSpec.groovy | 16 +- 42 files changed, 360 insertions(+), 364 deletions(-) diff --git a/grails-codecs-core/src/main/groovy/org/grails/plugins/codecs/Base64CodecExtensionMethods.groovy b/grails-codecs-core/src/main/groovy/org/grails/plugins/codecs/Base64CodecExtensionMethods.groovy index f4a7bd277ad..6a56864c534 100644 --- a/grails-codecs-core/src/main/groovy/org/grails/plugins/codecs/Base64CodecExtensionMethods.groovy +++ b/grails-codecs-core/src/main/groovy/org/grails/plugins/codecs/Base64CodecExtensionMethods.groovy @@ -21,6 +21,8 @@ package org.grails.plugins.codecs import org.apache.commons.codec.binary.Base64 import org.codehaus.groovy.runtime.NullObject +import java.nio.charset.StandardCharsets + /** * A codec that encodes and decodes Objects using Base64 encoding. * @@ -37,7 +39,7 @@ class Base64CodecExtensionMethods { return new String(Base64.encodeBase64(theTarget)) } - return new String(Base64.encodeBase64(theTarget.toString().getBytes("UTF-8"))) + return new String(Base64.encodeBase64(theTarget.toString().getBytes(StandardCharsets.UTF_8))) } static decodeBase64(theTarget) { @@ -49,6 +51,6 @@ class Base64CodecExtensionMethods { return Base64.decodeBase64(theTarget) } - return Base64.decodeBase64(theTarget.toString().getBytes("UTF-8")) + return Base64.decodeBase64(theTarget.toString().getBytes(StandardCharsets.UTF_8)) } } diff --git a/grails-codecs-core/src/main/groovy/org/grails/plugins/codecs/DigestUtils.groovy b/grails-codecs-core/src/main/groovy/org/grails/plugins/codecs/DigestUtils.groovy index d18e7e04747..fccb6489a10 100644 --- a/grails-codecs-core/src/main/groovy/org/grails/plugins/codecs/DigestUtils.groovy +++ b/grails-codecs-core/src/main/groovy/org/grails/plugins/codecs/DigestUtils.groovy @@ -18,6 +18,7 @@ */ package org.grails.plugins.codecs +import java.nio.charset.StandardCharsets import java.security.MessageDigest abstract class DigestUtils { @@ -38,7 +39,7 @@ abstract class DigestUtils { data.eachWithIndex { v, i -> src[i] = v } } else { - src = data.toString().getBytes("UTF-8") + src = data.toString().getBytes(StandardCharsets.UTF_8) } md.update(src) // This probably needs to use the thread's Locale encoding return md.digest() diff --git a/grails-codecs-core/src/main/groovy/org/grails/plugins/codecs/HexCodecExtensionMethods.groovy b/grails-codecs-core/src/main/groovy/org/grails/plugins/codecs/HexCodecExtensionMethods.groovy index 6fc77a2bd5b..7dda93f99a2 100644 --- a/grails-codecs-core/src/main/groovy/org/grails/plugins/codecs/HexCodecExtensionMethods.groovy +++ b/grails-codecs-core/src/main/groovy/org/grails/plugins/codecs/HexCodecExtensionMethods.groovy @@ -20,6 +20,8 @@ package org.grails.plugins.codecs import org.codehaus.groovy.runtime.NullObject +import java.nio.charset.StandardCharsets + class HexCodecExtensionMethods { static HEXDIGITS = '0123456789abcdef' @@ -32,7 +34,7 @@ class HexCodecExtensionMethods { def result = new StringBuilder() if (theTarget instanceof String) { - theTarget = theTarget.getBytes("UTF-8") + theTarget = theTarget.getBytes(StandardCharsets.UTF_8) } theTarget.each() { result << HexCodecExtensionMethods.HEXDIGITS[(it & 0xF0) >> 4] diff --git a/grails-core/src/main/groovy/org/grails/compiler/injection/GlobalGrailsClassInjectorTransformation.groovy b/grails-core/src/main/groovy/org/grails/compiler/injection/GlobalGrailsClassInjectorTransformation.groovy index 61080c37997..6eded3d6dc9 100644 --- a/grails-core/src/main/groovy/org/grails/compiler/injection/GlobalGrailsClassInjectorTransformation.groovy +++ b/grails-core/src/main/groovy/org/grails/compiler/injection/GlobalGrailsClassInjectorTransformation.groovy @@ -53,6 +53,7 @@ import org.grails.io.support.GrailsResourceUtils import org.grails.io.support.UrlResource import java.lang.reflect.Modifier +import java.nio.charset.StandardCharsets /** * A global transformation that applies Grails' transformations to classes within a Grails project @@ -282,7 +283,7 @@ class GlobalGrailsClassInjectorTransformation implements ASTTransformation, Comp PluginAstReader pluginAstReader = new PluginAstReader() def info = pluginAstReader.readPluginInfo(pluginClassNode) - pluginXml.withWriter("UTF-8") { Writer writer -> + pluginXml.withWriter(StandardCharsets.UTF_8.name()) { Writer writer -> def mkp = new MarkupBuilder(writer) def pluginName = GrailsNameUtils.getLogicalPropertyName(pluginClassNode.name, "GrailsPlugin") @@ -366,7 +367,7 @@ class GlobalGrailsClassInjectorTransformation implements ASTTransformation, Comp mkp.yield pluginXml } - pluginXmlFile.withWriter("UTF-8") { Writer writer -> + pluginXmlFile.withWriter(StandardCharsets.UTF_8.name()) { Writer writer -> writable.writeTo(writer) } diff --git a/grails-core/src/main/groovy/org/grails/core/io/MockFileResource.java b/grails-core/src/main/groovy/org/grails/core/io/MockFileResource.java index a06dd2f3858..406b66609aa 100644 --- a/grails-core/src/main/groovy/org/grails/core/io/MockFileResource.java +++ b/grails-core/src/main/groovy/org/grails/core/io/MockFileResource.java @@ -19,6 +19,7 @@ package org.grails.core.io; import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; import org.springframework.core.io.ByteArrayResource; @@ -33,7 +34,7 @@ public class MockFileResource extends ByteArrayResource { private String fileName; public MockFileResource(String fileName, String contents) throws UnsupportedEncodingException { - super(contents.getBytes("UTF-8")); + super(contents.getBytes(StandardCharsets.UTF_8)); this.fileName = fileName; } diff --git a/grails-core/src/main/groovy/org/grails/core/io/MockStringResourceLoader.java b/grails-core/src/main/groovy/org/grails/core/io/MockStringResourceLoader.java index 283bee40639..70eddad6a8c 100644 --- a/grails-core/src/main/groovy/org/grails/core/io/MockStringResourceLoader.java +++ b/grails-core/src/main/groovy/org/grails/core/io/MockStringResourceLoader.java @@ -19,6 +19,7 @@ package org.grails.core.io; import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; @@ -61,12 +62,7 @@ public void registerMockResource(String location, Resource res) { * @param contents The contents of the resource */ public void registerMockResource(String location, String contents) { - try { - mockResources.put(location, new GrailsByteArrayResource(contents.getBytes("UTF-8"), location)); - } - catch (UnsupportedEncodingException e) { - throw new RuntimeException(e); - } + mockResources.put(location, new GrailsByteArrayResource(contents.getBytes(StandardCharsets.UTF_8), location)); } /** diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsDomainBinder.java b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsDomainBinder.java index cbfbedcb26d..13c7983e5cb 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsDomainBinder.java +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsDomainBinder.java @@ -61,6 +61,7 @@ import java.io.UnsupportedEncodingException; import java.lang.reflect.Method; import java.math.BigInteger; +import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.sql.Types; @@ -2041,12 +2042,8 @@ protected void setGeneratedUniqueName(UniqueKey uk) { catch (NoSuchAlgorithmException e) { throw new RuntimeException(e); } - try { - md.update(sb.toString().getBytes("UTF-8")); - } - catch (UnsupportedEncodingException e) { - throw new RuntimeException(e); - } + + md.update(sb.toString().getBytes(StandardCharsets.UTF_8)); String name = "UK" + new BigInteger(1, md.digest()).toString(16); if (name.length() > 30) { diff --git a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/testing/OutputCaptureExtension.groovy b/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/testing/OutputCaptureExtension.groovy index 0d192a7721a..8cb4988c81f 100644 --- a/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/testing/OutputCaptureExtension.groovy +++ b/grails-data-hibernate5/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/testing/OutputCaptureExtension.groovy @@ -28,6 +28,8 @@ import org.spockframework.runtime.extension.IMethodInvocation import org.spockframework.runtime.model.FieldInfo import org.spockframework.runtime.model.SpecInfo +import java.nio.charset.StandardCharsets + class OutputCaptureExtension implements IAnnotationDrivenExtension { private final Map fieldBuffers = new HashMap(1); @@ -83,7 +85,7 @@ class OutputCaptureExtension implements IAnnotationDrivenExtension { - def mockFormFieldsTemplateService = Mock(FormFieldsTemplateService) + def mockFormFieldsTemplateService = Mock(FormFieldsTemplateService) - def setupSpec() { - mockDomain(Person) - } + def setupSpec() { + mockDomain(Person) + } - def setup() { - mockFormFieldsTemplateService.findTemplate(_, 'wrapper', null, null) >> [path: '/_fields/default/wrapper'] + def setup() { + mockFormFieldsTemplateService.findTemplate(_, 'wrapper', null, null) >> [path: '/_fields/default/wrapper'] mockFormFieldsTemplateService.getTemplateFor('wrapper') >> "wrapper" mockFormFieldsTemplateService.getTemplateFor('widget') >> "widget" mockFormFieldsTemplateService.getTemplateFor('displayWrapper') >> "displayWrapper" mockFormFieldsTemplateService.getTemplateFor('displayWidget') >> "displayWidget" - mockFormFieldsTemplateService.getWidgetPrefix() >> 'input-' - tagLib.formFieldsTemplateService = mockFormFieldsTemplateService + mockFormFieldsTemplateService.getWidgetPrefix() >> 'input-' + tagLib.formFieldsTemplateService = mockFormFieldsTemplateService mockEmbeddedSitemeshLayout tagLib } - void "field tag renders individual fields for embedded properties"() { - given: - views["/_fields/default/_wrapper.gsp"] = '${property} ' + void "field tag renders individual fields for embedded properties"() { + given: + views["/_fields/default/_wrapper.gsp"] = '${property} ' - when: - def output = applyTemplate('', [personInstance: personInstance]) + when: + def output = applyTemplate('', [personInstance: personInstance]) - then: - output.contains('address.city address.country address.street') - } + then: + output.contains('address.city address.country address.street') + } - void "field tag wraps embedded properties in a container"() { - given: - views["/_fields/default/_wrapper.gsp"] = '${property} ' + void "field tag wraps embedded properties in a container"() { + given: + views["/_fields/default/_wrapper.gsp"] = '${property} ' - expect: - applyTemplate('', [personInstance: personInstance]) == '
Addressaddress.city address.country address.street
' - } + expect: + applyTemplate('', [personInstance: personInstance]) == '
Addressaddress.city address.country address.street
' + } - void "embedded property label is resolved from message bundle"() { - given: - views["/_fields/default/_wrapper.gsp"] = '${property} ' + void "embedded property label is resolved from message bundle"() { + given: + views["/_fields/default/_wrapper.gsp"] = '${property} ' - and: - messageSource.addMessage('person.address.label', request.locale, 'Address of person') + and: + messageSource.addMessage('person.address.label', request.locale, 'Address of person') - when: - def output = applyTemplate('', [personInstance: personInstance]) + when: + def output = applyTemplate('', [personInstance: personInstance]) - then: - output.contains('Address of person') - } + then: + output.contains('Address of person') + } } \ No newline at end of file diff --git a/grails-gradle/docs-core/src/main/groovy/grails/doc/DocPublisher.groovy b/grails-gradle/docs-core/src/main/groovy/grails/doc/DocPublisher.groovy index d5ab9d34ef6..44b3c904b2d 100644 --- a/grails-gradle/docs-core/src/main/groovy/grails/doc/DocPublisher.groovy +++ b/grails-gradle/docs-core/src/main/groovy/grails/doc/DocPublisher.groovy @@ -35,6 +35,8 @@ import org.yaml.snakeyaml.LoaderOptions import org.yaml.snakeyaml.Yaml import org.yaml.snakeyaml.constructor.SafeConstructor +import java.nio.charset.StandardCharsets + /** * Coordinated the DocEngine the produce documentation based on the gdoc format. * @@ -366,7 +368,7 @@ class DocPublisher { def textiles = f.listFiles().findAll { it.name.endsWith(ext)}.sort() def usageFile = new File("${src}/ref/${section}${ext}") if (usageFile.exists()) { - def data = usageFile.getText("UTF-8") + def data = usageFile.getText(StandardCharsets.UTF_8.name()) context.set(DocEngine.SOURCE_FILE, usageFile) context.set(DocEngine.CONTEXT_PATH, pathToRoot) context.set(DocEngine.API_CONTEXT_PATH, vars.resourcesPath) @@ -379,7 +381,7 @@ class DocPublisher { } for (txt in textiles) { def name = txt.name[0..-6] - def data = txt.getText("UTF-8") + def data = txt.getText(StandardCharsets.UTF_8.name()) context.set(DocEngine.SOURCE_FILE, txt.name) context.set(DocEngine.CONTEXT_PATH, pathToRoot) context.set(DocEngine.API_CONTEXT_PATH, vars.resourcesPath) @@ -461,7 +463,7 @@ class DocPublisher { varsCopy.sectionToc = section.children varsCopy.sourcePath = section.file output.warn "Rendering document file $sourceFile.name" - varsCopy.content = engine.render(sourceFile.getText("UTF-8"), context) + varsCopy.content = engine.render(sourceFile.getText(StandardCharsets.UTF_8.name()), context) // First create the section content, which usually consists of a header // and the translated gdoc content. diff --git a/grails-gradle/docs-core/src/main/groovy/grails/doc/PdfBuilder.groovy b/grails-gradle/docs-core/src/main/groovy/grails/doc/PdfBuilder.groovy index d1e18272724..74d1e7ae27e 100644 --- a/grails-gradle/docs-core/src/main/groovy/grails/doc/PdfBuilder.groovy +++ b/grails-gradle/docs-core/src/main/groovy/grails/doc/PdfBuilder.groovy @@ -28,6 +28,8 @@ import org.jsoup.Jsoup import org.w3c.dom.Document import org.xhtmlrenderer.pdf.ITextRenderer +import java.nio.charset.StandardCharsets + @CompileStatic class PdfBuilder { @@ -61,7 +63,7 @@ class PdfBuilder { } static String createXml(File htmlFile, String base) { - String xml = htmlFile.getText("UTF-8") + String xml = htmlFile.getText(StandardCharsets.UTF_8.name()) // fix inner anchors xml = xml.replaceAll(' htmlParts = new ArrayList(); - Set bodyVarsDefined=new HashSet(); - Map attrsVarsMapDefinition=new HashMap(); + Set bodyVarsDefined = new HashSet(); + Map attrsVarsMapDefinition = new HashMap(); - int closureLevel=0; + int closureLevel = 0; /* * Set to true when whitespace is currently being saved for later output if @@ -127,17 +127,17 @@ public class GroovyPageParser implements Tokens { private int state; private static final String DEFAULT_CONTENT_TYPE = "text/html;charset=UTF-8"; private int constantCount = 0; - private Map constantsToNumbers = new HashMap(); + private Map constantsToNumbers = new HashMap(); private final String pageName; public static final String[] DEFAULT_IMPORTS = { - "grails.plugins.metadata.GrailsPlugin", - "org.grails.gsp.compiler.transform.LineNumber", - "org.grails.gsp.GroovyPage", - "org.grails.web.taglib.*", - "org.grails.taglib.GrailsTagException", - "org.springframework.web.util.*", - "grails.util.GrailsUtil" + "grails.plugins.metadata.GrailsPlugin", + "org.grails.gsp.compiler.transform.LineNumber", + "org.grails.gsp.GroovyPage", + "org.grails.web.taglib.*", + "org.grails.taglib.GrailsTagException", + "org.springframework.web.util.*", + "grails.util.GrailsUtil" }; public static final String CONFIG_PROPERTY_DEFAULT_CODEC = "grails.views.default.codec"; public static final String CONFIG_PROPERTY_GSP_ENCODING = "grails.views.gsp.encoding"; @@ -166,7 +166,7 @@ public class GroovyPageParser implements Tokens { private String expressionCodecDirectiveValue = OutputEncodingSettings.getDefaultValue(OutputEncodingSettings.EXPRESSION_CODEC_NAME); private String outCodecDirectiveValue = OutputEncodingSettings.getDefaultValue(OutputEncodingSettings.OUT_CODEC_NAME); private String staticCodecDirectiveValue = OutputEncodingSettings.getDefaultValue(OutputEncodingSettings.STATIC_CODEC_NAME); - private String taglibCodecDirectiveValue = OutputEncodingSettings.getDefaultValue(OutputEncodingSettings.TAGLIB_CODEC_NAME) ; + private String taglibCodecDirectiveValue = OutputEncodingSettings.getDefaultValue(OutputEncodingSettings.TAGLIB_CODEC_NAME); private String modelDirectiveValue; private File keepGeneratedDirectory; @@ -198,7 +198,7 @@ class TagMeta { int lineNumber; boolean emptyTag; int tagIndex; - boolean bufferMode=false; + boolean bufferMode = false; int bufferPartNumber = -1; @Override @@ -255,37 +255,36 @@ private void configure(ConfigMap config) { setExpressionCodecDirectiveValue( config.getProperty(OutputEncodingSettings.CONFIG_PROPERTY_GSP_CODECS + '.' + OutputEncodingSettings.EXPRESSION_CODEC_NAME, String.class, - config.getProperty( OutputEncodingSettings.CONFIG_PROPERTY_DEFAULT_CODEC, String.class, OutputEncodingSettings.getDefaultValue(OutputEncodingSettings.EXPRESSION_CODEC_NAME) )) + config.getProperty(OutputEncodingSettings.CONFIG_PROPERTY_DEFAULT_CODEC, String.class, OutputEncodingSettings.getDefaultValue(OutputEncodingSettings.EXPRESSION_CODEC_NAME))) ); setStaticCodecDirectiveValue( - config.getProperty(OutputEncodingSettings.CONFIG_PROPERTY_GSP_CODECS + '.' + OutputEncodingSettings.STATIC_CODEC_NAME, String.class, OutputEncodingSettings.getDefaultValue(OutputEncodingSettings.STATIC_CODEC_NAME )) + config.getProperty(OutputEncodingSettings.CONFIG_PROPERTY_GSP_CODECS + '.' + OutputEncodingSettings.STATIC_CODEC_NAME, String.class, OutputEncodingSettings.getDefaultValue(OutputEncodingSettings.STATIC_CODEC_NAME)) ); setTaglibCodecDirectiveValue( - config.getProperty(OutputEncodingSettings.CONFIG_PROPERTY_GSP_CODECS + '.' + OutputEncodingSettings.TAGLIB_CODEC_NAME, String.class, OutputEncodingSettings.getDefaultValue(OutputEncodingSettings.TAGLIB_CODEC_NAME )) + config.getProperty(OutputEncodingSettings.CONFIG_PROPERTY_GSP_CODECS + '.' + OutputEncodingSettings.TAGLIB_CODEC_NAME, String.class, OutputEncodingSettings.getDefaultValue(OutputEncodingSettings.TAGLIB_CODEC_NAME)) ); setOutCodecDirectiveValue( - config.getProperty(OutputEncodingSettings.CONFIG_PROPERTY_GSP_CODECS + '.' + OutputEncodingSettings.OUT_CODEC_NAME, String.class, OutputEncodingSettings.getDefaultValue(OutputEncodingSettings.OUT_CODEC_NAME )) + config.getProperty(OutputEncodingSettings.CONFIG_PROPERTY_GSP_CODECS + '.' + OutputEncodingSettings.OUT_CODEC_NAME, String.class, OutputEncodingSettings.getDefaultValue(OutputEncodingSettings.OUT_CODEC_NAME)) ); Object keepDirObj = config.getProperty(GroovyPageParser.CONFIG_PROPERTY_GSP_KEEPGENERATED_DIR, Object.class); if (keepDirObj instanceof File) { setKeepGeneratedDirectory((File) keepDirObj); - } - else if (keepDirObj != null) { + } else if (keepDirObj != null) { setKeepGeneratedDirectory(new File(String.valueOf(keepDirObj))); } } private Map parseDirectives(String gspSource) { - Map result=new HashMap(); + Map result = new HashMap(); // strip gsp comments String input = PRESCAN_COMMENT_PATTERN.matcher(gspSource).replaceAll(""); // find page directives - Matcher m=PRESCAN_PAGE_DIRECTIVE_PATTERN.matcher(input); + Matcher m = PRESCAN_PAGE_DIRECTIVE_PATTERN.matcher(input); if (m.find()) { Matcher mat = PAGE_DIRECTIVE_PATTERN.matcher(m.group(1)); while (mat.find()) { @@ -327,8 +326,7 @@ public InputStream parse() { try { streamBuffer.connectTo(new OutputStreamWriter(byteOutputBuffer.getOutputStream(), GROOVY_SOURCE_CHAR_ENCODING), true); - } - catch (UnsupportedEncodingException e) { + } catch (UnsupportedEncodingException e) { throw new RuntimeException("Grails cannot run unless your environment supports UTF-8!"); } @@ -340,8 +338,7 @@ public InputStream parse() { keepGeneratedWriter = new OutputStreamWriter( new FileOutputStream(keepGeneratedFile), GROOVY_SOURCE_CHAR_ENCODING); - } - catch (IOException e) { + } catch (IOException e) { LOG.warn("Cannot open keepgenerated file for writing. File's absolute path is '" + keepGeneratedFile.getAbsolutePath() + "'"); keepGeneratedFile = null; @@ -353,8 +350,7 @@ public InputStream parse() { try { generateGsp(target, false); return byteOutputBuffer.getInputStream(); - } - finally { + } finally { SpringIOUtils.closeQuietly(keepGeneratedWriter); } } @@ -400,8 +396,7 @@ public void writeHtmlParts(File filename) throws IOException { for (String part : htmlParts) { dataOut.writeUTF(part); } - } - finally { + } finally { SpringIOUtils.closeQuietly(dataOut); } } @@ -417,8 +412,7 @@ public void writeLineNumbers(File filename) throws IOException { for (int i = 0; i < lineNumbersCount; i++) { dataOut.writeInt(lineNumbers[i]); } - } - finally { + } finally { SpringIOUtils.closeQuietly(dataOut); } } @@ -512,8 +506,7 @@ private void directJspTagLib(String text) { final String namespace = prefix.substring(1, prefix.length() - 1); if (!GroovyPage.DEFAULT_NAMESPACE.equals(namespace)) { jspTags.put(namespace, uri.substring(1, uri.length() - 1)); - } - else { + } else { LOG.error("You cannot override the default 'g' namespace with the directive <%@ taglib prefix=\"g\" %>. Please select another namespace."); } } @@ -538,7 +531,7 @@ private void expr() { String text = scan.getToken().trim(); text = getExpressionText(text); if (text != null && text.length() > 2 && text.startsWith("(") && text.endsWith(")")) { - out.printlnToResponse(GroovyPage.EXPRESSION_OUT_STATEMENT, text.substring(1,text.length()-1)); + out.printlnToResponse(GroovyPage.EXPRESSION_OUT_STATEMENT, text.substring(1, text.length() - 1)); } else { out.printlnToResponse(GroovyPage.EXPRESSION_OUT_STATEMENT, text); } @@ -547,12 +540,11 @@ private void expr() { /** * Returns an expression text for the given expression * - * @param text - * The text + * @param text The text * @return An expression text */ public String getExpressionText(String text) { - return getExpressionText(text,true); + return getExpressionText(text, true); } public String getExpressionText(String text, boolean _safeDereference) { @@ -567,12 +559,11 @@ public String getExpressionText(String text, boolean _safeDereference) { text = "evaluate('" + escaped + "', " + getCurrentOutputLineNumber() + ", it) { return " + text + " }" + (safeDereference ? "?" : ""); - } - else { + } else { // add extra parenthesis, see http://jira.codehaus.org/browse/GRAILS-4351 // or GroovyPagesTemplateEngineTests.testForEachInProductionMode - text = "(" + text + ")"+ (safeDereference ? "?" : ""); + text = "(" + text + ")" + (safeDereference ? "?" : ""); } return text; } @@ -589,8 +580,7 @@ private String escapeGroovy(String text) { private void bufferedPrintlnToResponse(String s) { if (currentlyBufferingWhitespace) { whitespaceBuffer.append(s); - } - else { + } else { flushTagBuffering(); out.printlnToResponse(s); } @@ -631,7 +621,6 @@ public void flushTagBuffering() { } - private void html() { if (!finalPass) return; @@ -645,8 +634,7 @@ private void html() { boolean contentIsWhitespace = !NON_WHITESPACE_PATTERN.matcher(text).find(); if (!contentIsWhitespace && currentlyBufferingWhitespace) { flushBufferedWhiteSpace(); - } - else { + } else { currentlyBufferingWhitespace = contentIsWhitespace; } // We need to know if the last content output was not whitespace, for tag safety checks @@ -654,8 +642,7 @@ private void html() { if (currentlyBufferingWhitespace) { whitespaceBuffer.append(text); - } - else { + } else { appendHtmlPart(text); } } @@ -693,8 +680,7 @@ private void makeName(String uri) { if (slash > -1) { name = uri.substring(slash + 1) + '_' + name; } - } - else { + } else { name = uri; } StringBuilder buf = new StringBuilder(name.length()); @@ -703,8 +689,7 @@ private void makeName(String uri) { if (c < '0' || (c > '9' && c < '@') || (c > 'Z' && c < '_') || (c > '_' && c < 'a') || c > 'z') { c = '_'; - } - else if (ix == 0 && c >= '0' && c <= '9') { + } else if (ix == 0 && c >= '0' && c <= '9') { c = '_'; } buf.append(c); @@ -771,7 +756,7 @@ private void page() { out.print(" extends "); out.print(resolveGspSuperClassName()); out.println(" {"); - if(modelDirectiveValue != null) { + if (modelDirectiveValue != null) { out.println("// start model fields"); out.println(modelDirectiveValue); out.println("// end model fields"); @@ -790,11 +775,11 @@ private void page() { //out.println("JspTagLib jspTag"); } - loop: for (;;) { + loop: + for (; ; ) { if (doNextScan) { state = scan.nextToken(); - } - else { + } else { doNextScan = true; } @@ -887,11 +872,11 @@ private void page() { out.println("public static final String " + CONSTANT_NAME_TAGLIB_CODEC + " = '" + escapeGroovy(taglibCodecDirectiveValue) + "'"); - if(isCompileStaticMode()) { + if (isCompileStaticMode()) { out.println("public static final boolean " + CONSTANT_NAME_COMPILE_STATIC_MODE + " = " + isCompileStaticMode()); } - if(modelFieldsMode) { + if (modelFieldsMode) { out.println("public static final boolean " + CONSTANT_NAME_MODEL_FIELDS_MODE + " = " + modelFieldsMode); } @@ -901,8 +886,7 @@ private void page() { if (shouldAddLineNumbers()) { addLineNumbers(); } - } - else { + } else { for (int i = 0; i < DEFAULT_IMPORTS.length; i++) { out.print("import "); out.println(DEFAULT_IMPORTS[i]); @@ -911,7 +895,7 @@ private void page() { } private String resolveGspSuperClassName() { - Class gspSuperClass = isCompileStaticMode() ? CompileStaticGroovyPage.class : (isModelRecordingModeEnabled() ? ModelRecordingGroovyPage.class : GroovyPage.class); + Class gspSuperClass = isCompileStaticMode() ? CompileStaticGroovyPage.class : (isModelRecordingModeEnabled() ? ModelRecordingGroovyPage.class : GroovyPage.class); return gspSuperClass.getName(); } @@ -964,7 +948,7 @@ private void addLineNumbers() { */ private int[] filterTrailing0s(int[] lineNumbers) { int startLocation = lineNumbers.length - 1; - for (int i = lineNumbers.length -1; i >= 0; i--) { + for (int i = lineNumbers.length - 1; i >= 0; i--) { if (lineNumbers[i] > 0) { startLocation = i + 1; break; @@ -1005,14 +989,12 @@ private void endTag() { if (tm.instance instanceof GroovySyntaxTag) { GroovySyntaxTag tag = (GroovySyntaxTag) tm.instance; tag.doEndTag(); - } - else { + } else { throw new GrailsTagException("Grails tag [" + tagName + "] was not closed", pageName, getCurrentOutputLineNumber()); } - } - else { + } else { int bodyTagIndex = -1; if (!tm.emptyTag && !tm.bufferMode) { bodyTagIndex = tagIndex; @@ -1042,14 +1024,12 @@ private void endTag() { out.print("null"); } out.println(")"); - } - else { + } else { if (tm.hasAttributes) { out.println("invokeTag('" + tagName + "','" + ns + "'," + getCurrentOutputLineNumber() + "," + attrsVarsMapDefinition.get(tagIndex) + "," + bodyTagIndex + ")"); - } - else { + } else { out.println("invokeTag('" + tagName + "','" + ns + "'," + getCurrentOutputLineNumber() + ",[:]," + bodyTagIndex + ")"); } @@ -1061,7 +1041,7 @@ private void endTag() { tagIndex--; } - @SuppressWarnings({ "unchecked", "rawtypes" }) + @SuppressWarnings({"unchecked", "rawtypes"}) private void startTag() { if (!finalPass) return; @@ -1079,8 +1059,7 @@ private void startTag() { buf.append("${"); buf.append(scan.getToken().trim()); buf.append("}"); - } - else { + } else { buf.append(scan.getToken()); } state = scan.nextToken(); @@ -1096,7 +1075,7 @@ private void startTag() { String tagName; Map attrs = new LinkedHashMap(); - Matcher m=WHITESPACE_PATTERN.matcher(text); + Matcher m = WHITESPACE_PATTERN.matcher(text); if (m.find()) { // ignores carriage returns and new lines tagName = text.substring(0, m.start()); @@ -1111,7 +1090,7 @@ private void startTag() { if (state == EOF) { throw new GrailsTagException( "Unexpected end of file encountered parsing Tag [" + tagName + "] for " + className + - ". Are you missing a closing brace '}'?", pageName, + ". Are you missing a closing brace '}'?", pageName, getCurrentOutputLineNumber()); } @@ -1138,13 +1117,11 @@ private void startTag() { if (tag.isKeepPrecedingWhiteSpace() && currentlyBufferingWhitespace) { flushBufferedWhiteSpace(); - } - else if (!tag.isAllowPrecedingContent() && previousContentWasNonWhitespace) { + } else if (!tag.isAllowPrecedingContent() && previousContentWasNonWhitespace) { throw new GrailsTagException("Tag [" + tag.getName() + "] cannot have non-whitespace characters directly preceding it.", pageName, getCurrentOutputLineNumber()); - } - else { + } else { // If tag does not specify buffering of WS, we swallow it here clearBufferedWhiteSpace(); } @@ -1152,8 +1129,7 @@ else if (!tag.isAllowPrecedingContent() && previousContentWasNonWhitespace) { tag.doStartTag(); tm.instance = tag; - } - else { + } else { // Custom taglibs have to always flush the whitespace, there's no // "allowPrecedingWhitespace" property on tags yet flushBufferedWhiteSpace(); @@ -1161,11 +1137,11 @@ else if (!tag.isAllowPrecedingContent() && previousContentWasNonWhitespace) { if (attrs.size() > 0) { FastStringWriter buffer = new FastStringWriter(); buffer.print("["); - for (Iterator i = attrs.keySet().iterator(); i.hasNext();) { + for (Iterator i = attrs.keySet().iterator(); i.hasNext(); ) { String name = (String) i.next(); - String cleanedName=name; + String cleanedName = name; if (name.startsWith("\"") && name.endsWith("\"")) { - cleanedName="'" + name.substring(1,name.length()-1) + "'"; + cleanedName = "'" + name.substring(1, name.length() - 1) + "'"; } buffer.print(cleanedName); buffer.print(':'); @@ -1173,8 +1149,7 @@ else if (!tag.isAllowPrecedingContent() && previousContentWasNonWhitespace) { buffer.print(getExpressionText(attrs.get(name).toString())); if (i.hasNext()) { buffer.print(','); - } - else { + } else { buffer.print("]"); } } @@ -1215,8 +1190,8 @@ private void flushBufferedWhiteSpace() { private void populateMapWithAttributes(Map attrs, String attrTokens) { attrTokens = attrTokens.trim(); - int startPos=0; - while(startPos < attrTokens.length()) { + int startPos = 0; + while (startPos < attrTokens.length()) { // parse name (before '=' character) int equalsignPos = attrTokens.indexOf('=', startPos); if (equalsignPos == -1) { @@ -1227,33 +1202,32 @@ private void populateMapWithAttributes(Map attrs, String attrTok // parse value startPos = equalsignPos + 1; char ch = attrTokens.charAt(startPos++); - while(Character.isWhitespace(ch) && startPos < attrTokens.length()) { + while (Character.isWhitespace(ch) && startPos < attrTokens.length()) { ch = attrTokens.charAt(startPos++); } - if (!(ch=='\'' || ch=='"')) { + if (!(ch == '\'' || ch == '"')) { throw new GrailsTagException("Attribute value must be quoted (" + attrTokens + ").", pageName, getCurrentOutputLineNumber()); } char quoteChar = ch; - GroovyPageExpressionParser expressionParser = new GroovyPageExpressionParser(attrTokens, startPos, quoteChar, (char)0, false); + GroovyPageExpressionParser expressionParser = new GroovyPageExpressionParser(attrTokens, startPos, quoteChar, (char) 0, false); int endQuotepos = expressionParser.parse(); - if (endQuotepos==-1) { + if (endQuotepos == -1) { throw new GrailsTagException("Attribute value quote wasn't closed (" + attrTokens + ").", pageName, getCurrentOutputLineNumber()); } - String val=attrTokens.substring(startPos, endQuotepos); + String val = attrTokens.substring(startPos, endQuotepos); if (val.startsWith("${") && val.endsWith("}") && !expressionParser.isContainsGstrings()) { val = val.substring(2, val.length() - 1); - } - else if (!(val.startsWith("[") && val.endsWith("]"))) { - if (val.indexOf('"')==-1) { + } else if (!(val.startsWith("[") && val.endsWith("]"))) { + if (val.indexOf('"') == -1) { quoteChar = '"'; } String quoteStr; // use multiline groovy string if the value contains newlines if (val.indexOf('\n') != -1 || val.indexOf('\r') != -1) { - if (quoteChar=='"') { + if (quoteChar == '"') { quoteStr = MULTILINE_GROOVY_STRING_DOUBLEQUOTES; } else { quoteStr = MULTILINE_GROOVY_STRING_SINGLEQUOTES; @@ -1279,12 +1253,12 @@ private void pageImport(String value) { private static String readStream(InputStream in, String gspEncoding) throws IOException { if (gspEncoding == null) { - gspEncoding = DEFAULT_ENCODING; + gspEncoding = DEFAULT_ENCODING; } return IOUtils.toString(in, gspEncoding); } - public static String getGspEncoding(){ + public static String getGspEncoding() { return DEFAULT_ENCODING; } @@ -1316,32 +1290,26 @@ private void write(CharSequence text, boolean gsp) { rep = " "; break; } - } - else if (c == '&') { + } else if (c == '&') { if (match(";", text, ix)) { rep = ";"; ix += 5; - } - else if (match("&", text, ix)) { + } else if (match("&", text, ix)) { rep = "&"; ix += 4; - } - else if (match("<", text, ix)) { + } else if (match("<", text, ix)) { rep = "<"; ix += 3; - } - else if (match(">", text, ix)) { + } else if (match(">", text, ix)) { rep = ">"; ix += 3; } - } - else if (c == '<') { + } else if (c == '<') { if (match("
", text, ix) || match("
", text, ix)) { rep = "\n"; //incrementLineNumber(); ix += 3; - } - else { + } else { int end = match(PARA_BREAK, text, ix); if (end <= 0) end = match(ROW_BREAK, text, ix); @@ -1354,8 +1322,7 @@ else if (c == '<') { } if (rep != null) { out.print(rep); - } - else { + } else { out.print(c); } } diff --git a/grails-gsp/grails-web-gsp/src/main/groovy/org/grails/web/gsp/GroovyPagesTemplateRenderer.java b/grails-gsp/grails-web-gsp/src/main/groovy/org/grails/web/gsp/GroovyPagesTemplateRenderer.java index 49832d5c17d..b5ac1dd70f7 100644 --- a/grails-gsp/grails-web-gsp/src/main/groovy/org/grails/web/gsp/GroovyPagesTemplateRenderer.java +++ b/grails-gsp/grails-web-gsp/src/main/groovy/org/grails/web/gsp/GroovyPagesTemplateRenderer.java @@ -52,6 +52,7 @@ import java.io.IOException; import java.io.Writer; import java.lang.reflect.Method; +import java.nio.charset.StandardCharsets; import java.util.Collection; import java.util.Iterator; import java.util.LinkedHashMap; @@ -282,7 +283,7 @@ private Template generateScaffoldedTemplate(GrailsWebRequest webRequest, String } FastStringWriter sw = new FastStringWriter(); ReflectionUtils.invokeMethod(generateViewMethod, scaffoldingTemplateGenerator, domainClass, scaffoldedtemplateName, sw); - t = groovyPagesTemplateEngine.createTemplate(new ByteArrayResource(sw.toString().getBytes("UTF-8"), uri), false); + t = groovyPagesTemplateEngine.createTemplate(new ByteArrayResource(sw.toString().getBytes(StandardCharsets.UTF_8), uri), false); } } return t; diff --git a/grails-gsp/grails-web-gsp/src/main/groovy/org/grails/web/pages/GSPResponseWriter.java b/grails-gsp/grails-web-gsp/src/main/groovy/org/grails/web/pages/GSPResponseWriter.java index efee4595f53..281a147ad39 100644 --- a/grails-gsp/grails-web-gsp/src/main/groovy/org/grails/web/pages/GSPResponseWriter.java +++ b/grails-gsp/grails-web-gsp/src/main/groovy/org/grails/web/pages/GSPResponseWriter.java @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ + package org.grails.web.pages; import org.apache.commons.logging.Log; diff --git a/grails-gsp/grails-web-gsp/src/main/groovy/org/grails/web/pages/GroovyPagesServlet.java b/grails-gsp/grails-web-gsp/src/main/groovy/org/grails/web/pages/GroovyPagesServlet.java index af21cb3dd6e..ab075fe8169 100644 --- a/grails-gsp/grails-web-gsp/src/main/groovy/org/grails/web/pages/GroovyPagesServlet.java +++ b/grails-gsp/grails-web-gsp/src/main/groovy/org/grails/web/pages/GroovyPagesServlet.java @@ -52,7 +52,7 @@ * Main servlet class. Example usage in web.xml: * *
- * {@code 
+ * {@code
  *     
  *       GroovyPagesServlet
  *       GroovyPagesServlet
@@ -70,7 +70,7 @@
  *
  * @author Troy Heninger
  * @author Graeme Rocher
- *
+ * 

* Date: Jan 10, 2004 */ public class GroovyPagesServlet extends FrameworkServlet implements PluginManagerAware { @@ -92,10 +92,9 @@ public GroovyPagesServlet() { @Override protected ServletRequestAttributes buildRequestAttributes(HttpServletRequest request, HttpServletResponse response, RequestAttributes previousAttributes) { - if(previousAttributes instanceof GrailsWebRequest) { + if (previousAttributes instanceof GrailsWebRequest) { return null; - } - else { + } else { return super.buildRequestAttributes(request, response, previousAttributes); } } @@ -135,16 +134,15 @@ protected void doService(HttpServletRequest request, HttpServletResponse respons request.setAttribute(GrailsApplicationAttributes.REQUEST_SCOPE_ID, grailsAttributes); request.setAttribute(GroovyPagesServlet.SERVLET_INSTANCE, this); - String pageName = (String)request.getAttribute(GrailsApplicationAttributes.GSP_TO_RENDER); + String pageName = (String) request.getAttribute(GrailsApplicationAttributes.GSP_TO_RENDER); if (GrailsStringUtils.isBlank(pageName)) { pageName = getCurrentRequestUri(request); } - boolean isNotInclude = !WebUtils.isIncludeRequest(request) ; + boolean isNotInclude = !WebUtils.isIncludeRequest(request); if (isNotInclude && isSecurePath(pageName)) { sendNotFound(response, pageName); - } - else { + } else { GroovyPageScriptSource scriptSource = groovyPagesTemplateEngine.findScriptSource(pageName); @@ -209,30 +207,26 @@ protected GroovyPageScriptSource findPageInBinaryPlugins(String pageName) { /** * Attempts to render the page with the given arguments * - * - * @param engine The GroovyPagesTemplateEngine to use - * @param request The HttpServletRequest - * @param response The HttpServletResponse + * @param engine The GroovyPagesTemplateEngine to use + * @param request The HttpServletRequest + * @param response The HttpServletResponse * @param scriptSource The template - * * @throws IOException Thrown when an I/O exception occurs rendering the page */ protected void renderPageWithEngine(GroovyPagesTemplateEngine engine, HttpServletRequest request, - HttpServletResponse response, GroovyPageScriptSource scriptSource) throws Exception { + HttpServletResponse response, GroovyPageScriptSource scriptSource) throws Exception { request.setAttribute(RENDERING_VIEW_ATTRIBUTE, Boolean.TRUE); GSPResponseWriter out = createResponseWriter(response); try { Template template = engine.createTemplate(scriptSource); if (template instanceof GroovyPageTemplate) { - ((GroovyPageTemplate)template).setAllowSettingContentType(true); + ((GroovyPageTemplate) template).setAllowSettingContentType(true); } template.make().writeTo(out); - } - catch(Exception e) { + } catch (Exception e) { out.setError(); throw e; - } - finally { + } finally { if (out != null) out.close(); } } @@ -245,7 +239,7 @@ protected void renderPageWithEngine(GroovyPagesTemplateEngine engine, HttpServle */ protected GSPResponseWriter createResponseWriter(HttpServletResponse response) { GSPResponseWriter out = GSPResponseWriter.getInstance(response); - GrailsWebRequest webRequest = (GrailsWebRequest) RequestContextHolder.currentRequestAttributes(); + GrailsWebRequest webRequest = (GrailsWebRequest) RequestContextHolder.currentRequestAttributes(); webRequest.setOut(out); return out; } diff --git a/grails-gsp/plugin/src/test/groovy/org/grails/gsp/compiler/tags/GroovyEachParseTests.groovy b/grails-gsp/plugin/src/test/groovy/org/grails/gsp/compiler/tags/GroovyEachParseTests.groovy index 6fd312501d3..ea296d520b1 100644 --- a/grails-gsp/plugin/src/test/groovy/org/grails/gsp/compiler/tags/GroovyEachParseTests.groovy +++ b/grails-gsp/plugin/src/test/groovy/org/grails/gsp/compiler/tags/GroovyEachParseTests.groovy @@ -32,7 +32,7 @@ class GroovyEachParseTests extends ParseTests { """) - assertEquals(trimAndRemoveCR(makeImports()+"""\n + assertEquals(trimAndRemoveCR(makeImports() + """\n class myTest extends org.grails.gsp.GroovyPage { public String getGroovyPageFileName() { "myTest" } public Object run() { @@ -45,7 +45,7 @@ printHtmlPart(0) } printHtmlPart(0) }""" + GSP_FOOTER -),trimAndRemoveCR(output.toString())) + ), trimAndRemoveCR(output.toString())) assertEquals("\n", output.htmlParts[0]) } @@ -54,7 +54,7 @@ printHtmlPart(0) def output = parseCode("myTest", """ """) - assertEquals(trimAndRemoveCR(makeImports()+"""\n + assertEquals(trimAndRemoveCR(makeImports() + """\n class myTest extends org.grails.gsp.GroovyPage { public String getGroovyPageFileName() { "myTest" } public Object run() { @@ -65,7 +65,7 @@ printHtmlPart(0) for( t in evaluate('"blah"', 1, it) { return "blah" } ) { } }""" + GSP_FOOTER -),trimAndRemoveCR(output.toString())) + ), trimAndRemoveCR(output.toString())) assertEquals("\n", output.htmlParts[0]) } @@ -76,7 +76,7 @@ for( t in evaluate('"blah"', 1, it) { return "blah" } ) { """) - assertEquals(trimAndRemoveCR(makeImports()+"""\n + assertEquals(trimAndRemoveCR(makeImports() + """\n class myTest2 extends org.grails.gsp.GroovyPage { public String getGroovyPageFileName() { "myTest2" } public Object run() { @@ -93,7 +93,7 @@ i++ } printHtmlPart(0) }""" + GSP_FOOTER -),trimAndRemoveCR(output.toString())) + ), trimAndRemoveCR(output.toString())) assertEquals("\n", output.htmlParts[0]) } diff --git a/grails-gsp/plugin/src/test/groovy/org/grails/web/mapping/RestfulReverseUrlRenderingTests.groovy b/grails-gsp/plugin/src/test/groovy/org/grails/web/mapping/RestfulReverseUrlRenderingTests.groovy index a40869e5ec9..918b4a2b666 100644 --- a/grails-gsp/plugin/src/test/groovy/org/grails/web/mapping/RestfulReverseUrlRenderingTests.groovy +++ b/grails-gsp/plugin/src/test/groovy/org/grails/web/mapping/RestfulReverseUrlRenderingTests.groovy @@ -59,7 +59,7 @@ class RestfulReverseUrlRenderingTests extends Specification implements UrlMappin } } -@Artefact("UrlMappings") +@Artefact('UrlMappings') class RestfulReverseUrlMappings { static mappings = { "/car" (controller: "restfulCar", action: [GET: "create", POST: "save"]) diff --git a/grails-gsp/plugin/src/test/groovy/org/grails/web/mapping/ReverseUrlMappingTests.groovy b/grails-gsp/plugin/src/test/groovy/org/grails/web/mapping/ReverseUrlMappingTests.groovy index 8424754739e..367996d2b5c 100644 --- a/grails-gsp/plugin/src/test/groovy/org/grails/web/mapping/ReverseUrlMappingTests.groovy +++ b/grails-gsp/plugin/src/test/groovy/org/grails/web/mapping/ReverseUrlMappingTests.groovy @@ -140,7 +140,7 @@ class ReverseUrlMappingTests extends Specification implements UrlMappingsUnitTes } } -@Artefact("UrlMappings") +@Artefact('UrlMappings') public class CustomUrlMappings { static mappings = { "/$mslug/$controller/$action/$id?" {} diff --git a/grails-gsp/plugin/src/test/groovy/org/grails/web/mapping/ReverseUrlMappingToDefaultActionTests.groovy b/grails-gsp/plugin/src/test/groovy/org/grails/web/mapping/ReverseUrlMappingToDefaultActionTests.groovy index e3b3ad4d2bd..c5e10de490f 100644 --- a/grails-gsp/plugin/src/test/groovy/org/grails/web/mapping/ReverseUrlMappingToDefaultActionTests.groovy +++ b/grails-gsp/plugin/src/test/groovy/org/grails/web/mapping/ReverseUrlMappingToDefaultActionTests.groovy @@ -46,7 +46,7 @@ class ReverseUrlMappingToDefaultActionTests extends Specification implements Url } } -@Artefact("UrlMappings") +@Artefact('UrlMappings') class ReverseUrlMappingToDefaultActionUrlMappings { static mappings = { "/$id?"{ diff --git a/grails-gsp/plugin/src/test/groovy/org/grails/web/mapping/RootUrlMappingTests.groovy b/grails-gsp/plugin/src/test/groovy/org/grails/web/mapping/RootUrlMappingTests.groovy index 3ebbf33a023..d8e57bc77d8 100644 --- a/grails-gsp/plugin/src/test/groovy/org/grails/web/mapping/RootUrlMappingTests.groovy +++ b/grails-gsp/plugin/src/test/groovy/org/grails/web/mapping/RootUrlMappingTests.groovy @@ -36,7 +36,7 @@ class RootUrlMappingTests extends Specification implements UrlMappingsUnitTestGroovy conversion. Normally, to compare the code, you can * run the page with a showSource parameter specified. - * + *

* The methods parseCode() and trimAndRemoveCR() have been added * to simplify test case code. * @@ -60,7 +60,9 @@ class ParsedResult { String[] htmlParts; @Override - public String toString() { return generatedGsp; } + public String toString() { + return generatedGsp; + } } protected static final String GSP_FOOTER = "public static final Map JSP_TAGS = new HashMap()\n" @@ -87,14 +89,14 @@ protected String makeImports() { public void testParse() throws Exception { ParsedResult result = parseCode("myTest1", "

hi
"); String expected = makeImports() + - "\n" + - "class myTest1 extends org.grails.gsp.GroovyPage {\n" + - "public String getGroovyPageFileName() { \"myTest1\" }\n" + - "public Object run() {\n" + - "Writer out = getOut()\n" + - "Writer expressionOut = getExpressionOut()\n"+ - "printHtmlPart(0)\n" + - "}\n" + GSP_FOOTER; + "\n" + + "class myTest1 extends org.grails.gsp.GroovyPage {\n" + + "public String getGroovyPageFileName() { \"myTest1\" }\n" + + "public Object run() {\n" + + "Writer out = getOut()\n" + + "Writer expressionOut = getExpressionOut()\n" + + "printHtmlPart(0)\n" + + "}\n" + GSP_FOOTER; Assertions.assertEquals(trimAndRemoveCR(expected), trimAndRemoveCR(result.generatedGsp)); Assertions.assertEquals("
hi
", result.htmlParts[0]); } @@ -103,15 +105,15 @@ public void testParse() throws Exception { public void testParseWithUnclosedSquareBracket() throws Exception { String output = parseCode("myTest2", "").generatedGsp; String expected = makeImports() + - "\n" + - "class myTest2 extends org.grails.gsp.GroovyPage {\n" + - "public String getGroovyPageFileName() { \"myTest2\" }\n" + - "public Object run() {\n" + - "Writer out = getOut()\n" + - "Writer expressionOut = getExpressionOut()\n"+ + "\n" + + "class myTest2 extends org.grails.gsp.GroovyPage {\n" + + "public String getGroovyPageFileName() { \"myTest2\" }\n" + + "public Object run() {\n" + + "Writer out = getOut()\n" + + "Writer expressionOut = getExpressionOut()\n" + - "invokeTag('message','g',1,['code':evaluate('\"testing [\"', 1, it) { return \"testing [\" }],-1)\n" + - "}\n" + GSP_FOOTER; + "invokeTag('message','g',1,['code':evaluate('\"testing [\"', 1, it) { return \"testing [\" }],-1)\n" + + "}\n" + GSP_FOOTER; Assertions.assertEquals(trimAndRemoveCR(expected), trimAndRemoveCR(output)); } @@ -135,19 +137,18 @@ public void testParseWithUTF8() throws Exception { ParsedResult output = null; try { output = parseCode("myTest4", src); - } - finally { + } finally { RequestContextHolder.resetRequestAttributes(); } String expected = makeImports() + - "\n" + - "class myTest4 extends org.grails.gsp.GroovyPage {\n" + - "public String getGroovyPageFileName() { \"myTest4\" }\n" + - "public Object run() {\n" + - "Writer out = getOut()\n" + - "Writer expressionOut = getExpressionOut()\n"+ - "printHtmlPart(0)\n" + - "}\n" + GSP_FOOTER; + "\n" + + "class myTest4 extends org.grails.gsp.GroovyPage {\n" + + "public String getGroovyPageFileName() { \"myTest4\" }\n" + + "public Object run() {\n" + + "Writer out = getOut()\n" + + "Writer expressionOut = getExpressionOut()\n" + + "printHtmlPart(0)\n" + + "}\n" + GSP_FOOTER; Assertions.assertEquals(trimAndRemoveCR(expected), trimAndRemoveCR(output.generatedGsp)); Assertions.assertEquals(src, output.htmlParts[0]); } @@ -175,14 +176,14 @@ public void testParseWithLocalEncoding() throws IOException { ParsedResult output = null; output = parseCode("myTest5", src); String expected = makeImports() + - "\n" + - "class myTest5 extends org.grails.gsp.GroovyPage {\n" + - "public String getGroovyPageFileName() { \"myTest5\" }\n" + - "public Object run() {\n" + - "Writer out = getOut()\n" + - "Writer expressionOut = getExpressionOut()\n"+ - "printHtmlPart(0)\n" + - "}\n" + GSP_FOOTER; + "\n" + + "class myTest5 extends org.grails.gsp.GroovyPage {\n" + + "public String getGroovyPageFileName() { \"myTest5\" }\n" + + "public Object run() {\n" + + "Writer out = getOut()\n" + + "Writer expressionOut = getExpressionOut()\n" + + "printHtmlPart(0)\n" + + "}\n" + GSP_FOOTER; Assertions.assertEquals(trimAndRemoveCR(expected), trimAndRemoveCR(output.generatedGsp)); Assertions.assertEquals(src, output.htmlParts[0]); } @@ -190,7 +191,7 @@ public void testParseWithLocalEncoding() throws IOException { /** * Eliminate potential issues caused by operating system differences * and minor output differences that we don't care about. - * + *

* Note: this code is inefficient and could stand to be optimized. */ public String trimAndRemoveCR(String s) { @@ -221,40 +222,40 @@ public ParsedResult parseCode(String uri, String gsp) throws IOException { } @Test - public void testParseGTagsWithNamespaces() throws Exception { - String output = parseCode("myTest6", - "\n" + - " \n" + - "").generatedGsp; - System.out.println("output = " + output); - Assertions.assertTrue(output.indexOf("invokeTag('form','tt',2,[:],-1)") > -1, "should have call to tag with 'tt' namespace"); - } + public void testParseGTagsWithNamespaces() throws Exception { + String output = parseCode("myTest6", + "\n" + + " \n" + + "").generatedGsp; + System.out.println("output = " + output); + Assertions.assertTrue(output.indexOf("invokeTag('form','tt',2,[:],-1)") > -1, "should have call to tag with 'tt' namespace"); + } - @Test - public void testParseWithWhitespaceNotEaten() throws Exception { - String expected = makeImports() + - "\n" + - "class myTest7 extends org.grails.gsp.GroovyPage {\n" + - "public String getGroovyPageFileName() { \"myTest7\" }\n" + - "public Object run() {\n" + - "Writer out = getOut()\n" + - "Writer expressionOut = getExpressionOut()\n"+ - "printHtmlPart(0)\n" + - GroovyPage.EXPRESSION_OUT_STATEMENT + ".print(evaluate('uri', 3, it) { return uri })\n" + - "printHtmlPart(1)\n" + - "}\n" + GSP_FOOTER; + @Test + public void testParseWithWhitespaceNotEaten() throws Exception { + String expected = makeImports() + + "\n" + + "class myTest7 extends org.grails.gsp.GroovyPage {\n" + + "public String getGroovyPageFileName() { \"myTest7\" }\n" + + "public Object run() {\n" + + "Writer out = getOut()\n" + + "Writer expressionOut = getExpressionOut()\n" + + "printHtmlPart(0)\n" + + GroovyPage.EXPRESSION_OUT_STATEMENT + ".print(evaluate('uri', 3, it) { return uri })\n" + + "printHtmlPart(1)\n" + + "}\n" + GSP_FOOTER; - ParsedResult output = parseCode("myTest7", - "Please click the link below to confirm your email address:\n" + - "\n" + - "${uri}\n" + - "\n" + - "\n" + - "Thanks"); + ParsedResult output = parseCode("myTest7", + "Please click the link below to confirm your email address:\n" + + "\n" + + "${uri}\n" + + "\n" + + "\n" + + "Thanks"); - Assertions.assertEquals(expected.replaceAll("[\r\n]", ""), output.generatedGsp.replaceAll("[\r\n]", "")); - Assertions.assertEquals("Please click the link below to confirm your email address:\n\n", output.htmlParts[0]); - Assertions.assertEquals("\n\n\nThanks", output.htmlParts[1]); - } + Assertions.assertEquals(expected.replaceAll("[\r\n]", ""), output.generatedGsp.replaceAll("[\r\n]", "")); + Assertions.assertEquals("Please click the link below to confirm your email address:\n\n", output.htmlParts[0]); + Assertions.assertEquals("\n\n\nThanks", output.htmlParts[1]); + } } diff --git a/grails-gsp/plugin/src/test/groovy/org/grails/web/taglib/AbstractGrailsTagTests.groovy b/grails-gsp/plugin/src/test/groovy/org/grails/web/taglib/AbstractGrailsTagTests.groovy index 7229adaff00..9c659d87c1b 100644 --- a/grails-gsp/plugin/src/test/groovy/org/grails/web/taglib/AbstractGrailsTagTests.groovy +++ b/grails-gsp/plugin/src/test/groovy/org/grails/web/taglib/AbstractGrailsTagTests.groovy @@ -143,7 +143,7 @@ abstract class AbstractGrailsTagTests { for (i in 0..100) { callable.call() } - println "$name took ${System.currentTimeMillis()-now}ms" + println "$name took ${System.currentTimeMillis() - now}ms" } def withTag(String tagName, Writer out, String tagNamespace = 'g', Closure callable) { @@ -165,7 +165,7 @@ abstract class AbstractGrailsTagTests { appCtx.autowireCapableBeanFactory.autowireBeanProperties(go, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME, false) def gspTagLibraryLookup = appCtx.gspTagLibraryLookup - OutputEncodingStack stack=OutputEncodingStack.currentStack(OutputContextLookupHelper.lookupOutputContext(), true) + OutputEncodingStack stack = OutputEncodingStack.currentStack(OutputContextLookupHelper.lookupOutputContext(), true) stack.push(out) try { @@ -177,7 +177,7 @@ abstract class AbstractGrailsTagTests { if (!(attrs instanceof GroovyPageAttributes)) { attrs = new GroovyPageAttributes(attrs) } - ((GroovyPageAttributes)attrs).setGspTagSyntaxCall(true) + ((GroovyPageAttributes) attrs).setGspTagSyntaxCall(true) def body = args?.size() > 1 ? args[1] : null if (body && !(body instanceof Closure)) { body = new TagOutput.ConstantClosure(body) @@ -185,10 +185,10 @@ abstract class AbstractGrailsTagTests { def tagresult = null - boolean encodeAsPushedToStack=false + boolean encodeAsPushedToStack = false try { - boolean returnsObject=gspTagLibraryLookup.doesTagReturnObject(tagNamespace, tagName) - Object codecInfo=gspTagLibraryLookup.getEncodeAsForTag(tagNamespace, tagName) + boolean returnsObject = gspTagLibraryLookup.doesTagReturnObject(tagNamespace, tagName) + Object codecInfo = gspTagLibraryLookup.getEncodeAsForTag(tagNamespace, tagName) if (attrs.containsKey(GroovyPage.ENCODE_AS_ATTRIBUTE_NAME)) { codecInfo = attrs.get(GroovyPage.ENCODE_AS_ATTRIBUTE_NAME) } else if (GroovyPage.DEFAULT_NAMESPACE.equals(tagNamespace) && GroovyPage.APPLY_CODEC_TAG_NAME.equals(tagName)) { @@ -196,7 +196,7 @@ abstract class AbstractGrailsTagTests { } if (codecInfo != null) { stack.push(WithCodecHelper.createOutputStackAttributesBuilder(codecInfo, webRequest.getAttributes().getGrailsApplication()).build()) - encodeAsPushedToStack=true + encodeAsPushedToStack = true } switch (tag.getParameterTypes().length) { case 1: @@ -214,7 +214,7 @@ abstract class AbstractGrailsTagTests { Encoder taglibEncoder = stack.taglibEncoder if (returnsObject && tagresult && !(tagresult instanceof Writer) && taglibEncoder) { - tagresult=taglibEncoder.encode(tagresult) + tagresult = taglibEncoder.encode(tagresult) } tagresult } finally { @@ -240,7 +240,6 @@ abstract class AbstractGrailsTagTests { @BeforeEach protected void setUp() throws Exception { - GroovySystem.metaClassRegistry.addMetaClassRegistryChangeEventListener(registryCleaner) GroovyPageMetaInfo.DEFAULT_PLUGIN_PATH = null domBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder() @@ -253,25 +252,25 @@ abstract class AbstractGrailsTagTests { grailsApplication = new DefaultGrailsApplication(gcl.loadedClasses, gcl) ga = grailsApplication ga.config.merge( - ['grails': - ['resources': - ['pattern': '/**'] + ['grails': + ['resources': + ['pattern': '/**'] + ] ] - ] ) ga.config.merge( - ['grails': - ['gsp': - ['tldScanPattern': - [ - 'classpath*:/META-INF/spring*.tld', - 'classpath*:/META-INF/fmt.tld', - 'classpath*:/META-INF/c.tld', - 'classpath*:/META-INF/core.tld' - ].join(',') - ] + ['grails': + ['gsp': + ['tldScanPattern': + [ + 'classpath*:/META-INF/spring*.tld', + 'classpath*:/META-INF/fmt.tld', + 'classpath*:/META-INF/c.tld', + 'classpath*:/META-INF/core.tld' + ].join(',') + ] + ] ] - ] ) grailsApplication.initialise() mockManager = new MockGrailsPluginManager(grailsApplication) @@ -310,7 +309,7 @@ abstract class AbstractGrailsTagTests { dependantPluginClasses << gcl.loadClass('org.grails.plugins.web.controllers.ControllersGrailsPlugin') dependantPluginClasses << gcl.loadClass('org.grails.plugins.web.GroovyPagesGrailsPlugin') - def dependentPlugins = dependantPluginClasses.collect { new DefaultGrailsPlugin(it as Class, grailsApplication)} + def dependentPlugins = dependantPluginClasses.collect { new DefaultGrailsPlugin(it as Class, grailsApplication) } dependentPlugins.each { (mockManager as MockGrailsPluginManager).registerMockPlugin(it); @@ -324,7 +323,7 @@ abstract class AbstractGrailsTagTests { try { JstlUtils.exposeLocalizationContext(webRequest.getRequest(), null) } catch (Throwable ignore) { - + // ignore } servletContext = webRequest.servletContext @@ -384,8 +383,10 @@ abstract class AbstractGrailsTagTests { protected void onInit() { } + protected void onDestroy() { } + protected void onInitMockBeans() { } @@ -399,7 +400,7 @@ abstract class AbstractGrailsTagTests { void printCompiledSource(template, params = [:]) { // def text = getCompiledSource(template, params) - // println "----- GSP SOURCE -----" + // println '----- GSP SOURCE -----' // println text } @@ -421,7 +422,7 @@ abstract class AbstractGrailsTagTests { } def assertCompiledSourceContains(expected, template, params = [:]) { - def text = getCompiledSource(template, params) + def text = getCompiledSource(template, params) return text.indexOf(expected) > -1 } @@ -455,7 +456,7 @@ abstract class AbstractGrailsTagTests { GroovyPageTemplate t = createTemplate(template) /* - println "------------HTMLPARTS----------------------" + println '------------HTMLPARTS----------------------' t.metaInfo.htmlParts.eachWithIndex {it, i -> print "htmlpart[${i}]:\n>${it}<\n--------\n" } */ @@ -534,8 +535,10 @@ abstract class AbstractGrailsTagTests { class MockThemeSource implements ThemeSource { private messageSource + MockThemeSource(MessageSource messageSource) { this.messageSource = messageSource } + Theme getTheme(String themeName) { new SimpleTheme(themeName, messageSource) } } diff --git a/grails-gsp/plugin/src/test/groovy/org/grails/web/taglib/FormTagLibResourceTests.groovy b/grails-gsp/plugin/src/test/groovy/org/grails/web/taglib/FormTagLibResourceTests.groovy index 1b624d62337..8a0f33509ce 100644 --- a/grails-gsp/plugin/src/test/groovy/org/grails/web/taglib/FormTagLibResourceTests.groovy +++ b/grails-gsp/plugin/src/test/groovy/org/grails/web/taglib/FormTagLibResourceTests.groovy @@ -121,7 +121,7 @@ class FormTagLibResourceTests extends Specification implements UrlMappingsUnitTe } -@Artefact("UrlMappings") +@Artefact('UrlMappings') class TestFormTagUrlMappings { static mappings = { diff --git a/grails-gsp/plugin/src/test/groovy/org/grails/web/taglib/FormTagLibTests.groovy b/grails-gsp/plugin/src/test/groovy/org/grails/web/taglib/FormTagLibTests.groovy index 714131e0dfd..a46ffe6fdbc 100644 --- a/grails-gsp/plugin/src/test/groovy/org/grails/web/taglib/FormTagLibTests.groovy +++ b/grails-gsp/plugin/src/test/groovy/org/grails/web/taglib/FormTagLibTests.groovy @@ -56,7 +56,7 @@ class FormTagLibTests extends Specification implements TagLibUnitTest12Forward', template + assertOutputEquals('12Forward', template) template = '' - assertOutputEquals '12Forward', template + assertOutputEquals('12Forward', template) } void testSortableColumnNamespaceNull() { webRequest.controllerName = "MockController" def template = '' - assertOutputEquals 'ID', template + assertOutputEquals('ID', template) } void testSortableColumnNamespaceNullWithIndexAction() { @@ -229,14 +229,14 @@ class RenderTagLibTests extends Specification implements UrlMappingsUnitTestID', template + assertOutputEquals('ID', template) } void testSortableColumnWithCustomNamespace() { webRequest.controllerName = "MockController" def template = '' - assertOutputEquals 'ID', template + assertOutputEquals('ID', template) } void testSortableColumnWithCustomNamespaceFromRequest() { @@ -244,7 +244,7 @@ class RenderTagLibTests extends Specification implements UrlMappingsUnitTestID', template + assertOutputEquals('ID', template) } void testTemplateNamespace() { @@ -252,19 +252,19 @@ class RenderTagLibTests extends Specification implements UrlMappingsUnitTest${label}${value}') appCtx.groovyPagesTemplateEngine.groovyPageLocator.addResourceLoader(resourceLoader) - webRequest.controllerName = "table" + webRequest.controllerName = 'table' def template = '' - assertOutputEquals 'onetwo', template + assertOutputEquals('onetwo', template) // now test method call template = '${tmpl.tableRow(label:"one", value:"two", encodeAs:"raw")}' - assertOutputEquals 'onetwo', template + assertOutputEquals('onetwo', template) // execute twice to make sure methodMissing works - assertOutputEquals 'onetwo', template + assertOutputEquals('onetwo', template) } void testRenderWithNonExistantTemplate() { @@ -272,9 +272,8 @@ class RenderTagLibTests extends Specification implements UrlMappingsUnitTesthello' - assertOutputEquals 'content bar: hello', template + assertOutputEquals('content bar: hello', template) resourceLoader.registerMockResource('/foo/book/_book.gsp', 'foo ${foo}: ${body()}') resourceLoader.registerMockResource("/plugins/controllers-${GrailsUtil.grailsVersion}/foo/book/_book.gsp".toString(), 'plugin foo ${foo}: ${body()}') resourceLoader.registerMockResource("/plugins/controllers-${GrailsUtil.grailsVersion}/foo/book/_two.gsp".toString(), 'plugin foo ${foo}: ${body()}') template = 'hello' - assertOutputEquals 'plugin foo bar: hello', template + assertOutputEquals('plugin foo bar: hello', template) template = 'hello' - assertOutputEquals 'foo bar: hello', template + assertOutputEquals('foo bar: hello', template) request.setAttribute(GrailsApplicationAttributes.PAGE_SCOPE, new GroovyPageBinding("/plugins/controllers-${GrailsUtil.grailsVersion}")) - assertOutputEquals 'foo bar: hello', template // application template should be able to override plugin template + // application template should be able to override plugin template + assertOutputEquals('foo bar: hello', template) template = 'hello' request.removeAttribute GrailsApplicationAttributes.PAGE_SCOPE @@ -312,7 +312,7 @@ class RenderTagLibTests extends Specification implements UrlMappingsUnitTesthello' - assertOutputEquals 'content bar: hello', template + assertOutputEquals('content bar: hello', template) } void testRenderTagCollectionAndModel() { @@ -323,7 +323,7 @@ class RenderTagLibTests extends Specification implements UrlMappingsUnitTest' - assertOutputEquals '[book = The Stand it=The Stand foo=bar][book = The Shining it=The Shining foo=bar]', template, [books: ['The Stand', 'The Shining']] + assertOutputEquals('[book = The Stand it=The Stand foo=bar][book = The Shining it=The Shining foo=bar]', template, [books: ['The Stand', 'The Shining']]) } void testRenderTagBeforeAndAfterModel() { @@ -628,7 +628,7 @@ class RenderTagLibTests extends Specification implements UrlMappingsUnitTest' - assertOutputEquals '[hello world] 3', template + assertOutputEquals('[hello world] 3', template) } void testGRAILS7887failsBeforeFixing() { @@ -642,7 +642,7 @@ class RenderTagLibTests extends Specification implements UrlMappingsUnitTest' - assertOutputEquals '[hello world] 2', template + assertOutputEquals('[hello world] 2', template) } void testGRAILS7887okBeforeFixing() { @@ -653,7 +653,7 @@ class RenderTagLibTests extends Specification implements UrlMappingsUnitTest' - assertOutputEquals '[hello world] 1', template + assertOutputEquals('[hello world] 1', template) } void testGRAILS7871() { @@ -664,7 +664,7 @@ class RenderTagLibTests extends Specification implements UrlMappingsUnitTest' - assertOutputEquals '[hello world] 1', template + assertOutputEquals('[hello world] 1', template) def g = appCtx.gspTagLibraryLookup.lookupNamespaceDispatcher('g') webRequest.params.someparam = '2' @@ -681,7 +681,7 @@ class RenderTagLibTests extends Specification implements UrlMappingsUnitTest + destination.withWriter(StandardCharsets.UTF_8.name()) { Writer w -> template.make(model).writeTo(w) w.flush() } diff --git a/grails-shell-cli/src/main/groovy/org/grails/cli/profile/steps/RenderStep.groovy b/grails-shell-cli/src/main/groovy/org/grails/cli/profile/steps/RenderStep.groovy index 76112465756..d50fa9f1051 100644 --- a/grails-shell-cli/src/main/groovy/org/grails/cli/profile/steps/RenderStep.groovy +++ b/grails-shell-cli/src/main/groovy/org/grails/cli/profile/steps/RenderStep.groovy @@ -31,6 +31,8 @@ import org.grails.cli.profile.commands.templates.SimpleTemplate import org.grails.cli.profile.support.ArtefactVariableResolver import org.grails.io.support.Resource +import java.nio.charset.StandardCharsets + /** * A {@link org.grails.cli.profile.Step} that renders a template * @@ -104,7 +106,7 @@ class RenderStep extends AbstractStep { if(!templateFile) { throw new IOException("cannot find template " + parameters.template) } - destination.setText(new SimpleTemplate(templateFile.inputStream.getText("UTF-8")).render(variables), "UTF-8") + destination.setText(new SimpleTemplate(templateFile.inputStream.getText(StandardCharsets.UTF_8.name())).render(variables), StandardCharsets.UTF_8.name()) ClassNameCompleter.refreshAll() } diff --git a/grails-test-core/src/main/groovy/org/grails/plugins/testing/GrailsMockHttpServletRequest.groovy b/grails-test-core/src/main/groovy/org/grails/plugins/testing/GrailsMockHttpServletRequest.groovy index 72185d22197..37fd0dfd2a2 100644 --- a/grails-test-core/src/main/groovy/org/grails/plugins/testing/GrailsMockHttpServletRequest.groovy +++ b/grails-test-core/src/main/groovy/org/grails/plugins/testing/GrailsMockHttpServletRequest.groovy @@ -45,6 +45,8 @@ import org.springframework.util.MultiValueMap import org.springframework.web.multipart.MultipartFile import org.springframework.web.multipart.MultipartHttpServletRequest +import java.nio.charset.StandardCharsets + /** * A custom mock HTTP servlet request that provides the extra properties * and methods normally injected by the "servlets" plugin. @@ -109,13 +111,13 @@ class GrailsMockHttpServletRequest extends MockHttpServletRequest implements Mul setContentType('application/json; charset=UTF-8') setFormat('json') if (sourceJson instanceof String) { - setContent(sourceJson.getBytes("UTF-8")) + setContent(sourceJson.getBytes(StandardCharsets.UTF_8)) } else if (sourceJson instanceof JSON) { - setContent(sourceJson.toString().getBytes("UTF-8")) + setContent(sourceJson.toString().getBytes(StandardCharsets.UTF_8)) } else { - setContent(new JSON(sourceJson).toString().getBytes("UTF-8")) + setContent(new JSON(sourceJson).toString().getBytes(StandardCharsets.UTF_8)) } getAttribute("org.codehaus.groovy.grails.WEB_REQUEST")?.informParameterCreationListeners() } @@ -130,7 +132,7 @@ class GrailsMockHttpServletRequest extends MockHttpServletRequest implements Mul setFormat("xml") if (sourceXml instanceof String) { - setContent(sourceXml.getBytes("UTF-8")) + setContent(sourceXml.getBytes(StandardCharsets.UTF_8)) } else { XML xml @@ -139,7 +141,7 @@ class GrailsMockHttpServletRequest extends MockHttpServletRequest implements Mul } else { xml = new XML(sourceXml) } - setContent(xml.toString().getBytes("UTF-8")) + setContent(xml.toString().getBytes(StandardCharsets.UTF_8)) } getAttribute("org.codehaus.groovy.grails.WEB_REQUEST")?.informParameterCreationListeners() diff --git a/grails-test-suite-base/src/main/groovy/org/grails/support/MockApplicationContext.java b/grails-test-suite-base/src/main/groovy/org/grails/support/MockApplicationContext.java index efdabc3f950..1acaddf7679 100644 --- a/grails-test-suite-base/src/main/groovy/org/grails/support/MockApplicationContext.java +++ b/grails-test-suite-base/src/main/groovy/org/grails/support/MockApplicationContext.java @@ -45,6 +45,7 @@ import java.io.IOException; import java.io.InputStream; import java.lang.annotation.Annotation; +import java.nio.charset.StandardCharsets; import java.util.*; public class MockApplicationContext extends GroovyObjectSupport implements WebApplicationContext { @@ -436,7 +437,7 @@ public String getDescription() { } public InputStream getInputStream() throws IOException { - return new ByteArrayInputStream(contents.getBytes("UTF-8")); + return new ByteArrayInputStream(contents.getBytes(StandardCharsets.UTF_8)); } } diff --git a/grails-test-suite-uber/src/test/groovy/org/grails/plugins/testing/GrailsMockHttpServletRequestTests.groovy b/grails-test-suite-uber/src/test/groovy/org/grails/plugins/testing/GrailsMockHttpServletRequestTests.groovy index 3b2a9531922..703ed262aff 100644 --- a/grails-test-suite-uber/src/test/groovy/org/grails/plugins/testing/GrailsMockHttpServletRequestTests.groovy +++ b/grails-test-suite-uber/src/test/groovy/org/grails/plugins/testing/GrailsMockHttpServletRequestTests.groovy @@ -20,6 +20,8 @@ package org.grails.plugins.testing import spock.lang.Specification +import java.nio.charset.StandardCharsets + /** * Test case for {@link org.grails.plugins.testing.GrailsMockHttpServletRequest}. */ @@ -72,7 +74,7 @@ class GrailsMockHttpServletRequestTests extends Specification { when: request.method = 'POST' request.contentType = "application/xml; charset=UTF-8" - request.content = TEST_XML_CONTENT.getBytes("UTF-8") + request.content = TEST_XML_CONTENT.getBytes(StandardCharsets.UTF_8) then: verifyXmlResult request.XML diff --git a/grails-test-suite-uber/src/test/groovy/org/grails/web/util/StreamByteBufferTest.java b/grails-test-suite-uber/src/test/groovy/org/grails/web/util/StreamByteBufferTest.java index 43f6444c774..e9e58e3d3ef 100644 --- a/grails-test-suite-uber/src/test/groovy/org/grails/web/util/StreamByteBufferTest.java +++ b/grails-test-suite-uber/src/test/groovy/org/grails/web/util/StreamByteBufferTest.java @@ -23,6 +23,7 @@ import org.junit.jupiter.api.Test; import java.io.*; +import java.nio.charset.StandardCharsets; import java.util.Arrays; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -63,7 +64,7 @@ public void testToString() throws IOException { PrintWriter pw=new PrintWriter(new OutputStreamWriter(byteBuffer.getOutputStream(),"UTF-8")); pw.print(TEST_STRING); pw.close(); - assertEquals(TEST_STRING, byteBuffer.readAsString("UTF-8")); + assertEquals(TEST_STRING, byteBuffer.readAsString(StandardCharsets.UTF_8)); } @Test @@ -72,10 +73,10 @@ public void testToStringRetain() throws IOException { PrintWriter pw=new PrintWriter(new OutputStreamWriter(byteBuffer.getOutputStream(),"UTF-8")); pw.print(TEST_STRING); pw.close(); - assertEquals(TEST_STRING, byteBuffer.readAsString("UTF-8")); + assertEquals(TEST_STRING, byteBuffer.readAsString(StandardCharsets.UTF_8)); byteBuffer.reset(); // call a second time to test if the RETAIN_AFTER_READING mode works as expected - assertEquals(TEST_STRING, byteBuffer.readAsString("UTF-8")); + assertEquals(TEST_STRING, byteBuffer.readAsString(StandardCharsets.UTF_8)); } @Test diff --git a/grails-testing-support-datamapping/src/main/groovy/grails/testing/gorm/DataTest.groovy b/grails-testing-support-datamapping/src/main/groovy/grails/testing/gorm/DataTest.groovy index 560ff4065e8..a462461061e 100644 --- a/grails-testing-support-datamapping/src/main/groovy/grails/testing/gorm/DataTest.groovy +++ b/grails-testing-support-datamapping/src/main/groovy/grails/testing/gorm/DataTest.groovy @@ -140,10 +140,10 @@ trait DataTest extends GrailsUnitTest { GrailsClass grailsDomain = grailsApplication.getArtefact(DomainClassArtefactHandler.TYPE, domain.javaClass.name) "$validationBeanName"(MockCascadingDomainClassValidator) { bean -> - getDelegate().messageSource = ref("messageSource") bean.lazyInit = true - getDelegate().domainClass = grailsDomain - getDelegate().grailsApplication = grailsApplication + delegate.messageSource = ref("messageSource") + delegate.domainClass = grailsDomain + delegate.grailsApplication = grailsApplication } } else { "$validationBeanName"(PersistentEntityValidator, domain, ref("messageSource"), ref(DataTestSetupSpecInterceptor.BEAN_NAME)) diff --git a/grails-testing-support-web/src/main/groovy/grails/testing/web/UrlMappingsUnitTest.groovy b/grails-testing-support-web/src/main/groovy/grails/testing/web/UrlMappingsUnitTest.groovy index 7ad94f8c671..21138b41e0a 100644 --- a/grails-testing-support-web/src/main/groovy/grails/testing/web/UrlMappingsUnitTest.groovy +++ b/grails-testing-support-web/src/main/groovy/grails/testing/web/UrlMappingsUnitTest.groovy @@ -431,7 +431,7 @@ trait UrlMappingsUnitTest implements ParameterizedGrailsUnitTest, GrailsWe defineBeans { grailsUrlMappingsHolder(UrlMappingsHolderFactoryBean) { - getDelegate().grailsApplication = grailsApplication + delegate.grailsApplication = grailsApplication } } } diff --git a/grails-views-gson/src/test/groovy/grails/plugin/json/view/JsonViewTemplateEngineSpec.groovy b/grails-views-gson/src/test/groovy/grails/plugin/json/view/JsonViewTemplateEngineSpec.groovy index bd4bfb1115e..411386592c2 100644 --- a/grails-views-gson/src/test/groovy/grails/plugin/json/view/JsonViewTemplateEngineSpec.groovy +++ b/grails-views-gson/src/test/groovy/grails/plugin/json/view/JsonViewTemplateEngineSpec.groovy @@ -25,6 +25,8 @@ import grails.web.mapping.LinkGenerator import groovy.json.JsonSlurper import spock.lang.Specification +import java.nio.charset.StandardCharsets + /** * Created by graemerocher on 21/08/15. */ @@ -118,7 +120,7 @@ json { def output = writer.toString() then:"The output is correct" - new JsonSlurper().parse(output.getBytes("UTF-8")) + new JsonSlurper().parse(output.getBytes(StandardCharsets.UTF_8)) output == '''{ "_links": { "self": { diff --git a/grails-web-common/src/main/groovy/org/grails/web/util/IncludeResponseWrapper.java b/grails-web-common/src/main/groovy/org/grails/web/util/IncludeResponseWrapper.java index bda85dbd534..963c3f355be 100644 --- a/grails-web-common/src/main/groovy/org/grails/web/util/IncludeResponseWrapper.java +++ b/grails-web-common/src/main/groovy/org/grails/web/util/IncludeResponseWrapper.java @@ -26,6 +26,7 @@ import java.io.OutputStream; import java.io.PrintWriter; import java.nio.charset.CharacterCodingException; +import java.nio.charset.StandardCharsets; import java.util.Locale; import jakarta.servlet.ServletOutputStream; @@ -165,7 +166,7 @@ public PrintWriter getWriter() throws IOException { } public Object getContent() throws CharacterCodingException { - return getContent("UTF-8"); + return getContent(StandardCharsets.UTF_8.name()); } public Object getContent(String encoding) throws CharacterCodingException { diff --git a/grails-web-databinding/src/test/groovy/org/grails/web/databinding/bindingsource/hal/json/HalJsonDataBindingSourceCreatorSpec.groovy b/grails-web-databinding/src/test/groovy/org/grails/web/databinding/bindingsource/hal/json/HalJsonDataBindingSourceCreatorSpec.groovy index 02ae48d5689..f7a88c89110 100644 --- a/grails-web-databinding/src/test/groovy/org/grails/web/databinding/bindingsource/hal/json/HalJsonDataBindingSourceCreatorSpec.groovy +++ b/grails-web-databinding/src/test/groovy/org/grails/web/databinding/bindingsource/hal/json/HalJsonDataBindingSourceCreatorSpec.groovy @@ -22,6 +22,8 @@ import org.grails.web.databinding.bindingsource.HalJsonDataBindingSourceCreator import spock.lang.Specification +import java.nio.charset.StandardCharsets + class HalJsonDataBindingSourceCreatorSpec extends Specification { void 'Test JSON parsing'() { @@ -36,8 +38,8 @@ class HalJsonDataBindingSourceCreatorSpec extends Specification { } } ''' - def inputStream = new ByteArrayInputStream(json.getBytes("UTF-8")) - def bindingSource = new HalJsonDataBindingSourceCreator().createBindingSource(inputStream, "UTF-8") + def inputStream = new ByteArrayInputStream(json.getBytes(StandardCharsets.UTF_8)) + def bindingSource = new HalJsonDataBindingSourceCreator().createBindingSource(inputStream, StandardCharsets.UTF_8.name()) when: def propertyNames = bindingSource.propertyNames diff --git a/grails-web-databinding/src/test/groovy/org/grails/web/databinding/bindingsource/json/JsonDataBindingSourceCreatorSpec.groovy b/grails-web-databinding/src/test/groovy/org/grails/web/databinding/bindingsource/json/JsonDataBindingSourceCreatorSpec.groovy index 9308eb300b0..7b506cd7abc 100644 --- a/grails-web-databinding/src/test/groovy/org/grails/web/databinding/bindingsource/json/JsonDataBindingSourceCreatorSpec.groovy +++ b/grails-web-databinding/src/test/groovy/org/grails/web/databinding/bindingsource/json/JsonDataBindingSourceCreatorSpec.groovy @@ -23,6 +23,8 @@ import org.grails.web.databinding.bindingsource.JsonDataBindingSourceCreator import spock.lang.Specification +import java.nio.charset.StandardCharsets + class JsonDataBindingSourceCreatorSpec extends Specification { void 'Test JSON parsing'() { @@ -33,8 +35,8 @@ class JsonDataBindingSourceCreatorSpec extends Specification { "languages" : [ {"name": "Groovy", "company": "GoPivotal"}, {"name": "Java", "company": "Oracle"}] }''' - def inputStream = new ByteArrayInputStream(json.getBytes("UTF-8")) - def bindingSource = new JsonDataBindingSourceCreator().createBindingSource(inputStream, "UTF-8") + def inputStream = new ByteArrayInputStream(json.getBytes(StandardCharsets.UTF_8)) + def bindingSource = new JsonDataBindingSourceCreator().createBindingSource(inputStream, StandardCharsets.UTF_8.name()) when: def propertyNames = bindingSource.propertyNames @@ -68,7 +70,7 @@ class JsonDataBindingSourceCreatorSpec extends Specification { given: def json = '''{"mapData": {"name":"Jeff{{{''' - def inputStream = new ByteArrayInputStream(json.getBytes("UTF-8")) + def inputStream = new ByteArrayInputStream(json.getBytes(StandardCharsets.UTF_8)) when: diff --git a/grails-web-databinding/src/test/groovy/org/grails/web/databinding/bindingsource/json/api/JsonApiDataBindingSourceCreatorSpec.groovy b/grails-web-databinding/src/test/groovy/org/grails/web/databinding/bindingsource/json/api/JsonApiDataBindingSourceCreatorSpec.groovy index e859ffb9098..1b02a29668b 100644 --- a/grails-web-databinding/src/test/groovy/org/grails/web/databinding/bindingsource/json/api/JsonApiDataBindingSourceCreatorSpec.groovy +++ b/grails-web-databinding/src/test/groovy/org/grails/web/databinding/bindingsource/json/api/JsonApiDataBindingSourceCreatorSpec.groovy @@ -23,6 +23,8 @@ import org.grails.web.databinding.bindingsource.JsonApiDataBindingSourceCreator import spock.lang.Shared import spock.lang.Specification +import java.nio.charset.StandardCharsets + /** * Created by jameskleeh on 9/29/16. */ @@ -52,7 +54,7 @@ class JsonApiDataBindingSourceCreatorSpec extends Specification { }''' when: - def inputStream = new ByteArrayInputStream(json.getBytes("UTF-8")) + def inputStream = new ByteArrayInputStream(json.getBytes(StandardCharsets.UTF_8)) DataBindingSource source = creator.createDataBindingSource(null, null, inputStream) then: @@ -90,7 +92,7 @@ class JsonApiDataBindingSourceCreatorSpec extends Specification { }''' when: - def inputStream = new ByteArrayInputStream(json.getBytes("UTF-8")) + def inputStream = new ByteArrayInputStream(json.getBytes(StandardCharsets.UTF_8)) DataBindingSource source = creator.createDataBindingSource(null, null, inputStream) then: @@ -116,7 +118,7 @@ class JsonApiDataBindingSourceCreatorSpec extends Specification { }''' when: - def inputStream = new ByteArrayInputStream(json.getBytes("UTF-8")) + def inputStream = new ByteArrayInputStream(json.getBytes(StandardCharsets.UTF_8)) DataBindingSource source = creator.createDataBindingSource(null, null, inputStream) then: @@ -138,7 +140,7 @@ class JsonApiDataBindingSourceCreatorSpec extends Specification { }''' when: - def inputStream = new ByteArrayInputStream(json.getBytes("UTF-8")) + def inputStream = new ByteArrayInputStream(json.getBytes(StandardCharsets.UTF_8)) DataBindingSource source = creator.createDataBindingSource(null, null, inputStream) then: @@ -160,7 +162,7 @@ class JsonApiDataBindingSourceCreatorSpec extends Specification { }''' when: - def inputStream = new ByteArrayInputStream(json.getBytes("UTF-8")) + def inputStream = new ByteArrayInputStream(json.getBytes(StandardCharsets.UTF_8)) DataBindingSource source = creator.createDataBindingSource(null, null, inputStream) then: @@ -176,7 +178,7 @@ class JsonApiDataBindingSourceCreatorSpec extends Specification { }''' when: - def inputStream = new ByteArrayInputStream(json.getBytes("UTF-8")) + def inputStream = new ByteArrayInputStream(json.getBytes(StandardCharsets.UTF_8)) DataBindingSource source = creator.createDataBindingSource(null, null, inputStream) then: @@ -193,7 +195,7 @@ class JsonApiDataBindingSourceCreatorSpec extends Specification { }''' when: - def inputStream = new ByteArrayInputStream(json.getBytes("UTF-8")) + def inputStream = new ByteArrayInputStream(json.getBytes(StandardCharsets.UTF_8)) DataBindingSource source = creator.createDataBindingSource(null, null, inputStream) then: From d87b0e025e17eae3617834f27ecf6923be6d0aed Mon Sep 17 00:00:00 2001 From: James Daugherty Date: Fri, 4 Jul 2025 05:30:56 -0400 Subject: [PATCH 08/26] cleanup: remove sitemesh from package/test names --- .../{sitemesh => layout}/LayoutByConventionController.groovy | 2 +- .../LayoutSpecifiedByPropertyController.groovy | 2 +- .../{sitemesh => layout}/LayoutTemplateController.groovy | 2 +- .../LayoutFunctionalSpec.groovy} | 4 ++-- .../{sitemesh => layout}/LayoutWithTemplateSpec.groovy | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) rename grails-test-examples/app1/grails-app/controllers/functionaltests/{sitemesh => layout}/LayoutByConventionController.groovy (96%) rename grails-test-examples/app1/grails-app/controllers/functionaltests/{sitemesh => layout}/LayoutSpecifiedByPropertyController.groovy (96%) rename grails-test-examples/app1/grails-app/controllers/functionaltests/{sitemesh => layout}/LayoutTemplateController.groovy (96%) rename grails-test-examples/app1/src/integration-test/groovy/functionaltests/{sitemesh/SitemeshLayoutFunctionalSpec.groovy => layout/LayoutFunctionalSpec.groovy} (95%) rename grails-test-examples/app1/src/integration-test/groovy/functionaltests/{sitemesh => layout}/LayoutWithTemplateSpec.groovy (97%) diff --git a/grails-test-examples/app1/grails-app/controllers/functionaltests/sitemesh/LayoutByConventionController.groovy b/grails-test-examples/app1/grails-app/controllers/functionaltests/layout/LayoutByConventionController.groovy similarity index 96% rename from grails-test-examples/app1/grails-app/controllers/functionaltests/sitemesh/LayoutByConventionController.groovy rename to grails-test-examples/app1/grails-app/controllers/functionaltests/layout/LayoutByConventionController.groovy index d639762d7b2..4aa76a0804c 100644 --- a/grails-test-examples/app1/grails-app/controllers/functionaltests/sitemesh/LayoutByConventionController.groovy +++ b/grails-test-examples/app1/grails-app/controllers/functionaltests/layout/LayoutByConventionController.groovy @@ -17,7 +17,7 @@ * under the License. */ -package functionaltests.sitemesh +package functionaltests.layout class LayoutByConventionController { diff --git a/grails-test-examples/app1/grails-app/controllers/functionaltests/sitemesh/LayoutSpecifiedByPropertyController.groovy b/grails-test-examples/app1/grails-app/controllers/functionaltests/layout/LayoutSpecifiedByPropertyController.groovy similarity index 96% rename from grails-test-examples/app1/grails-app/controllers/functionaltests/sitemesh/LayoutSpecifiedByPropertyController.groovy rename to grails-test-examples/app1/grails-app/controllers/functionaltests/layout/LayoutSpecifiedByPropertyController.groovy index c9069c9af58..c48718dec46 100644 --- a/grails-test-examples/app1/grails-app/controllers/functionaltests/sitemesh/LayoutSpecifiedByPropertyController.groovy +++ b/grails-test-examples/app1/grails-app/controllers/functionaltests/layout/LayoutSpecifiedByPropertyController.groovy @@ -17,7 +17,7 @@ * under the License. */ -package functionaltests.sitemesh +package functionaltests.layout class LayoutSpecifiedByPropertyController { diff --git a/grails-test-examples/app1/grails-app/controllers/functionaltests/sitemesh/LayoutTemplateController.groovy b/grails-test-examples/app1/grails-app/controllers/functionaltests/layout/LayoutTemplateController.groovy similarity index 96% rename from grails-test-examples/app1/grails-app/controllers/functionaltests/sitemesh/LayoutTemplateController.groovy rename to grails-test-examples/app1/grails-app/controllers/functionaltests/layout/LayoutTemplateController.groovy index 307d9161d05..eb30300fa6c 100644 --- a/grails-test-examples/app1/grails-app/controllers/functionaltests/sitemesh/LayoutTemplateController.groovy +++ b/grails-test-examples/app1/grails-app/controllers/functionaltests/layout/LayoutTemplateController.groovy @@ -17,7 +17,7 @@ * under the License. */ -package functionaltests.sitemesh +package functionaltests.layout class LayoutTemplateController { diff --git a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/sitemesh/SitemeshLayoutFunctionalSpec.groovy b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/layout/LayoutFunctionalSpec.groovy similarity index 95% rename from grails-test-examples/app1/src/integration-test/groovy/functionaltests/sitemesh/SitemeshLayoutFunctionalSpec.groovy rename to grails-test-examples/app1/src/integration-test/groovy/functionaltests/layout/LayoutFunctionalSpec.groovy index 0155c3a9ceb..a9011b560e7 100644 --- a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/sitemesh/SitemeshLayoutFunctionalSpec.groovy +++ b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/layout/LayoutFunctionalSpec.groovy @@ -17,7 +17,7 @@ * under the License. */ -package functionaltests.sitemesh +package functionaltests.layout import functionaltests.Application import grails.plugin.geb.ContainerGebSpec @@ -26,7 +26,7 @@ import spock.lang.Issue import spock.lang.PendingFeature @Integration(applicationClass = Application) -class SitemeshLayoutFunctionalSpec extends ContainerGebSpec { +class LayoutFunctionalSpec extends ContainerGebSpec { @Issue('GRAILS-12045') @PendingFeature(reason = 'title is empty') diff --git a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/sitemesh/LayoutWithTemplateSpec.groovy b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/layout/LayoutWithTemplateSpec.groovy similarity index 97% rename from grails-test-examples/app1/src/integration-test/groovy/functionaltests/sitemesh/LayoutWithTemplateSpec.groovy rename to grails-test-examples/app1/src/integration-test/groovy/functionaltests/layout/LayoutWithTemplateSpec.groovy index bfbff118768..5194e573400 100644 --- a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/sitemesh/LayoutWithTemplateSpec.groovy +++ b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/layout/LayoutWithTemplateSpec.groovy @@ -17,7 +17,7 @@ * under the License. */ -package functionaltests.sitemesh +package functionaltests.layout import functionaltests.Application import grails.gorm.transactions.Rollback From cbe80181ea50a7e8f1049a5f26f1fd92775ce0de Mon Sep 17 00:00:00 2001 From: James Daugherty Date: Fri, 4 Jul 2025 05:32:28 -0400 Subject: [PATCH 09/26] cleanup: mockEmbeddedSitemeshLayout -> mockEmbeddedGrailsLayout --- .../formfields/taglib/AbstractFormFieldsTagLibSpec.groovy | 2 +- .../groovy/grails/plugin/formfields/taglib/AllTagSpec.groovy | 2 +- .../taglib/AttributesOfWithAndAllTagsArePropagatedSpec.groovy | 2 +- .../plugin/formfields/taglib/EmbeddedPropertiesSpec.groovy | 2 +- .../grails/plugin/formfields/taglib/FieldNamePrefixSpec.groovy | 2 +- .../groovy/grails/plugin/formfields/taglib/TableSpec.groovy | 2 +- .../groovy/grails/plugin/formfields/taglib/WithTagSpec.groovy | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/grails-fields/src/test/groovy/grails/plugin/formfields/taglib/AbstractFormFieldsTagLibSpec.groovy b/grails-fields/src/test/groovy/grails/plugin/formfields/taglib/AbstractFormFieldsTagLibSpec.groovy index 9955e8f4095..7d39cf98e24 100644 --- a/grails-fields/src/test/groovy/grails/plugin/formfields/taglib/AbstractFormFieldsTagLibSpec.groovy +++ b/grails-fields/src/test/groovy/grails/plugin/formfields/taglib/AbstractFormFieldsTagLibSpec.groovy @@ -75,7 +75,7 @@ abstract class AbstractFormFieldsTagLibSpec extends Specification implements Gra } } - protected void mockEmbeddedSitemeshLayout(taglib) { + protected void mockEmbeddedGrailsLayout(taglib) { taglib.metaClass.applyLayout = { Map attrs, Closure body -> if (attrs.name == '_fields/embedded') { out << '

' diff --git a/grails-fields/src/test/groovy/grails/plugin/formfields/taglib/AllTagSpec.groovy b/grails-fields/src/test/groovy/grails/plugin/formfields/taglib/AllTagSpec.groovy index 8e9ba73bd32..7de46973742 100644 --- a/grails-fields/src/test/groovy/grails/plugin/formfields/taglib/AllTagSpec.groovy +++ b/grails-fields/src/test/groovy/grails/plugin/formfields/taglib/AllTagSpec.groovy @@ -41,7 +41,7 @@ class AllTagSpec extends AbstractFormFieldsTagLibSpec implements TagLibUnitTest< mockFormFieldsTemplateService.findTemplate(_, 'wrapper', _, null) >> [path: '/_fields/default/wrapper'] tagLib.formFieldsTemplateService = mockFormFieldsTemplateService - mockEmbeddedSitemeshLayout(tagLib) + mockEmbeddedGrailsLayout(tagLib) } void "all tag renders fields for all properties"() { diff --git a/grails-fields/src/test/groovy/grails/plugin/formfields/taglib/AttributesOfWithAndAllTagsArePropagatedSpec.groovy b/grails-fields/src/test/groovy/grails/plugin/formfields/taglib/AttributesOfWithAndAllTagsArePropagatedSpec.groovy index f789368f4a9..726fd7911a6 100644 --- a/grails-fields/src/test/groovy/grails/plugin/formfields/taglib/AttributesOfWithAndAllTagsArePropagatedSpec.groovy +++ b/grails-fields/src/test/groovy/grails/plugin/formfields/taglib/AttributesOfWithAndAllTagsArePropagatedSpec.groovy @@ -53,7 +53,7 @@ class AttributesOfWithAndAllTagsArePropagatedSpec extends AbstractFormFieldsTagL tagLib.formFieldsTemplateService = mockFormFieldsTemplateService - mockEmbeddedSitemeshLayout(tagLib) + mockEmbeddedGrailsLayout(tagLib) views["/_fields/default/_wrapper.gsp"] = '${widget}' views["/_fields/default/_displayWrapper.gsp"] = '${widget}' diff --git a/grails-fields/src/test/groovy/grails/plugin/formfields/taglib/EmbeddedPropertiesSpec.groovy b/grails-fields/src/test/groovy/grails/plugin/formfields/taglib/EmbeddedPropertiesSpec.groovy index 56effab0c53..2e3915e2df8 100644 --- a/grails-fields/src/test/groovy/grails/plugin/formfields/taglib/EmbeddedPropertiesSpec.groovy +++ b/grails-fields/src/test/groovy/grails/plugin/formfields/taglib/EmbeddedPropertiesSpec.groovy @@ -41,7 +41,7 @@ class EmbeddedPropertiesSpec extends AbstractFormFieldsTagLibSpec implements Tag mockFormFieldsTemplateService.getWidgetPrefix() >> 'input-' tagLib.formFieldsTemplateService = mockFormFieldsTemplateService - mockEmbeddedSitemeshLayout tagLib + mockEmbeddedGrailsLayout(tagLib) } void "field tag renders individual fields for embedded properties"() { diff --git a/grails-fields/src/test/groovy/grails/plugin/formfields/taglib/FieldNamePrefixSpec.groovy b/grails-fields/src/test/groovy/grails/plugin/formfields/taglib/FieldNamePrefixSpec.groovy index 7602817fa2f..67cd8845898 100644 --- a/grails-fields/src/test/groovy/grails/plugin/formfields/taglib/FieldNamePrefixSpec.groovy +++ b/grails-fields/src/test/groovy/grails/plugin/formfields/taglib/FieldNamePrefixSpec.groovy @@ -41,7 +41,7 @@ class FieldNamePrefixSpec extends AbstractFormFieldsTagLibSpec implements TagLib mockFormFieldsTemplateService.getWidgetPrefix() >> 'input-' tagLib.formFieldsTemplateService = mockFormFieldsTemplateService - mockEmbeddedSitemeshLayout(tagLib) + mockEmbeddedGrailsLayout(tagLib) } void 'a prefix can be added to the field names generated by f:field'() { diff --git a/grails-fields/src/test/groovy/grails/plugin/formfields/taglib/TableSpec.groovy b/grails-fields/src/test/groovy/grails/plugin/formfields/taglib/TableSpec.groovy index 56880606c22..03f9259f678 100644 --- a/grails-fields/src/test/groovy/grails/plugin/formfields/taglib/TableSpec.groovy +++ b/grails-fields/src/test/groovy/grails/plugin/formfields/taglib/TableSpec.groovy @@ -52,7 +52,7 @@ class TableSpec extends AbstractFormFieldsTagLibSpec implements TagLibUnitTest> 'input-' tagLib.formFieldsTemplateService = mockFormFieldsTemplateService - mockEmbeddedSitemeshLayout tagLib + mockEmbeddedGrailsLayout(tagLib) } void 'bean attribute does not have to be specified if it is in scope from f:with'() { From de701f4b07a2e698cf03bf707c69e1c0556eb129 Mon Sep 17 00:00:00 2001 From: James Daugherty Date: Fri, 4 Jul 2025 05:41:29 -0400 Subject: [PATCH 10/26] fix: tests require databind; do not transitively include --- grails-test-suite-web/build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/grails-test-suite-web/build.gradle b/grails-test-suite-web/build.gradle index 28d15b4330f..5f9dc53314e 100644 --- a/grails-test-suite-web/build.gradle +++ b/grails-test-suite-web/build.gradle @@ -37,6 +37,7 @@ dependencies { testImplementation project(':grails-interceptors') testImplementation project(':grails-rest-transforms') testImplementation 'org.apache.groovy:groovy' + testImplementation 'com.fasterxml.jackson.core:jackson-databind' testImplementation project(':grails-testing-support-web'), { // This is a local project dependency exclude group: 'org.apache.grails', module: 'grails-testing-support-core' From 4f07ccbc5659fe7b0e5e26bdddf8e4411c8b48ea Mon Sep 17 00:00:00 2001 From: James Daugherty Date: Fri, 4 Jul 2025 06:57:54 -0400 Subject: [PATCH 11/26] test: convert to specification --- .../compiler/tags/GroovyEachParseTests.groovy | 7 +- .../{ParseTests.java => ParseSpec.groovy} | 334 +++++++++--------- 2 files changed, 180 insertions(+), 161 deletions(-) rename grails-gsp/plugin/src/test/groovy/org/grails/web/pages/{ParseTests.java => ParseSpec.groovy} (50%) diff --git a/grails-gsp/plugin/src/test/groovy/org/grails/gsp/compiler/tags/GroovyEachParseTests.groovy b/grails-gsp/plugin/src/test/groovy/org/grails/gsp/compiler/tags/GroovyEachParseTests.groovy index ea296d520b1..5d9d1b60bc1 100644 --- a/grails-gsp/plugin/src/test/groovy/org/grails/gsp/compiler/tags/GroovyEachParseTests.groovy +++ b/grails-gsp/plugin/src/test/groovy/org/grails/gsp/compiler/tags/GroovyEachParseTests.groovy @@ -18,12 +18,15 @@ */ package org.grails.gsp.compiler.tags -import org.grails.web.pages.ParseTests import org.junit.jupiter.api.Test +import static org.grails.web.pages.ParseSpec.parseCode +import static org.grails.web.pages.ParseSpec.trimAndRemoveCR +import static org.grails.web.pages.ParseSpec.makeImports +import static org.grails.web.pages.ParseSpec.GSP_FOOTER import static org.junit.jupiter.api.Assertions.assertEquals -class GroovyEachParseTests extends ParseTests { +class GroovyEachParseTests { @Test void testEachOutput() { diff --git a/grails-gsp/plugin/src/test/groovy/org/grails/web/pages/ParseTests.java b/grails-gsp/plugin/src/test/groovy/org/grails/web/pages/ParseSpec.groovy similarity index 50% rename from grails-gsp/plugin/src/test/groovy/org/grails/web/pages/ParseTests.java rename to grails-gsp/plugin/src/test/groovy/org/grails/web/pages/ParseSpec.groovy index 992a9589f18..cf1a403ba56 100644 --- a/grails-gsp/plugin/src/test/groovy/org/grails/web/pages/ParseTests.java +++ b/grails-gsp/plugin/src/test/groovy/org/grails/web/pages/ParseSpec.groovy @@ -16,31 +16,27 @@ * specific language governing permissions and limitations * under the License. */ -package org.grails.web.pages; - -import grails.core.DefaultGrailsApplication; -import grails.core.GrailsApplication; -import grails.util.GrailsWebMockUtil; -import grails.util.GrailsWebUtil; -import grails.web.pages.GroovyPagesUriService; -import groovy.util.ConfigObject; -import groovy.util.ConfigSlurper; -import org.codehaus.groovy.runtime.IOGroovyMethods; -import org.grails.gsp.GroovyPage; -import org.grails.gsp.compiler.GroovyPageParser; -import org.grails.taglib.GrailsTagException; -import org.grails.web.servlet.mvc.GrailsWebRequest; -import org.grails.web.util.GrailsApplicationAttributes; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.springframework.mock.web.MockServletContext; -import org.springframework.web.context.WebApplicationContext; -import org.springframework.web.context.request.RequestContextHolder; -import org.springframework.web.context.support.GenericWebApplicationContext; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; + +package org.grails.web.pages + +import grails.core.DefaultGrailsApplication +import grails.core.GrailsApplication +import grails.util.GrailsWebMockUtil +import grails.util.GrailsWebUtil +import grails.web.pages.GroovyPagesUriService +import groovy.transform.CompileStatic +import org.codehaus.groovy.runtime.IOGroovyMethods +import org.grails.gsp.GroovyPage +import org.grails.gsp.compiler.GroovyPageParser +import org.grails.taglib.GrailsTagException +import org.grails.web.servlet.mvc.GrailsWebRequest +import org.grails.web.util.GrailsApplicationAttributes +import org.junit.jupiter.api.Assertions +import org.springframework.mock.web.MockServletContext +import org.springframework.web.context.WebApplicationContext +import org.springframework.web.context.request.RequestContextHolder +import org.springframework.web.context.support.GenericWebApplicationContext +import spock.lang.Specification /** * Tests the GSP parser. This can detect issues caused by improper @@ -49,45 +45,23 @@ *

* The methods parseCode() and trimAndRemoveCR() have been added * to simplify test case code. - * - * @author Daiji */ -public class ParseTests { - - class ParsedResult { - String generatedGsp; - GroovyPageParser parser; - String[] htmlParts; - - @Override - public String toString() { - return generatedGsp; - } - } - - protected static final String GSP_FOOTER = "public static final Map JSP_TAGS = new HashMap()\n" - + "protected void init() {\n" - + "\tthis.jspTags = JSP_TAGS\n" - + "}\n" - + "public static final String CONTENT_TYPE = 'text/html;charset=UTF-8'\n" - + "public static final long LAST_MODIFIED = 0L\n" - + "public static final String EXPRESSION_CODEC = 'HTML'\n" - + "public static final String STATIC_CODEC = 'none'\n" - + "public static final String OUT_CODEC = 'none'\n" - + "public static final String TAGLIB_CODEC = 'none'\n" + - "}\n"; - - protected String makeImports() { - StringBuilder result = new StringBuilder(); - for (int i = 0; i < GroovyPageParser.DEFAULT_IMPORTS.length; i++) { - result.append("import ").append(GroovyPageParser.DEFAULT_IMPORTS[i]).append("\n"); - } - return result.toString(); - } +class ParseSpec extends Specification { + static final String GSP_FOOTER = """public static final Map JSP_TAGS = new HashMap() +protected void init() { +\tthis.jspTags = JSP_TAGS +} +public static final String CONTENT_TYPE = 'text/html;charset=UTF-8' +public static final long LAST_MODIFIED = 0L +public static final String EXPRESSION_CODEC = 'HTML' +public static final String STATIC_CODEC = 'none' +public static final String OUT_CODEC = 'none' +public static final String TAGLIB_CODEC = 'none' +} +""" - @Test - public void testParse() throws Exception { - ParsedResult result = parseCode("myTest1", "

hi
"); + void "parse"() { + given: String expected = makeImports() + "\n" + "class myTest1 extends org.grails.gsp.GroovyPage {\n" + @@ -96,14 +70,18 @@ public void testParse() throws Exception { "Writer out = getOut()\n" + "Writer expressionOut = getExpressionOut()\n" + "printHtmlPart(0)\n" + - "}\n" + GSP_FOOTER; - Assertions.assertEquals(trimAndRemoveCR(expected), trimAndRemoveCR(result.generatedGsp)); - Assertions.assertEquals("
hi
", result.htmlParts[0]); + "}\n" + GSP_FOOTER + + when: + ParsedResult result = parseCode("myTest1", "
hi
") + + then: + trimAndRemoveCR(expected) == trimAndRemoveCR(result.generatedGsp) + "
hi
" == result.htmlParts[0] } - @Test - public void testParseWithUnclosedSquareBracket() throws Exception { - String output = parseCode("myTest2", "").generatedGsp; + void "parse with unclosed square brackets"() { + given: String expected = makeImports() + "\n" + "class myTest2 extends org.grails.gsp.GroovyPage {\n" + @@ -113,33 +91,30 @@ public void testParseWithUnclosedSquareBracket() throws Exception { "Writer expressionOut = getExpressionOut()\n" + "invokeTag('message','g',1,['code':evaluate('\"testing [\"', 1, it) { return \"testing [\" }],-1)\n" + - "}\n" + GSP_FOOTER; + "}\n" + GSP_FOOTER + + when: + String output = parseCode("myTest2", "").generatedGsp; - Assertions.assertEquals(trimAndRemoveCR(expected), trimAndRemoveCR(output)); + then: + trimAndRemoveCR(expected) == trimAndRemoveCR(output) } - @Test - public void testParseWithUnclosedGstringThrowsException() throws IOException { - Assertions.assertThrows(GrailsTagException.class, () -> parseCode("myTest3", ""), "[myTest3:1] Unclosed GSP expression"); + void "parse without unclosed gstring throws exception"() { + when: + parseCode('myTest3', '') + + then: + def e = thrown(GrailsTagException) + e.message == '[myTest3:1] Unclosed GSP expression' } - @Test - public void testParseWithUTF8() throws Exception { + void "parse with utf8"() { + given: // This is some unicode Chinese (who knows what it says!) - String src = "Chinese text: \u3421\u3437\u343f\u3443\u3410\u3405\u38b3\u389a\u395e\u3947\u3adb\u3b5a\u3b67"; - // Sanity check the string loaded OK as unicode - it won't look right if you output it, default stdout is not UTF-8 - // on many OSes - Assertions.assertEquals(src.indexOf('?'), -1); + String src = "Chinese text: \u3421\u3437\u343f\u3443\u3410\u3405\u38b3\u389a\u395e\u3947\u3adb\u3b5a\u3b67" - ConfigObject config = new ConfigSlurper().parse("grails.views.gsp.encoding = \"UTF-8\""); - - buildMockRequest(config); - ParsedResult output = null; - try { - output = parseCode("myTest4", src); - } finally { - RequestContextHolder.resetRequestAttributes(); - } + and: String expected = makeImports() + "\n" + "class myTest4 extends org.grails.gsp.GroovyPage {\n" + @@ -148,33 +123,33 @@ public void testParseWithUTF8() throws Exception { "Writer out = getOut()\n" + "Writer expressionOut = getExpressionOut()\n" + "printHtmlPart(0)\n" + - "}\n" + GSP_FOOTER; - Assertions.assertEquals(trimAndRemoveCR(expected), trimAndRemoveCR(output.generatedGsp)); - Assertions.assertEquals(src, output.htmlParts[0]); - } + "}\n" + GSP_FOOTER + + // Sanity check the string loaded OK as unicode - it won't look right if you output it, default stdout is not UTF-8 + // on many OSes + Assertions.assertEquals(src.indexOf('?'), -1) + ConfigObject config = new ConfigSlurper().parse("grails.views.gsp.encoding = \"UTF-8\"") + buildMockRequest(config) - private GrailsWebRequest buildMockRequest(ConfigObject config) throws Exception { - GenericWebApplicationContext appCtx = new GenericWebApplicationContext(new MockServletContext()); - appCtx.refresh(); - appCtx.getBeanFactory().registerSingleton(GroovyPagesUriService.BEAN_ID, new DefaultGroovyPagesUriService()); - - DefaultGrailsApplication grailsApplication = new DefaultGrailsApplication(); - grailsApplication.setConfig(config); - appCtx.getBeanFactory().registerSingleton(GrailsApplication.APPLICATION_ID, grailsApplication); - appCtx.getServletContext().setAttribute(GrailsApplicationAttributes.APPLICATION_CONTEXT, appCtx); - appCtx.getServletContext().setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, appCtx); - return GrailsWebMockUtil.bindMockWebRequest(appCtx); + when: + ParsedResult output = parseCode("myTest4", src) + + then: + trimAndRemoveCR(expected) == trimAndRemoveCR(output.generatedGsp) + src == output.htmlParts[0] + + cleanup: + RequestContextHolder.resetRequestAttributes() } - @Test - public void testParseWithLocalEncoding() throws IOException { - String src = "This is just plain ASCII to make sure test works on all platforms"; + void "parse with local encoding"() { + given: + String src = 'This is just plain ASCII to make sure test works on all platforms' // Sanity check the string loaded OK as unicode - it won't look right if you output it, // default stdout is not UTF-8 on many OSes - Assertions.assertEquals(src.indexOf('?'), -1); + Assertions.assertEquals(src.indexOf('?'), -1) - ParsedResult output = null; - output = parseCode("myTest5", src); + and: String expected = makeImports() + "\n" + "class myTest5 extends org.grails.gsp.GroovyPage {\n" + @@ -183,56 +158,30 @@ public void testParseWithLocalEncoding() throws IOException { "Writer out = getOut()\n" + "Writer expressionOut = getExpressionOut()\n" + "printHtmlPart(0)\n" + - "}\n" + GSP_FOOTER; - Assertions.assertEquals(trimAndRemoveCR(expected), trimAndRemoveCR(output.generatedGsp)); - Assertions.assertEquals(src, output.htmlParts[0]); - } + "}\n" + GSP_FOOTER - /** - * Eliminate potential issues caused by operating system differences - * and minor output differences that we don't care about. - *

- * Note: this code is inefficient and could stand to be optimized. - */ - public String trimAndRemoveCR(String s) { - int index; - StringBuilder sb = new StringBuilder(s.trim()); - while (((index = sb.toString().indexOf('\r')) != -1) || ((index = sb.toString().indexOf('\n')) != -1)) { - sb.deleteCharAt(index); - } - return sb.toString(); - } - - public ParsedResult parseCode(String uri, String gsp) throws IOException { - // Simulate what the parser does so we get it in the encoding expected - Object enc = GrailsWebUtil.currentConfiguration().get("grails.views.gsp.encoding"); - if ((enc == null) || (enc.toString().trim().length() == 0)) { - enc = System.getProperty("file.encoding", "us-ascii"); - } + when: + ParsedResult output = parseCode("myTest5", src) - InputStream gspIn = new ByteArrayInputStream(gsp.getBytes(enc.toString())); - GroovyPageParser parse = new GroovyPageParser(uri, uri, uri, gspIn, enc.toString(), "HTML", null); - - InputStream in = parse.parse(); - ParsedResult result = new ParsedResult(); - result.parser = parse; - result.generatedGsp = IOGroovyMethods.getText(in, enc.toString()); - result.htmlParts = parse.getHtmlPartsArray(); - return result; + then: + trimAndRemoveCR(expected) == trimAndRemoveCR(output.generatedGsp) + src == output.htmlParts[0] } - @Test - public void testParseGTagsWithNamespaces() throws Exception { + void "parse gtags with namespace"() { + given: String output = parseCode("myTest6", "\n" + " \n" + "").generatedGsp; System.out.println("output = " + output); - Assertions.assertTrue(output.indexOf("invokeTag('form','tt',2,[:],-1)") > -1, "should have call to tag with 'tt' namespace"); + + expect: "should have call to tag with 'tt' namespace" + output.indexOf("invokeTag('form','tt',2,[:],-1)") > -1 } - @Test - public void testParseWithWhitespaceNotEaten() throws Exception { + void "parse with whitespace not eaten"() { + given: String expected = makeImports() + "\n" + "class myTest7 extends org.grails.gsp.GroovyPage {\n" + @@ -245,17 +194,84 @@ public void testParseWithWhitespaceNotEaten() throws Exception { "printHtmlPart(1)\n" + "}\n" + GSP_FOOTER; - ParsedResult output = parseCode("myTest7", - "Please click the link below to confirm your email address:\n" + - "\n" + - "${uri}\n" + - "\n" + - "\n" + - "Thanks"); - - Assertions.assertEquals(expected.replaceAll("[\r\n]", ""), output.generatedGsp.replaceAll("[\r\n]", "")); - Assertions.assertEquals("Please click the link below to confirm your email address:\n\n", output.htmlParts[0]); - Assertions.assertEquals("\n\n\nThanks", output.htmlParts[1]); + when: + ParsedResult output = parseCode('myTest7', + 'Please click the link below to confirm your email address:\n' + + '\n' + + '${uri}\n' + + '\n' + + '\n' + + 'Thanks') + + then: + expected.replaceAll("[\r\n]", "") == output.generatedGsp.replaceAll("[\r\n]", "") + "Please click the link below to confirm your email address:\n\n" == output.htmlParts[0] + "\n\n\nThanks" == output.htmlParts[1] + } + + static ParsedResult parseCode(String uri, String gsp) throws IOException { + // Simulate what the parser does so we get it in the encoding expected + Object enc = GrailsWebUtil.currentConfiguration().get("grails.views.gsp.encoding") + if ((enc == null) || (enc.toString().trim().length() == 0)) { + enc = System.getProperty("file.encoding", "us-ascii") + } + + InputStream gspIn = new ByteArrayInputStream(gsp.getBytes(enc.toString())) + GroovyPageParser parse = new GroovyPageParser(uri, uri, uri, gspIn, enc.toString(), "HTML", null) + + InputStream inStream = parse.parse() + ParsedResult result = new ParsedResult() + result.parser = parse + result.generatedGsp = IOGroovyMethods.getText(inStream, enc.toString()) + result.htmlParts = parse.getHtmlPartsArray() + return result + } + + static String makeImports() { + StringBuilder result = new StringBuilder() + for (int i = 0; i < GroovyPageParser.DEFAULT_IMPORTS.length; i++) { + result.append("import ").append(GroovyPageParser.DEFAULT_IMPORTS[i]).append("\n") + } + return result.toString() } + /** + * Eliminate potential issues caused by operating system differences + * and minor output differences that we don't care about. + *

+ * Note: this code is inefficient and could stand to be optimized. + */ + static String trimAndRemoveCR(String s) { + int index + StringBuilder sb = new StringBuilder(s.trim()) + while (((index = sb.toString().indexOf('\r')) != -1) || ((index = sb.toString().indexOf('\n')) != -1)) { + sb.deleteCharAt(index) + } + return sb.toString() + } + + static GrailsWebRequest buildMockRequest(ConfigObject config) throws Exception { + GenericWebApplicationContext appCtx = new GenericWebApplicationContext(new MockServletContext()) + appCtx.refresh() + appCtx.getBeanFactory().registerSingleton(GroovyPagesUriService.BEAN_ID, new DefaultGroovyPagesUriService()) + + DefaultGrailsApplication grailsApplication = new DefaultGrailsApplication() + grailsApplication.setConfig(config) + appCtx.getBeanFactory().registerSingleton(GrailsApplication.APPLICATION_ID, grailsApplication) + appCtx.getServletContext().setAttribute(GrailsApplicationAttributes.APPLICATION_CONTEXT, appCtx) + appCtx.getServletContext().setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, appCtx) + return GrailsWebMockUtil.bindMockWebRequest(appCtx) + } +} + +@CompileStatic +class ParsedResult { + String generatedGsp; + GroovyPageParser parser; + String[] htmlParts; + + @Override + String toString() { + return generatedGsp; + } } From ade8dbc732cd79f5d73f088bfb91d3b74f2fd259 Mon Sep 17 00:00:00 2001 From: James Daugherty Date: Fri, 4 Jul 2025 07:32:39 -0400 Subject: [PATCH 12/26] test: add missing sitemesh2 tests --- .../org/grails/web/pages/ParseSpec.groovy | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/grails-gsp/plugin/src/test/groovy/org/grails/web/pages/ParseSpec.groovy b/grails-gsp/plugin/src/test/groovy/org/grails/web/pages/ParseSpec.groovy index cf1a403ba56..fa715af1d59 100644 --- a/grails-gsp/plugin/src/test/groovy/org/grails/web/pages/ParseSpec.groovy +++ b/grails-gsp/plugin/src/test/groovy/org/grails/web/pages/ParseSpec.groovy @@ -36,6 +36,7 @@ import org.springframework.mock.web.MockServletContext import org.springframework.web.context.WebApplicationContext import org.springframework.web.context.request.RequestContextHolder import org.springframework.web.context.support.GenericWebApplicationContext +import spock.lang.PendingFeature import spock.lang.Specification /** @@ -209,6 +210,73 @@ public static final String TAGLIB_CODEC = 'none' "\n\n\nThanks" == output.htmlParts[1] } + @PendingFeature + void 'body with gstring attribute'() { + given: + String expected = makeImports() + + "\n" + + "class GRAILS5598 extends org.grails.gsp.GroovyPage {\n" + + "public String getGroovyPageFileName() { \"GRAILS5598\" }\n" + + "public Object run() {\n" + + "Writer out = getOut()\n" + + "Writer expressionOut = getExpressionOut()\n" + + "createClosureForHtmlPart(0, 1)\n" + + "invokeTag('captureBody','grailsLayout',1,['class':evaluate('\"\${page.name} \${page.group.name.toLowerCase()}\"', 1, it) { return \"\${page.name} \${page.group.name.toLowerCase()}\" }],1)\n" + + "}\n" + GSP_FOOTER + + when: + ParsedResult result = parseCode("GRAILS5598", 'text') + + then: + trimAndRemoveCR(expected) == trimAndRemoveCR(result.generatedGsp) + "text" == result.htmlParts[0] + } + + void "bypass grails layout preprocess"() { + given: + String expected = makeImports() + + "\n" + + "class GRAILS_LAYOUT_PREPROCESS_TEST extends org.grails.gsp.GroovyPage {\n" + + "public String getGroovyPageFileName() { \"GRAILS_LAYOUT_PREPROCESS_TEST\" }\n" + + "public Object run() {\n" + + "Writer out = getOut()\n" + + "Writer expressionOut = getExpressionOut()\n" + + "printHtmlPart(0)\n" + + "}\n" + GSP_FOOTER + + when: + ParsedResult result = parseCode("GRAILS_LAYOUT_PREPROCESS_TEST", "<%@page grailsLayoutPreprocess=\"false\"%>\ntext") + + then: + trimAndRemoveCR(expected) == trimAndRemoveCR(result.generatedGsp) + "\ntext" == result.htmlParts[0] + } + + @PendingFeature + void "meta with gstring attribute"() { + given: + String expected = makeImports() + + "\n" + + "class GRAILS5605 extends org.grails.gsp.GroovyPage {\n" + + "public String getGroovyPageFileName() { \"GRAILS5605\" }\n" + + "public Object run() {\n" + + "Writer out = getOut()\n" + + "Writer expressionOut = getExpressionOut()\n" + + "printHtmlPart(0)\n" + + "createTagBody(1, {->\n" + + "invokeTag('captureMeta','grailsLayout',1,['gsp_sm_xmlClosingForEmptyTag':evaluate('\"/\"', 1, it) { return \"/\" },'name':evaluate('\"SomeName\"', 1, it) { return \"SomeName\" },'content':evaluate('\"\${grailsApplication.config.myFirstConfig}/something/\${someVar}\"', 1, it) { return \"\${grailsApplication.config.myFirstConfig}/something/\${someVar}\" }],-1)\n" + + "})\n" + + "invokeTag('captureHead','grailsLayout',1,[:],1)\n" + + "printHtmlPart(1)\n" + + "}\n" + GSP_FOOTER + + when: + ParsedResult result = parseCode("GRAILS5605", ""); + + then: + trimAndRemoveCR(expected) == trimAndRemoveCR(result.generatedGsp) + } + static ParsedResult parseCode(String uri, String gsp) throws IOException { // Simulate what the parser does so we get it in the encoding expected Object enc = GrailsWebUtil.currentConfiguration().get("grails.views.gsp.encoding") From 59a618bd60d7ec9a6669ace6ba7b9ba3719f34ae Mon Sep 17 00:00:00 2001 From: James Daugherty Date: Fri, 4 Jul 2025 12:50:46 -0400 Subject: [PATCH 13/26] test: add test for no layout at the controller level --- .../layout/NoLayoutController.groovy | 28 +++++++++++++ .../app1/grails-app/views/noLayout/index.gsp | 28 +++++++++++++ .../layout/NoLayoutControllerSpec.groovy | 42 +++++++++++++++++++ 3 files changed, 98 insertions(+) create mode 100644 grails-test-examples/app1/grails-app/controllers/functionaltests/layout/NoLayoutController.groovy create mode 100644 grails-test-examples/app1/grails-app/views/noLayout/index.gsp create mode 100644 grails-test-examples/app1/src/integration-test/groovy/functionaltests/layout/NoLayoutControllerSpec.groovy diff --git a/grails-test-examples/app1/grails-app/controllers/functionaltests/layout/NoLayoutController.groovy b/grails-test-examples/app1/grails-app/controllers/functionaltests/layout/NoLayoutController.groovy new file mode 100644 index 00000000000..6cae03cb677 --- /dev/null +++ b/grails-test-examples/app1/grails-app/controllers/functionaltests/layout/NoLayoutController.groovy @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 functionaltests.layout + +class NoLayoutController { + static layout = 'none' + + def index() { + [:] + } +} diff --git a/grails-test-examples/app1/grails-app/views/noLayout/index.gsp b/grails-test-examples/app1/grails-app/views/noLayout/index.gsp new file mode 100644 index 00000000000..4eaae6f1c1a --- /dev/null +++ b/grails-test-examples/app1/grails-app/views/noLayout/index.gsp @@ -0,0 +1,28 @@ +<%-- + ~ Licensed to the Apache Software Foundation (ASF) under one + ~ or more contributor license agreements. See the NOTICE file + ~ distributed with this work for additional information + ~ regarding copyright ownership. The ASF licenses this file + ~ to you 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. + --%> +<%@ page contentType="text/html;charset=UTF-8" %> + + + No Default Title + + + +

No layout should be applied to this page.

+ + \ No newline at end of file diff --git a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/layout/NoLayoutControllerSpec.groovy b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/layout/NoLayoutControllerSpec.groovy new file mode 100644 index 00000000000..bdb5ca8815d --- /dev/null +++ b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/layout/NoLayoutControllerSpec.groovy @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 functionaltests.layout + + +import grails.plugin.geb.ContainerGebSpec +import grails.testing.mixin.integration.Integration + +@Integration +class NoLayoutControllerSpec extends ContainerGebSpec { + def "no layout"() { + when: + go '/noLayout/index' + + then: "The title is correct" + browser.driver.pageSource == """ + No Default Title + + + +

No layout should be applied to this page.

+ +""" + } +} From 76a122f9a76a658aa2f92cdc1a3b3bd5497698d3 Mon Sep 17 00:00:00 2001 From: James Daugherty Date: Fri, 4 Jul 2025 12:57:51 -0400 Subject: [PATCH 14/26] docs: update docs to not include Sitemesh in the name --- grails-doc/resources/doc.properties | 2 +- grails-doc/src/en/guide/index.adoc | 8 ++++---- grails-doc/src/en/guide/links.yml | 4 ++-- ...sitemeshContentBlocks.adoc => contentBlocks.adoc} | 0 grails-doc/src/en/guide/toc.yml | 4 ++-- .../src/test/resources/docs/guide/single.html | 12 ++++++------ .../docs-core/src/test/resources/docs/index.html | 4 ++-- 7 files changed, 17 insertions(+), 17 deletions(-) rename grails-doc/src/en/guide/theWebLayer/gsp/{sitemeshContentBlocks.adoc => contentBlocks.adoc} (100%) diff --git a/grails-doc/resources/doc.properties b/grails-doc/resources/doc.properties index c77b1a81cdf..1a8eaea3b98 100644 --- a/grails-doc/resources/doc.properties +++ b/grails-doc/resources/doc.properties @@ -66,7 +66,7 @@ alias.identity=5.5.2.4 Custom Database Identity alias.interceptors=6.1.5 Controller Interceptors alias.ivy=3.7 Dependency Resolution alias.JSON=6.1.7 XML and JSON Responses -alias.layouts=6.2.4 Layouts with Sitemesh +alias.layouts=6.2.4 Layouts alias.locking=5.3.5 Pessimistic and Optimistic Locking alias.logging=3.1.2 Logging alias.mappingHTTP=6.4.5 Mapping to HTTP methods diff --git a/grails-doc/src/en/guide/index.adoc b/grails-doc/src/en/guide/index.adoc index 44c73da5026..9dcf31ca7e4 100644 --- a/grails-doc/src/en/guide/index.adoc +++ b/grails-doc/src/en/guide/index.adoc @@ -456,7 +456,7 @@ include::theWebLayer/gsp/tags/tagsAsMethodCalls.adoc[] include::theWebLayer/gsp/viewsAndTemplates.adoc[] [[layouts]] -==== Layouts with Sitemesh +==== Layouts include::theWebLayer/gsp/layouts.adoc[] @@ -465,10 +465,10 @@ include::theWebLayer/gsp/layouts.adoc[] include::theWebLayer/gsp/resources.adoc[] -[[sitemeshContentBlocks]] -==== Sitemesh Content Blocks +[[contentBlocks]] +==== Content Blocks -include::theWebLayer/gsp/sitemeshContentBlocks.adoc[] +include::theWebLayer/gsp/contentBlocks.adoc[] [[makingChangesToADeployedApplication]] ==== Making Changes to a Deployed Application diff --git a/grails-doc/src/en/guide/links.yml b/grails-doc/src/en/guide/links.yml index 035809c38fd..b7a4ffd16ed 100644 --- a/grails-doc/src/en/guide/links.yml +++ b/grails-doc/src/en/guide/links.yml @@ -142,7 +142,7 @@ linksAndResources: 7.2.2.4 Links and Resources formsAndFields: 7.2.2.5 Forms and Fields tagsAsMethodCalls: 7.2.2.6 Tags as Method Calls viewsAndTemplates: 7.2.3 Views and Templates -layouts: 7.2.4 Layouts with Sitemesh +layouts: 7.2.4 Layouts resources: 7.2.5 Static Resources includingResourcesUsingTheResourceTags: 7.2.5.1 Including resources using the resource tags otherResourceTags: 7.2.5.2 Other resource tags @@ -152,7 +152,7 @@ optimizingYourResources: 7.2.5.5 Optimizing your resources debugging: 7.2.5.6 Debugging preventingProcessingOfResources: 7.2.5.7 Preventing processing of resources otherResourcesPlugins: 7.2.5.8 Other Resources-aware plugins -sitemeshContentBlocks: 7.2.6 Sitemesh Content Blocks +contentBlocks: 7.2.6 Content Blocks makingChangesToADeployedApplication: 7.2.7 Making Changes to a Deployed Application GSPDebugging: 7.2.8 GSP Debugging taglibs: 7.3 Tag Libraries diff --git a/grails-doc/src/en/guide/theWebLayer/gsp/sitemeshContentBlocks.adoc b/grails-doc/src/en/guide/theWebLayer/gsp/contentBlocks.adoc similarity index 100% rename from grails-doc/src/en/guide/theWebLayer/gsp/sitemeshContentBlocks.adoc rename to grails-doc/src/en/guide/theWebLayer/gsp/contentBlocks.adoc diff --git a/grails-doc/src/en/guide/toc.yml b/grails-doc/src/en/guide/toc.yml index 0379eaace4b..1891557fd2d 100644 --- a/grails-doc/src/en/guide/toc.yml +++ b/grails-doc/src/en/guide/toc.yml @@ -130,8 +130,8 @@ theWebLayer: tagsAsMethodCalls: Tags as Method Calls viewsAndTemplates: Views and Templates layouts: - title: Layouts with Sitemesh - sitemeshContentBlocks: Sitemesh Content Blocks + title: Layouts + contentBlocks: Content Blocks resources: Static Resources makingChangesToADeployedApplication: Making Changes to a Deployed Application taglibs: diff --git a/grails-gradle/docs-core/src/test/resources/docs/guide/single.html b/grails-gradle/docs-core/src/test/resources/docs/guide/single.html index b62969250d3..d3b4282875d 100644 --- a/grails-gradle/docs-core/src/test/resources/docs/guide/single.html +++ b/grails-gradle/docs-core/src/test/resources/docs/guide/single.html @@ -318,11 +318,11 @@

Table of Contents

- + - + @@ -10230,8 +10230,8 @@

Templates in Controllers an - -

8.2.4 Layouts with Sitemesh

+ +

8.2.4 Layouts

-

8.2.6 Sitemesh Content Blocks

+

8.2.6 Content Blocks

-
diff --git a/grails-gradle/docs-core/src/test/resources/docs/index.html b/grails-gradle/docs-core/src/test/resources/docs/index.html index 424aa87b245..540e83ff7d6 100644 --- a/grails-gradle/docs-core/src/test/resources/docs/index.html +++ b/grails-gradle/docs-core/src/test/resources/docs/index.html @@ -318,11 +318,11 @@

Table of Contents

- + - + From b22d7473c24499f0e996a25444e5d82fb6824ff1 Mon Sep 17 00:00:00 2001 From: James Daugherty Date: Fri, 4 Jul 2025 13:19:39 -0400 Subject: [PATCH 15/26] cleanup: use StandardCharsets --- .../src/main/groovy/grails/util/GrailsWebUtil.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/grails-web-common/src/main/groovy/grails/util/GrailsWebUtil.java b/grails-web-common/src/main/groovy/grails/util/GrailsWebUtil.java index f99915691e3..d2cb3fc26f9 100644 --- a/grails-web-common/src/main/groovy/grails/util/GrailsWebUtil.java +++ b/grails-web-common/src/main/groovy/grails/util/GrailsWebUtil.java @@ -24,6 +24,7 @@ import groovy.lang.GroovyObject; import groovy.util.ConfigObject; +import java.nio.charset.StandardCharsets; import java.util.Collections; import java.util.Map; import java.util.regex.Pattern; @@ -46,7 +47,7 @@ @SuppressWarnings("rawtypes") public class GrailsWebUtil { - public static final String DEFAULT_ENCODING = "UTF-8"; + public static final String DEFAULT_ENCODING = StandardCharsets.UTF_8.name(); private static final String CHARSET_ATTRIBUTE = ";charset="; private static final Pattern CHARSET_IN_CONTENT_TYPE_REGEXP = Pattern.compile(";\\s*charset\\s*=", Pattern.CASE_INSENSITIVE); From 25638ca25870501221c1f0910a0da5e7d0eefbf8 Mon Sep 17 00:00:00 2001 From: James Daugherty Date: Fri, 4 Jul 2025 13:20:18 -0400 Subject: [PATCH 16/26] refactor: move RENDERING_VIEW_ATTRIBUTE to GroovyPagesUriService --- .../main/groovy/org/grails/web/pages/GroovyPagesServlet.java | 5 ++--- .../groovy/org/grails/web/servlet/view/GroovyPageView.java | 5 ++--- .../main/groovy/grails/web/pages/GroovyPagesUriService.java | 2 ++ 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/grails-gsp/grails-web-gsp/src/main/groovy/org/grails/web/pages/GroovyPagesServlet.java b/grails-gsp/grails-web-gsp/src/main/groovy/org/grails/web/pages/GroovyPagesServlet.java index ab075fe8169..c7e5ffff007 100644 --- a/grails-gsp/grails-web-gsp/src/main/groovy/org/grails/web/pages/GroovyPagesServlet.java +++ b/grails-gsp/grails-web-gsp/src/main/groovy/org/grails/web/pages/GroovyPagesServlet.java @@ -22,6 +22,7 @@ import grails.plugins.GrailsPluginManager; import grails.plugins.PluginManagerAware; import grails.util.GrailsStringUtils; +import grails.web.pages.GroovyPagesUriService; import org.grails.web.util.GrailsApplicationAttributes; import groovy.text.Template; import org.grails.core.io.support.GrailsFactoriesLoader; @@ -77,8 +78,6 @@ public class GroovyPagesServlet extends FrameworkServlet implements PluginManage private static final long serialVersionUID = -1918149859392123495L; - public static final String RENDERING_VIEW_ATTRIBUTE = "org.grails.rendering.view"; - private static final String WEB_INF = "/WEB-INF"; private static final String GRAILS_APP = "/grails-app"; @@ -215,7 +214,7 @@ protected GroovyPageScriptSource findPageInBinaryPlugins(String pageName) { */ protected void renderPageWithEngine(GroovyPagesTemplateEngine engine, HttpServletRequest request, HttpServletResponse response, GroovyPageScriptSource scriptSource) throws Exception { - request.setAttribute(RENDERING_VIEW_ATTRIBUTE, Boolean.TRUE); + request.setAttribute(GroovyPagesUriService.RENDERING_VIEW_ATTRIBUTE, Boolean.TRUE); GSPResponseWriter out = createResponseWriter(response); try { Template template = engine.createTemplate(scriptSource); diff --git a/grails-gsp/grails-web-gsp/src/main/groovy/org/grails/web/servlet/view/GroovyPageView.java b/grails-gsp/grails-web-gsp/src/main/groovy/org/grails/web/servlet/view/GroovyPageView.java index f61aada783a..bdd8d0ffdd1 100644 --- a/grails-gsp/grails-web-gsp/src/main/groovy/org/grails/web/servlet/view/GroovyPageView.java +++ b/grails-gsp/grails-web-gsp/src/main/groovy/org/grails/web/servlet/view/GroovyPageView.java @@ -20,6 +20,7 @@ import grails.util.Environment; import grails.util.GrailsUtil; +import grails.web.pages.GroovyPagesUriService; import groovy.text.Template; import java.io.IOException; @@ -39,8 +40,6 @@ import org.springframework.core.io.Resource; import org.springframework.scripting.ScriptSource; -import static org.grails.web.pages.GroovyPagesServlet.RENDERING_VIEW_ATTRIBUTE; - /** * A Spring View that renders Groovy Server Pages to the response. It requires an instance * of GroovyPagesTemplateEngine to be set and will render to view returned by the getUrl() @@ -70,7 +69,7 @@ public class GroovyPageView extends AbstractGrailsView { @Override protected void renderTemplate(Map model, GrailsWebRequest webRequest, HttpServletRequest request, HttpServletResponse response) { - request.setAttribute(RENDERING_VIEW_ATTRIBUTE, Boolean.TRUE); + request.setAttribute(GroovyPagesUriService.RENDERING_VIEW_ATTRIBUTE, Boolean.TRUE); GSPResponseWriter out = null; try { out = createResponseWriter(webRequest, response); diff --git a/grails-web-common/src/main/groovy/grails/web/pages/GroovyPagesUriService.java b/grails-web-common/src/main/groovy/grails/web/pages/GroovyPagesUriService.java index 60491ed74dc..aeb12c24ef1 100644 --- a/grails-web-common/src/main/groovy/grails/web/pages/GroovyPagesUriService.java +++ b/grails-web-common/src/main/groovy/grails/web/pages/GroovyPagesUriService.java @@ -28,6 +28,8 @@ */ public interface GroovyPagesUriService { + String RENDERING_VIEW_ATTRIBUTE = "org.grails.rendering.view"; + String BEAN_ID = "groovyPagesUriService"; /** From 7783899e18fa621f5b127710da62eea32eb3f5d2 Mon Sep 17 00:00:00 2001 From: James Daugherty Date: Fri, 4 Jul 2025 13:25:21 -0400 Subject: [PATCH 17/26] chore: reformat code --- .../web/GroovyPagesGrailsPlugin.groovy | 288 +++++++++--------- 1 file changed, 144 insertions(+), 144 deletions(-) diff --git a/grails-gsp/plugin/src/main/groovy/org/grails/plugins/web/GroovyPagesGrailsPlugin.groovy b/grails-gsp/plugin/src/main/groovy/org/grails/plugins/web/GroovyPagesGrailsPlugin.groovy index 918f136f4d7..654edf6b1d0 100644 --- a/grails-gsp/plugin/src/main/groovy/org/grails/plugins/web/GroovyPagesGrailsPlugin.groovy +++ b/grails-gsp/plugin/src/main/groovy/org/grails/plugins/web/GroovyPagesGrailsPlugin.groovy @@ -73,15 +73,15 @@ class GroovyPagesGrailsPlugin extends Plugin { def loadAfter = ['filters'] def providedArtefacts = [ - ApplicationTagLib, - CountryTagLib, - FormatTagLib, - FormTagLib, - JavascriptTagLib, - RenderTagLib, - UrlMappingTagLib, - ValidationTagLib, - PluginTagLib + ApplicationTagLib, + CountryTagLib, + FormatTagLib, + FormTagLib, + JavascriptTagLib, + RenderTagLib, + UrlMappingTagLib, + ValidationTagLib, + PluginTagLib ] @@ -97,180 +97,180 @@ class GroovyPagesGrailsPlugin extends Plugin { /** * Configures the various Spring beans required by GSP */ - Closure doWithSpring() {{-> - def application = grailsApplication - Config config = application.config - boolean developmentMode = isDevelopmentMode() - Environment env = Environment.current + Closure doWithSpring() { + { -> + def application = grailsApplication + Config config = application.config + boolean developmentMode = isDevelopmentMode() + Environment env = Environment.current - boolean enableReload = env.isReloadEnabled() || - config.getProperty(GroovyPagesTemplateEngine.CONFIG_PROPERTY_GSP_ENABLE_RELOAD, Boolean, false) || - (developmentMode && env == Environment.DEVELOPMENT) + boolean enableReload = env.isReloadEnabled() || + config.getProperty(GroovyPagesTemplateEngine.CONFIG_PROPERTY_GSP_ENABLE_RELOAD, Boolean, false) || + (developmentMode && env == Environment.DEVELOPMENT) - boolean warDeployed = application.warDeployed - boolean warDeployedWithReload = warDeployed && enableReload + boolean warDeployed = application.warDeployed + boolean warDeployedWithReload = warDeployed && enableReload - long gspCacheTimeout = config.getProperty(GSP_RELOAD_INTERVAL, Long, (developmentMode && env == Environment.DEVELOPMENT) ? 0L : 5000L) - boolean enableCacheResources = !config.getProperty(GroovyPagesTemplateEngine.CONFIG_PROPERTY_DISABLE_CACHING_RESOURCES, Boolean, false) - String viewsDir = config.getProperty(GSP_VIEWS_DIR, '') + long gspCacheTimeout = config.getProperty(GSP_RELOAD_INTERVAL, Long, (developmentMode && env == Environment.DEVELOPMENT) ? 0L : 5000L) + boolean enableCacheResources = !config.getProperty(GroovyPagesTemplateEngine.CONFIG_PROPERTY_DISABLE_CACHING_RESOURCES, Boolean, false) + String viewsDir = config.getProperty(GSP_VIEWS_DIR, '') - RuntimeSpringConfiguration spring = springConfig + RuntimeSpringConfiguration spring = springConfig - // resolves JSP tag libraries - boolean resolveJspTagLibraries = ClassUtils.isPresent('org.grails.gsp.jsp.TagLibraryResolverImpl', application.classLoader) - if (resolveJspTagLibraries) { - jspTagLibraryResolver(TagLibraryResolverImpl) - } + // resolves JSP tag libraries + boolean resolveJspTagLibraries = ClassUtils.isPresent('org.grails.gsp.jsp.TagLibraryResolverImpl', application.classLoader) + if (resolveJspTagLibraries) { + jspTagLibraryResolver(TagLibraryResolverImpl) + } - // resolves GSP tag libraries - gspTagLibraryLookup(TagLibraryLookup) { bean -> - bean.lazyInit = true - } + // resolves GSP tag libraries + gspTagLibraryLookup(TagLibraryLookup) { bean -> + bean.lazyInit = true + } - boolean customResourceLoader = false - // If the development environment is used we need to load GSP files relative to the base directory - // as oppose to in WAR deployment where views are loaded from /WEB-INF + boolean customResourceLoader = false + // If the development environment is used we need to load GSP files relative to the base directory + // as oppose to in WAR deployment where views are loaded from /WEB-INF - if (viewsDir) { - log.info "Configuring GSP views directory as '${viewsDir}'" - customResourceLoader = true - groovyPageResourceLoader(GroovyPageResourceLoader) { - baseResource = "file:${viewsDir}" - } - } - else { - if (developmentMode) { + if (viewsDir) { + log.info "Configuring GSP views directory as '${viewsDir}'" customResourceLoader = true - groovyPageResourceLoader(GroovyPageResourceLoader) { bean -> - bean.lazyInit = true - def location = GroovyPagesGrailsPlugin.transformToValidLocation(BuildSettings.BASE_DIR.absolutePath) - baseResource = "file:$location" + groovyPageResourceLoader(GroovyPageResourceLoader) { + baseResource = "file:${viewsDir}" } - } - else { - if (warDeployedWithReload && env.hasReloadLocation()) { + } else { + if (developmentMode) { customResourceLoader = true - groovyPageResourceLoader(GroovyPageResourceLoader) { - def location = GroovyPagesGrailsPlugin.transformToValidLocation(env.reloadLocation) - baseResource = "file:${location}" + groovyPageResourceLoader(GroovyPageResourceLoader) { bean -> + bean.lazyInit = true + def location = GroovyPagesGrailsPlugin.transformToValidLocation(BuildSettings.BASE_DIR.absolutePath) + baseResource = "file:$location" + } + } else { + if (warDeployedWithReload && env.hasReloadLocation()) { + customResourceLoader = true + groovyPageResourceLoader(GroovyPageResourceLoader) { + def location = GroovyPagesGrailsPlugin.transformToValidLocation(env.reloadLocation) + baseResource = "file:${location}" + } } } } - } - def deployed = !Metadata.getCurrent().isDevelopmentEnvironmentAvailable() - groovyPageLocator(CachingGrailsConventionGroovyPageLocator) { bean -> - bean.lazyInit = true - if (customResourceLoader) { - resourceLoader = groovyPageResourceLoader - } - if (deployed) { - Resource defaultViews = applicationContext?.getResource('gsp/views.properties') + def deployed = !Metadata.getCurrent().isDevelopmentEnvironmentAvailable() + groovyPageLocator(CachingGrailsConventionGroovyPageLocator) { bean -> + bean.lazyInit = true + if (customResourceLoader) { + resourceLoader = groovyPageResourceLoader + } + if (deployed) { + Resource defaultViews = applicationContext?.getResource('gsp/views.properties') - if(defaultViews != null) { - if(!defaultViews.exists()) { - defaultViews = applicationContext?.getResource('classpath:gsp/views.properties') + if (defaultViews != null) { + if (!defaultViews.exists()) { + defaultViews = applicationContext?.getResource('classpath:gsp/views.properties') + } } - } - if(defaultViews?.exists()) { - precompiledGspMap = { PropertiesFactoryBean pfb -> - ignoreResourceNotFound = true - locations = [defaultViews] as Resource[] + if (defaultViews?.exists()) { + precompiledGspMap = { PropertiesFactoryBean pfb -> + ignoreResourceNotFound = true + locations = [defaultViews] as Resource[] + } } } + if (enableReload) { + cacheTimeout = gspCacheTimeout + } + reloadEnabled = enableReload } - if (enableReload) { - cacheTimeout = gspCacheTimeout - } - reloadEnabled = enableReload - } - grailsResourceLocator(CachingGroovyPageStaticResourceLocator) { bean -> - bean.parent = "abstractGrailsResourceLocator" - if (enableReload) { - cacheTimeout = gspCacheTimeout + grailsResourceLocator(CachingGroovyPageStaticResourceLocator) { bean -> + bean.parent = "abstractGrailsResourceLocator" + if (enableReload) { + cacheTimeout = gspCacheTimeout + } } - } - // Setup the main templateEngine used to render GSPs - groovyPagesTemplateEngine(GroovyPagesTemplateEngine) { - classLoader = ref("classLoader") - groovyPageLocator = groovyPageLocator - if (enableReload) { - reloadEnabled = enableReload - } - tagLibraryLookup = gspTagLibraryLookup - if (resolveJspTagLibraries) { - jspTagLibraryResolver = jspTagLibraryResolver + // Setup the main templateEngine used to render GSPs + groovyPagesTemplateEngine(GroovyPagesTemplateEngine) { + classLoader = ref("classLoader") + groovyPageLocator = groovyPageLocator + if (enableReload) { + reloadEnabled = enableReload + } + tagLibraryLookup = gspTagLibraryLookup + if (resolveJspTagLibraries) { + jspTagLibraryResolver = jspTagLibraryResolver + } + cacheResources = enableCacheResources } - cacheResources = enableCacheResources - } - spring.addAlias('groovyTemplateEngine', 'groovyPagesTemplateEngine') + spring.addAlias('groovyTemplateEngine', 'groovyPagesTemplateEngine') - groovyPageRenderer(PageRenderer, ref("groovyPagesTemplateEngine")) { bean -> - bean.lazyInit = true - groovyPageLocator = groovyPageLocator - } + groovyPageRenderer(PageRenderer, ref("groovyPagesTemplateEngine")) { bean -> + bean.lazyInit = true + groovyPageLocator = groovyPageLocator + } - groovyPagesTemplateRenderer(GroovyPagesTemplateRenderer) { bean -> - bean.autowire = true - if (enableReload) { - reloadEnabled = enableReload + groovyPagesTemplateRenderer(GroovyPagesTemplateRenderer) { bean -> + bean.autowire = true + if (enableReload) { + reloadEnabled = enableReload + } } - } - // Setup the GroovyPagesUriService - groovyPagesUriService(DefaultGroovyPagesUriService) { bean -> - bean.lazyInit = true - } - - boolean jstlPresent = ClassUtils.isPresent( - "jakarta.servlet.jsp.jstl.core.Config", InternalResourceViewResolver.class.getClassLoader()) - - abstractViewResolver { - prefix = GrailsApplicationAttributes.PATH_TO_VIEWS - suffix = jstlPresent ? GroovyPageViewResolver.JSP_SUFFIX : GroovyPageViewResolver.GSP_SUFFIX - resolveJspView = jstlPresent - templateEngine = groovyPagesTemplateEngine - groovyPageLocator = groovyPageLocator - if (enableReload) { - cacheTimeout = gspCacheTimeout + // Setup the GroovyPagesUriService + groovyPagesUriService(DefaultGroovyPagesUriService) { bean -> + bean.lazyInit = true } - } - // Configure a Spring MVC view resolver - jspViewResolver(GroovyPageViewResolver) { bean -> - bean.lazyInit = true - bean.parent = "abstractViewResolver" - } - // Now go through tag libraries and configure them in Spring too. With AOP proxies and so on - for (taglib in application.tagLibClasses) { + boolean jstlPresent = ClassUtils.isPresent( + "jakarta.servlet.jsp.jstl.core.Config", InternalResourceViewResolver.class.getClassLoader()) + + abstractViewResolver { + prefix = GrailsApplicationAttributes.PATH_TO_VIEWS + suffix = jstlPresent ? GroovyPageViewResolver.JSP_SUFFIX : GroovyPageViewResolver.GSP_SUFFIX + resolveJspView = jstlPresent + templateEngine = groovyPagesTemplateEngine + groovyPageLocator = groovyPageLocator + if (enableReload) { + cacheTimeout = gspCacheTimeout + } + } + // Configure a Spring MVC view resolver + jspViewResolver(GroovyPageViewResolver) { bean -> + bean.lazyInit = true + bean.parent = "abstractViewResolver" + } - final tagLibClass = taglib.clazz + // Now go through tag libraries and configure them in Spring too. With AOP proxies and so on + for (taglib in application.tagLibClasses) { - "${taglib.fullName}"(tagLibClass) { bean -> - bean.autowire = true - bean.lazyInit = true + final tagLibClass = taglib.clazz + + "${taglib.fullName}"(tagLibClass) { bean -> + bean.autowire = true + bean.lazyInit = true - // Taglib scoping support could be easily added here. Scope could be based on a static field in the taglib class. - //bean.scope = 'request' + // Taglib scoping support could be easily added here. Scope could be based on a static field in the taglib class. + //bean.scope = 'request' + } } - } - errorsViewStackTracePrinter(ErrorsViewStackTracePrinter, ref('grailsResourceLocator')) - filteringCodecsByContentTypeSettings(FilteringCodecsByContentTypeSettings, application) + errorsViewStackTracePrinter(ErrorsViewStackTracePrinter, ref('grailsResourceLocator')) + filteringCodecsByContentTypeSettings(FilteringCodecsByContentTypeSettings, application) - groovyPagesServlet(ServletRegistrationBean, new GroovyPagesServlet(), "*.gsp") { - if(Environment.isDevelopmentMode()) { - initParameters = [showSource:"1"] + groovyPagesServlet(ServletRegistrationBean, new GroovyPagesServlet(), "*.gsp") { + if (Environment.isDevelopmentMode()) { + initParameters = [showSource: "1"] + } } - } - grailsTagDateHelper(DefaultGrailsTagDateHelper) - }} + grailsTagDateHelper(DefaultGrailsTagDateHelper) + } + } protected boolean isDevelopmentMode() { Metadata.getCurrent().isDevelopmentEnvironmentAvailable() @@ -288,7 +288,7 @@ class GroovyPagesGrailsPlugin extends Plugin { def ctx = applicationContext if (application.isArtefactOfType(TagLibArtefactHandler.TYPE, event.source)) { - GrailsTagLibClass taglibClass = (GrailsTagLibClass)application.addArtefact(TagLibArtefactHandler.TYPE, event.source) + GrailsTagLibClass taglibClass = (GrailsTagLibClass) application.addArtefact(TagLibArtefactHandler.TYPE, event.source) if (taglibClass) { // replace tag library bean def beanName = taglibClass.fullName @@ -306,7 +306,7 @@ class GroovyPagesGrailsPlugin extends Plugin { } } // clear uri cache after changes - ctx.getBean('groovyPagesUriService',GroovyPagesUriService).clear() + ctx.getBean('groovyPagesUriService', GroovyPagesUriService).clear() } @CompileStatic From e8f7c76968017e96939249fb6555d914807953ec Mon Sep 17 00:00:00 2001 From: James Daugherty Date: Fri, 4 Jul 2025 14:07:20 -0400 Subject: [PATCH 18/26] refactor: introduce common interface to customize view in rendering --- .../support/ResponseRenderer.groovy | 15 ++++++++-- .../web/pages/GrailsRenderViewMutator.java | 30 +++++++++++++++++++ 2 files changed, 42 insertions(+), 3 deletions(-) create mode 100644 grails-web-common/src/main/groovy/grails/web/pages/GrailsRenderViewMutator.java diff --git a/grails-controllers/src/main/groovy/grails/artefact/controller/support/ResponseRenderer.groovy b/grails-controllers/src/main/groovy/grails/artefact/controller/support/ResponseRenderer.groovy index d12a74660ae..f2f338a8ea7 100644 --- a/grails-controllers/src/main/groovy/grails/artefact/controller/support/ResponseRenderer.groovy +++ b/grails-controllers/src/main/groovy/grails/artefact/controller/support/ResponseRenderer.groovy @@ -27,6 +27,7 @@ import grails.web.api.WebAttributes import grails.web.http.HttpHeaders import grails.web.mime.MimeType import grails.web.mime.MimeUtility +import grails.web.pages.GrailsRenderViewMutator import groovy.json.StreamingJsonBuilder import groovy.transform.CompileStatic import groovy.transform.Generated @@ -54,6 +55,7 @@ import jakarta.servlet.http.HttpServletRequest import jakarta.servlet.http.HttpServletResponse import static org.grails.plugins.web.controllers.metaclass.RenderDynamicMethod.* + /** * * A trait that adds behavior to allow rendering of objects to the response @@ -68,10 +70,16 @@ trait ResponseRenderer extends WebAttributes { private Collection actionResultTransformers = [] - private MimeUtility mimeUtility + private GrailsRenderViewMutator grailsRenderViewMutator private GrailsPluginManager pluginManager + @Generated + @Autowired(required = false) + void setGrailsRenderViewMutator(GrailsRenderViewMutator grailsRenderViewMutator) { + this.grailsRenderViewMutator = grailsRenderViewMutator + } + @Generated @Autowired(required = false) @Qualifier("grailsMimeUtility") @@ -298,14 +306,15 @@ trait ResponseRenderer extends WebAttributes { throw new ControllerExecutionException("Unable to load template for uri [$templateUri]. Template not found.") } - boolean renderWithLayout = (layoutArg || webRequest.getCurrentRequest().getAttribute(WebUtils.LAYOUT_ATTRIBUTE)) // if automatic decoration occurred unwrap, since this is a partial - if (renderWithLayout) { setLayout webRequest.currentRequest, layoutArg } + if(grailsRenderViewMutator) { + view = grailsRenderViewMutator.mutateView(renderWithLayout, templateUri, webRequest.locale, view) + } Map binding = [:] diff --git a/grails-web-common/src/main/groovy/grails/web/pages/GrailsRenderViewMutator.java b/grails-web-common/src/main/groovy/grails/web/pages/GrailsRenderViewMutator.java new file mode 100644 index 00000000000..20388668df0 --- /dev/null +++ b/grails-web-common/src/main/groovy/grails/web/pages/GrailsRenderViewMutator.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 grails.web.pages; + +import org.springframework.web.servlet.View; + +import java.util.Locale; + +/** + * Interface to customize the view when rendering + */ +public interface GrailsRenderViewMutator { + View mutateView(boolean renderWithLayout, String templateUri, Locale locale, View exisitngView); +} From 8e0b9caea2f64fc0558a0e0f3862de3218df59e5 Mon Sep 17 00:00:00 2001 From: James Daugherty Date: Fri, 4 Jul 2025 14:19:18 -0400 Subject: [PATCH 19/26] refactor: introduce common interface to customize layout in rendering --- .../support/ResponseRenderer.groovy | 32 +++++++++++++------ .../web/pages/GrailsLayoutSelector.java | 32 +++++++++++++++++++ 2 files changed, 55 insertions(+), 9 deletions(-) create mode 100644 grails-web-common/src/main/groovy/grails/web/pages/GrailsLayoutSelector.java diff --git a/grails-controllers/src/main/groovy/grails/artefact/controller/support/ResponseRenderer.groovy b/grails-controllers/src/main/groovy/grails/artefact/controller/support/ResponseRenderer.groovy index f2f338a8ea7..b834e5dc540 100644 --- a/grails-controllers/src/main/groovy/grails/artefact/controller/support/ResponseRenderer.groovy +++ b/grails-controllers/src/main/groovy/grails/artefact/controller/support/ResponseRenderer.groovy @@ -27,6 +27,7 @@ import grails.web.api.WebAttributes import grails.web.http.HttpHeaders import grails.web.mime.MimeType import grails.web.mime.MimeUtility +import grails.web.pages.GrailsLayoutSelector import grails.web.pages.GrailsRenderViewMutator import groovy.json.StreamingJsonBuilder import groovy.transform.CompileStatic @@ -72,6 +73,7 @@ trait ResponseRenderer extends WebAttributes { private MimeUtility mimeUtility private GrailsRenderViewMutator grailsRenderViewMutator + private GrailsLayoutSelector grailsLayoutSelector private GrailsPluginManager pluginManager @Generated @@ -80,6 +82,12 @@ trait ResponseRenderer extends WebAttributes { this.grailsRenderViewMutator = grailsRenderViewMutator } + @Generated + @Autowired(required = false) + void setGrailsLayoutSelector(GrailsLayoutSelector grailsLayoutSelector) { + this.grailsLayoutSelector = grailsLayoutSelector + } + @Generated @Autowired(required = false) @Qualifier("grailsMimeUtility") @@ -150,7 +158,7 @@ trait ResponseRenderer extends WebAttributes { else { renderMarkupInternal webRequest, closure, response } - setLayout webRequest.currentRequest, layoutArg + setLayout webRequest.currentRequest, false, layoutArg } private void renderJsonInternal(HttpServletResponse response, @DelegatesTo(value = StreamingJsonBuilder.StreamingJsonDelegate.class, strategy = Closure.DELEGATE_FIRST) Closure callable) { @@ -174,7 +182,7 @@ trait ResponseRenderer extends WebAttributes { applyContentType response, argMap, body handleStatusArgument argMap, webRequest, response render body - setLayout webRequest.currentRequest, layoutArg + setLayout webRequest.currentRequest, false, layoutArg } /** @@ -218,7 +226,7 @@ trait ResponseRenderer extends WebAttributes { handleStatusArgument argMap, webRequest, response applyContentType response, argMap, writable renderWritable writable, response - setLayout webRequest.currentRequest, layoutArg + setLayout webRequest.currentRequest, false, layoutArg webRequest.renderView = false } @@ -246,7 +254,7 @@ trait ResponseRenderer extends WebAttributes { CharSequence text = (textArg instanceof CharSequence) ? ((CharSequence)textArg) : textArg.toString() render text } - setLayout webRequest.currentRequest, layoutArg + setLayout webRequest.currentRequest, false, layoutArg } else if (argMap.containsKey(ARGUMENT_VIEW)) { String viewName = argMap[ARGUMENT_VIEW].toString() @@ -274,7 +282,7 @@ trait ResponseRenderer extends WebAttributes { } ((GroovyObject)this).setProperty "modelAndView", new ModelAndView(viewUri, model) - setLayout webRequest.currentRequest, layoutArg + setLayout webRequest.currentRequest, true, layoutArg } else if (argMap.containsKey(ARGUMENT_TEMPLATE)) { applyContentType response, argMap, null, false @@ -309,7 +317,7 @@ trait ResponseRenderer extends WebAttributes { boolean renderWithLayout = (layoutArg || webRequest.getCurrentRequest().getAttribute(WebUtils.LAYOUT_ATTRIBUTE)) // if automatic decoration occurred unwrap, since this is a partial if (renderWithLayout) { - setLayout webRequest.currentRequest, layoutArg + setLayout webRequest.currentRequest, false, layoutArg } if(grailsRenderViewMutator) { @@ -544,9 +552,15 @@ trait ResponseRenderer extends WebAttributes { renderArgument instanceof GPathResult ? APPLICATION_XML : defaultEncoding } - private void setLayout(HttpServletRequest request, String layout) { - if (layout != null && request.getAttribute(WebUtils.LAYOUT_ATTRIBUTE) == null) { - request.setAttribute WebUtils.LAYOUT_ATTRIBUTE, layout + private void setLayout(HttpServletRequest request, boolean renderingView, String explicitLayoutArg) { + if (explicitLayoutArg == null && request.getAttribute(WebUtils.LAYOUT_ATTRIBUTE) != null) { + // layout has been set already + return + } + + String selectedLayout = grailsLayoutSelector == null ? explicitLayoutArg : grailsLayoutSelector.selectLayout(explicitLayoutArg, renderingView) + if (selectedLayout != null) { + request.setAttribute WebUtils.LAYOUT_ATTRIBUTE, selectedLayout } } diff --git a/grails-web-common/src/main/groovy/grails/web/pages/GrailsLayoutSelector.java b/grails-web-common/src/main/groovy/grails/web/pages/GrailsLayoutSelector.java new file mode 100644 index 00000000000..80e050d81f5 --- /dev/null +++ b/grails-web-common/src/main/groovy/grails/web/pages/GrailsLayoutSelector.java @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 grails.web.pages; + +/** + * Interface to override the selected layout during the rendering process. + */ +public interface GrailsLayoutSelector { + /** + * + * @param explicitLayoutArg the layout argument set by the caller (layout: 'myLayout'), may be null + * @param renderView whether the view is being rendered + * @return the view to render + */ + String selectLayout(String explicitLayoutArg, boolean renderView); +} From 24db59dfd41cec2d81f2ac47f13a732b8baa663a Mon Sep 17 00:00:00 2001 From: James Daugherty Date: Fri, 4 Jul 2025 14:49:34 -0400 Subject: [PATCH 20/26] refactor: decouple further response processing in exception resolving --- .../buffer/GrailsResponseMutator.groovy | 31 +++++++++++++++++++ .../web/errors/GrailsExceptionResolver.java | 5 +++ 2 files changed, 36 insertions(+) create mode 100644 grails-encoder/src/main/groovy/org/grails/buffer/GrailsResponseMutator.groovy diff --git a/grails-encoder/src/main/groovy/org/grails/buffer/GrailsResponseMutator.groovy b/grails-encoder/src/main/groovy/org/grails/buffer/GrailsResponseMutator.groovy new file mode 100644 index 00000000000..e3358671dce --- /dev/null +++ b/grails-encoder/src/main/groovy/org/grails/buffer/GrailsResponseMutator.groovy @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.buffer + +/** + * Interface to assign to a HttpServletResponse wrapper so on an error, it can be deactivated to not further + * change the response. + */ +interface GrailsResponseMutator { + /** + * Do not mutate the response & stop any processing of it. + */ + void deactivateResponseMutator(); +} \ No newline at end of file diff --git a/grails-web-mvc/src/main/groovy/org/grails/web/errors/GrailsExceptionResolver.java b/grails-web-mvc/src/main/groovy/org/grails/web/errors/GrailsExceptionResolver.java index 23c4faa98ca..10a4948e513 100644 --- a/grails-web-mvc/src/main/groovy/org/grails/web/errors/GrailsExceptionResolver.java +++ b/grails-web-mvc/src/main/groovy/org/grails/web/errors/GrailsExceptionResolver.java @@ -35,6 +35,7 @@ import org.apache.commons.logging.LogFactory; import org.codehaus.groovy.control.CompilationFailedException; import grails.core.GrailsApplication; +import org.grails.buffer.GrailsResponseMutator; import org.grails.exceptions.reporting.DefaultStackTraceFilterer; import org.grails.core.exceptions.GrailsRuntimeException; import org.grails.exceptions.reporting.StackTraceFilterer; @@ -194,6 +195,10 @@ protected ModelAndView resolveViewOrForward(Exception ex, UrlMappingsHolder urlM else if (info != null && info.getControllerName() != null) { String uri = determineUri(request); if (!response.isCommitted()) { + if (response instanceof GrailsResponseMutator) { + // prevent further mutation of the request since an error page needs rendered instead + ((GrailsResponseMutator) response).deactivateResponseMutator(); + } forwardRequest(info, request, response, mv, uri); // return an empty ModelAndView since the error handler has been processed return new ModelAndView(); From 514bb2ad7f03499d4475e7c9b17901bd40fbd3f3 Mon Sep 17 00:00:00 2001 From: James Daugherty Date: Sat, 5 Jul 2025 13:33:40 -0400 Subject: [PATCH 21/26] feedback: styling --- .../support/ResponseRenderer.groovy | 221 ++++++------- .../tests/AuthorControllerSpec.groovy | 2 +- .../tests/BookControllerSpec.groovy | 2 +- .../tests/BookControllerSpec.groovy | 2 +- .../en/guide/testing/functionalTesting.adoc | 2 +- .../feature/test/template/spock.rocker.raw | 2 +- .../src/main/templates/FunctionalSpec.groovy | 2 +- .../grails/gsp/compiler/GroovyPageParser.java | 18 +- .../web/GroovyPagesGrailsPlugin.groovy | 44 +-- .../RestfulReverseUrlRenderingTests.groovy | 4 +- .../org/grails/web/pages/ParseSpec.groovy | 204 ++++++------ .../ForwardingController.groovy | 8 +- .../AsyncFunctionalSpec.groovy | 4 +- .../functionaltests/BookFunctionalSpec.groovy | 52 +-- .../ConfigTestControllerSpec.groovy | 2 +- .../ControllerFromPluginSpec.groovy | 2 +- .../ControllerIncludesSpec.groovy | 48 +-- .../ErrorsFunctionalSpec.groovy | 36 +-- .../functionaltests/ForwardingSpec.groovy | 64 ++-- .../groovy/functionaltests/HomeSpec.groovy | 36 +-- .../InspectConfigControllerSpec.groovy | 2 +- .../InterceptorDependencyInjectionSpec.groovy | 2 +- .../InterceptorFunctionalSpec.groovy | 16 +- .../functionaltests/LoadAfterSpec.groovy | 2 +- .../functionaltests/MiscFunctionalSpec.groovy | 10 +- .../PluginViewsControllerSpec.groovy | 4 +- .../RedirectIntercetorSpec.groovy | 4 +- ...tWithAndWithoutParamsFunctionalSpec.groovy | 14 +- ...riMatchingInterceptorFunctionalSpec.groovy | 4 +- .../ValidationFunctionalSpec.groovy | 4 +- ...NamespacedControllersFunctionalSpec.groovy | 4 +- .../layout/LayoutFunctionalSpec.groovy | 6 +- .../layout/LayoutWithTemplateSpec.groovy | 2 +- .../layout/NoLayoutControllerSpec.groovy | 7 +- .../scaffolding/BarFunctionalSpec.groovy | 2 +- .../scaffolding/FooFunctionalSpec.groovy | 2 +- .../groovy/app2/ErrorsControllerSpec.groovy | 4 +- .../groovy/app2/NotFoundHandlerSpec.groovy | 4 +- .../groovy/app3/LoadAfterSpec.groovy | 2 +- .../com/demo/CacheTagIntegrationSpec.groovy | 50 +-- .../demo/CachingServiceIntegrationSpec.groovy | 306 +++++++++--------- ...NotCachingControllerIntegrationSpec.groovy | 4 +- .../org/demo/spock/DownloadSupportSpec.groovy | 2 +- .../org/demo/spock/InheritedConfigSpec.groovy | 8 +- .../groovy/org/demo/spock/RootPageSpec.groovy | 2 +- .../spock/ServerNameControllerSpec.groovy | 2 +- .../groovy/EndToEndSpec.groovy | 45 +-- .../groovy/GrailsLayoutSpec.groovy | 26 +- .../tests/BookControllerSpec.groovy | 2 +- .../hyphenated/FooBarControllerSpec.groovy | 6 +- .../hyphenated/HyphenateControllerSpec.groovy | 2 +- .../NameSpacedControllerSpec.groovy | 6 +- .../tests/BookControllerSpec.groovy | 2 +- .../tests/AuthorControllerSpec.groovy | 4 +- .../tests/BookControllerSpec.groovy | 2 +- .../groovy/context/ContextPathSpec.groovy | 4 +- .../NamespaceViewRenderingSpec.groovy | 4 +- .../namespaces/PageControllerSpec.groovy | 4 +- .../admin/ReportControllerSpec.groovy | 4 +- .../grails/testing/gorm/DataTest.groovy | 6 +- 60 files changed, 665 insertions(+), 676 deletions(-) diff --git a/grails-controllers/src/main/groovy/grails/artefact/controller/support/ResponseRenderer.groovy b/grails-controllers/src/main/groovy/grails/artefact/controller/support/ResponseRenderer.groovy index b834e5dc540..016cdc2ab59 100644 --- a/grails-controllers/src/main/groovy/grails/artefact/controller/support/ResponseRenderer.groovy +++ b/grails-controllers/src/main/groovy/grails/artefact/controller/support/ResponseRenderer.groovy @@ -60,7 +60,7 @@ import static org.grails.plugins.web.controllers.metaclass.RenderDynamicMethod.* /** * * A trait that adds behavior to allow rendering of objects to the response - * + * * @author Jeff Brown * @author Graeme Rocher * @@ -108,10 +108,10 @@ trait ResponseRenderer extends WebAttributes { */ @Generated void render(object) { - GrailsWebRequest webRequest = (GrailsWebRequest)RequestContextHolder.currentRequestAttributes() + GrailsWebRequest webRequest = (GrailsWebRequest) RequestContextHolder.currentRequestAttributes() HttpServletResponse response = webRequest.currentResponse webRequest.renderView = false - applyContentType response, null, object + applyContentType(response, null, object) try { response.writer.write object.inspect() @@ -128,10 +128,10 @@ trait ResponseRenderer extends WebAttributes { */ @Generated void render(@DelegatesTo(strategy = Closure.DELEGATE_FIRST) Closure closure) { - GrailsWebRequest webRequest = (GrailsWebRequest)RequestContextHolder.currentRequestAttributes() + GrailsWebRequest webRequest = (GrailsWebRequest) RequestContextHolder.currentRequestAttributes() HttpServletResponse response = webRequest.currentResponse - setContentType response, TEXT_HTML, DEFAULT_ENCODING, true + setContentType(response, TEXT_HTML, DEFAULT_ENCODING, true) renderMarkupInternal webRequest, closure, response } @@ -144,7 +144,7 @@ trait ResponseRenderer extends WebAttributes { */ @Generated void render(Map argMap, @DelegatesTo(strategy = Closure.DELEGATE_FIRST) Closure closure) { - GrailsWebRequest webRequest = (GrailsWebRequest)RequestContextHolder.currentRequestAttributes() + GrailsWebRequest webRequest = (GrailsWebRequest) RequestContextHolder.currentRequestAttributes() HttpServletResponse response = webRequest.currentResponse String layoutArg = argMap[ARGUMENT_LAYOUT]?.toString() ?: null @@ -154,11 +154,10 @@ trait ResponseRenderer extends WebAttributes { if (BUILDER_TYPE_JSON.equals(argMap.get(ARGUMENT_BUILDER)) || isJSONResponse(response)) { renderJsonInternal(response, closure) webRequest.renderView = false + } else { + renderMarkupInternal(webRequest, closure, response) } - else { - renderMarkupInternal webRequest, closure, response - } - setLayout webRequest.currentRequest, false, layoutArg + setLayout(webRequest.currentRequest, false, layoutArg) } private void renderJsonInternal(HttpServletResponse response, @DelegatesTo(value = StreamingJsonBuilder.StreamingJsonDelegate.class, strategy = Closure.DELEGATE_FIRST) Closure callable) { @@ -175,14 +174,14 @@ trait ResponseRenderer extends WebAttributes { */ @Generated void render(Map argMap, CharSequence body) { - GrailsWebRequest webRequest = (GrailsWebRequest)RequestContextHolder.currentRequestAttributes() + GrailsWebRequest webRequest = (GrailsWebRequest) RequestContextHolder.currentRequestAttributes() HttpServletResponse response = webRequest.currentResponse String layoutArg = argMap[ARGUMENT_LAYOUT]?.toString() ?: null applyContentType response, argMap, body handleStatusArgument argMap, webRequest, response render body - setLayout webRequest.currentRequest, false, layoutArg + setLayout(webRequest.currentRequest, false, layoutArg) } /** @@ -192,16 +191,15 @@ trait ResponseRenderer extends WebAttributes { */ @Generated void render(CharSequence txt) { - GrailsWebRequest webRequest = (GrailsWebRequest)RequestContextHolder.currentRequestAttributes() + GrailsWebRequest webRequest = (GrailsWebRequest) RequestContextHolder.currentRequestAttributes() HttpServletResponse response = webRequest.currentResponse - applyContentType response, null, txt + applyContentType(response, null, txt) try { PrintWriter writer = response.getWriter() if (writer instanceof PrintWriter) { - ((PrintWriter)writer).print txt - } - else { - writer.write txt.toString() + ((PrintWriter) writer).print(txt) + } else { + writer.write(txt.toString()) } writer.flush() webRequest.renderView = false @@ -219,14 +217,14 @@ trait ResponseRenderer extends WebAttributes { */ @Generated void render(Map argMap, Writable writable) { - GrailsWebRequest webRequest = (GrailsWebRequest)RequestContextHolder.currentRequestAttributes() + GrailsWebRequest webRequest = (GrailsWebRequest) RequestContextHolder.currentRequestAttributes() HttpServletResponse response = webRequest.currentResponse String layoutArg = argMap[ARGUMENT_LAYOUT]?.toString() ?: null - handleStatusArgument argMap, webRequest, response - applyContentType response, argMap, writable - renderWritable writable, response - setLayout webRequest.currentRequest, false, layoutArg + handleStatusArgument(argMap, webRequest, response) + applyContentType(response, argMap, writable) + renderWritable(writable, response) + setLayout(webRequest.currentRequest, false, layoutArg) webRequest.renderView = false } @@ -237,7 +235,7 @@ trait ResponseRenderer extends WebAttributes { */ @Generated void render(Map argMap) { - GrailsWebRequest webRequest = (GrailsWebRequest)RequestContextHolder.currentRequestAttributes() + GrailsWebRequest webRequest = (GrailsWebRequest) RequestContextHolder.currentRequestAttributes() HttpServletResponse response = webRequest.currentResponse String layoutArg = argMap[ARGUMENT_LAYOUT]?.toString() ?: null boolean statusSet = handleStatusArgument(argMap, webRequest, response) @@ -248,26 +246,25 @@ trait ResponseRenderer extends WebAttributes { def textArg = argMap[ARGUMENT_TEXT] applyContentType response, argMap, textArg if (textArg instanceof Writable) { - renderWritable((Writable)textArg, response) + renderWritable((Writable) textArg, response) webRequest.renderView = false } else { - CharSequence text = (textArg instanceof CharSequence) ? ((CharSequence)textArg) : textArg.toString() + CharSequence text = (textArg instanceof CharSequence) ? ((CharSequence) textArg) : textArg.toString() render text } - setLayout webRequest.currentRequest, false, layoutArg - } - else if (argMap.containsKey(ARGUMENT_VIEW)) { + setLayout(webRequest.currentRequest, false, layoutArg) + } else if (argMap.containsKey(ARGUMENT_VIEW)) { String viewName = argMap[ARGUMENT_VIEW].toString() - String viewUri = applicationAttributes.getNoSuffixViewURI((GroovyObject)this, viewName) + String viewUri = applicationAttributes.getNoSuffixViewURI((GroovyObject) this, viewName) String contextPath = getContextPath(webRequest, argMap) - if(contextPath) { + if (contextPath) { viewUri = contextPath + viewUri } Object modelObject = argMap[ARGUMENT_MODEL] if (modelObject) { Collection resultTransformers = actionResultTransformers for (ActionResultTransformer resultTransformer : resultTransformers) { - modelObject = resultTransformer.transformActionResult webRequest,viewUri, modelObject + modelObject = resultTransformer.transformActionResult webRequest, viewUri, modelObject } } @@ -276,30 +273,28 @@ trait ResponseRenderer extends WebAttributes { Map model if (modelObject instanceof Map) { model = (Map) modelObject - } - else { + } else { model = [:] } - ((GroovyObject)this).setProperty "modelAndView", new ModelAndView(viewUri, model) - setLayout webRequest.currentRequest, true, layoutArg - } - else if (argMap.containsKey(ARGUMENT_TEMPLATE)) { + ((GroovyObject) this).setProperty "modelAndView", new ModelAndView(viewUri, model) + setLayout(webRequest.currentRequest, true, layoutArg) + } else if (argMap.containsKey(ARGUMENT_TEMPLATE)) { applyContentType response, argMap, null, false webRequest.renderView = false boolean hasModel = argMap.containsKey(ARGUMENT_MODEL) def modelObject - if(hasModel) { + if (hasModel) { modelObject = argMap[ARGUMENT_MODEL] } String templateName = argMap[ARGUMENT_TEMPLATE].toString() String var if (argMap.containsKey(ARGUMENT_VAR)) { - var = String.valueOf( argMap[ARGUMENT_VAR] ) + var = String.valueOf(argMap[ARGUMENT_VAR]) } // get the template uri - String templateUri = applicationAttributes.getTemplateURI((GroovyObject)this, templateName, false) + String templateUri = applicationAttributes.getTemplateURI((GroovyObject) this, templateName, false) // retrieve view resolver def applicationContext = applicationAttributes.getApplicationContext() @@ -307,8 +302,8 @@ trait ResponseRenderer extends WebAttributes { try { View view = viewResolver.resolveView(templateUri, webRequest.locale) - if(view instanceof GroovyPageView) { - ((GroovyPageTemplate)((GroovyPageView)view).template).allowSettingContentType = true + if (view instanceof GroovyPageView) { + ((GroovyPageTemplate) ((GroovyPageView) view).template).allowSettingContentType = true } if (view == null) { throw new ControllerExecutionException("Unable to load template for uri [$templateUri]. Template not found.") @@ -317,10 +312,10 @@ trait ResponseRenderer extends WebAttributes { boolean renderWithLayout = (layoutArg || webRequest.getCurrentRequest().getAttribute(WebUtils.LAYOUT_ATTRIBUTE)) // if automatic decoration occurred unwrap, since this is a partial if (renderWithLayout) { - setLayout webRequest.currentRequest, false, layoutArg + setLayout(webRequest.currentRequest, false, layoutArg) } - if(grailsRenderViewMutator) { + if (grailsRenderViewMutator) { view = grailsRenderViewMutator.mutateView(renderWithLayout, templateUri, webRequest.locale, view) } @@ -330,57 +325,52 @@ trait ResponseRenderer extends WebAttributes { Object bean = argMap[ARGUMENT_BEAN] if (hasModel) { if (modelObject instanceof Map) { - setTemplateModel webRequest, binding, (Map) modelObject + setTemplateModel(webRequest, binding, (Map) modelObject) } } if (GrailsStringUtils.isBlank(var)) { - binding.put DEFAULT_ARGUMENT, bean + binding.put(DEFAULT_ARGUMENT, bean) + } else { + binding.put(var, bean) } - else { - binding.put var, bean - } - renderViewForTemplate webRequest, view, binding - } - else if (argMap.containsKey(ARGUMENT_COLLECTION)) { + renderViewForTemplate(webRequest, view, binding) + } else if (argMap.containsKey(ARGUMENT_COLLECTION)) { Object colObject = argMap[ARGUMENT_COLLECTION] if (hasModel) { if (modelObject instanceof Map) { - setTemplateModel webRequest, binding, (Map)modelObject + setTemplateModel(webRequest, binding, (Map) modelObject) } } - renderTemplateForCollection webRequest, view, binding, colObject, var - } - else if (hasModel) { + renderTemplateForCollection(webRequest, view, binding, colObject, var) + } else if (hasModel) { if (modelObject instanceof Map) { - setTemplateModel webRequest, binding, (Map)modelObject + setTemplateModel webRequest, binding, (Map) modelObject } - renderViewForTemplate webRequest, view, binding - } - else { - renderViewForTemplate webRequest, view, binding + renderViewForTemplate(webRequest, view, binding) + } else { + renderViewForTemplate(webRequest, view, binding) } } catch (GroovyRuntimeException gre) { throw new ControllerExecutionException("Error rendering template [$templateName]: ${gre.message}", gre) } catch (IOException ioex) { - throw new ControllerExecutionException("I/O error executing render method for arguments [$argMap]: ${ioex.message}" , ioex) + throw new ControllerExecutionException("I/O error executing render method for arguments [$argMap]: ${ioex.message}", ioex) } - } - else if (argMap.containsKey(ARGUMENT_FILE)) { + } else if (argMap.containsKey(ARGUMENT_FILE)) { webRequest.renderView = false def o = argMap[ARGUMENT_FILE] def fnO = argMap[ARGUMENT_FILE_NAME] - String fileName = fnO ? fnO.toString() : ((o instanceof File) ? ((File)o).name : null ) + String fileName = fnO ? fnO.toString() : ((o instanceof File) ? ((File) o).name : null) if (o) { boolean hasContentType = applyContentType(response, argMap, null, false) if (fileName) { - if(!hasContentType) { + if (!hasContentType) { hasContentType = detectContentTypeFromFileName(webRequest, response, argMap, fileName) } if (fnO) { - response.setHeader HttpHeaders.CONTENT_DISPOSITION, "$DISPOSITION_HEADER_PREFIX\"$fileName\"" + response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "$DISPOSITION_HEADER_PREFIX\"$fileName\"") } } if (!hasContentType) { @@ -392,14 +382,11 @@ trait ResponseRenderer extends WebAttributes { try { if (o instanceof File) { input = IOUtils.openStream(o) - } - else if (o instanceof InputStream) { - input = (InputStream)o - } - else if (o instanceof byte[]) { - input = new ByteArrayInputStream((byte[])o) - } - else { + } else if (o instanceof InputStream) { + input = (InputStream) o + } else if (o instanceof byte[]) { + input = new ByteArrayInputStream((byte[]) o) + } else { input = IOUtils.openStream(new File(o.toString())) } SpringIOUtils.copy input, response.getOutputStream() @@ -410,44 +397,39 @@ trait ResponseRenderer extends WebAttributes { finally { if (input) { try { - ((InputStream)input).close() + ((InputStream) input).close() } catch (IOException e) { // ignore } } } } - } - else if( !statusSet ) { + } else if (!statusSet) { webRequest.renderView = false - if(argMap instanceof JSONElement) { + if (argMap instanceof JSONElement) { response.contentType = GrailsWebUtil.getContentType(MimeType.JSON.name, DEFAULT_ENCODING) - renderWritable( (JSONElement)argMap, response ) - } - else { - applyContentType response, argMap, argMap + renderWritable((JSONElement) argMap, response) + } else { + applyContentType(response, argMap, argMap) try { - response.writer.write argMap.inspect() + response.writer.write(argMap.inspect()) } catch (IOException e) { throw new ControllerExecutionException("I/O error obtaining response writer: ${e.message}", e) } } - } - else { + } else { // reached here so only the status was set, just send it back String message = argMap?.message?.toString() int statusCode = response.status - if( message ) { - response.sendError(statusCode, message ) - } - else { + if (message) { + response.sendError(statusCode, message) + } else { // if the status code is an error trigger the container // forwarding logic - if(statusCode >= 300) { + if (statusCode >= 300) { response.sendError(statusCode) - } - else { + } else { // otherwise just ensure the status is propagated to the client response.setStatus(statusCode) response.flushBuffer() @@ -457,14 +439,13 @@ trait ResponseRenderer extends WebAttributes { } - private boolean handleStatusArgument(Map argMap, GrailsWebRequest webRequest, HttpServletResponse response) { boolean statusSet if (argMap.containsKey(ARGUMENT_STATUS)) { def statusObj = argMap.get(ARGUMENT_STATUS) if (statusObj != null) { if (statusObj instanceof HttpStatus) { - response.status = ((HttpStatus)statusObj).value() + response.status = ((HttpStatus) statusObj).value() statusSet = true } else { @@ -480,7 +461,7 @@ trait ResponseRenderer extends WebAttributes { } } } - if(statusSet) { + if (statusSet) { webRequest.renderView = false } return statusSet @@ -493,7 +474,7 @@ trait ResponseRenderer extends WebAttributes { Writable markup = (Writable) b.bind(closure) renderWritable markup, response - webRequest.setRenderView false + webRequest.setRenderView(false) } private boolean isJSONResponse(HttpServletResponse response) { @@ -522,29 +503,29 @@ trait ResponseRenderer extends WebAttributes { String contentType = resolveContentTypeBySourceType(renderArgument, useDefault ? TEXT_HTML : null) String encoding = DEFAULT_ENCODING if (argMap != null) { - if(argMap.containsKey(ARGUMENT_CONTENT_TYPE)) { + if (argMap.containsKey(ARGUMENT_CONTENT_TYPE)) { contentType = argMap.get(ARGUMENT_CONTENT_TYPE).toString() contentTypeIsDefault = false } - if(argMap.containsKey(ARGUMENT_ENCODING)) { + if (argMap.containsKey(ARGUMENT_ENCODING)) { encoding = argMap.get(ARGUMENT_ENCODING).toString() contentTypeIsDefault = false } } - if(contentType != null) { - setContentType response, contentType, encoding, contentTypeIsDefault + if (contentType != null) { + setContentType(response, contentType, encoding, contentTypeIsDefault) return true } false } private void setContentType(HttpServletResponse response, String contentType, String encoding) { - setContentType response, contentType, encoding, false + setContentType(response, contentType, encoding, false) } private void setContentType(HttpServletResponse response, String contentType, String encoding, boolean contentTypeIsDefault) { - if (!contentTypeIsDefault || response.getContentType()==null) { - response.setContentType GrailsWebUtil.getContentType(contentType, encoding) + if (!contentTypeIsDefault || response.getContentType() == null) { + response.setContentType(GrailsWebUtil.getContentType(contentType, encoding)) } } @@ -560,7 +541,7 @@ trait ResponseRenderer extends WebAttributes { String selectedLayout = grailsLayoutSelector == null ? explicitLayoutArg : grailsLayoutSelector.selectLayout(explicitLayoutArg, renderingView) if (selectedLayout != null) { - request.setAttribute WebUtils.LAYOUT_ATTRIBUTE, selectedLayout + request.setAttribute(WebUtils.LAYOUT_ATTRIBUTE, selectedLayout) } } @@ -578,7 +559,7 @@ trait ResponseRenderer extends WebAttributes { } private GrailsPluginManager getPluginManager(GrailsWebRequest webRequest) { - if(pluginManager == null) { + if (pluginManager == null) { pluginManager = webRequest.getApplicationContext().getBean(GrailsPluginManager) } pluginManager @@ -586,8 +567,8 @@ trait ResponseRenderer extends WebAttributes { private void setTemplateModel(GrailsWebRequest webRequest, Map binding, Map modelObject) { Map modelMap = modelObject - webRequest.setAttribute GrailsApplicationAttributes.TEMPLATE_MODEL, modelMap, RequestAttributes.SCOPE_REQUEST - binding.putAll modelMap + webRequest.setAttribute(GrailsApplicationAttributes.TEMPLATE_MODEL, modelMap, RequestAttributes.SCOPE_REQUEST) + binding.putAll(modelMap) } private void renderTemplateForCollection(GrailsWebRequest webRequest, View view, Map binding, Object colObject, String var) throws IOException { @@ -595,28 +576,26 @@ trait ResponseRenderer extends WebAttributes { Iterable c = (Iterable) colObject for (Object o : c) { if (GrailsStringUtils.isBlank(var)) { - binding.put DEFAULT_ARGUMENT, o - } - else { - binding.put var, o + binding.put(DEFAULT_ARGUMENT, o) + } else { + binding.put(var, o) } - renderViewForTemplate webRequest, view, binding + renderViewForTemplate(webRequest, view, binding) } - } - else { + } else { if (GrailsStringUtils.isBlank(var)) { binding.put DEFAULT_ARGUMENT, colObject - } - else { + } else { binding.put var, colObject } - renderViewForTemplate webRequest, view, binding + renderViewForTemplate(webRequest, view, binding) } } + private void renderViewForTemplate(GrailsWebRequest webRequest, View view, Map binding) { try { - view.render binding, webRequest.getCurrentRequest(), webRequest.getResponse() + view.render(binding, webRequest.getCurrentRequest(), webRequest.getResponse()) } catch (Exception e) { throw new ControllerExecutionException(e.getMessage(), e) @@ -630,7 +609,7 @@ trait ResponseRenderer extends WebAttributes { String contentType = mimeType.name def encodingObj = argMap.get(ARGUMENT_ENCODING) String encoding = encodingObj ? encodingObj.toString() : DEFAULT_ENCODING - setContentType response, contentType, encoding + setContentType(response, contentType, encoding) return true } } diff --git a/grails-data-neo4j/examples/grails3-neo4j-hibernate/src/integration-test/groovy/functional/tests/AuthorControllerSpec.groovy b/grails-data-neo4j/examples/grails3-neo4j-hibernate/src/integration-test/groovy/functional/tests/AuthorControllerSpec.groovy index 8f9489fccd7..29d8b73d250 100644 --- a/grails-data-neo4j/examples/grails3-neo4j-hibernate/src/integration-test/groovy/functional/tests/AuthorControllerSpec.groovy +++ b/grails-data-neo4j/examples/grails3-neo4j-hibernate/src/integration-test/groovy/functional/tests/AuthorControllerSpec.groovy @@ -27,7 +27,7 @@ class AuthorControllerSpec extends GebSpec { void "Test list authors"() { when:"The home page is visited" - go '/author/index' + go('/author/index') then:"The name is correct" title == "Author List" diff --git a/grails-data-neo4j/examples/grails3-neo4j-hibernate/src/integration-test/groovy/functional/tests/BookControllerSpec.groovy b/grails-data-neo4j/examples/grails3-neo4j-hibernate/src/integration-test/groovy/functional/tests/BookControllerSpec.groovy index 3ca2bb74f91..46ea7429567 100644 --- a/grails-data-neo4j/examples/grails3-neo4j-hibernate/src/integration-test/groovy/functional/tests/BookControllerSpec.groovy +++ b/grails-data-neo4j/examples/grails3-neo4j-hibernate/src/integration-test/groovy/functional/tests/BookControllerSpec.groovy @@ -28,7 +28,7 @@ class BookControllerSpec extends GebSpec { void "Test list books"() { when:"The home page is visited" - go '/book/index' + go('/book/index') then:"The title is correct" title == "Book List" diff --git a/grails-data-neo4j/examples/grails3-neo4j/src/integration-test/groovy/functional/tests/BookControllerSpec.groovy b/grails-data-neo4j/examples/grails3-neo4j/src/integration-test/groovy/functional/tests/BookControllerSpec.groovy index 014f9e32d0e..b8f19afee1d 100644 --- a/grails-data-neo4j/examples/grails3-neo4j/src/integration-test/groovy/functional/tests/BookControllerSpec.groovy +++ b/grails-data-neo4j/examples/grails3-neo4j/src/integration-test/groovy/functional/tests/BookControllerSpec.groovy @@ -27,7 +27,7 @@ class BookControllerSpec extends GebSpec { void "Test list books"() { when:"The home page is visited" - go '/book/index' + go('/book/index') then:"The title is correct" title == "Book List" diff --git a/grails-doc/src/en/guide/testing/functionalTesting.adoc b/grails-doc/src/en/guide/testing/functionalTesting.adoc index a54be72fb51..c7a6d3a3b11 100644 --- a/grails-doc/src/en/guide/testing/functionalTesting.adoc +++ b/grails-doc/src/en/guide/testing/functionalTesting.adoc @@ -42,7 +42,7 @@ class HomeSpec extends GebSpec { void "Test the home page renders correctly"() { when:"The home page is visited" - go '/' + go('/') then:"The title is correct" $('title').text() == "Welcome to Grails" diff --git a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/test/template/spock.rocker.raw b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/test/template/spock.rocker.raw index e9634796d8a..46cd9d486fd 100644 --- a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/test/template/spock.rocker.raw +++ b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/test/template/spock.rocker.raw @@ -39,7 +39,7 @@ class @project.getClassName()Spec extends ContainerGebSpec { void 'should display the correct title on the home page'() { when: 'visiting the home page' - go '/' + go('/') then: 'the page title is correct' title == 'Welcome to Grails' diff --git a/grails-geb/src/main/templates/FunctionalSpec.groovy b/grails-geb/src/main/templates/FunctionalSpec.groovy index dadd96d7541..86686c1adcd 100644 --- a/grails-geb/src/main/templates/FunctionalSpec.groovy +++ b/grails-geb/src/main/templates/FunctionalSpec.groovy @@ -20,7 +20,7 @@ class ${className}Spec extends GebSpec { void "test something"() { when:"The home page is visited" - go '/' + go('/') then:"The title is correct" title == "Welcome to Grails" diff --git a/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/GroovyPageParser.java b/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/GroovyPageParser.java index 4896411624f..29253d612e6 100644 --- a/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/GroovyPageParser.java +++ b/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/GroovyPageParser.java @@ -22,8 +22,8 @@ import grails.io.IOUtils; import grails.util.Environment; import grails.util.GrailsStringUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.codehaus.groovy.runtime.DefaultGroovyMethods; import org.grails.buffer.FastStringWriter; import org.grails.buffer.StreamByteBuffer; @@ -44,7 +44,7 @@ /** * NOTE: Based on work done by the GSP standalone project (https://gsp.dev.java.net/). - * + *

* Parsing implementation for GSP files * * @author Troy Heninger @@ -53,7 +53,7 @@ */ public class GroovyPageParser implements Tokens { - public static final Log LOG = LogFactory.getLog(GroovyPageParser.class); + private static final Logger LOG = LoggerFactory.getLogger(GroovyPageParser.class); private static final Pattern PARA_BREAK = Pattern.compile( "/p>\\s*]*>", Pattern.CASE_INSENSITIVE); @@ -339,8 +339,7 @@ public InputStream parse() { new FileOutputStream(keepGeneratedFile), GROOVY_SOURCE_CHAR_ENCODING); } catch (IOException e) { - LOG.warn("Cannot open keepgenerated file for writing. File's absolute path is '" + - keepGeneratedFile.getAbsolutePath() + "'"); + LOG.warn("Cannot open keepgenerated file for writing. File's absolute path is '{}'", keepGeneratedFile.getAbsolutePath()); keepGeneratedFile = null; } streamBuffer.connectTo(keepGeneratedWriter, true); @@ -357,9 +356,7 @@ public InputStream parse() { private void resolveKeepGeneratedDirectory() { if (keepGeneratedDirectory != null && !keepGeneratedDirectory.isDirectory()) { - LOG.warn("The directory specified with " + CONFIG_PROPERTY_GSP_KEEPGENERATED_DIR + - " config parameter doesn't exist or isn't a readable directory. Absolute path: '" + - keepGeneratedDirectory.getAbsolutePath() + "' Keepgenerated will be disabled."); + LOG.warn("The directory specified with {} config parameter doesn't exist or isn't a readable directory. Absolute path: '{}' Keepgenerated will be disabled.", CONFIG_PROPERTY_GSP_KEEPGENERATED_DIR, keepGeneratedDirectory.getAbsolutePath()); keepGeneratedDirectory = null; } } @@ -699,6 +696,7 @@ private void makeName(String uri) { /** * find the simple name of this gsp + * * @param filename the fully qualified file name */ private void makeSourceName(String filename) { @@ -905,6 +903,7 @@ private boolean isModelRecordingModeEnabled() { /** * Determines if the line numbers array should be added to the generated Groovy class. + * * @return true if they should */ private boolean shouldAddLineNumbers() { @@ -943,6 +942,7 @@ private void addLineNumbers() { /** * Filters trailing 0s from the line number array + * * @param lineNumbers the line number array * @return a new array that removes all 0s from the end of it */ diff --git a/grails-gsp/plugin/src/main/groovy/org/grails/plugins/web/GroovyPagesGrailsPlugin.groovy b/grails-gsp/plugin/src/main/groovy/org/grails/plugins/web/GroovyPagesGrailsPlugin.groovy index 654edf6b1d0..3e477928279 100644 --- a/grails-gsp/plugin/src/main/groovy/org/grails/plugins/web/GroovyPagesGrailsPlugin.groovy +++ b/grails-gsp/plugin/src/main/groovy/org/grails/plugins/web/GroovyPagesGrailsPlugin.groovy @@ -28,13 +28,21 @@ import grails.util.GrailsUtil import grails.util.Metadata import grails.web.pages.GroovyPagesUriService import groovy.transform.CompileStatic -import groovy.util.logging.Commons +import groovy.util.logging.Slf4j import org.grails.core.artefact.gsp.TagLibArtefactHandler import org.grails.gsp.GroovyPageResourceLoader import org.grails.gsp.GroovyPagesTemplateEngine import org.grails.gsp.io.CachingGroovyPageStaticResourceLocator import org.grails.gsp.jsp.TagLibraryResolverImpl -import org.grails.plugins.web.taglib.* +import org.grails.plugins.web.taglib.ApplicationTagLib +import org.grails.plugins.web.taglib.CountryTagLib +import org.grails.plugins.web.taglib.FormTagLib +import org.grails.plugins.web.taglib.FormatTagLib +import org.grails.plugins.web.taglib.JavascriptTagLib +import org.grails.plugins.web.taglib.PluginTagLib +import org.grails.plugins.web.taglib.RenderTagLib +import org.grails.plugins.web.taglib.UrlMappingTagLib +import org.grails.plugins.web.taglib.ValidationTagLib import org.grails.spring.RuntimeSpringConfiguration import org.grails.taglib.TagLibraryLookup import org.grails.taglib.TagLibraryMetaUtils @@ -58,7 +66,7 @@ import org.springframework.web.servlet.view.InternalResourceViewResolver * @author Graeme Rocher * @since 1.1 */ -@Commons +@Slf4j class GroovyPagesGrailsPlugin extends Plugin { public static final String GSP_RELOAD_INTERVAL = "grails.gsp.reload.interval" @@ -68,7 +76,7 @@ class GroovyPagesGrailsPlugin extends Plugin { "file:./grails-app/taglib/**/*TagLib.groovy"] def grailsVersion = "7.0.0-SNAPSHOT > *" - def dependsOn = [core: GrailsUtil.getGrailsVersion(), i18n: GrailsUtil.getGrailsVersion()] + def dependsOn = [core: GrailsUtil.grailsVersion, i18n: GrailsUtil.grailsVersion] def observe = ['controllers'] def loadAfter = ['filters'] @@ -101,10 +109,10 @@ class GroovyPagesGrailsPlugin extends Plugin { { -> def application = grailsApplication Config config = application.config - boolean developmentMode = isDevelopmentMode() + boolean developmentMode = developmentMode Environment env = Environment.current - boolean enableReload = env.isReloadEnabled() || + boolean enableReload = env.reloadEnabled || config.getProperty(GroovyPagesTemplateEngine.CONFIG_PROPERTY_GSP_ENABLE_RELOAD, Boolean, false) || (developmentMode && env == Environment.DEVELOPMENT) @@ -134,7 +142,7 @@ class GroovyPagesGrailsPlugin extends Plugin { // as oppose to in WAR deployment where views are loaded from /WEB-INF if (viewsDir) { - log.info "Configuring GSP views directory as '${viewsDir}'" + log.info("Configuring GSP views directory as '{}'", viewsDir) customResourceLoader = true groovyPageResourceLoader(GroovyPageResourceLoader) { baseResource = "file:${viewsDir}" @@ -158,7 +166,7 @@ class GroovyPagesGrailsPlugin extends Plugin { } } - def deployed = !Metadata.getCurrent().isDevelopmentEnvironmentAvailable() + def deployed = !Metadata.current.developmentEnvironmentAvailable groovyPageLocator(CachingGrailsConventionGroovyPageLocator) { bean -> bean.lazyInit = true if (customResourceLoader) { @@ -187,7 +195,7 @@ class GroovyPagesGrailsPlugin extends Plugin { } grailsResourceLocator(CachingGroovyPageStaticResourceLocator) { bean -> - bean.parent = "abstractGrailsResourceLocator" + bean.parent = 'abstractGrailsResourceLocator' if (enableReload) { cacheTimeout = gspCacheTimeout } @@ -195,7 +203,7 @@ class GroovyPagesGrailsPlugin extends Plugin { // Setup the main templateEngine used to render GSPs groovyPagesTemplateEngine(GroovyPagesTemplateEngine) { - classLoader = ref("classLoader") + classLoader = ref('classLoader') groovyPageLocator = groovyPageLocator if (enableReload) { reloadEnabled = enableReload @@ -209,7 +217,7 @@ class GroovyPagesGrailsPlugin extends Plugin { spring.addAlias('groovyTemplateEngine', 'groovyPagesTemplateEngine') - groovyPageRenderer(PageRenderer, ref("groovyPagesTemplateEngine")) { bean -> + groovyPageRenderer(PageRenderer, ref('groovyPagesTemplateEngine')) { bean -> bean.lazyInit = true groovyPageLocator = groovyPageLocator } @@ -227,7 +235,7 @@ class GroovyPagesGrailsPlugin extends Plugin { } boolean jstlPresent = ClassUtils.isPresent( - "jakarta.servlet.jsp.jstl.core.Config", InternalResourceViewResolver.class.getClassLoader()) + 'jakarta.servlet.jsp.jstl.core.Config', InternalResourceViewResolver.class.classLoader) abstractViewResolver { prefix = GrailsApplicationAttributes.PATH_TO_VIEWS @@ -242,7 +250,7 @@ class GroovyPagesGrailsPlugin extends Plugin { // Configure a Spring MVC view resolver jspViewResolver(GroovyPageViewResolver) { bean -> bean.lazyInit = true - bean.parent = "abstractViewResolver" + bean.parent = 'abstractViewResolver' } // Now go through tag libraries and configure them in Spring too. With AOP proxies and so on @@ -262,9 +270,9 @@ class GroovyPagesGrailsPlugin extends Plugin { errorsViewStackTracePrinter(ErrorsViewStackTracePrinter, ref('grailsResourceLocator')) filteringCodecsByContentTypeSettings(FilteringCodecsByContentTypeSettings, application) - groovyPagesServlet(ServletRegistrationBean, new GroovyPagesServlet(), "*.gsp") { - if (Environment.isDevelopmentMode()) { - initParameters = [showSource: "1"] + groovyPagesServlet(ServletRegistrationBean, new GroovyPagesServlet(), '*.gsp') { + if (Environment.developmentMode) { + initParameters = [showSource: '1'] } } @@ -273,7 +281,7 @@ class GroovyPagesGrailsPlugin extends Plugin { } protected boolean isDevelopmentMode() { - Metadata.getCurrent().isDevelopmentEnvironmentAvailable() + Metadata.current.developmentEnvironmentAvailable } static String transformToValidLocation(String location) { @@ -298,7 +306,7 @@ class GroovyPagesGrailsPlugin extends Plugin { } } - // The tag library lookup class caches "tag -> taglib class" + // The tag library lookup class caches 'tag -> taglib class' // so we need to update it now. def lookup = applicationContext.getBean('gspTagLibraryLookup', TagLibraryLookup) lookup.registerTagLib(taglibClass) diff --git a/grails-gsp/plugin/src/test/groovy/org/grails/web/mapping/RestfulReverseUrlRenderingTests.groovy b/grails-gsp/plugin/src/test/groovy/org/grails/web/mapping/RestfulReverseUrlRenderingTests.groovy index 918b4a2b666..a2071988f78 100644 --- a/grails-gsp/plugin/src/test/groovy/org/grails/web/mapping/RestfulReverseUrlRenderingTests.groovy +++ b/grails-gsp/plugin/src/test/groovy/org/grails/web/mapping/RestfulReverseUrlRenderingTests.groovy @@ -62,11 +62,11 @@ class RestfulReverseUrlRenderingTests extends Specification implements UrlMappin @Artefact('UrlMappings') class RestfulReverseUrlMappings { static mappings = { - "/car" (controller: "restfulCar", action: [GET: "create", POST: "save"]) + '/car' (controller: 'restfulCar', action: [GET: 'create', POST: 'save']) } } -@Artefact("Controller") +@Artefact('Controller') class RestfulCarController { def create = {} def save = {} diff --git a/grails-gsp/plugin/src/test/groovy/org/grails/web/pages/ParseSpec.groovy b/grails-gsp/plugin/src/test/groovy/org/grails/web/pages/ParseSpec.groovy index fa715af1d59..3e5e73a55f0 100644 --- a/grails-gsp/plugin/src/test/groovy/org/grails/web/pages/ParseSpec.groovy +++ b/grails-gsp/plugin/src/test/groovy/org/grails/web/pages/ParseSpec.groovy @@ -61,47 +61,47 @@ public static final String TAGLIB_CODEC = 'none' } """ - void "parse"() { + void 'parse'() { given: String expected = makeImports() + - "\n" + - "class myTest1 extends org.grails.gsp.GroovyPage {\n" + - "public String getGroovyPageFileName() { \"myTest1\" }\n" + - "public Object run() {\n" + - "Writer out = getOut()\n" + - "Writer expressionOut = getExpressionOut()\n" + - "printHtmlPart(0)\n" + - "}\n" + GSP_FOOTER + '\n' + + 'class myTest1 extends org.grails.gsp.GroovyPage {\n' + + 'public String getGroovyPageFileName() { "myTest1" }\n' + + 'public Object run() {\n' + + 'Writer out = getOut()\n' + + 'Writer expressionOut = getExpressionOut()\n' + + 'printHtmlPart(0)\n' + + '}\n' + GSP_FOOTER when: - ParsedResult result = parseCode("myTest1", "

hi
") + def result = parseCode('myTest1', '
hi
') then: trimAndRemoveCR(expected) == trimAndRemoveCR(result.generatedGsp) - "
hi
" == result.htmlParts[0] + '
hi
' == result.htmlParts[0] } - void "parse with unclosed square brackets"() { + void 'parse with unclosed square brackets'() { given: String expected = makeImports() + - "\n" + - "class myTest2 extends org.grails.gsp.GroovyPage {\n" + - "public String getGroovyPageFileName() { \"myTest2\" }\n" + - "public Object run() {\n" + - "Writer out = getOut()\n" + + '\n' + + 'class myTest2 extends org.grails.gsp.GroovyPage {\n' + + 'public String getGroovyPageFileName() { "myTest2" }\n' + + 'public Object run() {\n' + + 'Writer out = getOut()\n' + "Writer expressionOut = getExpressionOut()\n" + "invokeTag('message','g',1,['code':evaluate('\"testing [\"', 1, it) { return \"testing [\" }],-1)\n" + - "}\n" + GSP_FOOTER + '}\n' + GSP_FOOTER when: - String output = parseCode("myTest2", "").generatedGsp; + String output = parseCode('myTest2', '').generatedGsp; then: trimAndRemoveCR(expected) == trimAndRemoveCR(output) } - void "parse without unclosed gstring throws exception"() { + void 'parse without unclosed gstring throws exception'() { when: parseCode('myTest3', '') @@ -110,30 +110,30 @@ public static final String TAGLIB_CODEC = 'none' e.message == '[myTest3:1] Unclosed GSP expression' } - void "parse with utf8"() { + void 'parse with utf8'() { given: // This is some unicode Chinese (who knows what it says!) - String src = "Chinese text: \u3421\u3437\u343f\u3443\u3410\u3405\u38b3\u389a\u395e\u3947\u3adb\u3b5a\u3b67" + String src = 'Chinese text: \u3421\u3437\u343f\u3443\u3410\u3405\u38b3\u389a\u395e\u3947\u3adb\u3b5a\u3b67' and: String expected = makeImports() + - "\n" + - "class myTest4 extends org.grails.gsp.GroovyPage {\n" + - "public String getGroovyPageFileName() { \"myTest4\" }\n" + - "public Object run() {\n" + - "Writer out = getOut()\n" + - "Writer expressionOut = getExpressionOut()\n" + - "printHtmlPart(0)\n" + - "}\n" + GSP_FOOTER + '\n' + + 'class myTest4 extends org.grails.gsp.GroovyPage {\n' + + 'public String getGroovyPageFileName() { "myTest4" }\n' + + 'public Object run() {\n' + + 'Writer out = getOut()\n' + + 'Writer expressionOut = getExpressionOut()\n' + + 'printHtmlPart(0)\n' + + '}\n' + GSP_FOOTER // Sanity check the string loaded OK as unicode - it won't look right if you output it, default stdout is not UTF-8 // on many OSes Assertions.assertEquals(src.indexOf('?'), -1) - ConfigObject config = new ConfigSlurper().parse("grails.views.gsp.encoding = \"UTF-8\"") + def config =new ConfigSlurper().parse('grails.views.gsp.encoding = "UTF-8"') buildMockRequest(config) when: - ParsedResult output = parseCode("myTest4", src) + def output = parseCode('myTest4', src) then: trimAndRemoveCR(expected) == trimAndRemoveCR(output.generatedGsp) @@ -143,7 +143,7 @@ public static final String TAGLIB_CODEC = 'none' RequestContextHolder.resetRequestAttributes() } - void "parse with local encoding"() { + void 'parse with local encoding'() { given: String src = 'This is just plain ASCII to make sure test works on all platforms' // Sanity check the string loaded OK as unicode - it won't look right if you output it, @@ -152,51 +152,51 @@ public static final String TAGLIB_CODEC = 'none' and: String expected = makeImports() + - "\n" + - "class myTest5 extends org.grails.gsp.GroovyPage {\n" + - "public String getGroovyPageFileName() { \"myTest5\" }\n" + - "public Object run() {\n" + - "Writer out = getOut()\n" + - "Writer expressionOut = getExpressionOut()\n" + - "printHtmlPart(0)\n" + - "}\n" + GSP_FOOTER + '\n' + + 'class myTest5 extends org.grails.gsp.GroovyPage {\n' + + 'public String getGroovyPageFileName() { "myTest5" }\n' + + 'public Object run() {\n' + + 'Writer out = getOut()\n' + + 'Writer expressionOut = getExpressionOut()\n' + + 'printHtmlPart(0)\n' + + '}\n' + GSP_FOOTER when: - ParsedResult output = parseCode("myTest5", src) + def output = parseCode('myTest5', src) then: trimAndRemoveCR(expected) == trimAndRemoveCR(output.generatedGsp) src == output.htmlParts[0] } - void "parse gtags with namespace"() { + void 'parse gtags with namespace'() { given: - String output = parseCode("myTest6", - "\n" + - " \n" + - "").generatedGsp; - System.out.println("output = " + output); + String output = parseCode('myTest6', + '\n' + + ' \n' + + '').generatedGsp; + System.out.println('output = ' + output); expect: "should have call to tag with 'tt' namespace" output.indexOf("invokeTag('form','tt',2,[:],-1)") > -1 } - void "parse with whitespace not eaten"() { + void 'parse with whitespace not eaten'() { given: String expected = makeImports() + - "\n" + - "class myTest7 extends org.grails.gsp.GroovyPage {\n" + - "public String getGroovyPageFileName() { \"myTest7\" }\n" + - "public Object run() {\n" + - "Writer out = getOut()\n" + - "Writer expressionOut = getExpressionOut()\n" + - "printHtmlPart(0)\n" + + '\n' + + 'class myTest7 extends org.grails.gsp.GroovyPage {\n' + + 'public String getGroovyPageFileName() { "myTest7" }\n' + + 'public Object run() {\n' + + 'Writer out = getOut()\n' + + 'Writer expressionOut = getExpressionOut()\n' + + 'printHtmlPart(0)\n' + GroovyPage.EXPRESSION_OUT_STATEMENT + ".print(evaluate('uri', 3, it) { return uri })\n" + - "printHtmlPart(1)\n" + - "}\n" + GSP_FOOTER; + 'printHtmlPart(1)\n' + + '}\n' + GSP_FOOTER; when: - ParsedResult output = parseCode('myTest7', + def output = parseCode('myTest7', 'Please click the link below to confirm your email address:\n' + '\n' + '${uri}\n' + @@ -205,73 +205,73 @@ public static final String TAGLIB_CODEC = 'none' 'Thanks') then: - expected.replaceAll("[\r\n]", "") == output.generatedGsp.replaceAll("[\r\n]", "") - "Please click the link below to confirm your email address:\n\n" == output.htmlParts[0] - "\n\n\nThanks" == output.htmlParts[1] + expected.replaceAll('[\r\n]', '') == output.generatedGsp.replaceAll('[\r\n]', '') + 'Please click the link below to confirm your email address:\n\n' == output.htmlParts[0] + '\n\n\nThanks' == output.htmlParts[1] } @PendingFeature - void 'body with gstring attribute'() { + void 'body with gstring attribute'() { given: String expected = makeImports() + - "\n" + - "class GRAILS5598 extends org.grails.gsp.GroovyPage {\n" + - "public String getGroovyPageFileName() { \"GRAILS5598\" }\n" + - "public Object run() {\n" + - "Writer out = getOut()\n" + - "Writer expressionOut = getExpressionOut()\n" + - "createClosureForHtmlPart(0, 1)\n" + + '\n' + + 'class GRAILS5598 extends org.grails.gsp.GroovyPage {\n' + + 'public String getGroovyPageFileName() { \'GRAILS5598\' }\n' + + 'public Object run() {\n' + + 'Writer out = getOut()\n' + + 'Writer expressionOut = getExpressionOut()\n' + + 'createClosureForHtmlPart(0, 1)\n' + "invokeTag('captureBody','grailsLayout',1,['class':evaluate('\"\${page.name} \${page.group.name.toLowerCase()}\"', 1, it) { return \"\${page.name} \${page.group.name.toLowerCase()}\" }],1)\n" + - "}\n" + GSP_FOOTER + '}\n' + GSP_FOOTER when: - ParsedResult result = parseCode("GRAILS5598", 'text') + def result = parseCode('GRAILS5598', 'text') then: trimAndRemoveCR(expected) == trimAndRemoveCR(result.generatedGsp) - "text" == result.htmlParts[0] + 'text' == result.htmlParts[0] } - void "bypass grails layout preprocess"() { + void 'bypass grails layout preprocess'() { given: String expected = makeImports() + - "\n" + - "class GRAILS_LAYOUT_PREPROCESS_TEST extends org.grails.gsp.GroovyPage {\n" + - "public String getGroovyPageFileName() { \"GRAILS_LAYOUT_PREPROCESS_TEST\" }\n" + - "public Object run() {\n" + - "Writer out = getOut()\n" + - "Writer expressionOut = getExpressionOut()\n" + - "printHtmlPart(0)\n" + - "}\n" + GSP_FOOTER + '\n' + + 'class GRAILS_LAYOUT_PREPROCESS_TEST extends org.grails.gsp.GroovyPage {\n' + + 'public String getGroovyPageFileName() { "GRAILS_LAYOUT_PREPROCESS_TEST" }\n' + + 'public Object run() {\n' + + 'Writer out = getOut()\n' + + 'Writer expressionOut = getExpressionOut()\n' + + 'printHtmlPart(0)\n' + + '}\n' + GSP_FOOTER when: - ParsedResult result = parseCode("GRAILS_LAYOUT_PREPROCESS_TEST", "<%@page grailsLayoutPreprocess=\"false\"%>\ntext") + def result = parseCode('GRAILS_LAYOUT_PREPROCESS_TEST', '<%@page grailsLayoutPreprocess="false"%>\ntext') then: trimAndRemoveCR(expected) == trimAndRemoveCR(result.generatedGsp) - "\ntext" == result.htmlParts[0] + '\ntext' == result.htmlParts[0] } @PendingFeature - void "meta with gstring attribute"() { + void 'meta with gstring attribute'() { given: String expected = makeImports() + - "\n" + - "class GRAILS5605 extends org.grails.gsp.GroovyPage {\n" + - "public String getGroovyPageFileName() { \"GRAILS5605\" }\n" + - "public Object run() {\n" + - "Writer out = getOut()\n" + - "Writer expressionOut = getExpressionOut()\n" + - "printHtmlPart(0)\n" + - "createTagBody(1, {->\n" + + '\n' + + 'class GRAILS5605 extends org.grails.gsp.GroovyPage {\n' + + 'public String getGroovyPageFileName() { "GRAILS5605" }\n' + + 'public Object run() {\n' + + 'Writer out = getOut()\n' + + 'Writer expressionOut = getExpressionOut()\n' + + 'printHtmlPart(0)\n' + + 'createTagBody(1, {->\n' + "invokeTag('captureMeta','grailsLayout',1,['gsp_sm_xmlClosingForEmptyTag':evaluate('\"/\"', 1, it) { return \"/\" },'name':evaluate('\"SomeName\"', 1, it) { return \"SomeName\" },'content':evaluate('\"\${grailsApplication.config.myFirstConfig}/something/\${someVar}\"', 1, it) { return \"\${grailsApplication.config.myFirstConfig}/something/\${someVar}\" }],-1)\n" + - "})\n" + + '})\n' + "invokeTag('captureHead','grailsLayout',1,[:],1)\n" + - "printHtmlPart(1)\n" + - "}\n" + GSP_FOOTER + 'printHtmlPart(1)\n' + + '}\n' + GSP_FOOTER when: - ParsedResult result = parseCode("GRAILS5605", ""); + def result = parseCode('GRAILS5605', ""); then: trimAndRemoveCR(expected) == trimAndRemoveCR(result.generatedGsp) @@ -279,16 +279,16 @@ public static final String TAGLIB_CODEC = 'none' static ParsedResult parseCode(String uri, String gsp) throws IOException { // Simulate what the parser does so we get it in the encoding expected - Object enc = GrailsWebUtil.currentConfiguration().get("grails.views.gsp.encoding") + Object enc = GrailsWebUtil.currentConfiguration().get('grails.views.gsp.encoding') if ((enc == null) || (enc.toString().trim().length() == 0)) { - enc = System.getProperty("file.encoding", "us-ascii") + enc = System.getProperty('file.encoding', 'us-ascii') } InputStream gspIn = new ByteArrayInputStream(gsp.getBytes(enc.toString())) - GroovyPageParser parse = new GroovyPageParser(uri, uri, uri, gspIn, enc.toString(), "HTML", null) + GroovyPageParser parse = new GroovyPageParser(uri, uri, uri, gspIn, enc.toString(), 'HTML', null) InputStream inStream = parse.parse() - ParsedResult result = new ParsedResult() + def result = new ParsedResult() result.parser = parse result.generatedGsp = IOGroovyMethods.getText(inStream, enc.toString()) result.htmlParts = parse.getHtmlPartsArray() @@ -298,7 +298,7 @@ public static final String TAGLIB_CODEC = 'none' static String makeImports() { StringBuilder result = new StringBuilder() for (int i = 0; i < GroovyPageParser.DEFAULT_IMPORTS.length; i++) { - result.append("import ").append(GroovyPageParser.DEFAULT_IMPORTS[i]).append("\n") + result.append('import ').append(GroovyPageParser.DEFAULT_IMPORTS[i]).append('\n') } return result.toString() } diff --git a/grails-test-examples/app1/grails-app/controllers/functionaltests/ForwardingController.groovy b/grails-test-examples/app1/grails-app/controllers/functionaltests/ForwardingController.groovy index eba12783d40..6e9842d363d 100644 --- a/grails-test-examples/app1/grails-app/controllers/functionaltests/ForwardingController.groovy +++ b/grails-test-examples/app1/grails-app/controllers/functionaltests/ForwardingController.groovy @@ -24,15 +24,15 @@ import org.springframework.http.HttpStatus class ForwardingController { def one() { - forward action:"next" + forward action: 'next' } def two() { - forward controller:"forwarding", action:"next" + forward controller: 'forwarding', action: 'next' } def three() { - forward controller:"forwarding", action:"next", params:[param1:'test'] + forward controller: 'forwarding', action: 'next', params: [param1: 'test'] } def next() { @@ -44,7 +44,7 @@ class ForwardingController { } def forwardWithRender(String anArgument) { - if(!anArgument) { + if (!anArgument) { forward action: 'renderedView' return } diff --git a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/AsyncFunctionalSpec.groovy b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/AsyncFunctionalSpec.groovy index 51ff23308cb..4bd988bf67e 100644 --- a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/AsyncFunctionalSpec.groovy +++ b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/AsyncFunctionalSpec.groovy @@ -35,10 +35,10 @@ class AsyncFunctionalSpec extends ContainerGebSpec { @PendingFeature(reason = 'pageSource == ') void "Test async response rendering works"() { when:"When an async response is rendered" - go '/async/test' + go('/async/test') then:"The rendered page is correct" - driver.pageSource.contains 'Hello' + pageSource.contains 'Hello' } } diff --git a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/BookFunctionalSpec.groovy b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/BookFunctionalSpec.groovy index d532f3be1bf..24ff37e1df0 100644 --- a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/BookFunctionalSpec.groovy +++ b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/BookFunctionalSpec.groovy @@ -23,44 +23,44 @@ import grails.plugin.geb.ContainerGebSpec import grails.testing.mixin.integration.Integration import spock.lang.Issue -@Integration(applicationClass=functionaltests.Application) +@Integration(applicationClass = functionaltests.Application) class BookFunctionalSpec extends ContainerGebSpec { void "Test that when the /viewBooks URL is hit it redirects to the book list"() { - when:"We go to the book URI" - go "/book/index" + when: "We go to the book URI" + go "/book/index" - then:"Then thew show book view is rendered" - title == "Book List" - } + then: "Then thew show book view is rendered" + title == "Book List" + } - void "Test that a book was created in the Bootstrap class"() { - when:"We go to the book URI" - go '/book/show/1' + void "Test that a book was created in the Bootstrap class"() { + when: "We go to the book URI" + go('/book/show/1') - then:"Then thew show book view is rendered" - title == "Show Book" - } + then: "Then thew show book view is rendered" + title == "Show Book" + } - void "Test that switching language results in correct encodings"() { - when:"the show page is rendered in german" - go "/book/show/1?lang=de" - println driver.pageSource - then:"The language is correct" - $('a', class:'create').text() == 'Book anlegen' - $('input', class:'delete').@value == 'Löschen' - } + void "Test that switching language results in correct encodings"() { + when: "the show page is rendered in german" + go "/book/show/1?lang=de" + println pageSource + then: "The language is correct" + $('a', class: 'create').text() == 'Book anlegen' + $('input', class: 'delete').@value == 'Löschen' + } @Issue('10965') void "When creating a book the params are not on the url"() { when: 'creating a book' - go "/book/create" - $('#title').value('The Stand') - $('#create').click() + go "/book/create" + $('#title').value('The Stand') + $('#create').click() then: - title == 'Show Book' - !currentUrl.contains('title') - !currentUrl.contains('create') + title == 'Show Book' + !currentUrl.contains('title') + !currentUrl.contains('create') } } diff --git a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/ConfigTestControllerSpec.groovy b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/ConfigTestControllerSpec.groovy index d95385beeed..1f6982ae815 100644 --- a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/ConfigTestControllerSpec.groovy +++ b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/ConfigTestControllerSpec.groovy @@ -29,7 +29,7 @@ class ConfigTestControllerSpec extends ContainerGebSpec { void "Test that configuration properties are correctly read"() { when:"When evaluting configuration values" - go '/configTest/index' + go('/configTest/index') then:"The values are correct" $('div', 0).text() == 'test' diff --git a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/ControllerFromPluginSpec.groovy b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/ControllerFromPluginSpec.groovy index 0416bef0ed8..2b8ccfd084a 100644 --- a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/ControllerFromPluginSpec.groovy +++ b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/ControllerFromPluginSpec.groovy @@ -27,7 +27,7 @@ class ControllerFromPluginSpec extends ContainerGebSpec { void 'test invoking a controller provided by a plugin'() { when: - go '/alpha' + go('/alpha') then: $('h2',0).text() == 'This is views/alpha/index.gsp' diff --git a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/ControllerIncludesSpec.groovy b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/ControllerIncludesSpec.groovy index eee87a4a974..70c465e1cb0 100644 --- a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/ControllerIncludesSpec.groovy +++ b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/ControllerIncludesSpec.groovy @@ -29,51 +29,51 @@ import grails.testing.mixin.integration.Integration class ControllerIncludesSpec extends ContainerGebSpec { void "Test includes that render a view work when called from a controller action"() { - when:"When an include that renders a view is used inside a controller action" - go '/includes/includeFromControllerActionRenderingView' + when: "When an include that renders a view is used inside a controller action" + go('/includes/includeFromControllerActionRenderingView') - then:"Then the include worked" - driver.pageSource.contains 'Model is bar' + then: "Then the include worked" + pageSource.contains 'Model is bar' } void "Test includes that render text work when called from a controller action"() { - when:"When an include that renders text is used inside a controller action" - go '/includes/includeFromControllerActionRenderingText' + when: "When an include that renders text is used inside a controller action" + go('/includes/includeFromControllerActionRenderingText') - then:"Then the include worked" - driver.pageSource.contains 'Test' + then: "Then the include worked" + pageSource.contains 'Test' } void "Test includes that render a view work when called from another view"() { - when:"When an include that is executed inside another view is used" - go '/includes/includeFromViewRenderingView' + when: "When an include that is executed inside another view is used" + go('/includes/includeFromViewRenderingView') - then:"Then the include worked" - driver.pageSource.trim().contains 'Include: \nModel is bar' + then: "Then the include worked" + pageSource.trim().contains 'Include: \nModel is bar' } void "Test includes that render text work when called from another view"() { - when:"When an include that renders text is used inside a view" - go '/includes/includeFromViewRenderingText' + when: "When an include that renders text is used inside a view" + go('/includes/includeFromViewRenderingText') - then:"Then the include worked" - driver.pageSource.contains 'Include: Test' + then: "Then the include worked" + pageSource.contains 'Include: Test' } void "Test includes that render a view work when called from a template"() { - when:"When an include that is executed inside another view is used" - go '/includes/includeFromTemplateRenderingView' + when: "When an include that is executed inside another view is used" + go('/includes/includeFromTemplateRenderingView') - then:"Then the include worked" - driver.pageSource.trim().contains 'Include: \nModel is bar' + then: "Then the include worked" + pageSource.trim().contains 'Include: \nModel is bar' } void "Test includes that render text work when called from a template"() { - when:"When an include that renders text is used inside a view" - go '/includes/includeFromTemplateRenderingText' + when: "When an include that renders text is used inside a view" + go('/includes/includeFromTemplateRenderingText') - then:"Then the include worked" - driver.pageSource.contains 'Include: Test' + then: "Then the include worked" + pageSource.contains 'Include: Test' } } diff --git a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/ErrorsFunctionalSpec.groovy b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/ErrorsFunctionalSpec.groovy index 39d70127092..8912132a350 100644 --- a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/ErrorsFunctionalSpec.groovy +++ b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/ErrorsFunctionalSpec.groovy @@ -32,36 +32,36 @@ import spock.lang.PendingFeature class ErrorsFunctionalSpec extends ContainerGebSpec { void "Test exception handling methods for internal controller exceptions"() { - when:"An action that throws a custom error that is handled by a 500 mapping in UrlMappings.groovy" - go '/errors/throwCustomError' + when: "An action that throws a custom error that is handled by a 500 mapping in UrlMappings.groovy" + go('/errors/throwCustomError') - then:"The correct action is executed" - driver.pageSource.contains 'Message = Something bad' + then: "The correct action is executed" + pageSource.contains 'Message = Something bad' } void "Test 500 mappings for custom exceptions"() { - when:"An action that throws a custom error that is handled by a 500 mapping in UrlMappings.groovy" - go '/demo/throwCustomError' + when: "An action that throws a custom error that is handled by a 500 mapping in UrlMappings.groovy" + go('/demo/throwCustomError') - then:"The correct action is executed" - driver.pageSource.contains 'Message = Something bad' + then: "The correct action is executed" + pageSource.contains 'Message = Something bad' } void "Test default 500 mapping"() { - when:"An excetion that throws a general error handled by the default 500 mapping in UrlMapings.groovy" - go '/errors/throwGeneralError' + when: "An excetion that throws a general error handled by the default 500 mapping in UrlMapings.groovy" + go('/errors/throwGeneralError') - println driver.pageSource + println pageSource - then:"The title is correct" - $('ul', class:'errors').text() == 'An error has occurred' + then: "The title is correct" + $('ul', class: 'errors').text() == 'An error has occurred' } void "Test 404 mapping to controller"() { - when:"When an action returns a 404" - go '/errors/notFoundTest' - then:"Make sure the global 404 handler is triggered" - driver.pageSource.contains 'Page Not Found' + when: "When an action returns a 404" + go('/errors/notFoundTest') + then: "Make sure the global 404 handler is triggered" + pageSource.contains 'Page Not Found' } @Issue("https://github.com/apache/grails-core/issues/9548") @@ -70,7 +70,7 @@ class ErrorsFunctionalSpec extends ContainerGebSpec { !System.properties[ErrorsControllerInterceptor.PROPERTY] when: "An action that throws an exception is requested" - go '/errors/throwException' + go('/errors/throwException') then: System.properties[ErrorsControllerInterceptor.PROPERTY] == 'Oops!' diff --git a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/ForwardingSpec.groovy b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/ForwardingSpec.groovy index fe112994bb6..e2299985f94 100644 --- a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/ForwardingSpec.groovy +++ b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/ForwardingSpec.groovy @@ -29,81 +29,81 @@ import spock.lang.PendingFeature @Integration(applicationClass = Application) @Rollback class ForwardingSpec extends ContainerGebSpec { - void "params extracted from the URL path by a custom UrlMapping are forwarded"() { + void 'params extracted from the URL path by a custom UrlMapping are forwarded'() { when: 'a url mapping such as /forward/$param1 is matched' - go '/forward/test' + go('/forward/test') then: 'param1 is passed to the forwarded action' $().text() == 'Forward Destination. Params: test' } - void "verifies params from the original url are passed to the forwarded action but not duplicated"() { + void 'verifies params from the original url are passed to the forwarded action but not duplicated'() { when: - go '/forwarding/two?param1=test' + go('/forwarding/two?param1=test') then: $().text() == 'Forward Destination. Params: test' } - void "Test forward to same controller"() { - when:"A forward is issued to an action in the same controller" - go '/forwarding/one' + void 'Test forward to same controller'() { + when: 'A forward is issued to an action in the same controller' + go('/forwarding/one') - then:"The forward works correctly" - $().text() == 'Forward Destination. Params:' + then: 'The forward works correctly' + $().text() == 'Forward Destination. Params:' } - void "Test forward to named controller"() { - when:"A forward is issued to an action in the same controller" - go '/forwarding/two' + void 'Test forward to named controller'() { + when: 'A forward is issued to an action in the same controller' + go('/forwarding/two') - then:"The forward works correctly" - $().text() == 'Forward Destination. Params:' + then: 'The forward works correctly' + $().text() == 'Forward Destination. Params:' } - void "Test forward with parameters"() { - when:"A forward is issued to an action with parameters" - go '/forwarding/three' + void 'Test forward with parameters'() { + when: 'A forward is issued to an action with parameters' + go('/forwarding/three') - then:"The forward works correctly" - $().text() == 'Forward Destination. Params: test' + then: 'The forward works correctly' + $().text() == 'Forward Destination. Params: test' } void 'Test forwarding to an action which returns a Map'() { when: - go '/forwarding/forwardToList' + go('/forwarding/forwardToList') then: - $('li', text: 'Jeff') - $('li', text: 'Zack') - $('li', text: 'Jake') - $('li', text: 'Betsy') + $('li', text: 'Jeff') + $('li', text: 'Zack') + $('li', text: 'Jake') + $('li', text: 'Betsy') } - void "Test forward after populating flash"() { + void 'Test forward after populating flash'() { when: 'an acton populates flash and then forwards' - go '/forwarding/putMessageInFlash' + go('/forwarding/putMessageInFlash') then: 'the flash data is available in the action that was forwarded to' $('div', id: 'message').text() == 'flash.message is [some message]' when: 'a subsequent request is initiated' - go '/forwarding/displayFlash' + go('/forwarding/displayFlash') then: 'the flash data is still available' $('div', id: 'message').text() == 'flash.message is [some message]' when: 'any further request is initiated' - go '/forwarding/displayFlash' + go('/forwarding/displayFlash') then: 'the flash message has been cleared' $('div', id: 'message').text() == 'flash.message is []' } @PendingFeature - void "forwarding to a view"() { - when: "A forward is issued to a view" - go '/forwarding/forwardWithRender' + void 'forwarding to a view'() { + when: 'A forward is issued to a view' + go('/forwarding/forwardWithRender') - then: "The view is rendered correctly" + then: 'The view is rendered correctly' $('p', id: 'message').text() == 'Hello from a forwarded view' } } diff --git a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/HomeSpec.groovy b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/HomeSpec.groovy index 27886bc970e..fe034499aa6 100644 --- a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/HomeSpec.groovy +++ b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/HomeSpec.groovy @@ -28,24 +28,24 @@ import spock.lang.PendingFeature class HomeSpec extends ContainerGebSpec { void "Test the home page renders correctly"() { - when:"The home page is visited" - go '/' - if(title != "Welcome to Grails") { - println driver.pageSource - } - then:"The title is correct" - title == "Welcome to Grails" - $('li.controller', text: 'demo.AlphaController') - $('li.controller', text: 'functionaltests.BookController') - $('li.controller', text: 'functionaltests.ErrorsController') - $('li.controller', text: 'functionaltests.ForwardingController') - $('li.controller', text: 'functionaltests.InspectConfigController') - $('li.controller', text: 'functionaltests.MiscController') - $('li.controller', text: 'functionaltests.UploadController') - $('li.controller', text: 'grails.functionaltests.InGrailsPackageController') - - // SimpleController should not become a controller as it is not in a grails-app/controllers dir - !$('li.controller', text: 'functionaltests.SimpleController') + when: "The home page is visited" + go('/') + if (title != "Welcome to Grails") { + println pageSource + } + then: "The title is correct" + title == "Welcome to Grails" + $('li.controller', text: 'demo.AlphaController') + $('li.controller', text: 'functionaltests.BookController') + $('li.controller', text: 'functionaltests.ErrorsController') + $('li.controller', text: 'functionaltests.ForwardingController') + $('li.controller', text: 'functionaltests.InspectConfigController') + $('li.controller', text: 'functionaltests.MiscController') + $('li.controller', text: 'functionaltests.UploadController') + $('li.controller', text: 'grails.functionaltests.InGrailsPackageController') + + // SimpleController should not become a controller as it is not in a grails-app/controllers dir + !$('li.controller', text: 'functionaltests.SimpleController') } } diff --git a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/InspectConfigControllerSpec.groovy b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/InspectConfigControllerSpec.groovy index e460ed69c16..68e18f260c7 100644 --- a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/InspectConfigControllerSpec.groovy +++ b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/InspectConfigControllerSpec.groovy @@ -29,7 +29,7 @@ class InspectConfigControllerSpec extends ContainerGebSpec { @Issue('GRAILS-11951') void "test config properties from plugins"() { when: - go '/inspectConfig/showPropertyValues' + go('/inspectConfig/showPropertyValues') then: $('div', 0).text() == 'Prop One Defined By LoadFirst Plugin' diff --git a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/InterceptorDependencyInjectionSpec.groovy b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/InterceptorDependencyInjectionSpec.groovy index 0588a584f9c..ceb355923dd 100644 --- a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/InterceptorDependencyInjectionSpec.groovy +++ b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/InterceptorDependencyInjectionSpec.groovy @@ -30,7 +30,7 @@ class InterceptorDependencyInjectionSpec extends ContainerGebSpec { void "Test that interceptors are subjected to autowire by name"() { when: - go '/misc/actionWhichReturnsMap' + go('/misc/actionWhichReturnsMap') then: $('h2', text: 'The Magic Number Is 42') diff --git a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/InterceptorFunctionalSpec.groovy b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/InterceptorFunctionalSpec.groovy index adaf191fca9..982b44ebaa4 100644 --- a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/InterceptorFunctionalSpec.groovy +++ b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/InterceptorFunctionalSpec.groovy @@ -30,7 +30,7 @@ class InterceptorFunctionalSpec extends ContainerGebSpec { @Issue('apache/grails-core#9434') void "Test that an interceptor exception is handled correctly"() { when: - go '/errors/throwErrorInInterceptor' + go('/errors/throwErrorInInterceptor') then: $().text() == 'Message = Interceptor threw error' @@ -39,7 +39,7 @@ class InterceptorFunctionalSpec extends ContainerGebSpec { @Issue('apache/grails-core#9183') void "Test that an after interceptor can render text and return false to disable view rendering"() { when: - go '/demo/show' + go('/demo/show') then: $().text() == 'the after interceptor rendered this' @@ -47,7 +47,7 @@ class InterceptorFunctionalSpec extends ContainerGebSpec { void 'Test that after interceptor can render a model and view'() { when: - go '/demo/show?interceptorRendersView=true' + go('/demo/show?interceptorRendersView=true') then: $().text() == 'Name: JSB' @@ -55,7 +55,7 @@ class InterceptorFunctionalSpec extends ContainerGebSpec { void 'Test that before interceptor can render a model and view'() { when: - go '/demo/another' + go('/demo/another') then: $().text() == 'Name: JSB' @@ -63,7 +63,7 @@ class InterceptorFunctionalSpec extends ContainerGebSpec { void 'Test that after interceptor can render text'() { when: - go '/demo/show?interceptorRendersText=true' + go('/demo/show?interceptorRendersText=true') then: $().text() == 'text rendered by interceptor' @@ -72,7 +72,7 @@ class InterceptorFunctionalSpec extends ContainerGebSpec { @Issue('apache/grails-core#9194') void 'Test that after interceptor can redirect'() { when: - go '/demo/show?interceptorRedirects=true' + go('/demo/show?interceptorRedirects=true') then: $().text() == 'Hi There! Special Action: redirect' @@ -82,7 +82,7 @@ class InterceptorFunctionalSpec extends ContainerGebSpec { @Issue('apache/grails-core#9194') void 'Test that after interceptor can forward'() { when: - go '/demo/show?interceptorForwards=true' + go('/demo/show?interceptorForwards=true') then: $().text() == 'Hi There! Special Action: forward' @@ -91,7 +91,7 @@ class InterceptorFunctionalSpec extends ContainerGebSpec { @Issue('apache/grails-core#9194') void 'Test that after interceptor can chain'() { when: - go '/demo/show?interceptorChains=true' + go('/demo/show?interceptorChains=true') then: $().text() == 'Hi There! Special Action: chain' diff --git a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/LoadAfterSpec.groovy b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/LoadAfterSpec.groovy index db386cc2696..2367d0426c2 100644 --- a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/LoadAfterSpec.groovy +++ b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/LoadAfterSpec.groovy @@ -28,7 +28,7 @@ class LoadAfterSpec extends ContainerGebSpec { void "Test override one plugin view from another plugin"() { when: - go '/login/auth' + go('/login/auth') then: title == "My Plugin Login Auth" diff --git a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/MiscFunctionalSpec.groovy b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/MiscFunctionalSpec.groovy index a771e47aea9..104ce87fbfc 100644 --- a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/MiscFunctionalSpec.groovy +++ b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/MiscFunctionalSpec.groovy @@ -29,17 +29,17 @@ class MiscFunctionalSpec extends ContainerGebSpec { @Issue('9133') void "Test that bean override configuration works"() { when: - go '/misc/beanPropertyOverrideTest' + go('/misc/beanPropertyOverrideTest') then: - driver.pageSource.contains 'Brian' + pageSource.contains 'Brian' } @Issue('GRAILS-12028') void "Test that when an action returns null the view is rendered by convention"() { when: - go '/misc/actionWhichReturnsNull' + go('/misc/actionWhichReturnsNull') then: title == 'Action Which Returns Null GSP' @@ -47,9 +47,9 @@ class MiscFunctionalSpec extends ContainerGebSpec { void "Test that placeholder configuration works for the config object"() { when: - go '/misc/placeHolderConfig' + go('/misc/placeHolderConfig') then: - driver.pageSource.contains '[test test test]' + pageSource.contains '[test test test]' } } diff --git a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/PluginViewsControllerSpec.groovy b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/PluginViewsControllerSpec.groovy index 94a809b18d0..55520bbf4d0 100644 --- a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/PluginViewsControllerSpec.groovy +++ b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/PluginViewsControllerSpec.groovy @@ -31,7 +31,7 @@ class PluginViewsControllerSpec extends ContainerGebSpec { void "Test that when plugin templates are rendered they render correctly"() { when:"A view that renders plugin templates is visisted" - go '/pluginViews/testTemplateFromPlugin' + go('/pluginViews/testTemplateFromPlugin') then:"The title is correct" $('div', 0).text() == "Template from plugin: Hello from plugin" @@ -40,7 +40,7 @@ class PluginViewsControllerSpec extends ContainerGebSpec { void "Test that views from a plugin loaded after another plugin override when using loadAfter"() { when:"A view that renders plugin views" - go '/pluginViews/testPluginViewOverrideInPlugin' + go('/pluginViews/testPluginViewOverrideInPlugin') then:"The title is correct" $('h1', 0).text() == "Second Plugin" diff --git a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/RedirectIntercetorSpec.groovy b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/RedirectIntercetorSpec.groovy index f83cefe5fdb..4d426f16710 100644 --- a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/RedirectIntercetorSpec.groovy +++ b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/RedirectIntercetorSpec.groovy @@ -30,9 +30,9 @@ class RedirectInterceptorSpec extends ContainerGebSpec { void "Test that an interceptor that redirects works"() { when: - go '/misc/interceptedByInterceptor' + go('/misc/interceptedByInterceptor') then: - driver.pageSource.contains 'Test' // the redirect worked + pageSource.contains 'Test' // the redirect worked } } diff --git a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/RedirectWithAndWithoutParamsFunctionalSpec.groovy b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/RedirectWithAndWithoutParamsFunctionalSpec.groovy index 2b4b1397a92..2f29846a658 100644 --- a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/RedirectWithAndWithoutParamsFunctionalSpec.groovy +++ b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/RedirectWithAndWithoutParamsFunctionalSpec.groovy @@ -38,8 +38,8 @@ class RedirectWithAndWithoutParamsFunctionalSpec extends ContainerGebSpec { then: 'the params are not added to the url' !currentUrl.contains('?name=foo') - driver.pageSource.contains('"id":') - driver.pageSource.contains('"name":"foo"') + pageSource.contains('"id":') + pageSource.contains('"name":"foo"') } @Issue('grails-core-#10622') @@ -51,7 +51,7 @@ class RedirectWithAndWithoutParamsFunctionalSpec extends ContainerGebSpec { !currentUrl.contains('/new-url?name=foo') and: 'the params are not on the output' - !driver.pageSource.contains('"name":"foo"') + !pageSource.contains('"name":"foo"') when: 'redirecting from url mappings without enabling params redirect' go "/old-with-controller-action?name=foo" @@ -60,7 +60,7 @@ class RedirectWithAndWithoutParamsFunctionalSpec extends ContainerGebSpec { !currentUrl.contains('/new-url?name=foo') and: 'the params are not on the output' - !driver.pageSource.contains('"name":"foo"') + !pageSource.contains('"name":"foo"') } @Issue('grails-core-#10622') @@ -72,7 +72,7 @@ class RedirectWithAndWithoutParamsFunctionalSpec extends ContainerGebSpec { !currentUrl.contains('/new-url?name=foo') and: 'the params are not on the output' - !driver.pageSource.contains('"name":"foo"') + !pageSource.contains('"name":"foo"') when: 'redirecting from url mappings without enabling params redirect' go "/old-with-controller-action-2?name=foo" @@ -81,7 +81,7 @@ class RedirectWithAndWithoutParamsFunctionalSpec extends ContainerGebSpec { !currentUrl.contains('/new-url?name=foo') and: 'the params are not on the output' - !driver.pageSource.contains('"name":"foo"') + !pageSource.contains('"name":"foo"') } @Issue('grails-core-#10622') @@ -93,6 +93,6 @@ class RedirectWithAndWithoutParamsFunctionalSpec extends ContainerGebSpec { currentUrl.contains('/new-url?name=foo') and: 'the params are on the output' - driver.pageSource.contains('"name":"foo"') + pageSource.contains('"name":"foo"') } } diff --git a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/UriMatchingInterceptorFunctionalSpec.groovy b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/UriMatchingInterceptorFunctionalSpec.groovy index 0f0d3eb6efa..8b970321f97 100644 --- a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/UriMatchingInterceptorFunctionalSpec.groovy +++ b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/UriMatchingInterceptorFunctionalSpec.groovy @@ -28,13 +28,13 @@ class UriMatchingInterceptorFunctionalSpec extends ContainerGebSpec { void "Test that an interceptor that redirects works"() { when: - go '/interceptorDemo/one' + go('/interceptorDemo/one') then: $().text() == 'interceptor did match for the one action' when: - go '/interceptorDemo/two' + go('/interceptorDemo/two') then: $().text() == 'interceptor did not match for the two action' diff --git a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/ValidationFunctionalSpec.groovy b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/ValidationFunctionalSpec.groovy index 10aab02b9fb..dfe95e2459c 100644 --- a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/ValidationFunctionalSpec.groovy +++ b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/ValidationFunctionalSpec.groovy @@ -29,7 +29,7 @@ class ValidationFunctionalSpec extends ContainerGebSpec { @Issue('GRAILS-12039') void "Test validation of an invalid Hibernate entity"() { when: - go '/book/validateBook' + go('/book/validateBook') then: $().text() == 'The validate method returned false' @@ -38,7 +38,7 @@ class ValidationFunctionalSpec extends ContainerGebSpec { @Issue('GRAILS-12039') void "Test validation of a valid Hibernate entity"() { when: - go '/book/validateBook?title=DGG' + go('/book/validateBook?title=DGG') then: $().text() == 'The validate method returned true' diff --git a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/chaining/ChainingToNamespacedControllersFunctionalSpec.groovy b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/chaining/ChainingToNamespacedControllersFunctionalSpec.groovy index 7674903680b..18b4034c9f5 100644 --- a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/chaining/ChainingToNamespacedControllersFunctionalSpec.groovy +++ b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/chaining/ChainingToNamespacedControllersFunctionalSpec.groovy @@ -28,13 +28,13 @@ class ChainingToNamespacedControllersFunctionalSpec extends ContainerGebSpec { void "Test chaining to a namespaced controller"() { when:"A controller action chains to a namespaced controller" - go '/chainingHome/chainDemo?ns=alpha' + go('/chainingHome/chainDemo?ns=alpha') then:"The chain works correctly" $('body').text() == 'rendered from the Demo controller in the alpha namespace' when:"A controller action chains to a namespaced controller" - go '/chainingHome/chainDemo?ns=beta' + go('/chainingHome/chainDemo?ns=beta') then:"The chain works correctly" $('body').text() == 'rendered from the Demo controller in the beta namespace' diff --git a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/layout/LayoutFunctionalSpec.groovy b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/layout/LayoutFunctionalSpec.groovy index a9011b560e7..4d9b06ced53 100644 --- a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/layout/LayoutFunctionalSpec.groovy +++ b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/layout/LayoutFunctionalSpec.groovy @@ -32,7 +32,7 @@ class LayoutFunctionalSpec extends ContainerGebSpec { @PendingFeature(reason = 'title is empty') void 'test layout by convention'() { when: - go '/layoutByConvention' + go('/layoutByConvention') then: title == 'Convention Layout' @@ -42,7 +42,7 @@ class LayoutFunctionalSpec extends ContainerGebSpec { @PendingFeature(reason='title is empty') void 'test layout specified in controller property'() { when: - go '/layoutSpecifiedByProperty' + go('/layoutSpecifiedByProperty') then: title == 'Foo Layout' @@ -53,7 +53,7 @@ class LayoutFunctionalSpec extends ContainerGebSpec { @PendingFeature(reason='text does not contain the value') void 'test layout specified in controller property applied to a GSP that does not contain a root html tag'() { when: - go '/layoutSpecifiedByProperty/snippetView' + go('/layoutSpecifiedByProperty/snippetView') then: title == 'Foo Layout' diff --git a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/layout/LayoutWithTemplateSpec.groovy b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/layout/LayoutWithTemplateSpec.groovy index 5194e573400..ad6e0b93d35 100644 --- a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/layout/LayoutWithTemplateSpec.groovy +++ b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/layout/LayoutWithTemplateSpec.groovy @@ -30,7 +30,7 @@ class LayoutWithTemplateSpec extends ContainerGebSpec { void "Test that a layout is not applied to a template rendered by a controller by default"() { when:"The home page is visited" - go '/layoutTemplate/index' + go('/layoutTemplate/index') then:"The title is correct" title == "Welcome to My Partial" } diff --git a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/layout/NoLayoutControllerSpec.groovy b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/layout/NoLayoutControllerSpec.groovy index bdb5ca8815d..47620890df1 100644 --- a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/layout/NoLayoutControllerSpec.groovy +++ b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/layout/NoLayoutControllerSpec.groovy @@ -25,12 +25,13 @@ import grails.testing.mixin.integration.Integration @Integration class NoLayoutControllerSpec extends ContainerGebSpec { - def "no layout"() { + + def 'no layout'() { when: - go '/noLayout/index' + go('/noLayout/index') then: "The title is correct" - browser.driver.pageSource == """ + pageSource == """ No Default Title diff --git a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/scaffolding/BarFunctionalSpec.groovy b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/scaffolding/BarFunctionalSpec.groovy index ae263930303..03d25e38e72 100644 --- a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/scaffolding/BarFunctionalSpec.groovy +++ b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/scaffolding/BarFunctionalSpec.groovy @@ -30,7 +30,7 @@ class BarFunctionalSpec extends ContainerGebSpec { void "Test that a scaffolded view is resolved correctly"() { when: - go '/bar/index' + go('/bar/index') then: title == "Bar List" diff --git a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/scaffolding/FooFunctionalSpec.groovy b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/scaffolding/FooFunctionalSpec.groovy index bac08b493e3..4596c6f3389 100644 --- a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/scaffolding/FooFunctionalSpec.groovy +++ b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/scaffolding/FooFunctionalSpec.groovy @@ -30,7 +30,7 @@ class FooFunctionalSpec extends ContainerGebSpec { void "Test that a scaffolded view is resolved correctly"() { when: - go '/foo/index' + go('/foo/index') then: title == "Foo List" diff --git a/grails-test-examples/app2/src/integration-test/groovy/app2/ErrorsControllerSpec.groovy b/grails-test-examples/app2/src/integration-test/groovy/app2/ErrorsControllerSpec.groovy index e18f9dfe6f0..7240f0a7371 100644 --- a/grails-test-examples/app2/src/integration-test/groovy/app2/ErrorsControllerSpec.groovy +++ b/grails-test-examples/app2/src/integration-test/groovy/app2/ErrorsControllerSpec.groovy @@ -31,10 +31,10 @@ class ErrorsControllerSpec extends ContainerGebSpec { void "Test a global 500 mapping that maps to another controller"() { when: "An action that throws a error that is handled by a 500 mapping in UrlMappings.groovy" - go '/test/throwGeneralError' + go('/test/throwGeneralError') then: "The correct action is executed" - driver.pageSource.contains 'my error occurred' + pageSource.contains 'my error occurred' } } diff --git a/grails-test-examples/app2/src/integration-test/groovy/app2/NotFoundHandlerSpec.groovy b/grails-test-examples/app2/src/integration-test/groovy/app2/NotFoundHandlerSpec.groovy index 50874826c7f..6f0810a5c5e 100644 --- a/grails-test-examples/app2/src/integration-test/groovy/app2/NotFoundHandlerSpec.groovy +++ b/grails-test-examples/app2/src/integration-test/groovy/app2/NotFoundHandlerSpec.groovy @@ -29,13 +29,13 @@ class NotFoundHandlerSpec extends ContainerGebSpec { void "Test that a 404 handler renders the view correctly when a forward is executed"() { when:"An action is visited where an interceptor uses response.sendError(404)" - go '/foo/index' + go('/foo/index') then:"The 404 handler is rendered" title == "Page Not Found" when:"No response.sendError(404) method is called" - go '/foo/index?user=admin' + go('/foo/index?user=admin') then:"The 404 handler is not executed" title == "Foo List" diff --git a/grails-test-examples/app3/src/integration-test/groovy/app3/LoadAfterSpec.groovy b/grails-test-examples/app3/src/integration-test/groovy/app3/LoadAfterSpec.groovy index 09fe61edc72..bf36505d1b0 100644 --- a/grails-test-examples/app3/src/integration-test/groovy/app3/LoadAfterSpec.groovy +++ b/grails-test-examples/app3/src/integration-test/groovy/app3/LoadAfterSpec.groovy @@ -27,7 +27,7 @@ class LoadAfterSpec extends ContainerGebSpec { void "Test override one plugin view from another plugin"() { when: - go '/login/auth' + go('/login/auth') then: title == "My Plugin Login Auth" diff --git a/grails-test-examples/cache/src/integration-test/groovy/com/demo/CacheTagIntegrationSpec.groovy b/grails-test-examples/cache/src/integration-test/groovy/com/demo/CacheTagIntegrationSpec.groovy index b189bddfd07..87d7f4c24cc 100644 --- a/grails-test-examples/cache/src/integration-test/groovy/com/demo/CacheTagIntegrationSpec.groovy +++ b/grails-test-examples/cache/src/integration-test/groovy/com/demo/CacheTagIntegrationSpec.groovy @@ -29,21 +29,21 @@ class CacheTagIntegrationSpec extends ContainerGebSpec { void 'test clear cache'() { when: - go '/demo/clearBlocksCache' + go('/demo/clearBlocksCache') then: - browser.driver.pageSource.contains 'cleared blocks cache' + pageSource.contains 'cleared blocks cache' when: - go '/demo/clearTemplatesCache' + go('/demo/clearTemplatesCache') then: - browser.driver.pageSource.contains 'cleared templates cache' + pageSource.contains 'cleared templates cache' } void 'test block tag'() { when: - go '/demo/blockCache?counter=5' + go('/demo/blockCache?counter=5') then: $().text().contains 'First block counter 6' @@ -51,7 +51,7 @@ class CacheTagIntegrationSpec extends ContainerGebSpec { $().text().contains 'Third block counter 8' when: - go '/demo/blockCache?counter=42' + go('/demo/blockCache?counter=42') then: $().text().contains 'First block counter 6' @@ -61,13 +61,13 @@ class CacheTagIntegrationSpec extends ContainerGebSpec { void 'test clear blocks cache'() { when: - go '/demo/clearBlocksCache' + go('/demo/clearBlocksCache') then: - browser.driver.pageSource.contains 'cleared blocks cache' + pageSource.contains('cleared blocks cache') when: - go '/demo/blockCache?counter=100' + go('/demo/blockCache?counter=100') then: $().text().contains 'First block counter 101' @@ -75,7 +75,7 @@ class CacheTagIntegrationSpec extends ContainerGebSpec { $().text().contains 'Third block counter 103' when: - go '/demo/blockCache?counter=42' + go('/demo/blockCache?counter=42') then: $().text().contains 'First block counter 101' @@ -83,13 +83,13 @@ class CacheTagIntegrationSpec extends ContainerGebSpec { $().text().contains 'Third block counter 103' when: - go '/demo/clearBlocksCache' + go('/demo/clearBlocksCache') then: - browser.driver.pageSource.contains 'cleared blocks cache' + pageSource.contains 'cleared blocks cache' when: - go '/demo/blockCache?counter=50' + go('/demo/blockCache?counter=50') then: $().text().contains 'First block counter 51' @@ -97,7 +97,7 @@ class CacheTagIntegrationSpec extends ContainerGebSpec { $().text().contains 'Third block counter 53' when: - go '/demo/blockCache?counter=150' + go('/demo/blockCache?counter=150') then: $().text().contains 'First block counter 51' @@ -109,7 +109,7 @@ class CacheTagIntegrationSpec extends ContainerGebSpec { def ttlSeconds = 10 when: - go "/demo/blockCacheTTL?counter=100&ttl=${ttlSeconds}" + go("/demo/blockCacheTTL?counter=100&ttl=${ttlSeconds}") then: $().text().contains 'First block counter 101' @@ -117,7 +117,7 @@ class CacheTagIntegrationSpec extends ContainerGebSpec { $().text().contains 'Third block counter 103' when: - go "/demo/blockCacheTTL?counter=42&ttl=${ttlSeconds}" + go("/demo/blockCacheTTL?counter=42&ttl=${ttlSeconds}") then: $().text().contains 'First block counter 101' @@ -126,7 +126,7 @@ class CacheTagIntegrationSpec extends ContainerGebSpec { TimeUnit.SECONDS.sleep(ttlSeconds) when: - go "/demo/blockCacheTTL?counter=50&ttl=${ttlSeconds}" + go("/demo/blockCacheTTL?counter=50&ttl=${ttlSeconds}") then: $().text().contains 'First block counter 51' @@ -134,7 +134,7 @@ class CacheTagIntegrationSpec extends ContainerGebSpec { $().text().contains 'Third block counter 53' when: - go "/demo/blockCacheTTL?counter=150&ttl=${ttlSeconds}" + go("/demo/blockCacheTTL?counter=150&ttl=${ttlSeconds}") then: $().text().contains 'First block counter 51' @@ -144,7 +144,7 @@ class CacheTagIntegrationSpec extends ContainerGebSpec { void 'test render tag'() { when: - go '/demo/renderTag?counter=1' + go('/demo/renderTag?counter=1') then: $().text().contains 'First invocation: Counter value: 1' @@ -154,7 +154,7 @@ class CacheTagIntegrationSpec extends ContainerGebSpec { $().text().contains 'Fifth invocation: Counter value: 1' when: - go '/demo/renderTag?counter=5' + go('/demo/renderTag?counter=5') then: $().text().contains 'First invocation: Counter value: 1' @@ -164,13 +164,13 @@ class CacheTagIntegrationSpec extends ContainerGebSpec { $().text().contains 'Fifth invocation: Counter value: 1' when: - go '/demo/clearTemplatesCache' + go('/demo/clearTemplatesCache') then: - browser.driver.pageSource.contains 'cleared templates cache' + pageSource.contains 'cleared templates cache' when: - go '/demo/renderTag?counter=5' + go('/demo/renderTag?counter=5') then: $().text().contains 'First invocation: Counter value: 5' @@ -180,7 +180,7 @@ class CacheTagIntegrationSpec extends ContainerGebSpec { $().text().contains 'Fifth invocation: Counter value: 5' when: - go '/demo/renderTag?counter=1' + go('/demo/renderTag?counter=1') then: $().text().contains 'First invocation: Counter value: 5' @@ -194,7 +194,7 @@ class CacheTagIntegrationSpec extends ContainerGebSpec { def ttlSeconds = 10 when: - go "/demo/renderTagTTL?counter=1&ttl=${ttlSeconds}" + go("/demo/renderTagTTL?counter=1&ttl=${ttlSeconds}") then: $().text().contains 'First invocation: Counter value: 1' diff --git a/grails-test-examples/cache/src/integration-test/groovy/com/demo/CachingServiceIntegrationSpec.groovy b/grails-test-examples/cache/src/integration-test/groovy/com/demo/CachingServiceIntegrationSpec.groovy index 42a93609267..a72012b6aeb 100644 --- a/grails-test-examples/cache/src/integration-test/groovy/com/demo/CachingServiceIntegrationSpec.groovy +++ b/grails-test-examples/cache/src/integration-test/groovy/com/demo/CachingServiceIntegrationSpec.groovy @@ -25,241 +25,241 @@ import grails.testing.mixin.integration.Integration @Integration class CachingServiceIntegrationSpec extends ContainerGebSpec { - void 'test caching service with method params'() { - when: - go '/demo/basicCachingServiceInvocationCount' + void 'test caching service with method params'() { + when: + go('/demo/basicCachingServiceInvocationCount') - then: - browser.driver.pageSource.contains 'Basic Caching Service Invocation Count Is 0.' + then: + pageSource.contains('Basic Caching Service Invocation Count Is 0.') - when: - go '/demo/basicCachingServiceInvocation2Count' + when: + go('/demo/basicCachingServiceInvocation2Count') - then: - browser.driver.pageSource.contains 'Basic Caching Service Invocation Count Is 100.' + then: + pageSource.contains('Basic Caching Service Invocation Count Is 100.') - when: - // first retrieval. no cache. service method is invoked for each call. - go '/demo/basicCachingService' + when: + // first retrieval. no cache. service method is invoked for each call. + go('/demo/basicCachingService') - then: - browser.driver.pageSource.contains 'Value From Service Is "Hello World!"' + then: + pageSource.contains('Value From Service Is "Hello World!"') - when: - go '/demo/basicCachingServiceInvocationCount' + when: + go('/demo/basicCachingServiceInvocationCount') - then: - browser.driver.pageSource.contains 'Basic Caching Service Invocation Count Is 1.' + then: + pageSource.contains('Basic Caching Service Invocation Count Is 1.') - when: - go '/demo/basicCaching2Service' + when: + go('/demo/basicCaching2Service') - then: - browser.driver.pageSource.contains 'Value From Service Is "Hello World 2!"' + then: + pageSource.contains('Value From Service Is "Hello World 2!"') - when: - go '/demo/basicCachingServiceInvocation2Count' + when: + go('/demo/basicCachingServiceInvocation2Count') - then: - browser.driver.pageSource.contains 'Basic Caching Service Invocation Count Is 101.' + then: + pageSource.contains('Basic Caching Service Invocation Count Is 101.') - when: - // there's should be no change because it took the value from cache. and both service methods don't get mixed up - go '/demo/basicCachingService' + when: + // there's should be no change because it took the value from cache. and both service methods don't get mixed up + go('/demo/basicCachingService') - then: - browser.driver.pageSource.contains 'Value From Service Is "Hello World!"' + then: + pageSource.contains('Value From Service Is "Hello World!"') - when: - go '/demo/basicCachingServiceInvocationCount' + when: + go('/demo/basicCachingServiceInvocationCount') - then: - browser.driver.pageSource.contains 'Basic Caching Service Invocation Count Is 1.' + then: + pageSource.contains('Basic Caching Service Invocation Count Is 1.') - when: - go '/demo/basicCaching2Service' + when: + go('/demo/basicCaching2Service') - then: - browser.driver.pageSource.contains 'Value From Service Is "Hello World 2!"' + then: + pageSource.contains('Value From Service Is "Hello World 2!"') - when: - go '/demo/basicCachingServiceInvocation2Count' + when: + go('/demo/basicCachingServiceInvocation2Count') - then: - browser.driver.pageSource.contains 'Basic Caching Service Invocation Count Is 101.' + then: + pageSource.contains('Basic Caching Service Invocation Count Is 101.') - when: - go '/demo/basicCaching2Service' + when: + go('/demo/basicCaching2Service') - then: - browser.driver.pageSource.contains 'Value From Service Is "Hello World 2!"' + then: + pageSource.contains('Value From Service Is "Hello World 2!"') - when: - go '/demo/basicCachingServiceInvocation2Count' + when: + go('/demo/basicCachingServiceInvocation2Count') - then: - browser.driver.pageSource.contains 'Basic Caching Service Invocation Count Is 101.' + then: + pageSource.contains('Basic Caching Service Invocation Count Is 101.') - when: - go '/demo/basicCachingService' + when: + go('/demo/basicCachingService') - then: - browser.driver.pageSource.contains 'Value From Service Is "Hello World!"' + then: + pageSource.contains('Value From Service Is "Hello World!"') - when: - go '/demo/basicCachingServiceInvocationCount' + when: + go('/demo/basicCachingServiceInvocationCount') - then: - browser.driver.pageSource.contains 'Basic Caching Service Invocation Count Is 1.' + then: + pageSource.contains('Basic Caching Service Invocation Count Is 1.') - when: - // reset - go '/demo/basicResetCachingService' - go '/demo/basicCachingServiceInvocationCount' + when: + // reset + go('/demo/basicResetCachingService') + go('/demo/basicCachingServiceInvocationCount') - then: - browser.driver.pageSource.contains 'Basic Caching Service Invocation Count Is 0.' + then: + pageSource.contains('Basic Caching Service Invocation Count Is 0.') - when: - go '/demo/basicCachingServiceInvocation2Count' + when: + go('/demo/basicCachingServiceInvocation2Count') - then: - browser.driver.pageSource.contains 'Basic Caching Service Invocation Count Is 100.' - } + then: + pageSource.contains('Basic Caching Service Invocation Count Is 100.') + } - void 'test basic caching service'() { - when: - go '/demo/basicCachingServiceInvocationCount' + void 'test basic caching service'() { + when: + go('/demo/basicCachingServiceInvocationCount') - then: - browser.driver.pageSource.contains 'Basic Caching Service Invocation Count Is 0.' + then: + pageSource.contains('Basic Caching Service Invocation Count Is 0.') - when: - go '/demo/basicCachingServiceInvocationCount' + when: + go('/demo/basicCachingServiceInvocationCount') - then: - browser.driver.pageSource.contains 'Basic Caching Service Invocation Count Is 0.' + then: + pageSource.contains('Basic Caching Service Invocation Count Is 0.') - when: - go '/demo/basicCachingService' + when: + go('/demo/basicCachingService') - then: - browser.driver.pageSource.contains 'Value From Service Is "Hello World!"' + then: + pageSource.contains('Value From Service Is "Hello World!"') - when: - go '/demo/basicCachingServiceInvocationCount' + when: + go('/demo/basicCachingServiceInvocationCount') - then: - browser.driver.pageSource.contains 'Basic Caching Service Invocation Count Is 1.' + then: + pageSource.contains('Basic Caching Service Invocation Count Is 1.') - when: - go '/demo/basicCachingService' + when: + go('/demo/basicCachingService') - then: - browser.driver.pageSource.contains 'Value From Service Is "Hello World!"' + then: + pageSource.contains('Value From Service Is "Hello World!"') - when: - go '/demo/basicCachingServiceInvocationCount' + when: + go('/demo/basicCachingServiceInvocationCount') - then: - browser.driver.pageSource.contains 'Basic Caching Service Invocation Count Is 1.' - } + then: + pageSource.contains('Basic Caching Service Invocation Count Is 1.') + } - void 'test basic cache put service'() { - when: - go '/demo/cacheGet?key=band' + void 'test basic cache put service'() { + when: + go('/demo/cacheGet?key=band') - then: - browser.driver.pageSource.contains 'Result: null' + then: + pageSource.contains('Result: null') - when: - go '/demo/cachePut?key=band&value=Thin+Lizzy' + when: + go('/demo/cachePut?key=band&value=Thin+Lizzy') - then: - browser.driver.pageSource.contains 'Result: ** Thin Lizzy **' + then: + pageSource.contains('Result: ** Thin Lizzy **') - when: - go '/demo/cacheGet?key=band' + when: + go('/demo/cacheGet?key=band') - then: - browser.driver.pageSource.contains 'Result: ** Thin Lizzy' + then: + pageSource.contains('Result: ** Thin Lizzy') - when: - go '/demo/cacheGet?key=singer' + when: + go('/demo/cacheGet?key=singer') - then: - browser.driver.pageSource.contains 'Result: null' + then: + pageSource.contains('Result: null') - when: - go '/demo/cachePut?key=singer&value=Phil+Lynott' + when: + go('/demo/cachePut?key=singer&value=Phil+Lynott') - then: - browser.driver.pageSource.contains 'Result: ** Phil Lynott **' + then: + pageSource.contains('Result: ** Phil Lynott **') - when: - go '/demo/cacheGet?key=singer' + when: + go('/demo/cacheGet?key=singer') - then: - browser.driver.pageSource.contains 'Result: ** Phil Lynott' + then: + pageSource.contains('Result: ** Phil Lynott') - when: - go '/demo/cachePut?key=singer&value=John+Sykes' + when: + go('/demo/cachePut?key=singer&value=John+Sykes') - then: - browser.driver.pageSource.contains 'Result: ** John Sykes **' + then: + pageSource.contains('Result: ** John Sykes **') - when: - go '/demo/cacheGet?key=singer' + when: + go('/demo/cacheGet?key=singer') - then: - browser.driver.pageSource.contains 'Result: ** John Sykes' + then: + pageSource.contains('Result: ** John Sykes') - when: - go '/demo/cacheGet?key=band' + when: + go('/demo/cacheGet?key=band') - then: - browser.driver.pageSource.contains 'Result: ** Thin Lizzy' - } + then: + pageSource.contains('Result: ** Thin Lizzy') + } - void 'test basic cache evict key service'() { - when: - go '/demo/cachePut?key=band&value=Thin+Lizzy' + void 'test basic cache evict key service'() { + when: + go('/demo/cachePut?key=band&value=Thin+Lizzy') - then: - browser.driver.pageSource.contains 'Result: ** Thin Lizzy **' + then: + pageSource.contains('Result: ** Thin Lizzy **') - when: - go '/demo/cacheEvictAndGet?key=band' + when: + go('/demo/cacheEvictAndGet?key=band') - then: - browser.driver.pageSource.contains 'Result: null' - } + then: + pageSource.contains('Result: null') + } - void 'test basic cache evict all service'() { + void 'test basic cache evict all service'() { when: - go '/demo/cachePut?key=band&value=Thin+Lizzy' + go('/demo/cachePut?key=band&value=Thin+Lizzy') then: - browser.driver.pageSource.contains 'Result: ** Thin Lizzy **' + pageSource.contains('Result: ** Thin Lizzy **') when: - go '/demo/cacheEvictAllAndGet?key=band' + go('/demo/cacheEvictAllAndGet?key=band') then: - browser.driver.pageSource.contains 'Result: null' + pageSource.contains('Result: null') } void 'test basic cache clear service'() { when: - go '/demo/cachePut?key=band&value=Thin+Lizzy' + go('/demo/cachePut?key=band&value=Thin+Lizzy') then: - browser.driver.pageSource.contains 'Result: ** Thin Lizzy **' + pageSource.contains('Result: ** Thin Lizzy **') when: - go '/demo/cacheClearAndGet?key=band' + go('/demo/cacheClearAndGet?key=band') then: - browser.driver.pageSource.contains 'Result: null' + pageSource.contains('Result: null') } } diff --git a/grails-test-examples/cache/src/integration-test/groovy/com/demo/NotCachingControllerIntegrationSpec.groovy b/grails-test-examples/cache/src/integration-test/groovy/com/demo/NotCachingControllerIntegrationSpec.groovy index 05cfbd0d6bf..02486440b66 100644 --- a/grails-test-examples/cache/src/integration-test/groovy/com/demo/NotCachingControllerIntegrationSpec.groovy +++ b/grails-test-examples/cache/src/integration-test/groovy/com/demo/NotCachingControllerIntegrationSpec.groovy @@ -27,13 +27,13 @@ class NotCachingControllerIntegrationSpec extends ContainerGebSpec { void 'test action controller with different parameters'() { when: - go '/demo/show/1' + go('/demo/show/1') then: $().text().contains 'Hello World!1' when: - go '/demo/show/2' + go('/demo/show/2') then: $().text().contains 'Hello World!2' diff --git a/grails-test-examples/geb/src/integration-test/groovy/org/demo/spock/DownloadSupportSpec.groovy b/grails-test-examples/geb/src/integration-test/groovy/org/demo/spock/DownloadSupportSpec.groovy index 10bcb40e9fb..1c3d6da5bcb 100644 --- a/grails-test-examples/geb/src/integration-test/groovy/org/demo/spock/DownloadSupportSpec.groovy +++ b/grails-test-examples/geb/src/integration-test/groovy/org/demo/spock/DownloadSupportSpec.groovy @@ -27,7 +27,7 @@ class DownloadSupportSpec extends ContainerGebSpec { void 'should be able to use download methods'() { when: - go '/' + go('/') then: downloadText().contains('Welcome to Grails') diff --git a/grails-test-examples/geb/src/integration-test/groovy/org/demo/spock/InheritedConfigSpec.groovy b/grails-test-examples/geb/src/integration-test/groovy/org/demo/spock/InheritedConfigSpec.groovy index ef348fbc0d4..ab770d17371 100644 --- a/grails-test-examples/geb/src/integration-test/groovy/org/demo/spock/InheritedConfigSpec.groovy +++ b/grails-test-examples/geb/src/integration-test/groovy/org/demo/spock/InheritedConfigSpec.groovy @@ -43,7 +43,7 @@ class NotSuperSpec extends ContainerGebSpec {} class InheritedConfigSpec extends SuperSpec { void 'should show the right server name when visiting /serverName'() { when: 'visiting the server name controller' - go '/serverName' + go(('/serverName')) then: 'the emitted hostname is correct' pageSource.contains('Server name: super.example.com') @@ -54,7 +54,7 @@ class InheritedConfigSpec extends SuperSpec { class NotInheritedConfigSpec extends NotSuperSpec { void 'should show the right server name when visiting /serverName'() { when: 'visiting the server name controller' - go '/serverName' + go('/serverName') then: 'the emitted hostname is correct' !pageSource.contains('Server name: not.example.com') @@ -70,7 +70,7 @@ class ChildPreferenceInheritedConfigSpec extends SuperSpec { void 'should show the right server name when visiting /serverName'() { when: 'visiting the server name controller' - go '/serverName' + go('/serverName') then: 'the emitted hostname is correct' pageSource.contains('Server name: child.example.com') @@ -98,7 +98,7 @@ class SuperSuperInheritedConfigSpec extends SuperSpec { class MultipleInheritanceSpec extends SuperSuperInheritedConfigSpec { void 'should show the right server name when visiting /serverName'() { when: 'visiting the server name controller' - go '/serverName' + go('/serverName') then: 'the emitted hostname is correct' pageSource.contains('Server name: super.example.com') diff --git a/grails-test-examples/geb/src/integration-test/groovy/org/demo/spock/RootPageSpec.groovy b/grails-test-examples/geb/src/integration-test/groovy/org/demo/spock/RootPageSpec.groovy index 7ca233ddf65..cba2cf4657a 100644 --- a/grails-test-examples/geb/src/integration-test/groovy/org/demo/spock/RootPageSpec.groovy +++ b/grails-test-examples/geb/src/integration-test/groovy/org/demo/spock/RootPageSpec.groovy @@ -42,7 +42,7 @@ class RootPageSpec extends ContainerGebSpec { void 'should display the correct title on the home page'() { when: 'visiting the home page' - go '/' + go('/') then: 'the page title is correct' report('root page report') diff --git a/grails-test-examples/geb/src/integration-test/groovy/org/demo/spock/ServerNameControllerSpec.groovy b/grails-test-examples/geb/src/integration-test/groovy/org/demo/spock/ServerNameControllerSpec.groovy index e59fc633f59..93c3686a778 100644 --- a/grails-test-examples/geb/src/integration-test/groovy/org/demo/spock/ServerNameControllerSpec.groovy +++ b/grails-test-examples/geb/src/integration-test/groovy/org/demo/spock/ServerNameControllerSpec.groovy @@ -33,7 +33,7 @@ class ServerNameControllerSpec extends ContainerGebSpec { void 'should show the right server name when visiting /serverName'() { when: 'visiting the server name controller' - go '/serverName' + go('/serverName') then: 'the emitted hostname is correct' $('p').text() == 'Server name: testing.example.com' diff --git a/grails-test-examples/gsp-layout/src/integration-test/groovy/EndToEndSpec.groovy b/grails-test-examples/gsp-layout/src/integration-test/groovy/EndToEndSpec.groovy index 5e1259a2078..5c26d2bb266 100644 --- a/grails-test-examples/gsp-layout/src/integration-test/groovy/EndToEndSpec.groovy +++ b/grails-test-examples/gsp-layout/src/integration-test/groovy/EndToEndSpec.groovy @@ -1,7 +1,3 @@ -import grails.plugin.geb.ContainerGebSpec -import grails.testing.mixin.integration.Integration -import spock.lang.PendingFeature - /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -20,62 +16,67 @@ import spock.lang.PendingFeature * specific language governing permissions and limitations * under the License. */ +import grails.plugin.geb.ContainerGebSpec +import grails.testing.mixin.integration.Integration +import spock.lang.PendingFeature + @Integration class EndToEndSpec extends ContainerGebSpec { - def "simple layout"() { + + def 'simple layout'() { when: - browser.go 'endToEnd/simpleLayout' + go('endToEnd/simpleLayout') then: - browser.driver.pageSource == """Decorated This is the title + pageSource == """Decorated This is the title

Hello

body text """ } - def "title in subtemplate"() { + def 'title in subtemplate'() { when: - browser.go 'endToEnd/titleInSubtemplate' + go('endToEnd/titleInSubtemplate') then: - browser.driver.pageSource == """Decorated This is the title + pageSource == """Decorated This is the title

Hello

body text """ } @PendingFeature - def "multiple levels of layouts"() { + def 'multiple levels of layouts'() { when: - browser.go 'endToEnd/multipleLevelsOfLayouts' + go('endToEnd/multipleLevelsOfLayouts') then: - browser.driver.pageSource == """Decorated Base - Dialog - This is the title + pageSource == """Decorated Base - Dialog - This is the title

Hello

body text
""" } - def "parameters"() { + def 'parameters'() { when: - browser.go 'endToEnd/parameters' + go('endToEnd/parameters') then: - browser.driver.pageSource == """

pageProperty: here!

""" + pageSource == """

pageProperty: here!

""" } - def "parameters with logic"() { + def 'parameters with logic'() { when: - browser.go 'endToEnd/parametersWithLogic' + go('endToEnd/parametersWithLogic') then: - browser.driver.pageSource == "good" + pageSource == "good" } - def "multiline title"() { + def 'multiline title'() { when: - browser.go 'endToEnd/multilineTitle' + go('endToEnd/multilineTitle') then: - browser.driver.pageSource == """Decorated + pageSource == """<html><head><title>Decorated This is the title diff --git a/grails-test-examples/gsp-layout/src/integration-test/groovy/GrailsLayoutSpec.groovy b/grails-test-examples/gsp-layout/src/integration-test/groovy/GrailsLayoutSpec.groovy index 87921443c60..598fe2edf08 100644 --- a/grails-test-examples/gsp-layout/src/integration-test/groovy/GrailsLayoutSpec.groovy +++ b/grails-test-examples/gsp-layout/src/integration-test/groovy/GrailsLayoutSpec.groovy @@ -25,34 +25,34 @@ class GrailsLayoutSpec extends ContainerGebSpec { void "forced layout"() { when: - browser.go 'demo/index' + browser.go('demo/index') then: - browser.driver.pageSource.contains('Do you like BootStrap?') + pageSource.contains('Do you like BootStrap?') } void "decorator chaining"() { when: - browser.go 'demo/chaining' + browser.go('demo/chaining') then: - browser.driver.pageSource.contains('This is so cool.') + pageSource.contains('This is so cool.') } void "jsp demo"() { when: - browser.go 'demo/jsp' + browser.go('demo/jsp') then: def container = browser.$('div.container') container - browser.driver.pageSource.contains('Hello World, I am a JSP page!') + pageSource.contains('Hello World, I am a JSP page!') } void "text"() { when: - browser.go 'demo/renderText' + browser.go('demo/renderText') then: downloadText() == '''

Hello World

''' @@ -60,25 +60,25 @@ class GrailsLayoutSpec extends ContainerGebSpec { void "Controller 500 Example"() { when: - browser.go 'demo/exception' + browser.go('demo/exception') then: - browser.driver.pageSource.contains('Whoops, why would you ever want to see an exception??') + pageSource.contains('Whoops, why would you ever want to see an exception??') } void "View 500 Example"() { when: - browser.go 'demo/viewException' + browser.go('demo/viewException') then: - browser.driver.pageSource.contains('Oh Man, this view sucks!') + pageSource.contains('Oh Man, this view sucks!') } void "404 Error"() { when: - browser.go 'demo/404' + browser.go('demo/404') then: - browser.driver.pageSource.contains('Error: Page Not Found (404)') + pageSource.contains('Error: Page Not Found (404)') } } diff --git a/grails-test-examples/hibernate5/grails-hibernate/src/integration-test/groovy/functional/tests/BookControllerSpec.groovy b/grails-test-examples/hibernate5/grails-hibernate/src/integration-test/groovy/functional/tests/BookControllerSpec.groovy index 9fa198b5425..ec6446d3d2e 100644 --- a/grails-test-examples/hibernate5/grails-hibernate/src/integration-test/groovy/functional/tests/BookControllerSpec.groovy +++ b/grails-test-examples/hibernate5/grails-hibernate/src/integration-test/groovy/functional/tests/BookControllerSpec.groovy @@ -27,7 +27,7 @@ class BookControllerSpec extends ContainerGebSpec { void "Test list books"() { when:"The home page is visited" - go '/book/index' + go('/book/index') then:"The title is correct" title == "Book List" diff --git a/grails-test-examples/hyphenated/src/integration-test/groovy/hyphenated/FooBarControllerSpec.groovy b/grails-test-examples/hyphenated/src/integration-test/groovy/hyphenated/FooBarControllerSpec.groovy index 974d455c861..26a0720c23c 100644 --- a/grails-test-examples/hyphenated/src/integration-test/groovy/hyphenated/FooBarControllerSpec.groovy +++ b/grails-test-examples/hyphenated/src/integration-test/groovy/hyphenated/FooBarControllerSpec.groovy @@ -30,7 +30,7 @@ class FooBarControllerSpec extends ContainerGebSpec { void "test returns null"() { when:"The home page is visited" - go '/foo-bar/returns-null' + go('/foo-bar/returns-null') then:"The title is correct" $().text() == 'returns null' @@ -38,7 +38,7 @@ class FooBarControllerSpec extends ContainerGebSpec { void "test returns map"() { when:"The home page is visited" - go '/foo-bar/returns-map' + go('/foo-bar/returns-map') then:"The title is correct" $().text() == 'returns Map Sally' @@ -46,7 +46,7 @@ class FooBarControllerSpec extends ContainerGebSpec { void "test default action"() { when:"The home page is visited" - go '/foo-bar' + go('/foo-bar') then:"The title is correct" $().text() == 'default action' diff --git a/grails-test-examples/hyphenated/src/integration-test/groovy/hyphenated/HyphenateControllerSpec.groovy b/grails-test-examples/hyphenated/src/integration-test/groovy/hyphenated/HyphenateControllerSpec.groovy index b8e33eac6fc..e5c0af70f0c 100644 --- a/grails-test-examples/hyphenated/src/integration-test/groovy/hyphenated/HyphenateControllerSpec.groovy +++ b/grails-test-examples/hyphenated/src/integration-test/groovy/hyphenated/HyphenateControllerSpec.groovy @@ -29,7 +29,7 @@ class HyphenateControllerSpec extends ContainerGebSpec { void "test something"() { when:"The home page is visited" - go '/hyphenate/long-name' + go('/hyphenate/long-name') then:"The title is correct" $().text() == 'good' diff --git a/grails-test-examples/hyphenated/src/integration-test/groovy/hyphenated/NameSpacedControllerSpec.groovy b/grails-test-examples/hyphenated/src/integration-test/groovy/hyphenated/NameSpacedControllerSpec.groovy index 78283e8de46..182caa4ee78 100644 --- a/grails-test-examples/hyphenated/src/integration-test/groovy/hyphenated/NameSpacedControllerSpec.groovy +++ b/grails-test-examples/hyphenated/src/integration-test/groovy/hyphenated/NameSpacedControllerSpec.groovy @@ -30,7 +30,7 @@ class NameSpacedControllerSpec extends ContainerGebSpec { void "test returns null"() { when: "The home page is visited" - go '/abc-xyz/name-spaced/returns-null' + go('/abc-xyz/name-spaced/returns-null') then: "The title is correct" $().text() == 'returns null' @@ -38,7 +38,7 @@ class NameSpacedControllerSpec extends ContainerGebSpec { void "test returns map"() { when: "The home page is visited" - go '/abc-xyz/name-spaced/returns-map' + go('/abc-xyz/name-spaced/returns-map') then: "The title is correct" $().text() == 'returns Map Sally' @@ -46,7 +46,7 @@ class NameSpacedControllerSpec extends ContainerGebSpec { void "test default action"() { when: "The home page is visited" - go '/abc-xyz/name-spaced' + go('/abc-xyz/name-spaced') then: "The title is correct" $().text() == 'default action' diff --git a/grails-test-examples/mongodb/base/src/integration-test/groovy/functional/tests/BookControllerSpec.groovy b/grails-test-examples/mongodb/base/src/integration-test/groovy/functional/tests/BookControllerSpec.groovy index 04f3366c9fc..e470c355773 100644 --- a/grails-test-examples/mongodb/base/src/integration-test/groovy/functional/tests/BookControllerSpec.groovy +++ b/grails-test-examples/mongodb/base/src/integration-test/groovy/functional/tests/BookControllerSpec.groovy @@ -27,7 +27,7 @@ class BookControllerSpec extends ContainerGebSpec { void "Test list books"() { when:"The home page is visited" - go '/book/index' + go('/book/index') then:"The title is correct" title == "Book List" diff --git a/grails-test-examples/mongodb/hibernate5/src/integration-test/groovy/functional/tests/AuthorControllerSpec.groovy b/grails-test-examples/mongodb/hibernate5/src/integration-test/groovy/functional/tests/AuthorControllerSpec.groovy index b3caa2e20f3..2dfb64d4a5b 100644 --- a/grails-test-examples/mongodb/hibernate5/src/integration-test/groovy/functional/tests/AuthorControllerSpec.groovy +++ b/grails-test-examples/mongodb/hibernate5/src/integration-test/groovy/functional/tests/AuthorControllerSpec.groovy @@ -27,7 +27,7 @@ class AuthorControllerSpec extends ContainerGebSpec { void "Test list authors"() { when:"The home page is visited" - go '/author/index' + go('/author/index') then:"The name is correct" title == "Author List" @@ -35,7 +35,7 @@ class AuthorControllerSpec extends ContainerGebSpec { void "Test save author"() { when: - go "/author/create" + go("/author/create") $('form').name = "Stephen King" $('input.save').click() diff --git a/grails-test-examples/mongodb/hibernate5/src/integration-test/groovy/functional/tests/BookControllerSpec.groovy b/grails-test-examples/mongodb/hibernate5/src/integration-test/groovy/functional/tests/BookControllerSpec.groovy index 04f3366c9fc..e470c355773 100644 --- a/grails-test-examples/mongodb/hibernate5/src/integration-test/groovy/functional/tests/BookControllerSpec.groovy +++ b/grails-test-examples/mongodb/hibernate5/src/integration-test/groovy/functional/tests/BookControllerSpec.groovy @@ -27,7 +27,7 @@ class BookControllerSpec extends ContainerGebSpec { void "Test list books"() { when:"The home page is visited" - go '/book/index' + go('/book/index') then:"The title is correct" title == "Book List" diff --git a/grails-test-examples/namespaces/src/integration-test/groovy/context/ContextPathSpec.groovy b/grails-test-examples/namespaces/src/integration-test/groovy/context/ContextPathSpec.groovy index bf47263fc23..755b507de35 100644 --- a/grails-test-examples/namespaces/src/integration-test/groovy/context/ContextPathSpec.groovy +++ b/grails-test-examples/namespaces/src/integration-test/groovy/context/ContextPathSpec.groovy @@ -30,13 +30,13 @@ class ContextPathSpec extends ContainerGebSpec { void "test the context path defined in the environment overrides the standard one"() { when: - go '/myAppTest' + go('/myAppTest') then: title == "Welcome to Grails" when: - go '/myApp' + go('/myApp') then: title == "HTTP Status 404 – Not Found" diff --git a/grails-test-examples/namespaces/src/integration-test/groovy/namespaces/NamespaceViewRenderingSpec.groovy b/grails-test-examples/namespaces/src/integration-test/groovy/namespaces/NamespaceViewRenderingSpec.groovy index 1712d8465f2..f3f2e77b356 100644 --- a/grails-test-examples/namespaces/src/integration-test/groovy/namespaces/NamespaceViewRenderingSpec.groovy +++ b/grails-test-examples/namespaces/src/integration-test/groovy/namespaces/NamespaceViewRenderingSpec.groovy @@ -31,13 +31,13 @@ class NamespaceViewRenderingSpec extends ContainerGebSpec { void "Test view rendering works as expected when namespaces are used"() { when:"When an implicit namespace is used" - go '/myAppTest/test/implicitView' + go('/myAppTest/test/implicitView') then:"The view is rendered" $('body').text() == "Implicit View Rendered!" when:"When an explicit view with a namespace is used" - go '/myAppTest/test/explicitView' + go('/myAppTest/test/explicitView') then:"The view is rendered" $('body').text() == "Foo View Rendered" diff --git a/grails-test-examples/namespaces/src/integration-test/groovy/namespaces/PageControllerSpec.groovy b/grails-test-examples/namespaces/src/integration-test/groovy/namespaces/PageControllerSpec.groovy index bf832821617..46865684d59 100644 --- a/grails-test-examples/namespaces/src/integration-test/groovy/namespaces/PageControllerSpec.groovy +++ b/grails-test-examples/namespaces/src/integration-test/groovy/namespaces/PageControllerSpec.groovy @@ -29,13 +29,13 @@ class PageControllerSpec extends ContainerGebSpec { void "test that the page renders correctly"() { when: "The admin page is visited" - go '/myAppTest/admin/page/index' + go('/myAppTest/admin/page/index') then: "The title is correct" title == 'Admin Page' when: "The page is visited without namespace" - go '/myAppTest/page/index' + go('/myAppTest/page/index') then: "The title is correct" title == 'Frontend Page' diff --git a/grails-test-examples/namespaces/src/integration-test/groovy/namespaces/admin/ReportControllerSpec.groovy b/grails-test-examples/namespaces/src/integration-test/groovy/namespaces/admin/ReportControllerSpec.groovy index 8cb3a33b4d6..8edbc9cad84 100644 --- a/grails-test-examples/namespaces/src/integration-test/groovy/namespaces/admin/ReportControllerSpec.groovy +++ b/grails-test-examples/namespaces/src/integration-test/groovy/namespaces/admin/ReportControllerSpec.groovy @@ -28,13 +28,13 @@ class ReportControllerSpec extends ContainerGebSpec { void "test that admin report page renders correctly"() { when: "The admin report page is visited" - go '/myAppTest/admin/report/index' + go('/myAppTest/admin/report/index') then: "The title is correct" title == 'Admin Report' when: "The admin report page is visited without namespace" - go '/myAppTest/report/index' + go('/myAppTest/report/index') then: "The title is correct" title == 'Admin Report' diff --git a/grails-testing-support-datamapping/src/main/groovy/grails/testing/gorm/DataTest.groovy b/grails-testing-support-datamapping/src/main/groovy/grails/testing/gorm/DataTest.groovy index a462461061e..83142424a26 100644 --- a/grails-testing-support-datamapping/src/main/groovy/grails/testing/gorm/DataTest.groovy +++ b/grails-testing-support-datamapping/src/main/groovy/grails/testing/gorm/DataTest.groovy @@ -133,7 +133,7 @@ trait DataTest extends GrailsUnitTest { defineBeans { "${domain.javaClass.name}"(domain.javaClass) { bean -> bean.singleton = false - bean.autowire = "byName" + bean.autowire = 'byName' } if (DataTestSetupSpecInterceptor.IS_OLD_SETUP) { @@ -141,12 +141,12 @@ trait DataTest extends GrailsUnitTest { "$validationBeanName"(MockCascadingDomainClassValidator) { bean -> bean.lazyInit = true - delegate.messageSource = ref("messageSource") + delegate.messageSource = ref('messageSource') delegate.domainClass = grailsDomain delegate.grailsApplication = grailsApplication } } else { - "$validationBeanName"(PersistentEntityValidator, domain, ref("messageSource"), ref(DataTestSetupSpecInterceptor.BEAN_NAME)) + "$validationBeanName"(PersistentEntityValidator, domain, ref('messageSource'), ref(DataTestSetupSpecInterceptor.BEAN_NAME)) } } From 7d2e916ba3a2067c49fd9cdea84dc633bdf1aec9 Mon Sep 17 00:00:00 2001 From: James Daugherty Date: Sat, 5 Jul 2025 15:20:22 -0400 Subject: [PATCH 22/26] revert: some styling changes that cause test failures --- .../plugins/web/GroovyPagesGrailsPlugin.groovy | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/grails-gsp/plugin/src/main/groovy/org/grails/plugins/web/GroovyPagesGrailsPlugin.groovy b/grails-gsp/plugin/src/main/groovy/org/grails/plugins/web/GroovyPagesGrailsPlugin.groovy index 3e477928279..628c2662a51 100644 --- a/grails-gsp/plugin/src/main/groovy/org/grails/plugins/web/GroovyPagesGrailsPlugin.groovy +++ b/grails-gsp/plugin/src/main/groovy/org/grails/plugins/web/GroovyPagesGrailsPlugin.groovy @@ -76,7 +76,7 @@ class GroovyPagesGrailsPlugin extends Plugin { "file:./grails-app/taglib/**/*TagLib.groovy"] def grailsVersion = "7.0.0-SNAPSHOT > *" - def dependsOn = [core: GrailsUtil.grailsVersion, i18n: GrailsUtil.grailsVersion] + def dependsOn = [core: GrailsUtil.getGrailsVersion(), i18n: GrailsUtil.getGrailsVersion()] def observe = ['controllers'] def loadAfter = ['filters'] @@ -109,10 +109,10 @@ class GroovyPagesGrailsPlugin extends Plugin { { -> def application = grailsApplication Config config = application.config - boolean developmentMode = developmentMode + boolean developmentMode = isDevelopmentMode() Environment env = Environment.current - boolean enableReload = env.reloadEnabled || + boolean enableReload = env.isReloadEnabled() || config.getProperty(GroovyPagesTemplateEngine.CONFIG_PROPERTY_GSP_ENABLE_RELOAD, Boolean, false) || (developmentMode && env == Environment.DEVELOPMENT) @@ -166,7 +166,7 @@ class GroovyPagesGrailsPlugin extends Plugin { } } - def deployed = !Metadata.current.developmentEnvironmentAvailable + def deployed = !Metadata.getCurrent().isDevelopmentEnvironmentAvailable() groovyPageLocator(CachingGrailsConventionGroovyPageLocator) { bean -> bean.lazyInit = true if (customResourceLoader) { @@ -235,7 +235,7 @@ class GroovyPagesGrailsPlugin extends Plugin { } boolean jstlPresent = ClassUtils.isPresent( - 'jakarta.servlet.jsp.jstl.core.Config', InternalResourceViewResolver.class.classLoader) + "jakarta.servlet.jsp.jstl.core.Config", InternalResourceViewResolver.class.getClassLoader()) abstractViewResolver { prefix = GrailsApplicationAttributes.PATH_TO_VIEWS @@ -271,7 +271,7 @@ class GroovyPagesGrailsPlugin extends Plugin { filteringCodecsByContentTypeSettings(FilteringCodecsByContentTypeSettings, application) groovyPagesServlet(ServletRegistrationBean, new GroovyPagesServlet(), '*.gsp') { - if (Environment.developmentMode) { + if (Environment.isDevelopmentMode()) { initParameters = [showSource: '1'] } } @@ -281,7 +281,7 @@ class GroovyPagesGrailsPlugin extends Plugin { } protected boolean isDevelopmentMode() { - Metadata.current.developmentEnvironmentAvailable + Metadata.getCurrent().isDevelopmentEnvironmentAvailable() } static String transformToValidLocation(String location) { From c69a8a4170bf6516d3084548e160af7e3ac80ff1 Mon Sep 17 00:00:00 2001 From: James Daugherty Date: Sat, 5 Jul 2025 15:26:56 -0400 Subject: [PATCH 23/26] feedback: further code styling cleanup --- .../AsyncFunctionalSpec.groovy | 6 +- .../ControllerIncludesSpec.groovy | 12 +- .../ErrorsFunctionalSpec.groovy | 8 +- .../functionaltests/MiscFunctionalSpec.groovy | 11 +- .../RedirectIntercetorSpec.groovy | 2 +- .../groovy/app2/ErrorsControllerSpec.groovy | 4 +- .../com/demo/CacheTagIntegrationSpec.groovy | 154 +++++++++--------- ...NotCachingControllerIntegrationSpec.groovy | 4 +- .../org/demo/spock/InheritedConfigSpec.groovy | 4 +- .../groovy/GrailsLayoutSpec.groovy | 14 +- 10 files changed, 107 insertions(+), 112 deletions(-) diff --git a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/AsyncFunctionalSpec.groovy b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/AsyncFunctionalSpec.groovy index 4bd988bf67e..9db409059e9 100644 --- a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/AsyncFunctionalSpec.groovy +++ b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/AsyncFunctionalSpec.groovy @@ -34,11 +34,11 @@ class AsyncFunctionalSpec extends ContainerGebSpec { @PendingFeature(reason = 'pageSource == ') void "Test async response rendering works"() { - when:"When an async response is rendered" + when: "When an async response is rendered" go('/async/test') - then:"The rendered page is correct" - pageSource.contains 'Hello' + then: "The rendered page is correct" + pageSource.contains('Hello') } } diff --git a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/ControllerIncludesSpec.groovy b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/ControllerIncludesSpec.groovy index 70c465e1cb0..923f2ccbf5b 100644 --- a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/ControllerIncludesSpec.groovy +++ b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/ControllerIncludesSpec.groovy @@ -33,7 +33,7 @@ class ControllerIncludesSpec extends ContainerGebSpec { go('/includes/includeFromControllerActionRenderingView') then: "Then the include worked" - pageSource.contains 'Model is bar' + pageSource.contains('Model is bar') } void "Test includes that render text work when called from a controller action"() { @@ -41,7 +41,7 @@ class ControllerIncludesSpec extends ContainerGebSpec { go('/includes/includeFromControllerActionRenderingText') then: "Then the include worked" - pageSource.contains 'Test' + pageSource.contains('Test') } void "Test includes that render a view work when called from another view"() { @@ -49,7 +49,7 @@ class ControllerIncludesSpec extends ContainerGebSpec { go('/includes/includeFromViewRenderingView') then: "Then the include worked" - pageSource.trim().contains 'Include: \nModel is bar' + pageSource.trim().contains('Include: \nModel is bar') } void "Test includes that render text work when called from another view"() { @@ -57,7 +57,7 @@ class ControllerIncludesSpec extends ContainerGebSpec { go('/includes/includeFromViewRenderingText') then: "Then the include worked" - pageSource.contains 'Include: Test' + pageSource.contains('Include: Test') } void "Test includes that render a view work when called from a template"() { @@ -65,7 +65,7 @@ class ControllerIncludesSpec extends ContainerGebSpec { go('/includes/includeFromTemplateRenderingView') then: "Then the include worked" - pageSource.trim().contains 'Include: \nModel is bar' + pageSource.trim().contains('Include: \nModel is bar') } void "Test includes that render text work when called from a template"() { @@ -73,7 +73,7 @@ class ControllerIncludesSpec extends ContainerGebSpec { go('/includes/includeFromTemplateRenderingText') then: "Then the include worked" - pageSource.contains 'Include: Test' + pageSource.contains('Include: Test') } } diff --git a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/ErrorsFunctionalSpec.groovy b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/ErrorsFunctionalSpec.groovy index 8912132a350..ea5c082c1b6 100644 --- a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/ErrorsFunctionalSpec.groovy +++ b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/ErrorsFunctionalSpec.groovy @@ -25,8 +25,6 @@ import grails.testing.mixin.integration.Integration import spock.lang.Issue import spock.lang.PendingFeature -/** - */ @Integration(applicationClass = Application) @Rollback class ErrorsFunctionalSpec extends ContainerGebSpec { @@ -36,7 +34,7 @@ class ErrorsFunctionalSpec extends ContainerGebSpec { go('/errors/throwCustomError') then: "The correct action is executed" - pageSource.contains 'Message = Something bad' + pageSource.contains('Message = Something bad') } void "Test 500 mappings for custom exceptions"() { @@ -44,14 +42,14 @@ class ErrorsFunctionalSpec extends ContainerGebSpec { go('/demo/throwCustomError') then: "The correct action is executed" - pageSource.contains 'Message = Something bad' + pageSource.contains('Message = Something bad') } void "Test default 500 mapping"() { when: "An excetion that throws a general error handled by the default 500 mapping in UrlMapings.groovy" go('/errors/throwGeneralError') - println pageSource + println(pageSource) then: "The title is correct" $('ul', class: 'errors').text() == 'An error has occurred' diff --git a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/MiscFunctionalSpec.groovy b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/MiscFunctionalSpec.groovy index 104ce87fbfc..10fd4e9c82c 100644 --- a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/MiscFunctionalSpec.groovy +++ b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/MiscFunctionalSpec.groovy @@ -32,8 +32,7 @@ class MiscFunctionalSpec extends ContainerGebSpec { go('/misc/beanPropertyOverrideTest') then: - pageSource.contains 'Brian' - + pageSource.contains('Brian') } @Issue('GRAILS-12028') @@ -42,14 +41,14 @@ class MiscFunctionalSpec extends ContainerGebSpec { go('/misc/actionWhichReturnsNull') then: - title == 'Action Which Returns Null GSP' + title == ('Action Which Returns Null GSP') } void "Test that placeholder configuration works for the config object"() { - when: + when: go('/misc/placeHolderConfig') - then: - pageSource.contains '[test test test]' + then: + pageSource.contains('[test test test]') } } diff --git a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/RedirectIntercetorSpec.groovy b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/RedirectIntercetorSpec.groovy index 4d426f16710..608e1460ff2 100644 --- a/grails-test-examples/app1/src/integration-test/groovy/functionaltests/RedirectIntercetorSpec.groovy +++ b/grails-test-examples/app1/src/integration-test/groovy/functionaltests/RedirectIntercetorSpec.groovy @@ -33,6 +33,6 @@ class RedirectInterceptorSpec extends ContainerGebSpec { go('/misc/interceptedByInterceptor') then: - pageSource.contains 'Test' // the redirect worked + pageSource.contains('Test') // the redirect worked } } diff --git a/grails-test-examples/app2/src/integration-test/groovy/app2/ErrorsControllerSpec.groovy b/grails-test-examples/app2/src/integration-test/groovy/app2/ErrorsControllerSpec.groovy index 7240f0a7371..a234700b4c5 100644 --- a/grails-test-examples/app2/src/integration-test/groovy/app2/ErrorsControllerSpec.groovy +++ b/grails-test-examples/app2/src/integration-test/groovy/app2/ErrorsControllerSpec.groovy @@ -23,8 +23,6 @@ import grails.gorm.transactions.Rollback import grails.plugin.geb.ContainerGebSpec import grails.testing.mixin.integration.Integration -/** - */ @Integration(applicationClass = Application) @Rollback class ErrorsControllerSpec extends ContainerGebSpec { @@ -34,7 +32,7 @@ class ErrorsControllerSpec extends ContainerGebSpec { go('/test/throwGeneralError') then: "The correct action is executed" - pageSource.contains 'my error occurred' + pageSource.contains('my error occurred') } } diff --git a/grails-test-examples/cache/src/integration-test/groovy/com/demo/CacheTagIntegrationSpec.groovy b/grails-test-examples/cache/src/integration-test/groovy/com/demo/CacheTagIntegrationSpec.groovy index 87d7f4c24cc..ebb5d6f2e2e 100644 --- a/grails-test-examples/cache/src/integration-test/groovy/com/demo/CacheTagIntegrationSpec.groovy +++ b/grails-test-examples/cache/src/integration-test/groovy/com/demo/CacheTagIntegrationSpec.groovy @@ -32,13 +32,13 @@ class CacheTagIntegrationSpec extends ContainerGebSpec { go('/demo/clearBlocksCache') then: - pageSource.contains 'cleared blocks cache' + pageSource.contains('cleared blocks cache') when: go('/demo/clearTemplatesCache') then: - pageSource.contains 'cleared templates cache' + pageSource.contains('cleared templates cache') } void 'test block tag'() { @@ -46,17 +46,17 @@ class CacheTagIntegrationSpec extends ContainerGebSpec { go('/demo/blockCache?counter=5') then: - $().text().contains 'First block counter 6' - $().text().contains 'Second block counter 7' - $().text().contains 'Third block counter 8' + $().text().contains('First block counter 6') + $().text().contains('Second block counter 7') + $().text().contains('Third block counter 8') when: go('/demo/blockCache?counter=42') then: - $().text().contains 'First block counter 6' - $().text().contains 'Second block counter 7' - $().text().contains 'Third block counter 8' + $().text().contains('First block counter 6') + $().text().contains('Second block counter 7') + $().text().contains('Third block counter 8') } void 'test clear blocks cache'() { @@ -70,39 +70,39 @@ class CacheTagIntegrationSpec extends ContainerGebSpec { go('/demo/blockCache?counter=100') then: - $().text().contains 'First block counter 101' - $().text().contains 'Second block counter 102' - $().text().contains 'Third block counter 103' + $().text().contains('First block counter 101') + $().text().contains('Second block counter 102') + $().text().contains('Third block counter 103') when: go('/demo/blockCache?counter=42') then: - $().text().contains 'First block counter 101' - $().text().contains 'Second block counter 102' - $().text().contains 'Third block counter 103' + $().text().contains('First block counter 101') + $().text().contains('Second block counter 102') + $().text().contains('Third block counter 103') when: go('/demo/clearBlocksCache') then: - pageSource.contains 'cleared blocks cache' + pageSource.contains('cleared blocks cache') when: go('/demo/blockCache?counter=50') then: - $().text().contains 'First block counter 51' - $().text().contains 'Second block counter 52' - $().text().contains 'Third block counter 53' + $().text().contains('First block counter 51') + $().text().contains('Second block counter 52') + $().text().contains('Third block counter 53') when: go('/demo/blockCache?counter=150') then: - $().text().contains 'First block counter 51' - $().text().contains 'Second block counter 52' - $().text().contains 'Third block counter 53' + $().text().contains('First block counter 51') + $().text().contains('Second block counter 52') + $().text().contains('Third block counter 53') } void 'test expire blocks cache based on ttl'() { @@ -112,34 +112,34 @@ class CacheTagIntegrationSpec extends ContainerGebSpec { go("/demo/blockCacheTTL?counter=100&ttl=${ttlSeconds}") then: - $().text().contains 'First block counter 101' - $().text().contains 'Second block counter 102' - $().text().contains 'Third block counter 103' + $().text().contains('First block counter 101') + $().text().contains('Second block counter 102') + $().text().contains('Third block counter 103') when: go("/demo/blockCacheTTL?counter=42&ttl=${ttlSeconds}") then: - $().text().contains 'First block counter 101' - $().text().contains 'Second block counter 102' - $().text().contains 'Third block counter 103' + $().text().contains('First block counter 101') + $().text().contains('Second block counter 102') + $().text().contains('Third block counter 103') TimeUnit.SECONDS.sleep(ttlSeconds) when: go("/demo/blockCacheTTL?counter=50&ttl=${ttlSeconds}") then: - $().text().contains 'First block counter 51' - $().text().contains 'Second block counter 52' - $().text().contains 'Third block counter 53' + $().text().contains('First block counter 51') + $().text().contains('Second block counter 52') + $().text().contains('Third block counter 53') when: go("/demo/blockCacheTTL?counter=150&ttl=${ttlSeconds}") then: - $().text().contains 'First block counter 51' - $().text().contains 'Second block counter 52' - $().text().contains 'Third block counter 53' + $().text().contains('First block counter 51') + $().text().contains('Second block counter 52') + $().text().contains('Third block counter 53') } void 'test render tag'() { @@ -147,47 +147,47 @@ class CacheTagIntegrationSpec extends ContainerGebSpec { go('/demo/renderTag?counter=1') then: - $().text().contains 'First invocation: Counter value: 1' - $().text().contains 'Second invocation: Counter value: 1' - $().text().contains 'Third invocation: Counter value: 3' - $().text().contains 'Fourth invocation: Counter value: 3' - $().text().contains 'Fifth invocation: Counter value: 1' + $().text().contains('First invocation: Counter value: 1') + $().text().contains('Second invocation: Counter value: 1') + $().text().contains('Third invocation: Counter value: 3') + $().text().contains('Fourth invocation: Counter value: 3') + $().text().contains('Fifth invocation: Counter value: 1') when: go('/demo/renderTag?counter=5') then: - $().text().contains 'First invocation: Counter value: 1' - $().text().contains 'Second invocation: Counter value: 1' - $().text().contains 'Third invocation: Counter value: 3' - $().text().contains 'Fourth invocation: Counter value: 3' - $().text().contains 'Fifth invocation: Counter value: 1' + $().text().contains('First invocation: Counter value: 1') + $().text().contains('Second invocation: Counter value: 1') + $().text().contains('Third invocation: Counter value: 3') + $().text().contains('Fourth invocation: Counter value: 3') + $().text().contains('Fifth invocation: Counter value: 1') when: go('/demo/clearTemplatesCache') then: - pageSource.contains 'cleared templates cache' + pageSource.contains('cleared templates cache') when: go('/demo/renderTag?counter=5') then: - $().text().contains 'First invocation: Counter value: 5' - $().text().contains 'Second invocation: Counter value: 5' - $().text().contains 'Third invocation: Counter value: 7' - $().text().contains 'Fourth invocation: Counter value: 7' - $().text().contains 'Fifth invocation: Counter value: 5' + $().text().contains('First invocation: Counter value: 5') + $().text().contains('Second invocation: Counter value: 5') + $().text().contains('Third invocation: Counter value: 7') + $().text().contains('Fourth invocation: Counter value: 7') + $().text().contains('Fifth invocation: Counter value: 5') when: go('/demo/renderTag?counter=1') then: - $().text().contains 'First invocation: Counter value: 5' - $().text().contains 'Second invocation: Counter value: 5' - $().text().contains 'Third invocation: Counter value: 7' - $().text().contains 'Fourth invocation: Counter value: 7' - $().text().contains 'Fifth invocation: Counter value: 5' + $().text().contains('First invocation: Counter value: 5') + $().text().contains('Second invocation: Counter value: 5') + $().text().contains('Third invocation: Counter value: 7') + $().text().contains('Fourth invocation: Counter value: 7') + $().text().contains('Fifth invocation: Counter value: 5') } void 'test expire render cache based on ttl'() { @@ -197,41 +197,41 @@ class CacheTagIntegrationSpec extends ContainerGebSpec { go("/demo/renderTagTTL?counter=1&ttl=${ttlSeconds}") then: - $().text().contains 'First invocation: Counter value: 1' - $().text().contains 'Second invocation: Counter value: 1' - $().text().contains 'Third invocation: Counter value: 3' - $().text().contains 'Fourth invocation: Counter value: 3' - $().text().contains 'Fifth invocation: Counter value: 1' + $().text().contains('First invocation: Counter value: 1') + $().text().contains('Second invocation: Counter value: 1') + $().text().contains('Third invocation: Counter value: 3') + $().text().contains('Fourth invocation: Counter value: 3') + $().text().contains('Fifth invocation: Counter value: 1') when: - go "/demo/renderTagTTL?counter=5&ttl=${ttlSeconds}" + go("/demo/renderTagTTL?counter=5&ttl=${ttlSeconds}") then: - $().text().contains 'First invocation: Counter value: 1' - $().text().contains 'Second invocation: Counter value: 1' - $().text().contains 'Third invocation: Counter value: 3' - $().text().contains 'Fourth invocation: Counter value: 3' - $().text().contains 'Fifth invocation: Counter value: 1' + $().text().contains('First invocation: Counter value: 1') + $().text().contains('Second invocation: Counter value: 1') + $().text().contains('Third invocation: Counter value: 3') + $().text().contains('Fourth invocation: Counter value: 3') + $().text().contains('Fifth invocation: Counter value: 1') TimeUnit.SECONDS.sleep(ttlSeconds) when: - go "/demo/renderTagTTL?counter=5&ttl=${ttlSeconds}" + go("/demo/renderTagTTL?counter=5&ttl=${ttlSeconds}") then: - $().text().contains 'First invocation: Counter value: 5' - $().text().contains 'Second invocation: Counter value: 5' - $().text().contains 'Third invocation: Counter value: 7' - $().text().contains 'Fourth invocation: Counter value: 7' - $().text().contains 'Fifth invocation: Counter value: 5' + $().text().contains('First invocation: Counter value: 5') + $().text().contains('Second invocation: Counter value: 5') + $().text().contains('Third invocation: Counter value: 7') + $().text().contains('Fourth invocation: Counter value: 7') + $().text().contains('Fifth invocation: Counter value: 5') when: - go "/demo/renderTagTTL?counter=1&ttl=${ttlSeconds}" + go("/demo/renderTagTTL?counter=1&ttl=${ttlSeconds}") then: - $().text().contains 'First invocation: Counter value: 5' - $().text().contains 'Second invocation: Counter value: 5' - $().text().contains 'Third invocation: Counter value: 7' - $().text().contains 'Fourth invocation: Counter value: 7' - $().text().contains 'Fifth invocation: Counter value: 5' + $().text().contains('First invocation: Counter value: 5') + $().text().contains('Second invocation: Counter value: 5') + $().text().contains('Third invocation: Counter value: 7') + $().text().contains('Fourth invocation: Counter value: 7') + $().text().contains('Fifth invocation: Counter value: 5') } } diff --git a/grails-test-examples/cache/src/integration-test/groovy/com/demo/NotCachingControllerIntegrationSpec.groovy b/grails-test-examples/cache/src/integration-test/groovy/com/demo/NotCachingControllerIntegrationSpec.groovy index 02486440b66..b439ba9856f 100644 --- a/grails-test-examples/cache/src/integration-test/groovy/com/demo/NotCachingControllerIntegrationSpec.groovy +++ b/grails-test-examples/cache/src/integration-test/groovy/com/demo/NotCachingControllerIntegrationSpec.groovy @@ -30,12 +30,12 @@ class NotCachingControllerIntegrationSpec extends ContainerGebSpec { go('/demo/show/1') then: - $().text().contains 'Hello World!1' + $().text().contains('Hello World!1') when: go('/demo/show/2') then: - $().text().contains 'Hello World!2' + $().text().contains('Hello World!2') } } \ No newline at end of file diff --git a/grails-test-examples/geb/src/integration-test/groovy/org/demo/spock/InheritedConfigSpec.groovy b/grails-test-examples/geb/src/integration-test/groovy/org/demo/spock/InheritedConfigSpec.groovy index ab770d17371..970a6a6f9b0 100644 --- a/grails-test-examples/geb/src/integration-test/groovy/org/demo/spock/InheritedConfigSpec.groovy +++ b/grails-test-examples/geb/src/integration-test/groovy/org/demo/spock/InheritedConfigSpec.groovy @@ -43,7 +43,7 @@ class NotSuperSpec extends ContainerGebSpec {} class InheritedConfigSpec extends SuperSpec { void 'should show the right server name when visiting /serverName'() { when: 'visiting the server name controller' - go(('/serverName')) + go('/serverName') then: 'the emitted hostname is correct' pageSource.contains('Server name: super.example.com') @@ -67,7 +67,7 @@ class ChildPreferenceInheritedConfigSpec extends SuperSpec { String hostName() { return 'child.example.com' } - + void 'should show the right server name when visiting /serverName'() { when: 'visiting the server name controller' go('/serverName') diff --git a/grails-test-examples/gsp-layout/src/integration-test/groovy/GrailsLayoutSpec.groovy b/grails-test-examples/gsp-layout/src/integration-test/groovy/GrailsLayoutSpec.groovy index 598fe2edf08..d32c9b859e4 100644 --- a/grails-test-examples/gsp-layout/src/integration-test/groovy/GrailsLayoutSpec.groovy +++ b/grails-test-examples/gsp-layout/src/integration-test/groovy/GrailsLayoutSpec.groovy @@ -25,7 +25,7 @@ class GrailsLayoutSpec extends ContainerGebSpec { void "forced layout"() { when: - browser.go('demo/index') + go('demo/index') then: pageSource.contains('Do you like BootStrap?') @@ -33,7 +33,7 @@ class GrailsLayoutSpec extends ContainerGebSpec { void "decorator chaining"() { when: - browser.go('demo/chaining') + go('demo/chaining') then: pageSource.contains('This is so cool.') @@ -41,7 +41,7 @@ class GrailsLayoutSpec extends ContainerGebSpec { void "jsp demo"() { when: - browser.go('demo/jsp') + go('demo/jsp') then: def container = browser.$('div.container') @@ -52,7 +52,7 @@ class GrailsLayoutSpec extends ContainerGebSpec { void "text"() { when: - browser.go('demo/renderText') + go('demo/renderText') then: downloadText() == '''

Hello World

''' @@ -60,7 +60,7 @@ class GrailsLayoutSpec extends ContainerGebSpec { void "Controller 500 Example"() { when: - browser.go('demo/exception') + go('demo/exception') then: pageSource.contains('Whoops, why would you ever want to see an exception??') @@ -68,7 +68,7 @@ class GrailsLayoutSpec extends ContainerGebSpec { void "View 500 Example"() { when: - browser.go('demo/viewException') + go('demo/viewException') then: pageSource.contains('Oh Man, this view sucks!') @@ -76,7 +76,7 @@ class GrailsLayoutSpec extends ContainerGebSpec { void "404 Error"() { when: - browser.go('demo/404') + go('demo/404') then: pageSource.contains('Error: Page Not Found (404)') From 06031d5dd38b75a256c2f63b831fd16bdcbd08bf Mon Sep 17 00:00:00 2001 From: James Daugherty Date: Sat, 5 Jul 2025 17:48:14 -0400 Subject: [PATCH 24/26] refactor: move GrailsResponseMutator to grails-web-common --- .../main/groovy/grails/web/mvc}/GrailsResponseMutator.groovy | 2 +- .../groovy/org/grails/web/errors/GrailsExceptionResolver.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename {grails-encoder/src/main/groovy/org/grails/buffer => grails-web-common/src/main/groovy/grails/web/mvc}/GrailsResponseMutator.groovy (97%) diff --git a/grails-encoder/src/main/groovy/org/grails/buffer/GrailsResponseMutator.groovy b/grails-web-common/src/main/groovy/grails/web/mvc/GrailsResponseMutator.groovy similarity index 97% rename from grails-encoder/src/main/groovy/org/grails/buffer/GrailsResponseMutator.groovy rename to grails-web-common/src/main/groovy/grails/web/mvc/GrailsResponseMutator.groovy index e3358671dce..df97ad84074 100644 --- a/grails-encoder/src/main/groovy/org/grails/buffer/GrailsResponseMutator.groovy +++ b/grails-web-common/src/main/groovy/grails/web/mvc/GrailsResponseMutator.groovy @@ -17,7 +17,7 @@ * under the License. */ -package org.grails.buffer +package grails.web.mvc /** * Interface to assign to a HttpServletResponse wrapper so on an error, it can be deactivated to not further diff --git a/grails-web-mvc/src/main/groovy/org/grails/web/errors/GrailsExceptionResolver.java b/grails-web-mvc/src/main/groovy/org/grails/web/errors/GrailsExceptionResolver.java index 10a4948e513..918106535b1 100644 --- a/grails-web-mvc/src/main/groovy/org/grails/web/errors/GrailsExceptionResolver.java +++ b/grails-web-mvc/src/main/groovy/org/grails/web/errors/GrailsExceptionResolver.java @@ -35,7 +35,7 @@ import org.apache.commons.logging.LogFactory; import org.codehaus.groovy.control.CompilationFailedException; import grails.core.GrailsApplication; -import org.grails.buffer.GrailsResponseMutator; +import grails.web.mvc.GrailsResponseMutator; import org.grails.exceptions.reporting.DefaultStackTraceFilterer; import org.grails.core.exceptions.GrailsRuntimeException; import org.grails.exceptions.reporting.StackTraceFilterer; From 69f1cf4a6662d8947a186abd35aac45784feeff9 Mon Sep 17 00:00:00 2001 From: James Daugherty Date: Sun, 6 Jul 2025 08:50:12 -0400 Subject: [PATCH 25/26] feedback: styling --- .../DatabaseMigrationGrailsPlugin.groovy | 2 +- .../plugins/sitemesh3/Sitemesh3GrailsPlugin.groovy | 2 +- .../plugins/web/GroovyPagesGrailsPlugin.groovy | 12 ++++++------ .../grails/web/taglib/AbstractGrailsTagTests.groovy | 11 ++++++----- ...plesViewsFunctionalTestsPluginGrailsPlugin.groovy | 2 +- 5 files changed, 15 insertions(+), 14 deletions(-) diff --git a/grails-data-hibernate5/dbmigration/src/main/groovy/org/grails/plugins/databasemigration/DatabaseMigrationGrailsPlugin.groovy b/grails-data-hibernate5/dbmigration/src/main/groovy/org/grails/plugins/databasemigration/DatabaseMigrationGrailsPlugin.groovy index c6c2cc40d05..771ed86765b 100644 --- a/grails-data-hibernate5/dbmigration/src/main/groovy/org/grails/plugins/databasemigration/DatabaseMigrationGrailsPlugin.groovy +++ b/grails-data-hibernate5/dbmigration/src/main/groovy/org/grails/plugins/databasemigration/DatabaseMigrationGrailsPlugin.groovy @@ -32,7 +32,7 @@ class DatabaseMigrationGrailsPlugin extends Plugin { static final String CONFIG_MAIN_PREFIX = 'grails.plugin.databasemigration' - def grailsVersion = "7.0.0-SNAPSHOT > *" + def grailsVersion = '7.0.0-SNAPSHOT > *' def pluginExcludes = [ "**/testapp/**", "grails-app/views/error.gsp" diff --git a/grails-gsp/grails-sitemesh3/src/main/groovy/org/grails/plugins/sitemesh3/Sitemesh3GrailsPlugin.groovy b/grails-gsp/grails-sitemesh3/src/main/groovy/org/grails/plugins/sitemesh3/Sitemesh3GrailsPlugin.groovy index cb20ee5b7a0..8798f1ffb79 100644 --- a/grails-gsp/grails-sitemesh3/src/main/groovy/org/grails/plugins/sitemesh3/Sitemesh3GrailsPlugin.groovy +++ b/grails-gsp/grails-sitemesh3/src/main/groovy/org/grails/plugins/sitemesh3/Sitemesh3GrailsPlugin.groovy @@ -31,7 +31,7 @@ import org.springframework.core.env.PropertySource class Sitemesh3GrailsPlugin extends Plugin { - def grailsVersion = "7.0.0-SNAPSHOT > *" + def grailsVersion = '7.0.0-SNAPSHOT > *' def title = "SiteMesh 3" def author = "Scott Murphy" diff --git a/grails-gsp/plugin/src/main/groovy/org/grails/plugins/web/GroovyPagesGrailsPlugin.groovy b/grails-gsp/plugin/src/main/groovy/org/grails/plugins/web/GroovyPagesGrailsPlugin.groovy index 628c2662a51..0d18080d9c6 100644 --- a/grails-gsp/plugin/src/main/groovy/org/grails/plugins/web/GroovyPagesGrailsPlugin.groovy +++ b/grails-gsp/plugin/src/main/groovy/org/grails/plugins/web/GroovyPagesGrailsPlugin.groovy @@ -69,13 +69,13 @@ import org.springframework.web.servlet.view.InternalResourceViewResolver @Slf4j class GroovyPagesGrailsPlugin extends Plugin { - public static final String GSP_RELOAD_INTERVAL = "grails.gsp.reload.interval" + public static final String GSP_RELOAD_INTERVAL = 'grails.gsp.reload.interval' public static final String GSP_VIEWS_DIR = 'grails.gsp.view.dir' - def watchedResources = ["file:./plugins/*/grails-app/taglib/**/*TagLib.groovy", - "file:./grails-app/taglib/**/*TagLib.groovy"] + def watchedResources = ['file:./plugins/*/grails-app/taglib/**/*TagLib.groovy', + 'file:./grails-app/taglib/**/*TagLib.groovy'] - def grailsVersion = "7.0.0-SNAPSHOT > *" + def grailsVersion = '7.0.0-SNAPSHOT > *' def dependsOn = [core: GrailsUtil.getGrailsVersion(), i18n: GrailsUtil.getGrailsVersion()] def observe = ['controllers'] def loadAfter = ['filters'] @@ -99,7 +99,7 @@ class GroovyPagesGrailsPlugin extends Plugin { @CompileStatic @Override void doWithApplicationContext() { - applicationContext.getBean("groovyPagesTemplateEngine", GroovyPagesTemplateEngine).clearPageCache() + applicationContext.getBean('groovyPagesTemplateEngine', GroovyPagesTemplateEngine).clearPageCache() } /** @@ -235,7 +235,7 @@ class GroovyPagesGrailsPlugin extends Plugin { } boolean jstlPresent = ClassUtils.isPresent( - "jakarta.servlet.jsp.jstl.core.Config", InternalResourceViewResolver.class.getClassLoader()) + 'jakarta.servlet.jsp.jstl.core.Config', InternalResourceViewResolver.class.getClassLoader()) abstractViewResolver { prefix = GrailsApplicationAttributes.PATH_TO_VIEWS diff --git a/grails-gsp/plugin/src/test/groovy/org/grails/web/taglib/AbstractGrailsTagTests.groovy b/grails-gsp/plugin/src/test/groovy/org/grails/web/taglib/AbstractGrailsTagTests.groovy index 9c659d87c1b..859f091fdc2 100644 --- a/grails-gsp/plugin/src/test/groovy/org/grails/web/taglib/AbstractGrailsTagTests.groovy +++ b/grails-gsp/plugin/src/test/groovy/org/grails/web/taglib/AbstractGrailsTagTests.groovy @@ -143,7 +143,7 @@ abstract class AbstractGrailsTagTests { for (i in 0..100) { callable.call() } - println "$name took ${System.currentTimeMillis() - now}ms" + println("$name took ${System.currentTimeMillis() - now}ms") } def withTag(String tagName, Writer out, String tagNamespace = 'g', Closure callable) { @@ -428,14 +428,14 @@ abstract class AbstractGrailsTagTests { void assertOutputContains(expected, template, params = [:]) { def result = applyTemplate(template, params) - assertTrue result.indexOf(expected) > -1, - "Output does not contain expected string [$expected]. Output was: [${result}]" + assertTrue(result.indexOf(expected) > -1, + "Output does not contain expected string [$expected]. Output was: [${result}]") } void assertOutputNotContains(expected, template, params = [:]) { def result = applyTemplate(template, params) - assertFalse result.indexOf(expected) > -1, - "Output should not contain the expected string [$expected]. Output was: [${result}]" + assertFalse(result.indexOf(expected) > -1, + "Output should not contain the expected string [$expected]. Output was: [${result}]") } /** @@ -534,6 +534,7 @@ abstract class AbstractGrailsTagTests { } class MockThemeSource implements ThemeSource { + private messageSource MockThemeSource(MessageSource messageSource) { diff --git a/grails-test-examples/views-functional-tests-plugin/src/main/groovy/functional/tests/plugin/GrailsTestExamplesViewsFunctionalTestsPluginGrailsPlugin.groovy b/grails-test-examples/views-functional-tests-plugin/src/main/groovy/functional/tests/plugin/GrailsTestExamplesViewsFunctionalTestsPluginGrailsPlugin.groovy index 2ee83e68c79..08765d54b1a 100644 --- a/grails-test-examples/views-functional-tests-plugin/src/main/groovy/functional/tests/plugin/GrailsTestExamplesViewsFunctionalTestsPluginGrailsPlugin.groovy +++ b/grails-test-examples/views-functional-tests-plugin/src/main/groovy/functional/tests/plugin/GrailsTestExamplesViewsFunctionalTestsPluginGrailsPlugin.groovy @@ -24,7 +24,7 @@ import grails.plugins.Plugin class GrailsTestExamplesViewsFunctionalTestsPluginGrailsPlugin extends Plugin { // the version or versions of Grails the plugin is designed for - def grailsVersion = "7.0.0-SNAPSHOT > *" + def grailsVersion = '7.0.0-SNAPSHOT > *' // resources that are excluded from plugin packaging def pluginExcludes = [ "grails-app/views/error.gsp" From 146872d192bf76340d1d8f7d2d82e88e5e85e0ac Mon Sep 17 00:00:00 2001 From: James Daugherty Date: Sun, 6 Jul 2025 11:01:44 -0400 Subject: [PATCH 26/26] revert double quote conversion --- .../src/test/groovy/org/grails/web/pages/ParseSpec.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grails-gsp/plugin/src/test/groovy/org/grails/web/pages/ParseSpec.groovy b/grails-gsp/plugin/src/test/groovy/org/grails/web/pages/ParseSpec.groovy index 3e5e73a55f0..4f07bf67dbe 100644 --- a/grails-gsp/plugin/src/test/groovy/org/grails/web/pages/ParseSpec.groovy +++ b/grails-gsp/plugin/src/test/groovy/org/grails/web/pages/ParseSpec.groovy @@ -216,7 +216,7 @@ public static final String TAGLIB_CODEC = 'none' String expected = makeImports() + '\n' + 'class GRAILS5598 extends org.grails.gsp.GroovyPage {\n' + - 'public String getGroovyPageFileName() { \'GRAILS5598\' }\n' + + 'public String getGroovyPageFileName() { "GRAILS5598" }\n' + 'public Object run() {\n' + 'Writer out = getOut()\n' + 'Writer expressionOut = getExpressionOut()\n' +