github.com/josephbuchma/goa@v1.2.0/design/apidsl/media_type_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  var _ = Describe("MediaType", func() {
    12  	var name string
    13  	var dslFunc func()
    14  
    15  	var mt *MediaTypeDefinition
    16  
    17  	BeforeEach(func() {
    18  		dslengine.Reset()
    19  		name = ""
    20  		dslFunc = nil
    21  	})
    22  
    23  	JustBeforeEach(func() {
    24  		mt = MediaType(name, dslFunc)
    25  		dslengine.Run()
    26  	})
    27  
    28  	Context("with no dsl and no identifier", func() {
    29  		It("produces an error", func() {
    30  			Ω(mt).ShouldNot(BeNil())
    31  			Ω(mt.Validate()).Should(HaveOccurred())
    32  		})
    33  	})
    34  
    35  	Context("with no dsl", func() {
    36  		BeforeEach(func() {
    37  			name = "application/foo"
    38  		})
    39  
    40  		It("produces an error", func() {
    41  			Ω(mt).ShouldNot(BeNil())
    42  			Ω(mt.Validate()).Should(HaveOccurred())
    43  		})
    44  	})
    45  
    46  	Context("with attributes", func() {
    47  		const attName = "att"
    48  
    49  		BeforeEach(func() {
    50  			name = "application/foo"
    51  			dslFunc = func() {
    52  				Attributes(func() {
    53  					Attribute(attName)
    54  				})
    55  				View("default", func() { Attribute(attName) })
    56  			}
    57  		})
    58  
    59  		It("sets the attributes", func() {
    60  			Ω(mt).ShouldNot(BeNil())
    61  			Ω(mt.Validate()).ShouldNot(HaveOccurred())
    62  			Ω(mt.AttributeDefinition).ShouldNot(BeNil())
    63  			Ω(mt.Type).Should(BeAssignableToTypeOf(Object{}))
    64  			o := mt.Type.(Object)
    65  			Ω(o).Should(HaveLen(1))
    66  			Ω(o).Should(HaveKey(attName))
    67  		})
    68  	})
    69  
    70  	Context("with a content type", func() {
    71  		const attName = "att"
    72  		const contentType = "application/json"
    73  
    74  		BeforeEach(func() {
    75  			name = "application/foo"
    76  			dslFunc = func() {
    77  				ContentType(contentType)
    78  				Attributes(func() {
    79  					Attribute(attName)
    80  				})
    81  				View("default", func() { Attribute(attName) })
    82  			}
    83  		})
    84  
    85  		It("sets the content type", func() {
    86  			Ω(mt).ShouldNot(BeNil())
    87  			Ω(mt.Validate()).ShouldNot(HaveOccurred())
    88  			Ω(mt.ContentType).Should(Equal(contentType))
    89  		})
    90  	})
    91  
    92  	Context("with a description", func() {
    93  		const description = "desc"
    94  
    95  		BeforeEach(func() {
    96  			name = "application/foo"
    97  			dslFunc = func() {
    98  				Description(description)
    99  				Attributes(func() {
   100  					Attribute("attName")
   101  				})
   102  				View("default", func() { Attribute("attName") })
   103  			}
   104  		})
   105  
   106  		It("sets the description", func() {
   107  			Ω(mt).ShouldNot(BeNil())
   108  			Ω(mt.Validate()).ShouldNot(HaveOccurred())
   109  			Ω(mt.Description).Should(Equal(description))
   110  		})
   111  	})
   112  
   113  	Context("with links", func() {
   114  		const linkName = "link"
   115  		var link1Name, link2Name string
   116  		var link2View string
   117  		var mt1, mt2 *MediaTypeDefinition
   118  
   119  		BeforeEach(func() {
   120  			name = "foo"
   121  			link1Name = "l1"
   122  			link2Name = "l2"
   123  			link2View = "l2v"
   124  			mt1 = NewMediaTypeDefinition("application/mt1", "application/mt1", func() {
   125  				Attributes(func() {
   126  					Attribute("foo")
   127  				})
   128  				View("default", func() {
   129  					Attribute("foo")
   130  				})
   131  				View("link", func() {
   132  					Attribute("foo")
   133  				})
   134  			})
   135  			mt2 = NewMediaTypeDefinition("application/mt2", "application/mt2", func() {
   136  				Attributes(func() {
   137  					Attribute("foo")
   138  				})
   139  				View("l2v", func() {
   140  					Attribute("foo")
   141  				})
   142  				View("default", func() {
   143  					Attribute("foo")
   144  				})
   145  			})
   146  			Design.MediaTypes = make(map[string]*MediaTypeDefinition)
   147  			Design.MediaTypes["application/mt1"] = mt1
   148  			Design.MediaTypes["application/mt2"] = mt2
   149  			dslFunc = func() {
   150  				Attributes(func() {
   151  					Attributes(func() {
   152  						Attribute(link1Name, mt1)
   153  						Attribute(link2Name, mt2)
   154  					})
   155  					Links(func() {
   156  						Link(link1Name)
   157  						Link(link2Name, link2View)
   158  					})
   159  					View("default", func() {
   160  						Attribute(link1Name)
   161  						Attribute(link2Name)
   162  					})
   163  				})
   164  			}
   165  		})
   166  
   167  		It("sets the links", func() {
   168  			Ω(mt).ShouldNot(BeNil())
   169  			Ω(dslengine.Errors).Should(BeEmpty())
   170  			Ω(mt.Validate()).ShouldNot(HaveOccurred())
   171  			Ω(mt.Links).ShouldNot(BeNil())
   172  			Ω(mt.Links).Should(HaveLen(2))
   173  			Ω(mt.Links).Should(HaveKey(link1Name))
   174  			Ω(mt.Links[link1Name].Name).Should(Equal(link1Name))
   175  			Ω(mt.Links[link1Name].View).Should(Equal("link"))
   176  			Ω(mt.Links[link1Name].Parent).Should(Equal(mt))
   177  			Ω(mt.Links[link2Name].Name).Should(Equal(link2Name))
   178  			Ω(mt.Links[link2Name].View).Should(Equal(link2View))
   179  			Ω(mt.Links[link2Name].Parent).Should(Equal(mt))
   180  		})
   181  	})
   182  
   183  	Context("with views", func() {
   184  		const viewName = "view"
   185  		const viewAtt = "att"
   186  
   187  		BeforeEach(func() {
   188  			name = "application/foo"
   189  			dslFunc = func() {
   190  				Attributes(func() {
   191  					Attribute(viewAtt)
   192  				})
   193  				View(viewName, func() {
   194  					Attribute(viewAtt)
   195  				})
   196  				View("default", func() {
   197  					Attribute(viewAtt)
   198  				})
   199  			}
   200  		})
   201  
   202  		It("sets the views", func() {
   203  			Ω(mt).ShouldNot(BeNil())
   204  			Ω(mt.Validate()).ShouldNot(HaveOccurred())
   205  			Ω(mt.Views).ShouldNot(BeNil())
   206  			Ω(mt.Views).Should(HaveLen(2))
   207  			Ω(mt.Views).Should(HaveKey(viewName))
   208  			v := mt.Views[viewName]
   209  			Ω(v.Name).Should(Equal(viewName))
   210  			Ω(v.Parent).Should(Equal(mt))
   211  			Ω(v.AttributeDefinition).ShouldNot(BeNil())
   212  			Ω(v.AttributeDefinition.Type).Should(BeAssignableToTypeOf(Object{}))
   213  			o := v.AttributeDefinition.Type.(Object)
   214  			Ω(o).Should(HaveLen(1))
   215  			Ω(o).Should(HaveKey(viewAtt))
   216  			Ω(o[viewAtt]).ShouldNot(BeNil())
   217  			Ω(o[viewAtt].Type).Should(Equal(String))
   218  		})
   219  	})
   220  })
   221  
   222  var _ = Describe("Duplicate media types", func() {
   223  	var duplicate *MediaTypeDefinition
   224  	const id = "application/foo"
   225  	const attName = "bar"
   226  	var dslFunc = func() {
   227  		Attributes(func() {
   228  			Attribute(attName)
   229  		})
   230  		View("default", func() { Attribute(attName) })
   231  	}
   232  
   233  	BeforeEach(func() {
   234  		dslengine.Reset()
   235  		MediaType(id, dslFunc)
   236  		duplicate = MediaType(id, dslFunc)
   237  	})
   238  
   239  	It("produces an error", func() {
   240  		Ω(dslengine.Errors).Should(HaveOccurred())
   241  		Ω(dslengine.Errors.Error()).Should(ContainSubstring("is defined twice"))
   242  	})
   243  
   244  	Context("with a response definition using the duplicate", func() {
   245  		BeforeEach(func() {
   246  			Resource("foo", func() {
   247  				Action("show", func() {
   248  					Routing(GET(""))
   249  					Response(OK, func() {
   250  						Media(duplicate)
   251  					})
   252  				})
   253  			})
   254  		})
   255  
   256  		It("does not panic", func() {
   257  			Ω(func() { dslengine.Run() }).ShouldNot(Panic())
   258  		})
   259  	})
   260  })
   261  
   262  var _ = Describe("CollectionOf", func() {
   263  	Context("used on a global variable", func() {
   264  		var col *MediaTypeDefinition
   265  		BeforeEach(func() {
   266  			dslengine.Reset()
   267  			mt := MediaType("application/vnd.example", func() {
   268  				Attribute("id")
   269  				View("default", func() {
   270  					Attribute("id")
   271  				})
   272  			})
   273  			col = CollectionOf(mt)
   274  			Ω(dslengine.Errors).ShouldNot(HaveOccurred())
   275  		})
   276  
   277  		JustBeforeEach(func() {
   278  			dslengine.Run()
   279  			Ω(dslengine.Errors).ShouldNot(HaveOccurred())
   280  		})
   281  
   282  		It("produces a media type", func() {
   283  			Ω(col).ShouldNot(BeNil())
   284  			Ω(col.Identifier).ShouldNot(BeEmpty())
   285  			Ω(col.TypeName).ShouldNot(BeEmpty())
   286  			Ω(Design.MediaTypes).Should(HaveKey(col.Identifier))
   287  		})
   288  	})
   289  
   290  	Context("defined with the media type identifier", func() {
   291  		var col *MediaTypeDefinition
   292  		BeforeEach(func() {
   293  			dslengine.Reset()
   294  			MediaType("application/vnd.example+json", func() {
   295  				Attribute("id")
   296  				View("default", func() {
   297  					Attribute("id")
   298  				})
   299  			})
   300  			col = MediaType("application/vnd.parent+json", func() {
   301  				Attribute("mt", CollectionOf("application/vnd.example"))
   302  				View("default", func() {
   303  					Attribute("mt")
   304  				})
   305  			})
   306  		})
   307  
   308  		JustBeforeEach(func() {
   309  			dslengine.Run()
   310  			Ω(dslengine.Errors).ShouldNot(HaveOccurred())
   311  		})
   312  
   313  		It("produces a media type", func() {
   314  			Ω(col).ShouldNot(BeNil())
   315  			Ω(col.Identifier).Should(Equal("application/vnd.parent+json"))
   316  			Ω(col.TypeName).Should(Equal("Parent"))
   317  			Ω(col.Type).ShouldNot(BeNil())
   318  			Ω(col.Type.ToObject()).ShouldNot(BeNil())
   319  			Ω(col.Type.ToObject()).Should(HaveKey("mt"))
   320  			mt := col.Type.ToObject()["mt"]
   321  			Ω(mt.Type).ShouldNot(BeNil())
   322  			Ω(mt.Type).Should(BeAssignableToTypeOf(&MediaTypeDefinition{}))
   323  			Ω(mt.Type.Name()).Should(Equal("array"))
   324  			et := mt.Type.ToArray().ElemType
   325  			Ω(et).ShouldNot(BeNil())
   326  			Ω(et.Type).Should(BeAssignableToTypeOf(&MediaTypeDefinition{}))
   327  			Ω(et.Type.(*MediaTypeDefinition).Identifier).Should(Equal("application/vnd.example+json"))
   328  		})
   329  	})
   330  })
   331  
   332  var _ = Describe("Example", func() {
   333  	Context("defined examples in a media type", func() {
   334  		BeforeEach(func() {
   335  			dslengine.Reset()
   336  			ProjectedMediaTypes = make(MediaTypeRoot)
   337  		})
   338  		It("produces a media type with examples", func() {
   339  			mt := MediaType("application/vnd.example+json", func() {
   340  				Attributes(func() {
   341  					Attribute("test1", String, "test1 desc", func() {
   342  						Example("test1")
   343  					})
   344  					Attribute("test2", String, "test2 desc", func() {
   345  						NoExample()
   346  					})
   347  					Attribute("test3", Integer, "test3 desc", func() {
   348  						Minimum(1)
   349  					})
   350  					Attribute("test4", String, func() {
   351  						Format("email")
   352  						Pattern("@")
   353  					})
   354  					Attribute("test5", Any)
   355  
   356  					Attribute("test-failure1", Integer, func() {
   357  						Minimum(0)
   358  						Maximum(0)
   359  					})
   360  				})
   361  				View("default", func() {
   362  					Attribute("test1")
   363  				})
   364  			})
   365  
   366  			dslengine.Run()
   367  			Ω(dslengine.Errors).ShouldNot(HaveOccurred())
   368  
   369  			Ω(mt).ShouldNot(BeNil())
   370  			attr := mt.Type.ToObject()["test1"]
   371  			Ω(attr.Example).Should(Equal("test1"))
   372  			attr = mt.Type.ToObject()["test2"]
   373  			Ω(attr.Example).Should(Equal("-"))
   374  			attr = mt.Type.ToObject()["test3"]
   375  			Ω(attr.Example).Should(BeNumerically(">=", 1))
   376  			attr = mt.Type.ToObject()["test4"]
   377  			Ω(attr.Example).Should(MatchRegexp(`\w+@`))
   378  			attr = mt.Type.ToObject()["test5"]
   379  			Ω(attr.Example).ShouldNot(BeNil())
   380  			attr = mt.Type.ToObject()["test-failure1"]
   381  			Ω(attr.Example).Should(Equal(0))
   382  		})
   383  
   384  		It("produces a media type with HashOf examples", func() {
   385  			ut := Type("example", func() {
   386  				Attribute("test1", Integer)
   387  				Attribute("test2", Any)
   388  			})
   389  
   390  			mt := MediaType("application/vnd.example+json", func() {
   391  				Attributes(func() {
   392  					Attribute("test1", HashOf(String, Integer))
   393  					Attribute("test2", HashOf(Any, String))
   394  					Attribute("test3", HashOf(String, Any))
   395  					Attribute("test4", HashOf(Any, Any))
   396  
   397  					Attribute("test-with-user-type-1", HashOf(String, ut))
   398  					Attribute("test-with-user-type-2", HashOf(Any, ut))
   399  
   400  					Attribute("test-with-array-1", HashOf(String, ArrayOf(Integer)))
   401  					Attribute("test-with-array-2", HashOf(String, ArrayOf(Any)))
   402  					Attribute("test-with-array-3", HashOf(String, ArrayOf(ut)))
   403  					Attribute("test-with-array-4", HashOf(Any, ArrayOf(String)))
   404  					Attribute("test-with-array-5", HashOf(Any, ArrayOf(Any)))
   405  					Attribute("test-with-array-6", HashOf(Any, ArrayOf(ut)))
   406  
   407  					Attribute("test-with-example-1", HashOf(String, Boolean), func() {
   408  						Example(map[string]bool{})
   409  					})
   410  					Attribute("test-with-example-2", HashOf(Any, Boolean), func() {
   411  						Example(map[string]int{})
   412  					})
   413  				})
   414  				View("default", func() {
   415  					Attribute("test1")
   416  				})
   417  			})
   418  
   419  			dslengine.Run()
   420  			Ω(dslengine.Errors).ShouldNot(HaveOccurred())
   421  			Ω(mt).ShouldNot(BeNil())
   422  
   423  			attr := mt.Type.ToObject()["test1"]
   424  			Expect(attr.Example).Should(BeAssignableToTypeOf(map[string]int{}))
   425  			attr = mt.Type.ToObject()["test2"]
   426  			Expect(attr.Example).Should(BeAssignableToTypeOf(map[interface{}]string{}))
   427  			attr = mt.Type.ToObject()["test3"]
   428  			Expect(attr.Example).Should(BeAssignableToTypeOf(map[string]interface{}{}))
   429  			attr = mt.Type.ToObject()["test4"]
   430  			Expect(attr.Example).Should(BeAssignableToTypeOf(map[interface{}]interface{}{}))
   431  
   432  			attr = mt.Type.ToObject()["test-with-user-type-1"]
   433  			Expect(attr.Example).Should(BeAssignableToTypeOf(map[string]map[string]interface{}{}))
   434  			for _, utattr := range attr.Example.(map[string]map[string]interface{}) {
   435  				Expect(utattr).Should(HaveKey("test1"))
   436  				Expect(utattr).Should(HaveKey("test2"))
   437  				Expect(utattr["test1"]).Should(BeAssignableToTypeOf(int(0)))
   438  			}
   439  			attr = mt.Type.ToObject()["test-with-user-type-2"]
   440  			Expect(attr.Example).Should(BeAssignableToTypeOf(map[interface{}]map[string]interface{}{}))
   441  			for _, utattr := range attr.Example.(map[interface{}]map[string]interface{}) {
   442  				Expect(utattr).Should(HaveKey("test1"))
   443  				Expect(utattr).Should(HaveKey("test2"))
   444  				Expect(utattr["test1"]).Should(BeAssignableToTypeOf(int(0)))
   445  			}
   446  
   447  			attr = mt.Type.ToObject()["test-with-array-1"]
   448  			Expect(attr.Example).Should(BeAssignableToTypeOf(map[string][]int{}))
   449  			attr = mt.Type.ToObject()["test-with-array-2"]
   450  			Expect(attr.Example).Should(BeAssignableToTypeOf(map[string][]interface{}{}))
   451  			attr = mt.Type.ToObject()["test-with-array-3"]
   452  			Expect(attr.Example).Should(BeAssignableToTypeOf(map[string][]map[string]interface{}{}))
   453  			attr = mt.Type.ToObject()["test-with-array-4"]
   454  			Expect(attr.Example).Should(BeAssignableToTypeOf(map[interface{}][]string{}))
   455  			attr = mt.Type.ToObject()["test-with-array-5"]
   456  			Expect(attr.Example).Should(BeAssignableToTypeOf(map[interface{}][]interface{}{}))
   457  			attr = mt.Type.ToObject()["test-with-array-6"]
   458  			Expect(attr.Example).Should(BeAssignableToTypeOf(map[interface{}][]map[string]interface{}{}))
   459  
   460  			attr = mt.Type.ToObject()["test-with-example-1"]
   461  			Expect(attr.Example).Should(BeAssignableToTypeOf(map[string]bool{}))
   462  			attr = mt.Type.ToObject()["test-with-example-2"]
   463  			Expect(attr.Example).Should(BeAssignableToTypeOf(map[string]int{}))
   464  		})
   465  
   466  		It("produces a media type with examples in cyclical dependencies", func() {
   467  			mt := MediaType("vnd.application/foo", func() {
   468  				Attributes(func() {
   469  					Attribute("foo", "vnd.application/bar")
   470  					Attribute("others", Integer, func() {
   471  						Minimum(3)
   472  						Maximum(3)
   473  					})
   474  				})
   475  				View("default", func() {
   476  					Attribute("foo")
   477  					Attribute("others")
   478  				})
   479  			})
   480  
   481  			mt2 := MediaType("vnd.application/bar", func() {
   482  				Attributes(func() {
   483  					Attribute("bar", mt)
   484  					Attribute("others", Integer, func() {
   485  						Minimum(1)
   486  						Maximum(2)
   487  					})
   488  				})
   489  				View("default", func() {
   490  					Attribute("bar")
   491  					Attribute("others")
   492  				})
   493  			})
   494  
   495  			dslengine.Run()
   496  			Ω(dslengine.Errors).ShouldNot(HaveOccurred())
   497  
   498  			Ω(mt).ShouldNot(BeNil())
   499  			attr := mt.Type.ToObject()["foo"]
   500  			Ω(attr.Example).ShouldNot(BeNil())
   501  			Expect(attr.Example).Should(BeAssignableToTypeOf(map[string]interface{}{}))
   502  			attrChild := attr.Example.(map[string]interface{})
   503  			Ω(attrChild).Should(HaveKey("bar"))
   504  			Ω(attrChild["others"]).Should(BeNumerically(">=", 1))
   505  			Ω(attrChild["others"]).Should(BeNumerically("<=", 2))
   506  			attr = mt.Type.ToObject()["others"]
   507  			Ω(attr.Example).Should(Equal(3))
   508  
   509  			Ω(mt2).ShouldNot(BeNil())
   510  			attr = mt2.Type.ToObject()["bar"]
   511  			Ω(attr.Example).ShouldNot(BeNil())
   512  			Expect(attr.Example).Should(BeAssignableToTypeOf(map[string]interface{}{}))
   513  			attrChild = attr.Example.(map[string]interface{})
   514  			Ω(attrChild).Should(HaveKey("foo"))
   515  			Ω(attrChild["others"]).Should(Equal(3))
   516  			attr = mt2.Type.ToObject()["others"]
   517  			Ω(attr.Example).Should(BeNumerically(">=", 1))
   518  			Ω(attr.Example).Should(BeNumerically("<=", 2))
   519  		})
   520  
   521  		It("produces media type examples from the linked media type", func() {
   522  			mt := MediaType("application/vnd.example+json", func() {
   523  				Attributes(func() {
   524  					Attribute("test1", String, "test1 desc", func() {
   525  						Example("test1")
   526  					})
   527  					Attribute("test2", String, "test2 desc", func() {
   528  						NoExample()
   529  					})
   530  					Attribute("test3", Integer, "test3 desc", func() {
   531  						Minimum(1)
   532  					})
   533  				})
   534  				View("default", func() {
   535  					Attribute("test1")
   536  					Attribute("test2")
   537  					Attribute("test3")
   538  				})
   539  			})
   540  
   541  			pmt := MediaType("application/vnd.example.parent+json", func() {
   542  				Attributes(func() {
   543  					Attribute("test1", String, "test1 desc", func() {
   544  						Example("test1")
   545  					})
   546  					Attribute("test2", String, "test2 desc", func() {
   547  						NoExample()
   548  					})
   549  					Attribute("test3", Integer, "test3 desc", func() {
   550  						Minimum(1)
   551  					})
   552  					Attribute("test4", mt, "test4 desc")
   553  				})
   554  				View("default", func() {
   555  					Attribute("test1")
   556  					Attribute("test2")
   557  					Attribute("test3")
   558  					Attribute("test4")
   559  				})
   560  			})
   561  
   562  			dslengine.Run()
   563  			Ω(dslengine.Errors).ShouldNot(HaveOccurred())
   564  
   565  			Ω(mt).ShouldNot(BeNil())
   566  			attr := mt.Type.ToObject()["test1"]
   567  			Ω(attr.Example).Should(Equal("test1"))
   568  			attr = mt.Type.ToObject()["test2"]
   569  			Ω(attr.Example).Should(Equal("-"))
   570  			attr = mt.Type.ToObject()["test3"]
   571  			Ω(attr.Example).Should(BeNumerically(">=", 1))
   572  
   573  			Ω(pmt).ShouldNot(BeNil())
   574  			attr = pmt.Type.ToObject()["test1"]
   575  			Ω(attr.Example).Should(Equal("test1"))
   576  			attr = pmt.Type.ToObject()["test2"]
   577  			Ω(attr.Example).Should(Equal("-"))
   578  			attr = pmt.Type.ToObject()["test3"]
   579  			Ω(attr.Example).Should(BeNumerically(">=", 1))
   580  			attr = pmt.Type.ToObject()["test4"]
   581  			Ω(attr.Example).ShouldNot(BeNil())
   582  			Expect(attr.Example).Should(BeAssignableToTypeOf(map[string]interface{}{}))
   583  			attrChild := attr.Example.(map[string]interface{})
   584  			Ω(attrChild["test1"]).Should(Equal("test1"))
   585  			Ω(attrChild["test2"]).Should(Equal("-"))
   586  			Ω(attrChild["test3"]).Should(BeNumerically(">=", 1))
   587  		})
   588  
   589  		It("produces media type examples from the linked media type collection with custom examples", func() {
   590  			mt := MediaType("application/vnd.example+json", func() {
   591  				Attributes(func() {
   592  					Attribute("test1", String, "test1 desc", func() {
   593  						Example("test1")
   594  					})
   595  					Attribute("test2", String, "test2 desc", func() {
   596  						NoExample()
   597  					})
   598  					Attribute("test3", Integer, "test3 desc", func() {
   599  						Minimum(1)
   600  					})
   601  				})
   602  				View("default", func() {
   603  					Attribute("test1")
   604  					Attribute("test2")
   605  					Attribute("test3")
   606  				})
   607  			})
   608  
   609  			pmt := MediaType("application/vnd.example.parent+json", func() {
   610  				Attributes(func() {
   611  					Attribute("test1", String, "test1 desc", func() {
   612  						Example("test1")
   613  					})
   614  					Attribute("test2", String, "test2 desc", func() {
   615  						NoExample()
   616  					})
   617  					Attribute("test3", String, "test3 desc", func() {
   618  						Pattern("^1$")
   619  					})
   620  					Attribute("test4", CollectionOf(mt), "test4 desc")
   621  				})
   622  				View("default", func() {
   623  					Attribute("test1")
   624  					Attribute("test2")
   625  					Attribute("test3")
   626  					Attribute("test4")
   627  				})
   628  			})
   629  
   630  			dslengine.Run()
   631  			Ω(dslengine.Errors).ShouldNot(HaveOccurred())
   632  
   633  			Ω(mt).ShouldNot(BeNil())
   634  			attr := mt.Type.ToObject()["test1"]
   635  			Ω(attr.Example).Should(Equal("test1"))
   636  			attr = mt.Type.ToObject()["test2"]
   637  			Ω(attr.Example).Should(Equal("-"))
   638  			attr = mt.Type.ToObject()["test3"]
   639  			Ω(attr.Example).Should(BeNumerically(">=", 1))
   640  
   641  			Ω(pmt).ShouldNot(BeNil())
   642  			attr = pmt.Type.ToObject()["test1"]
   643  			Ω(attr.Example).Should(Equal("test1"))
   644  			attr = pmt.Type.ToObject()["test2"]
   645  			Ω(attr.Example).Should(Equal("-"))
   646  			attr = pmt.Type.ToObject()["test3"]
   647  			Ω(attr.Example).Should(Equal("1"))
   648  			attr = pmt.Type.ToObject()["test4"]
   649  			Ω(attr.Example).ShouldNot(BeNil())
   650  			Expect(attr.Example).Should(BeAssignableToTypeOf([]map[string]interface{}{}))
   651  			attrChildren := attr.Example.([]map[string]interface{})
   652  			Ω(attrChildren).Should(HaveLen(1))
   653  			Ω(attrChildren[0]).Should(BeAssignableToTypeOf(map[string]interface{}{}))
   654  			Ω(attrChildren[0]["test1"]).Should(Equal("test1"))
   655  			Ω(attrChildren[0]["test2"]).Should(Equal("-"))
   656  			Ω(attrChildren[0]["test3"]).Should(BeNumerically(">=", 1))
   657  		})
   658  
   659  		It("produces media type examples from the linked media type without custom examples", func() {
   660  			mt := MediaType("application/vnd.example.child+json", func() {
   661  				Attributes(func() {
   662  					Attribute("test1", String, "test1 desc")
   663  				})
   664  				View("default", func() {
   665  					Attribute("test1")
   666  				})
   667  			})
   668  
   669  			pmt := MediaType("application/vnd.example.parent+json", func() {
   670  				Attributes(func() {
   671  					Attribute("test1", String, "test1 desc", func() {
   672  						Example("test1")
   673  					})
   674  					Attribute("test2", String, "test2 desc", func() {
   675  						NoExample()
   676  					})
   677  					Attribute("test3", mt, "test3 desc")
   678  				})
   679  				View("default", func() {
   680  					Attribute("test1")
   681  					Attribute("test2")
   682  					Attribute("test3")
   683  				})
   684  			})
   685  
   686  			dslengine.Run()
   687  			Ω(dslengine.Errors).ShouldNot(HaveOccurred())
   688  			Ω(mt).ShouldNot(BeNil())
   689  			attr := mt.Type.ToObject()["test1"]
   690  			cexample := attr.Example
   691  			Ω(cexample).ShouldNot(BeEmpty())
   692  
   693  			Ω(pmt).ShouldNot(BeNil())
   694  			attr = pmt.Type.ToObject()["test1"]
   695  			Ω(attr.Example).Should(Equal("test1"))
   696  			attr = pmt.Type.ToObject()["test2"]
   697  			Ω(attr.Example).Should(Equal("-"))
   698  			attr = pmt.Type.ToObject()["test3"]
   699  			Ω(attr.Example).ShouldNot(BeNil())
   700  			Expect(attr.Example).Should(BeAssignableToTypeOf(map[string]interface{}{}))
   701  		})
   702  
   703  		It("produces media type examples from the linked media type collection without custom examples", func() {
   704  			mt := MediaType("application/vnd.example.child+json", func() {
   705  				Attributes(func() {
   706  					Attribute("test1", String, "test1 desc")
   707  				})
   708  				View("default", func() {
   709  					Attribute("test1")
   710  				})
   711  			})
   712  
   713  			pmt := MediaType("application/vnd.example.parent+json", func() {
   714  				Attributes(func() {
   715  					Attribute("test1", String, "test1 desc", func() {
   716  						Example("test1")
   717  					})
   718  					Attribute("test2", String, "test2 desc", func() {
   719  						NoExample()
   720  					})
   721  					Attribute("test3", CollectionOf(mt), "test3 desc")
   722  				})
   723  				View("default", func() {
   724  					Attribute("test1")
   725  				})
   726  			})
   727  
   728  			dslengine.Run()
   729  			Ω(dslengine.Errors).ShouldNot(HaveOccurred())
   730  
   731  			Ω(mt).ShouldNot(BeNil())
   732  			attr := mt.Type.ToObject()["test1"]
   733  			cexample := attr.Example
   734  			Ω(cexample).ShouldNot(BeEmpty())
   735  
   736  			Ω(pmt).ShouldNot(BeNil())
   737  			attr = pmt.Type.ToObject()["test1"]
   738  			Ω(attr.Example).Should(Equal("test1"))
   739  			attr = pmt.Type.ToObject()["test2"]
   740  			Ω(attr.Example).Should(Equal("-"))
   741  			attr = pmt.Type.ToObject()["test3"]
   742  			Ω(attr.Example).ShouldNot(BeNil())
   743  			Expect(attr.Example).Should(BeAssignableToTypeOf([]map[string]interface{}{}))
   744  			attrChildren := attr.Example.([]map[string]interface{})
   745  			Ω(len(attrChildren)).Should(BeNumerically(">=", 1))
   746  		})
   747  
   748  		It("produces a media type with appropriate MinLength and MaxLength examples", func() {
   749  			ut := Type("example", func() {
   750  				Attribute("test1", Integer, func() {
   751  					Minimum(-200)
   752  					Maximum(-100)
   753  				})
   754  			})
   755  
   756  			mt := MediaType("application/vnd.example+json", func() {
   757  				Attributes(func() {
   758  					Attribute("test1", ArrayOf(Any), func() {
   759  						MinLength(0)
   760  						MaxLength(10)
   761  					})
   762  					Attribute("test2", ArrayOf(Any), func() {
   763  						MinLength(1000)
   764  						MaxLength(2000)
   765  					})
   766  					Attribute("test3", ArrayOf(Any), func() {
   767  						MinLength(1000)
   768  						MaxLength(1000)
   769  					})
   770  
   771  					Attribute("test-failure1", ArrayOf(ut), func() {
   772  						MinLength(0)
   773  						MaxLength(0)
   774  					})
   775  				})
   776  				View("default", func() {
   777  					Attribute("test1")
   778  				})
   779  			})
   780  
   781  			dslengine.Run()
   782  			Ω(dslengine.Errors).ShouldNot(HaveOccurred())
   783  
   784  			Ω(mt).ShouldNot(BeNil())
   785  			attr := mt.Type.ToObject()["test1"]
   786  			Ω(attr.Example).Should(BeAssignableToTypeOf([]interface{}{}))
   787  			Ω(len(attr.Example.([]interface{}))).Should(BeNumerically("<=", 10))
   788  			attr = mt.Type.ToObject()["test2"]
   789  			Ω(attr.Example).Should(BeAssignableToTypeOf([]interface{}{}))
   790  			Ω(attr.Example.([]interface{})).Should(HaveLen(10))
   791  			attr = mt.Type.ToObject()["test3"]
   792  			Ω(attr.Example).Should(BeAssignableToTypeOf([]interface{}{}))
   793  			Ω(attr.Example.([]interface{})).Should(HaveLen(10))
   794  			attr = mt.Type.ToObject()["test-failure1"]
   795  			Ω(attr.Example).Should(BeNil())
   796  		})
   797  	})
   798  })