github.com/NewMillennialGames/goa@v1.4.0/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 a 'readOnly' attribute", func() { 198 BeforeEach(func() { 199 name = "foo" 200 dsl = func() { ReadOnly() } 201 }) 202 203 It("produces an attribute of type string set to readOnly", 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].IsReadOnly()).Should(BeTrue()) 212 }) 213 }) 214 215 Context("with a name and a DSL defining an enum validation", func() { 216 BeforeEach(func() { 217 name = "foo" 218 dsl = func() { Enum("one", "two") } 219 }) 220 221 It("produces an attribute of type string with a validation", func() { 222 t := parent.Type 223 Ω(t).ShouldNot(BeNil()) 224 Ω(t).Should(BeAssignableToTypeOf(Object{})) 225 o := t.(Object) 226 Ω(o).Should(HaveLen(1)) 227 Ω(o).Should(HaveKey(name)) 228 Ω(o[name].Type).Should(Equal(String)) 229 Ω(o[name].Validation).ShouldNot(BeNil()) 230 Ω(o[name].Validation.Values).Should(Equal([]interface{}{"one", "two"})) 231 }) 232 }) 233 234 Context("with a name, type datetime and a DSL defining a default value", func() { 235 BeforeEach(func() { 236 name = "foo" 237 dataType = DateTime 238 dsl = func() { Default("1978-06-30T10:00:00+09:00") } 239 }) 240 241 It("produces an attribute of type string with a default value", func() { 242 t := parent.Type 243 Ω(t).ShouldNot(BeNil()) 244 Ω(t).Should(BeAssignableToTypeOf(Object{})) 245 o := t.(Object) 246 Ω(o).Should(HaveLen(1)) 247 Ω(o).Should(HaveKey(name)) 248 Ω(o[name].Type).Should(Equal(DateTime)) 249 Ω(o[name].Validation).Should(BeNil()) 250 Ω(o[name].DefaultValue).Should(Equal(interface{}("1978-06-30T10:00:00+09:00"))) 251 }) 252 }) 253 254 Context("with a name, type integer and a DSL defining an enum validation", func() { 255 BeforeEach(func() { 256 name = "foo" 257 dataType = Integer 258 dsl = func() { Enum(1, 2) } 259 }) 260 261 It("produces an attribute of type integer with a validation", func() { 262 t := parent.Type 263 Ω(t).ShouldNot(BeNil()) 264 Ω(t).Should(BeAssignableToTypeOf(Object{})) 265 o := t.(Object) 266 Ω(o).Should(HaveLen(1)) 267 Ω(o).Should(HaveKey(name)) 268 Ω(o[name].Type).Should(Equal(Integer)) 269 Ω(o[name].Validation).ShouldNot(BeNil()) 270 Ω(o[name].Validation.Values).Should(Equal([]interface{}{1, 2})) 271 }) 272 }) 273 274 Context("with a name, type integer, a description and a DSL defining an enum validation", func() { 275 BeforeEach(func() { 276 name = "foo" 277 dataType = String 278 description = "bar" 279 dsl = func() { Enum("one", "two") } 280 }) 281 282 It("produces an attribute of type integer with a validation and the description", func() { 283 t := parent.Type 284 Ω(t).ShouldNot(BeNil()) 285 Ω(t).Should(BeAssignableToTypeOf(Object{})) 286 o := t.(Object) 287 Ω(o).Should(HaveLen(1)) 288 Ω(o).Should(HaveKey(name)) 289 Ω(o[name].Type).Should(Equal(String)) 290 Ω(o[name].Validation).ShouldNot(BeNil()) 291 Ω(o[name].Validation.Values).Should(Equal([]interface{}{"one", "two"})) 292 }) 293 }) 294 295 Context("with a name and type uuid", func() { 296 BeforeEach(func() { 297 name = "birthdate" 298 dataType = UUID 299 }) 300 301 It("produces an attribute of type date with a validation and the description", func() { 302 t := parent.Type 303 Ω(t).ShouldNot(BeNil()) 304 Ω(t).Should(BeAssignableToTypeOf(Object{})) 305 o := t.(Object) 306 Ω(o).Should(HaveLen(1)) 307 Ω(o).Should(HaveKey(name)) 308 Ω(o[name].Type).Should(Equal(UUID)) 309 }) 310 }) 311 312 Context("with a name and type date", func() { 313 BeforeEach(func() { 314 name = "birthdate" 315 dataType = DateTime 316 }) 317 318 It("produces an attribute of type date with a validation and the description", func() { 319 t := parent.Type 320 Ω(t).ShouldNot(BeNil()) 321 Ω(t).Should(BeAssignableToTypeOf(Object{})) 322 o := t.(Object) 323 Ω(o).Should(HaveLen(1)) 324 Ω(o).Should(HaveKey(name)) 325 Ω(o[name].Type).Should(Equal(DateTime)) 326 }) 327 }) 328 329 Context("with a name and a type defined by name", func() { 330 var Foo *UserTypeDefinition 331 332 BeforeEach(func() { 333 name = "fooatt" 334 dataType = "foo" 335 Foo = Type("foo", func() { 336 Attribute("bar") 337 }) 338 }) 339 340 It("produces an attribute of the corresponding type", func() { 341 t := parent.Type 342 Ω(t).ShouldNot(BeNil()) 343 Ω(t).Should(BeAssignableToTypeOf(Object{})) 344 o := t.(Object) 345 Ω(o).Should(HaveLen(1)) 346 Ω(o).Should(HaveKey(name)) 347 Ω(o[name].Type).Should(Equal(Foo)) 348 }) 349 }) 350 351 Context("with child attributes", func() { 352 const childAtt = "childAtt" 353 354 BeforeEach(func() { 355 name = "foo" 356 dsl = func() { Attribute(childAtt) } 357 }) 358 359 Context("on an attribute that is not an object", func() { 360 BeforeEach(func() { 361 dataType = Integer 362 }) 363 364 It("fails", func() { 365 Ω(dslengine.Errors).Should(HaveOccurred()) 366 }) 367 }) 368 369 Context("on an attribute that does not have a type", func() { 370 It("sets the type to Object", func() { 371 t := parent.Type 372 Ω(t).ShouldNot(BeNil()) 373 Ω(t).Should(BeAssignableToTypeOf(Object{})) 374 o := t.(Object) 375 Ω(o).Should(HaveLen(1)) 376 Ω(o).Should(HaveKey(name)) 377 Ω(o[name].Type).Should(BeAssignableToTypeOf(Object{})) 378 }) 379 }) 380 381 Context("on an attribute of type Object", func() { 382 BeforeEach(func() { 383 dataType = Object{} 384 }) 385 386 It("initializes the object attributes", func() { 387 Ω(dslengine.Errors).ShouldNot(HaveOccurred()) 388 t := parent.Type 389 Ω(t).ShouldNot(BeNil()) 390 Ω(t).Should(BeAssignableToTypeOf(Object{})) 391 o := t.(Object) 392 Ω(o).Should(HaveLen(1)) 393 Ω(o).Should(HaveKey(name)) 394 Ω(o[name].Type).Should(BeAssignableToTypeOf(Object{})) 395 co := o[name].Type.(Object) 396 Ω(co).Should(HaveLen(1)) 397 Ω(co).Should(HaveKey(childAtt)) 398 }) 399 }) 400 }) 401 })