github.com/ccrossley/goa@v1.3.1/design/apidsl/attribute_test.go (about) 1 package apidsl_test 2 3 import ( 4 . "github.com/goadesign/goa/design" 5 . "github.com/goadesign/goa/design/apidsl" 6 "github.com/goadesign/goa/dslengine" 7 . "github.com/onsi/ginkgo" 8 . "github.com/onsi/gomega" 9 ) 10 11 // TestCD is a test container definition. 12 type TestCD struct { 13 *AttributeDefinition 14 } 15 16 // Attribute returns a dummy attribute. 17 func (t *TestCD) Attribute() *AttributeDefinition { 18 return t.AttributeDefinition 19 } 20 21 // DSL implements Source 22 func (t *TestCD) DSL() func() { 23 return func() { 24 Attribute("foo") 25 } 26 } 27 28 // Context implement Definition 29 func (t *TestCD) Context() string { 30 return "test" 31 } 32 33 // DSLName returns the DSL name. 34 func (t *TestCD) DSLName() string { 35 return "TestCD" 36 } 37 38 // DependsOn returns the DSL dependencies. 39 func (t *TestCD) DependsOn() []dslengine.Root { 40 return nil 41 } 42 43 // IterateSets implement Root 44 func (t *TestCD) IterateSets(it dslengine.SetIterator) { 45 it([]dslengine.Definition{t}) 46 } 47 48 // Reset is a no-op 49 func (t *TestCD) Reset() {} 50 51 var _ = Describe("ContainerDefinition", func() { 52 var att *AttributeDefinition 53 var testCD *TestCD 54 BeforeEach(func() { 55 dslengine.Reset() 56 att = &AttributeDefinition{Type: Object{}} 57 testCD = &TestCD{AttributeDefinition: att} 58 dslengine.Register(testCD) 59 }) 60 61 JustBeforeEach(func() { 62 err := dslengine.Run() 63 Ω(err).ShouldNot(HaveOccurred()) 64 }) 65 66 It("contains attributes", func() { 67 Ω(testCD.Attribute()).Should(Equal(att)) 68 }) 69 }) 70 71 var _ = Describe("Attribute", func() { 72 var name string 73 var dataType interface{} 74 var description string 75 var dsl func() 76 77 var parent *AttributeDefinition 78 79 BeforeEach(func() { 80 dslengine.Reset() 81 name = "" 82 dataType = nil 83 description = "" 84 dsl = nil 85 }) 86 87 JustBeforeEach(func() { 88 Type("type", func() { 89 if dsl == nil { 90 if dataType == nil { 91 Attribute(name) 92 } else if description == "" { 93 Attribute(name, dataType) 94 } else { 95 Attribute(name, dataType, description) 96 } 97 } else if dataType == nil { 98 Attribute(name, dsl) 99 } else if description == "" { 100 Attribute(name, dataType, dsl) 101 } else { 102 Attribute(name, dataType, description, dsl) 103 } 104 }) 105 dslengine.Run() 106 if t, ok := Design.Types["type"]; ok { 107 parent = t.AttributeDefinition 108 } 109 }) 110 111 Context("with only a name", func() { 112 BeforeEach(func() { 113 name = "foo" 114 }) 115 116 It("produces an attribute of type string", func() { 117 t := parent.Type 118 Ω(t).ShouldNot(BeNil()) 119 Ω(t).Should(BeAssignableToTypeOf(Object{})) 120 o := t.(Object) 121 Ω(o).Should(HaveLen(1)) 122 Ω(o).Should(HaveKey(name)) 123 Ω(o[name].Type).Should(Equal(String)) 124 }) 125 }) 126 127 Context("with a name and datatype", func() { 128 BeforeEach(func() { 129 name = "foo" 130 dataType = Integer 131 }) 132 133 It("produces an attribute of given type", func() { 134 t := parent.Type 135 Ω(t).ShouldNot(BeNil()) 136 Ω(t).Should(BeAssignableToTypeOf(Object{})) 137 o := t.(Object) 138 Ω(o).Should(HaveLen(1)) 139 Ω(o).Should(HaveKey(name)) 140 Ω(o[name].Type).Should(Equal(Integer)) 141 }) 142 }) 143 144 Context("with a name and uuid datatype", func() { 145 BeforeEach(func() { 146 name = "foo" 147 dataType = UUID 148 }) 149 150 It("produces an attribute of uuid type", func() { 151 t := parent.Type 152 Ω(t).ShouldNot(BeNil()) 153 Ω(t).Should(BeAssignableToTypeOf(Object{})) 154 o := t.(Object) 155 Ω(o).Should(HaveLen(1)) 156 Ω(o).Should(HaveKey(name)) 157 Ω(o[name].Type).Should(Equal(UUID)) 158 }) 159 }) 160 161 Context("with a name and date datatype", func() { 162 BeforeEach(func() { 163 name = "foo" 164 dataType = DateTime 165 }) 166 167 It("produces an attribute of date type", func() { 168 t := parent.Type 169 Ω(t).ShouldNot(BeNil()) 170 Ω(t).Should(BeAssignableToTypeOf(Object{})) 171 o := t.(Object) 172 Ω(o).Should(HaveLen(1)) 173 Ω(o).Should(HaveKey(name)) 174 Ω(o[name].Type).Should(Equal(DateTime)) 175 }) 176 }) 177 178 Context("with a name, datatype and description", func() { 179 BeforeEach(func() { 180 name = "foo" 181 dataType = Integer 182 description = "bar" 183 }) 184 185 It("produces an attribute of given type and given description", func() { 186 t := parent.Type 187 Ω(t).ShouldNot(BeNil()) 188 Ω(t).Should(BeAssignableToTypeOf(Object{})) 189 o := t.(Object) 190 Ω(o).Should(HaveLen(1)) 191 Ω(o).Should(HaveKey(name)) 192 Ω(o[name].Type).Should(Equal(Integer)) 193 Ω(o[name].Description).Should(Equal(description)) 194 }) 195 }) 196 197 Context("with a name and a DSL defining an enum validation", func() { 198 BeforeEach(func() { 199 name = "foo" 200 dsl = func() { Enum("one", "two") } 201 }) 202 203 It("produces an attribute of type string with a validation", func() { 204 t := parent.Type 205 Ω(t).ShouldNot(BeNil()) 206 Ω(t).Should(BeAssignableToTypeOf(Object{})) 207 o := t.(Object) 208 Ω(o).Should(HaveLen(1)) 209 Ω(o).Should(HaveKey(name)) 210 Ω(o[name].Type).Should(Equal(String)) 211 Ω(o[name].Validation).ShouldNot(BeNil()) 212 Ω(o[name].Validation.Values).Should(Equal([]interface{}{"one", "two"})) 213 }) 214 }) 215 216 Context("with a name, type datetime and a DSL defining a default value", func() { 217 BeforeEach(func() { 218 name = "foo" 219 dataType = DateTime 220 dsl = func() { Default("1978-06-30T10:00:00+09:00") } 221 }) 222 223 It("produces an attribute of type string with a default value", func() { 224 t := parent.Type 225 Ω(t).ShouldNot(BeNil()) 226 Ω(t).Should(BeAssignableToTypeOf(Object{})) 227 o := t.(Object) 228 Ω(o).Should(HaveLen(1)) 229 Ω(o).Should(HaveKey(name)) 230 Ω(o[name].Type).Should(Equal(DateTime)) 231 Ω(o[name].Validation).Should(BeNil()) 232 Ω(o[name].DefaultValue).Should(Equal(interface{}("1978-06-30T10:00:00+09:00"))) 233 }) 234 }) 235 236 Context("with a name, type integer and a DSL defining an enum validation", func() { 237 BeforeEach(func() { 238 name = "foo" 239 dataType = Integer 240 dsl = func() { Enum(1, 2) } 241 }) 242 243 It("produces an attribute of type integer with a validation", func() { 244 t := parent.Type 245 Ω(t).ShouldNot(BeNil()) 246 Ω(t).Should(BeAssignableToTypeOf(Object{})) 247 o := t.(Object) 248 Ω(o).Should(HaveLen(1)) 249 Ω(o).Should(HaveKey(name)) 250 Ω(o[name].Type).Should(Equal(Integer)) 251 Ω(o[name].Validation).ShouldNot(BeNil()) 252 Ω(o[name].Validation.Values).Should(Equal([]interface{}{1, 2})) 253 }) 254 }) 255 256 Context("with a name, type integer, a description and a DSL defining an enum validation", func() { 257 BeforeEach(func() { 258 name = "foo" 259 dataType = String 260 description = "bar" 261 dsl = func() { Enum("one", "two") } 262 }) 263 264 It("produces an attribute of type integer with a validation and the description", func() { 265 t := parent.Type 266 Ω(t).ShouldNot(BeNil()) 267 Ω(t).Should(BeAssignableToTypeOf(Object{})) 268 o := t.(Object) 269 Ω(o).Should(HaveLen(1)) 270 Ω(o).Should(HaveKey(name)) 271 Ω(o[name].Type).Should(Equal(String)) 272 Ω(o[name].Validation).ShouldNot(BeNil()) 273 Ω(o[name].Validation.Values).Should(Equal([]interface{}{"one", "two"})) 274 }) 275 }) 276 277 Context("with a name and type uuid", func() { 278 BeforeEach(func() { 279 name = "birthdate" 280 dataType = UUID 281 }) 282 283 It("produces an attribute of type date with a validation and the description", func() { 284 t := parent.Type 285 Ω(t).ShouldNot(BeNil()) 286 Ω(t).Should(BeAssignableToTypeOf(Object{})) 287 o := t.(Object) 288 Ω(o).Should(HaveLen(1)) 289 Ω(o).Should(HaveKey(name)) 290 Ω(o[name].Type).Should(Equal(UUID)) 291 }) 292 }) 293 294 Context("with a name and type date", func() { 295 BeforeEach(func() { 296 name = "birthdate" 297 dataType = DateTime 298 }) 299 300 It("produces an attribute of type date with a validation and the description", func() { 301 t := parent.Type 302 Ω(t).ShouldNot(BeNil()) 303 Ω(t).Should(BeAssignableToTypeOf(Object{})) 304 o := t.(Object) 305 Ω(o).Should(HaveLen(1)) 306 Ω(o).Should(HaveKey(name)) 307 Ω(o[name].Type).Should(Equal(DateTime)) 308 }) 309 }) 310 311 Context("with a name and a type defined by name", func() { 312 var Foo *UserTypeDefinition 313 314 BeforeEach(func() { 315 name = "fooatt" 316 dataType = "foo" 317 Foo = Type("foo", func() { 318 Attribute("bar") 319 }) 320 }) 321 322 It("produces an attribute of the corresponding type", func() { 323 t := parent.Type 324 Ω(t).ShouldNot(BeNil()) 325 Ω(t).Should(BeAssignableToTypeOf(Object{})) 326 o := t.(Object) 327 Ω(o).Should(HaveLen(1)) 328 Ω(o).Should(HaveKey(name)) 329 Ω(o[name].Type).Should(Equal(Foo)) 330 }) 331 }) 332 333 Context("with child attributes", func() { 334 const childAtt = "childAtt" 335 336 BeforeEach(func() { 337 name = "foo" 338 dsl = func() { Attribute(childAtt) } 339 }) 340 341 Context("on an attribute that is not an object", func() { 342 BeforeEach(func() { 343 dataType = Integer 344 }) 345 346 It("fails", func() { 347 Ω(dslengine.Errors).Should(HaveOccurred()) 348 }) 349 }) 350 351 Context("on an attribute that does not have a type", func() { 352 It("sets the type to Object", func() { 353 t := parent.Type 354 Ω(t).ShouldNot(BeNil()) 355 Ω(t).Should(BeAssignableToTypeOf(Object{})) 356 o := t.(Object) 357 Ω(o).Should(HaveLen(1)) 358 Ω(o).Should(HaveKey(name)) 359 Ω(o[name].Type).Should(BeAssignableToTypeOf(Object{})) 360 }) 361 }) 362 363 Context("on an attribute of type Object", func() { 364 BeforeEach(func() { 365 dataType = Object{} 366 }) 367 368 It("initializes the object attributes", func() { 369 Ω(dslengine.Errors).ShouldNot(HaveOccurred()) 370 t := parent.Type 371 Ω(t).ShouldNot(BeNil()) 372 Ω(t).Should(BeAssignableToTypeOf(Object{})) 373 o := t.(Object) 374 Ω(o).Should(HaveLen(1)) 375 Ω(o).Should(HaveKey(name)) 376 Ω(o[name].Type).Should(BeAssignableToTypeOf(Object{})) 377 co := o[name].Type.(Object) 378 Ω(co).Should(HaveLen(1)) 379 Ω(co).Should(HaveKey(childAtt)) 380 }) 381 }) 382 }) 383 })