1/*
2 * Copyright 2004-2005 the original author or authors.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.codehaus.groovy.grails.web.servlet;
17
18import org.codehaus.groovy.grails.web.metaclass.BindDynamicMethod
19import org.codehaus.groovy.grails.web.servlet.mvc.AbstractGrailsControllerTests
20import org.codehaus.groovy.grails.web.servlet.mvc.GrailsParameterMap
21
22/**
23 * Tests for the bindData method
24 *
25 * @author Marc Palmer
26 */
27class BindDataMethodTests extends AbstractGrailsControllerTests {
28    def mockController
29    def method
30    def target
31    def safeMeta
32
33    void testBindDataFromMap() {
34        runTest() {
35            mockController = ga.getControllerClass("BindController")
36            def src = [ 'metaClass' : this.metaClass, 'name' : 'Marc Palmer' ]
37
38            method.invoke( mockController, "bindData", [target, src].toArray() )
39
40            assertEquals "Marc Palmer", target.name
41            assertEquals safeMeta, target.metaClass
42        }
43    }
44
45    void testBindDataWithExcluded() {
46        runTest() {
47            mockController = ga.getControllerClass("BindController")
48            def src = [ 'metaClass' : this.metaClass, 'name' : 'Marc Palmer', 'email' : 'dontwantthis' ]
49            def excludes = [exclude:['email']]
50
51            method.invoke( mockController,"bindData", [target, src, excludes].toArray() )
52
53            assertEquals "Marc Palmer", target.name
54            assertEquals safeMeta, target.metaClass
55            assertNull target.email
56        }
57    }
58
59    void testBindDataWithIncluded() {
60        runTest() {
61            mockController = ga.getControllerClass("BindController")
62            def src = [ 'metaClass' : this.metaClass, 'name' : 'Marc Palmer', 'email' : 'dontwantthis' ]
63            def includes = [include:['name']]
64
65            method.invoke( mockController,"bindData", [target, src, includes].toArray() )
66
67            assertEquals "Marc Palmer", target.name
68            assertEquals safeMeta, target.metaClass
69            assertNull target.email
70        }
71    }
72
73    void testBindDataWithNeitherIncludeOrExcludeIncludesAll() {
74        runTest() {
75            mockController = ga.getControllerClass("BindController")
76            def src = [ 'metaClass' : this.metaClass, 'name' : 'Marc Palmer', 'email' : 'dowantthis' ]
77            method.invoke( mockController,"bindData", [target, src, [:]].toArray() )
78
79            assertEquals "Marc Palmer", target.name
80            assertEquals safeMeta, target.metaClass
81            assertEquals target.email, 'dowantthis'
82        }
83    }
84
85    void testBindDataExcludedOverridesIncluded() {
86        runTest() {
87            mockController = ga.getControllerClass("BindController")
88            def src = [ 'metaClass' : this.metaClass, 'name' : 'Marc Palmer', 'email' : 'dontwantthis' ]
89            def includedAndExcluded = [include:['name','email'], exclude:['email']]
90
91            method.invoke( mockController,"bindData", [target, src, includedAndExcluded].toArray() )
92
93            assertEquals "Marc Palmer", target.name
94            assertEquals safeMeta, target.metaClass
95            assertNull target.email
96        }
97    }
98
99    void testBindDataWithPrefixFilter() {
100        runTest() {
101            mockController = ga.getControllerClass("BindController")
102            def src = [ 'metaClass' : this.metaClass, 'mark.name' : 'Marc Palmer', 'mark.email' : 'dontwantthis',
103                        'lee.name': 'Lee Butts', 'lee.email': 'lee@mail.com']
104            def filter = "lee"
105            method.invoke( mockController,"bindData", [target, src, filter].toArray() )
106            assertEquals "Lee Butts", target.name
107            assertEquals "lee@mail.com", target.email
108            assertEquals safeMeta, target.metaClass
109        }
110    }
111
112    void testBindDataWithDisallowedWithGrailsParameterMap() {
113        runTest() {
114            mockController = ga.getControllerClass("BindController")
115            def input = [ 'metaClass' : this.metaClass, 'name' : 'Marc Palmer', 'email' : 'dontwantthis',
116              'address.country':'gbr' ]
117            input.each() {
118                webRequest.currentRequest.addParameter((String)it.key, (String)it.value)
119            }
120            def excludes = [exclude:['email']]
121            def params = new GrailsParameterMap(webRequest.currentRequest)
122
123            method.invoke( mockController,"bindData", [target, params, excludes].toArray() )
124
125            assertEquals "Marc Palmer", target.name
126            assertEquals safeMeta, target.metaClass
127            assertEquals "gbr", target.address.country
128            assertNull target.email
129        }
130    }
131
132    void testBindDataWithPrefixFilterAndDisallowed() {
133        runTest() {
134            mockController = ga.getControllerClass("BindController")
135            def src = [ 'metaClass' : this.metaClass, 'mark.name' : 'Marc Palmer', 'mark.email' : 'dontwantthis',
136                        'lee.name': 'Lee Butts', 'lee.email': 'lee@mail.com']
137            def filter = "lee"
138            def disallowed = [exclude:["email"]]
139            method.invoke( mockController,"bindData", [target, src, disallowed, filter].toArray() )
140            assertEquals "Lee Butts", target.name
141            assertNull target.email
142            assertEquals safeMeta, target.metaClass
143        }
144    }
145
146     void testBindDataConvertsSingleStringInMapToList() {
147        runTest() {
148            mockController = ga.getControllerClass("BindController")
149            def src = [ 'metaClass' : this.metaClass, 'mark.name' : 'Marc Palmer', 'mark.email' : 'dontwantthis',
150                        'lee.name': 'Lee Butts', 'lee.email': 'lee@mail.com']
151            def filter = "lee"
152            def disallowed = [exclude:"email"]
153            method.invoke( mockController,"bindData", [target, src, disallowed, filter].toArray() )
154            assertEquals "Lee Butts", target.name
155            assertNull target.email
156            assertEquals safeMeta, target.metaClass
157        }
158    }
159
160    void onSetUp() {
161        gcl.parseClass(
162'''
163class BindController {
164}
165'''
166        )
167        method = new BindDynamicMethod()
168        target = new CommandObject()
169        safeMeta = target.metaClass
170    }
171}
172
173class CommandObject {
174    String name
175    String email
176    Address address = new Address()
177}
178
179class Address {
180    String country
181}
182