All Downloads are FREE. Search and download functionalities are using the official Maven repository.

grails.testing.web.UrlMappingsUnitTest.groovy Maven / Gradle / Ivy

The newest version!
/*
 *  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
 *
 *    http://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.testing.web

import grails.core.GrailsControllerClass
import grails.web.UrlConverter
import grails.web.mapping.UrlCreator
import grails.web.mapping.UrlMappingInfo
import grails.web.mapping.UrlMappingsHolder
import groovy.transform.CompileDynamic
import junit.framework.AssertionFailedError
import org.grails.core.artefact.ControllerArtefactHandler
import org.grails.core.artefact.UrlMappingsArtefactHandler
import org.grails.gsp.GroovyPagesTemplateEngine
import org.grails.testing.ParameterizedGrailsUnitTest
import org.grails.web.mapping.UrlMappingsHolderFactoryBean
import org.grails.web.mapping.mvc.GrailsControllerUrlMappingInfo
import junit.framework.ComparisonFailure

import static junit.framework.Assert.assertEquals
import static junit.framework.Assert.assertNotNull

trait UrlMappingsUnitTest implements ParameterizedGrailsUnitTest, GrailsWebUnitTest {

    public static final String KEY_EXCEPTION = 'exception'
    private final List assertionKeys = ["controller", "action", "view"]

    Class[] getControllersToMock() {
        []
    }

    void configuredMockedControllers() {
        for(Class c : controllersToMock) {
            final GrailsControllerClass controllerArtefact = (GrailsControllerClass)grailsApplication.addArtefact(ControllerArtefactHandler.TYPE, c)
            controllerArtefact.initialize()
            defineBeans {
                "$controllerArtefact.name"(c) { bean ->
                    bean.scope = 'prototype'
                    bean.autowire = true
                }
            }
        }
        getArtefactInstance()
    }

    /**
     * @return The {@link UrlMappingsHolder} bean
     */
    UrlMappingsHolder getUrlMappingsHolder() {
        applicationContext.getBean("grailsUrlMappingsHolder", UrlMappingsHolder)
    }

    /**
     * Maps a URI and returns the appropriate controller instance
     *
     * @param uri The URI to map
     * @return The controller instance
     */
    Object mapURI(String uri) {
        UrlMappingsHolder mappingsHolder = getUrlMappingsHolder()

        UrlMappingInfo[] mappingInfos = mappingsHolder.matchAll(uri, request.method)
        for (UrlMappingInfo info in mappingInfos) {
            def backupParams = new HashMap(webRequest.params)
            info.configure(webRequest)

            webRequest.params.putAll(backupParams)
            if (info.viewName == null && info.URI == null) {
                if(info instanceof GrailsControllerUrlMappingInfo) {
                    def controller = info.controllerClass
                    if (controller != null) {
                        return applicationContext.getBean(controller.name)
                    }
                }
            }
        }
    }

    private boolean checkController(String controller, boolean throwEx) {
        final controllerClass = getControllerClass(controller)
        if (!controllerClass && throwEx) {
            throw new AssertionFailedError("Url mapping assertion failed, '$controller' is not a valid controller")
        }
        return controllerClass != null
    }

    /**
     * asserts a controller exists for the specified name and url
     *
     * @param controller The controller name
     * @param url The url
     */
    void assertController(String controller) {
        checkController(controller, true)
    }

    /**
     * @param controller The controller name
     * @param url The url
     * @return true If a controller exists for the specified name and url
     */
    boolean verifyController(String controller) {
        checkController(controller, false)
    }

    private boolean checkAction(String controller, String action, boolean throwEx) {
        final controllerClass = getControllerClass(controller)
        boolean valid = controllerClass?.mapsToURI("/$controller/$action")
        if (!valid && throwEx) {
            throw new AssertionFailedError("Url mapping assertion failed, '$action' is not a valid action of controller '$controller'")
        }
        valid
    }

    /**
     * Asserts an action exists for the specified controller name, action name and url
     *
     * @param controller The controller name
     * @param action The action name
     */
    void assertAction(String controller, String action) {
        checkAction(controller, action, true)
    }

    /**
     * @param controller The controller name
     * @param action The action name
     * @return true If an action exists for the specified controller name and action name
     */
    boolean verifyAction(String controller, String action) {
        checkAction(controller, action, false)
    }

    private boolean checkView(String controller, String view, boolean throwEx) {
        def pathPattern =  ((controller) ? "$controller/" : "") + "${view}.gsp"
        if (!pathPattern.startsWith('/')) {
            pathPattern = "/$pathPattern"
        }
        GroovyPagesTemplateEngine templateEngine = applicationContext.getBean("groovyPagesTemplateEngine", GroovyPagesTemplateEngine)

        def t = templateEngine.createTemplate(pathPattern)
        if (!t && throwEx) {
            throw new AssertionFailedError(
                    (controller) ? "Url mapping assertion failed, '$view' is not a valid view of controller '$controller'" : "Url mapping assertion failed, '$view' is not a valid view")
        }
        t != null
    }

    /**
     * Asserts a view exists for the specified controller name and view name
     *
     * @param controller The controller name
     * @param view The view name
     */
    void assertView(String controller, String view) {
        checkView(controller, view, true)
    }

    /**
     *
     * @param controller The controller name
     * @param view The view name
     * @param url The url
     * @return true If a view exists for the specified controller and view
     */
    boolean verifyView(String controller, String view) {
        checkView(controller, view, false)
    }


    /**
     * Asserts a URL mapping maps to the specified controller, action, and optionally also parameters. Example:
     *
     * 
     * 
     *           assertUrlMapping("/action1", controller: "grailsUrlMappingsTestCaseFake", action: "action1") {
     *              param1 = "value1"
     *              param2 = "value2"
     *           }
     * 
     * 
* @param assertions The assertions as named parameters * @param url The URL as a string * @param paramAssertions The parameters to assert defined in the body of the closure */ void assertUrlMapping(Map assertions, String url, Closure paramAssertions = null) { assertForwardUrlMapping(assertions, url, paramAssertions) if (assertions.controller && !(url instanceof Integer)) { assertReverseUrlMapping(assertions, url, paramAssertions) } } /** * Verifies a URL mapping maps to the specified controller, action, and optionally also parameters. Example: * *
     * 
     *           verifyUrlMapping("/action1", controller: "grailsUrlMappingsTestCaseFake", action: "action1") {
     *              param1 = "value1"
     *              param2 = "value2"
     *           }
     * 
     * 
* @param assertions The assertions as named parameters * @param url The URL as a string * @param paramAssertions The parameters to assert defined in the body of the closure * * @return True if the url matches the assertions */ boolean verifyUrlMapping(Map assertions, String url, Closure paramAssertions = null) { boolean returnValue = verifyForwardUrlMapping(assertions, url, paramAssertions) if (assertions.controller && !(url instanceof Integer)) { returnValue = returnValue && verifyReverseUrlMapping(assertions, url, paramAssertions) } returnValue } private boolean checkForwardUrlMapping(Map assertions, Object url, Closure paramAssertions, boolean throwEx) { UrlMappingsHolder mappingsHolder = getUrlMappingsHolder() if (assertions.action && !assertions.controller) { throw new IllegalArgumentException("Cannot assert action for url mapping without asserting controller") } if (assertions.controller) { if (!checkController((String)assertions.controller, throwEx)) { return false } } if (assertions.action) { if (!checkAction((String)assertions.controller, (String)assertions.action, throwEx)) { return false } } if (assertions.view) { if (!checkView((String) assertions.controller, (String) assertions.view, throwEx)) { return false } } List mappingInfos if (url instanceof Integer) { mappingInfos = [] def mapping if (assertions."$KEY_EXCEPTION") { mapping = mappingsHolder.matchStatusCode(url, assertions."$KEY_EXCEPTION" as Throwable) } else { mapping = mappingsHolder.matchStatusCode(url) } if (mapping) mappingInfos << mapping } else { mappingInfos = mappingsHolder.matchAll((String)url, request.method).toList() } if (mappingInfos.size() == 0) { if (throwEx) { throw new AssertionFailedError("url '$url' did not match any mappings") } else { return false } } boolean returnVal = true def mappingMatched = mappingInfos.any {mapping -> mapping.configure(webRequest) for (key in assertionKeys) { if (assertions.containsKey(key)) { String expected = (String)assertions[key] String actual = mapping."${key}Name" switch (key) { case "controller": if (actual && !getControllerClass(actual)) return false break case "view": if (actual[0] == "/") actual = actual.substring(1) if (expected[0] == "/") expected = expected.substring(1) break case "action": if (key == "action" && actual == null) { final controllerClass = getControllerClass(assertions.controller) actual = controllerClass?.defaultAction } break } if (expected != actual) { if (throwEx) { throw new ComparisonFailure("Url mapping $key assertion for '$url' failed".toString(), expected, actual) } else { returnVal = false } } } } if (paramAssertions) { def params = [:] paramAssertions.delegate = params paramAssertions.resolveStrategy = Closure.DELEGATE_ONLY paramAssertions.call() params.each {name, value -> String actual = mapping.parameters[name] String expected = value if (expected != actual) { if (throwEx) { throw new ComparisonFailure("Url mapping $name assertion for '$url' failed".toString(), expected, actual) } else { returnVal = false } } } } return true } if (!mappingMatched) throw new IllegalArgumentException("url '$url' did not match any mappings") returnVal } void assertForwardUrlMapping(Map assertions, Object url, Closure paramAssertions = null) { checkForwardUrlMapping(assertions, url, paramAssertions, true) } boolean verifyForwardUrlMapping(Map assertions, Object url, Closure paramAssertions = null) { checkForwardUrlMapping(assertions, url, paramAssertions, false) } private boolean checkReverseUrlMapping(Map assertions, String url, Closure paramAssertions, boolean throwEx) { UrlMappingsHolder mappingsHolder = applicationContext.getBean("grailsUrlMappingsHolder", UrlMappingsHolder) UrlConverter urlConverter = applicationContext.getBean(UrlConverter.BEAN_NAME, UrlConverter) def controller = assertions.controller def action = assertions.action def method = assertions.method def plugin = assertions.plugin def namespace = assertions.namespace String convertedControllerName = null, convertedActionName = null if(controller) convertedControllerName = urlConverter.toUrlElement(controller) ?: controller if(action) convertedActionName = urlConverter.toUrlElement(action) ?: action def params = [:] if (paramAssertions) { paramAssertions.delegate = params paramAssertions.resolveStrategy = Closure.DELEGATE_ONLY paramAssertions.call() } UrlCreator urlCreator = mappingsHolder.getReverseMapping(controller, action, namespace, plugin, method, params) if (urlCreator == null) { if (throwEx) { throw new AssertionFailedError("could not create reverse mapping of '$url' for {controller = $controller, action = $action, params = $params}") } else { return false } } String createdUrl = urlCreator.createRelativeURL(convertedControllerName, convertedActionName, params, "UTF-8") if (url != createdUrl) { if (throwEx) { throw new ComparisonFailure("reverse mapping assertion for {controller = $controller, action = $action, params = $params}", url, createdUrl) } else { return false } } true } /** * Asserts the given controller and action produce the given reverse URL mapping * *
     * 
     *           assertReverseUrlMapping("/action1", controller: "grailsUrlMappingsTestCaseFake", action: "action1")
     * 
     * 
* @param assertions The assertions as named parameters * @param url The URL as a string * @param paramAssertions The parameters to assert defined in the body of the closure */ void assertReverseUrlMapping(Map assertions, String url, Closure paramAssertions = null) { checkReverseUrlMapping(assertions, url, paramAssertions, true) } /** * Asserts the given controller and action produce the given reverse URL mapping * *
     * 
     *           verifyReverseUrlMapping("/action1", controller: "grailsUrlMappingsTestCaseFake", action: "action1")
     * 
     * 
* @param assertions The assertions as named parameters * @param url The URL as a string * @param paramAssertions The parameters to assert defined in the body of the closure * * @return True if the url matches the assertions */ boolean verifyReverseUrlMapping(Map assertions, String url, Closure paramAssertions = null) { checkReverseUrlMapping(assertions, url, paramAssertions, false) } GrailsControllerClass getControllerClass(String controller) { (GrailsControllerClass)grailsApplication.getArtefactByLogicalPropertyName(ControllerArtefactHandler.TYPE, controller) } @CompileDynamic void mockArtefact(Class urlMappingsClass) { grailsApplication.addArtefact(UrlMappingsArtefactHandler.TYPE, urlMappingsClass) defineBeans { grailsUrlMappingsHolder(UrlMappingsHolderFactoryBean) { getDelegate().grailsApplication = grailsApplication } } } String getBeanName(Class urlMappingsClass) { null } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy