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

   **Suggested functional tests: HAL links for renamed controllers, in 
`views-functional-tests`**
   
   Could you add these to this PR? `RenamedControllerHalLinksSpec` serves 
`Magazine` through JSON views (`PeriodicalsController`) and `Journal` through 
`HalJsonRenderer` and `HalJsonCollectionRenderer`, registered in a new 
`resources.groovy` (`PapersController`). Both reference a `Publisher` served by 
`PublishersController`, and no controller is named after any of the three. It 
pins the instance and collection self links on both paths, and the renderer's 
association link to `publisher`.
   
   All 56 tests in the app pass at `5c4195c5a9`. All 4 new ones fail on 8.0.x, 
which renders `/magazine/show/1`, `/magazine/index`, `/journal/show/1` and 
`/publisher/show/1`.
   
   Apply from the repository root with `git apply`; it applies cleanly to 
`5c4195c5a9`.
   
   <details><summary><code>views-functional-tests</code> patch (11 
files)</summary>
   
   ```diff
   diff --git 
a/grails-test-examples/views-functional-tests/grails-app/conf/spring/resources.groovy
 
b/grails-test-examples/views-functional-tests/grails-app/conf/spring/resources.groovy
   new file mode 100644
   index 0000000000..b2357c3ac0
   --- /dev/null
   +++ 
b/grails-test-examples/views-functional-tests/grails-app/conf/spring/resources.groovy
   @@ -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.
   + */
   +import functional.tests.Journal
   +import grails.rest.render.hal.HalJsonCollectionRenderer
   +import grails.rest.render.hal.HalJsonRenderer
   +
   +beans = {
   +    journalHalRenderer(HalJsonRenderer, Journal)
   +    journalHalCollectionRenderer(HalJsonCollectionRenderer, Journal)
   +}
   diff --git 
a/grails-test-examples/views-functional-tests/grails-app/controllers/functional/tests/PapersController.groovy
 
b/grails-test-examples/views-functional-tests/grails-app/controllers/functional/tests/PapersController.groovy
   new file mode 100644
   index 0000000000..f4b6914677
   --- /dev/null
   +++ 
b/grails-test-examples/views-functional-tests/grails-app/controllers/functional/tests/PapersController.groovy
   @@ -0,0 +1,34 @@
   +/*
   + *  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 functional.tests
   +
   +import grails.rest.RestfulController
   +
   +/**
   + * Serves {@link Journal} through the HAL renderers registered in 
resources.groovy, under a name other
   + * than the domain class's.
   + */
   +class PapersController extends RestfulController<Journal> {
   +
   +    static responseFormats = ['json', 'hal']
   +
   +    PapersController() {
   +        super(Journal)
   +    }
   +}
   diff --git 
a/grails-test-examples/views-functional-tests/grails-app/controllers/functional/tests/PeriodicalsController.groovy
 
b/grails-test-examples/views-functional-tests/grails-app/controllers/functional/tests/PeriodicalsController.groovy
   new file mode 100644
   index 0000000000..25f3255c10
   --- /dev/null
   +++ 
b/grails-test-examples/views-functional-tests/grails-app/controllers/functional/tests/PeriodicalsController.groovy
   @@ -0,0 +1,33 @@
   +/*
   + *  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 functional.tests
   +
   +import grails.rest.RestfulController
   +
   +/**
   + * Serves {@link Magazine} through JSON views, under a name other than the 
domain class's.
   + */
   +class PeriodicalsController extends RestfulController<Magazine> {
   +
   +    static responseFormats = ['json', 'hal']
   +
   +    PeriodicalsController() {
   +        super(Magazine)
   +    }
   +}
   diff --git 
a/grails-test-examples/views-functional-tests/grails-app/controllers/functional/tests/PublishersController.groovy
 
b/grails-test-examples/views-functional-tests/grails-app/controllers/functional/tests/PublishersController.groovy
   new file mode 100644
   index 0000000000..43171935af
   --- /dev/null
   +++ 
b/grails-test-examples/views-functional-tests/grails-app/controllers/functional/tests/PublishersController.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 functional.tests
   +
   +import grails.rest.RestfulController
   +
   +class PublishersController extends RestfulController<Publisher> {
   +
   +    static responseFormats = ['json', 'hal']
   +
   +    PublishersController() {
   +        super(Publisher)
   +    }
   +}
   diff --git 
a/grails-test-examples/views-functional-tests/grails-app/controllers/functional/tests/UrlMappings.groovy
 
b/grails-test-examples/views-functional-tests/grails-app/controllers/functional/tests/UrlMappings.groovy
   index 886a14bd2b..5006cc9310 100644
   --- 
a/grails-test-examples/views-functional-tests/grails-app/controllers/functional/tests/UrlMappings.groovy
   +++ 
b/grails-test-examples/views-functional-tests/grails-app/controllers/functional/tests/UrlMappings.groovy
   @@ -46,6 +46,9 @@ class UrlMappings {
            "/teams/deep/$id"(controller: "team", action:"deep")
            "/teams/hal/$id"(controller: "team", action:"hal")
            "/authors"(resources:"author")
   +        "/periodicals"(resources:"periodicals")
   +        "/papers"(resources:"papers")
   +        "/publishers"(resources:"publishers")
            "/api/book/$action?"(controller: 'book', namespace: 'api')
            "/person-inheritance"(controller: 'personInheritance', action: 
'index')
            "/person-inheritance/npe"(controller: 'personInheritance', action: 
'npe')
   diff --git 
a/grails-test-examples/views-functional-tests/grails-app/domain/functional/tests/Journal.groovy
 
b/grails-test-examples/views-functional-tests/grails-app/domain/functional/tests/Journal.groovy
   new file mode 100644
   index 0000000000..09e0c8aa7e
   --- /dev/null
   +++ 
b/grails-test-examples/views-functional-tests/grails-app/domain/functional/tests/Journal.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 functional.tests
   +
   +class Journal {
   +
   +    String title
   +    Publisher publisher
   +}
   diff --git 
a/grails-test-examples/views-functional-tests/grails-app/domain/functional/tests/Magazine.groovy
 
b/grails-test-examples/views-functional-tests/grails-app/domain/functional/tests/Magazine.groovy
   new file mode 100644
   index 0000000000..1433cbe391
   --- /dev/null
   +++ 
b/grails-test-examples/views-functional-tests/grails-app/domain/functional/tests/Magazine.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 functional.tests
   +
   +class Magazine {
   +
   +    String title
   +    Publisher publisher
   +}
   diff --git 
a/grails-test-examples/views-functional-tests/grails-app/domain/functional/tests/Publisher.groovy
 
b/grails-test-examples/views-functional-tests/grails-app/domain/functional/tests/Publisher.groovy
   new file mode 100644
   index 0000000000..d401bf6eba
   --- /dev/null
   +++ 
b/grails-test-examples/views-functional-tests/grails-app/domain/functional/tests/Publisher.groovy
   @@ -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.
   + */
   +package functional.tests
   +
   +class Publisher {
   +
   +    String name
   +}
   diff --git 
a/grails-test-examples/views-functional-tests/grails-app/views/periodicals/index.gson
 
b/grails-test-examples/views-functional-tests/grails-app/views/periodicals/index.gson
   new file mode 100644
   index 0000000000..3bda0a74ce
   --- /dev/null
   +++ 
b/grails-test-examples/views-functional-tests/grails-app/views/periodicals/index.gson
   @@ -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.
   + */
   +import functional.tests.Magazine
   +
   +model {
   +    Iterable<Magazine> magazineList
   +}
   +
   +json hal.render(magazineList)
   diff --git 
a/grails-test-examples/views-functional-tests/grails-app/views/periodicals/show.gson
 
b/grails-test-examples/views-functional-tests/grails-app/views/periodicals/show.gson
   new file mode 100644
   index 0000000000..d563619379
   --- /dev/null
   +++ 
b/grails-test-examples/views-functional-tests/grails-app/views/periodicals/show.gson
   @@ -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.
   + */
   +import functional.tests.Magazine
   +
   +model {
   +    Magazine magazine
   +}
   +
   +json hal.render(magazine)
   diff --git 
a/grails-test-examples/views-functional-tests/src/integration-test/groovy/functional/tests/RenamedControllerHalLinksSpec.groovy
 
b/grails-test-examples/views-functional-tests/src/integration-test/groovy/functional/tests/RenamedControllerHalLinksSpec.groovy
   new file mode 100644
   index 0000000000..a07ebac53c
   --- /dev/null
   +++ 
b/grails-test-examples/views-functional-tests/src/integration-test/groovy/functional/tests/RenamedControllerHalLinksSpec.groovy
   @@ -0,0 +1,102 @@
   +/*
   + *  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 functional.tests
   +
   +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 HAL links rendered for domain classes served by controllers not 
named after them, through
   + * JSON views and through the HAL renderers.
   + */
   +@Integration
   +@Tag('http-client')
   +class RenamedControllerHalLinksSpec extends Specification implements 
HttpClientSupport {
   +
   +    private static final Map<String, String> HAL = [Accept: 
'application/hal+json']
   +
   +    @Shared
   +    Map<String, Long> ids = [:]
   +
   +    void setup() {
   +        if (!ids) {
   +            Publisher.withNewTransaction {
   +                Publisher publisher = new Publisher(name: 
'Penguin').save(flush: true, failOnError: true)
   +                ids.publisher = publisher.id
   +                ids.magazine = new Magazine(title: 'Wired', publisher: 
publisher).save(flush: true, failOnError: true).id
   +                ids.journal = new Journal(title: 'Nature', publisher: 
publisher).save(flush: true, failOnError: true).id
   +            }
   +        }
   +    }
   +
   +    void "a JSON view of an instance links it to the controller serving 
it"() {
   +        when:
   +        Map json = hal("/periodicals/${ids.magazine}")
   +
   +        then:
   +        path(json._links.self.href) == "/periodicals/${ids.magazine}"
   +    }
   +
   +    void "a JSON view of a collection links it, and each element, to the 
controller serving them"() {
   +        when:
   +        Map json = hal('/periodicals')
   +
   +        then:
   +        path(json._links.self.href) == '/periodicals'
   +        embedded(json)*._links*.self*.href.collect { path(it) } == 
["/periodicals/${ids.magazine}"]
   +    }
   +
   +    void "the HAL renderer links an instance and its lazy association to 
the controllers serving them"() {
   +        when:
   +        Map json = hal("/papers/${ids.journal}")
   +
   +        then:
   +        path(json._links.self.href) == "/papers/${ids.journal}"
   +        path(json._links.publisher.href) == "/publishers/${ids.publisher}"
   +    }
   +
   +    void "the HAL collection renderer links a collection, and each element, 
to the controller serving them"() {
   +        when:
   +        Map json = hal('/papers')
   +
   +        then:
   +        path(json._links.self.href) == '/papers'
   +        embedded(json)*._links*.self*.href.collect { path(it) } == 
["/papers/${ids.journal}"]
   +    }
   +
   +    private Map hal(String path) {
   +        TestHttpResponse response = http(HAL, path)
   +        assert response.statusCode() == 200
   +        response.json()
   +    }
   +
   +    private static List<Map> embedded(Map json) {
   +        def embedded = json._embedded
   +        (embedded instanceof Map ? ((Map) embedded).values().flatten() : 
embedded) as List<Map>
   +    }
   +
   +    private static String path(Object href) {
   +        href == null ? null : new URI(href.toString()).path
   +    }
   +}
   ```
   
   </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