jdaugherty commented on PR #16272:
URL: https://github.com/apache/grails-core/pull/16272#issuecomment-5878126830

   **Suggested functional tests: fields plugin links under a renamed scaffold, 
in `scaffolding-fields`**
   
   Could you add these to this PR? `RenamedScaffoldLinksSpec` adds `Crew 
hasMany Sailor`, with `Sailor` served by `@Scaffold(Sailor) class 
DeckhandsController` and no `SailorController`. It pins the one-to-many display 
links, the "Add" link of the one-to-many input, the to-one link back from the 
renamed controller, and the redirect after a form save.
   
   All 140 tests in the app pass at `5c4195c5a9`. 3 of the 4 new ones fail on 
8.0.x, where those links and the redirect all point at `/sailor/...`.
   
   Apply from the repository root with `git apply`; it applies cleanly to 
`5c4195c5a9`.
   
   <details><summary><code>scaffolding-fields</code> patch (6 files)</summary>
   
   ```diff
   diff --git a/grails-test-examples/scaffolding-fields/build.gradle 
b/grails-test-examples/scaffolding-fields/build.gradle
   index 328a0e7dc2..ec65fb4b3c 100644
   --- a/grails-test-examples/scaffolding-fields/build.gradle
   +++ b/grails-test-examples/scaffolding-fields/build.gradle
   @@ -53,6 +53,7 @@ dependencies {
    
    
        integrationTestImplementation 
testFixtures('org.apache.grails:grails-geb')
   +    integrationTestImplementation 
'org.apache.grails:grails-testing-support-http-client'
    }
    
    apply {
   diff --git 
a/grails-test-examples/scaffolding-fields/grails-app/controllers/scaffoldingfields/CrewController.groovy
 
b/grails-test-examples/scaffolding-fields/grails-app/controllers/scaffoldingfields/CrewController.groovy
   new file mode 100644
   index 0000000000..7e8f6a38c8
   --- /dev/null
   +++ 
b/grails-test-examples/scaffolding-fields/grails-app/controllers/scaffoldingfields/CrewController.groovy
   @@ -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.
   + */
   +package scaffoldingfields
   +
   +import grails.plugin.scaffolding.annotation.Scaffold
   +
   +@Scaffold(Crew)
   +class CrewController {
   +}
   diff --git 
a/grails-test-examples/scaffolding-fields/grails-app/controllers/scaffoldingfields/DeckhandsController.groovy
 
b/grails-test-examples/scaffolding-fields/grails-app/controllers/scaffoldingfields/DeckhandsController.groovy
   new file mode 100644
   index 0000000000..a091e4c834
   --- /dev/null
   +++ 
b/grails-test-examples/scaffolding-fields/grails-app/controllers/scaffoldingfields/DeckhandsController.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 scaffoldingfields
   +
   +import grails.plugin.scaffolding.annotation.Scaffold
   +
   +/**
   + * Serves {@link Sailor} under a name other than the domain class's, with 
no SailorController.
   + */
   +@Scaffold(Sailor)
   +class DeckhandsController {
   +}
   diff --git 
a/grails-test-examples/scaffolding-fields/grails-app/domain/scaffoldingfields/Crew.groovy
 
b/grails-test-examples/scaffolding-fields/grails-app/domain/scaffoldingfields/Crew.groovy
   new file mode 100644
   index 0000000000..7a16cfc8b2
   --- /dev/null
   +++ 
b/grails-test-examples/scaffolding-fields/grails-app/domain/scaffoldingfields/Crew.groovy
   @@ -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 scaffoldingfields
   +
   +class Crew {
   +
   +    String name
   +
   +    static hasMany = [sailors: Sailor]
   +
   +    String toString() {
   +        name
   +    }
   +}
   diff --git 
a/grails-test-examples/scaffolding-fields/grails-app/domain/scaffoldingfields/Sailor.groovy
 
b/grails-test-examples/scaffolding-fields/grails-app/domain/scaffoldingfields/Sailor.groovy
   new file mode 100644
   index 0000000000..5445bc62d5
   --- /dev/null
   +++ 
b/grails-test-examples/scaffolding-fields/grails-app/domain/scaffoldingfields/Sailor.groovy
   @@ -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 scaffoldingfields
   +
   +class Sailor {
   +
   +    String name
   +
   +    static belongsTo = [crew: Crew]
   +
   +    String toString() {
   +        name
   +    }
   +}
   diff --git 
a/grails-test-examples/scaffolding-fields/src/integration-test/groovy/scaffoldingfields/RenamedScaffoldLinksSpec.groovy
 
b/grails-test-examples/scaffolding-fields/src/integration-test/groovy/scaffoldingfields/RenamedScaffoldLinksSpec.groovy
   new file mode 100644
   index 0000000000..e8f0e0e173
   --- /dev/null
   +++ 
b/grails-test-examples/scaffolding-fields/src/integration-test/groovy/scaffoldingfields/RenamedScaffoldLinksSpec.groovy
   @@ -0,0 +1,118 @@
   +/*
   + *  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 scaffoldingfields
   +
   +import java.net.http.HttpClient
   +import java.util.regex.Matcher
   +import java.util.regex.Pattern
   +
   +import spock.lang.Shared
   +import spock.lang.Specification
   +import spock.lang.Tag
   +
   +import grails.testing.mixin.integration.Integration
   +import org.apache.grails.testing.http.client.HttpClientSupport
   +import org.apache.grails.testing.http.client.TestHttpResponse
   +
   +/**
   + * Pins the association links the fields plugin renders, and the redirect 
after a save, for a domain class
   + * served by a scaffolded controller not named after it.
   + */
   +@Integration
   +@Tag('http-client')
   +class RenamedScaffoldLinksSpec extends Specification implements 
HttpClientSupport {
   +
   +    @Shared
   +    Map<String, Long> ids = [:]
   +
   +    void setup() {
   +        if (!ids) {
   +            Crew.withNewTransaction {
   +                Crew crew = new Crew(name: 'Pequod')
   +                crew.addToSailors(new Sailor(name: 'Ishmael'))
   +                crew.save(flush: true, failOnError: true)
   +                ids.crew = crew.id
   +                ids.ishmael = crew.sailors.first().id
   +            }
   +        }
   +    }
   +
   +    void "a one-to-many association links each element to the controller 
serving it"() {
   +        when:
   +        String href = anchorHref(page("/crew/show/${ids.crew}"), 'Ishmael')
   +
   +        then:
   +        href == "${contextPath}/deckhands/show/${ids.ishmael}"
   +        bodyAt(href).contains('Ishmael')
   +    }
   +
   +    void "the add link of a one-to-many input targets the controller 
serving the element"() {
   +        when:
   +        String href = anchorHref(page("/crew/edit/${ids.crew}"), 'Add 
Sailor')
   +
   +        then:
   +        href == "${contextPath}/deckhands/create?crew.id=${ids.crew}"
   +        bodyAt(href).contains('Create Sailor')
   +    }
   +
   +    void "a to-one association rendered by the renamed controller links to 
its owner"() {
   +        when:
   +        String href = anchorHref(page("/deckhands/show/${ids.ishmael}"), 
'Pequod')
   +
   +        then:
   +        href == "${contextPath}/crew/show/${ids.crew}"
   +    }
   +
   +    void "a form save on the renamed controller redirects to it"() {
   +        given:
   +        HttpClient client = newHttpClientWith { 
followRedirects(HttpClient.Redirect.NEVER) }
   +
   +        when:
   +        TestHttpResponse response = httpPost([:], '/deckhands/save', 
"name=Starbuck&crew.id=${ids.crew}",
   +                'application/x-www-form-urlencoded', client)
   +        String location = new URI(response.headerValue('Location') ?: 
'').path
   +
   +        then:
   +        response.statusCode() == 302
   +        location ==~ Pattern.quote("${contextPath}/deckhands/show/") + /\d+/
   +        bodyAt(location).contains('Starbuck')
   +    }
   +
   +    private String page(String path) {
   +        TestHttpResponse response = http(path)
   +        assert response.statusCode() == 200
   +        response.body() as String
   +    }
   +
   +    private String getContextPath() {
   +        new URI(httpBaseUrl).path
   +    }
   +
   +    private String bodyAt(String path) {
   +        URI base = new URI(httpBaseUrl)
   +        TestHttpResponse response = 
http("${base.scheme}://${base.authority}${path}")
   +        response.statusCode() == 200 ? response.body() as String : "HTTP 
${response.statusCode()}"
   +    }
   +
   +    private static String anchorHref(String html, String text) {
   +        Matcher anchor = html =~ 
/<a\b[^>]*\bhref="([^"]*)"[^>]*>\s*${Pattern.quote(text)}\s*<\/a>/
   +        assert anchor.find(), "no link reading ${text}"
   +        anchor.group(1).replace('&amp;', '&')
   +    }
   +}
   ```
   
   </details>


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to