github.com/shogo82148/goa-v1@v1.6.2/design/apidsl/media_type_test.go (about)

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