github.com/brycereitano/goa@v0.0.0-20170315073847-8ffa6c85e265/design/validation_test.go (about)

     1  package design_test
     2  
     3  import (
     4  	"go/build"
     5  	"io/ioutil"
     6  	"os"
     7  	"path"
     8  
     9  	. "github.com/goadesign/goa/design"
    10  	. "github.com/goadesign/goa/design/apidsl"
    11  	"github.com/goadesign/goa/dslengine"
    12  	. "github.com/onsi/ginkgo"
    13  	. "github.com/onsi/gomega"
    14  )
    15  
    16  var _ = Describe("Validation", func() {
    17  	Context("with a type attribute", func() {
    18  		const attName = "attName"
    19  		var dsl func()
    20  
    21  		var att *AttributeDefinition
    22  
    23  		JustBeforeEach(func() {
    24  			dslengine.Reset()
    25  			Type("bar", func() {
    26  				dsl()
    27  			})
    28  			dslengine.Run()
    29  			if dslengine.Errors == nil {
    30  				Ω(Design.Types).ShouldNot(BeNil())
    31  				Ω(Design.Types).Should(HaveKey("bar"))
    32  				Ω(Design.Types["bar"]).ShouldNot(BeNil())
    33  				Ω(Design.Types["bar"].Type).Should(BeAssignableToTypeOf(Object{}))
    34  				o := Design.Types["bar"].Type.(Object)
    35  				Ω(o).Should(HaveKey(attName))
    36  				att = o[attName]
    37  			}
    38  		})
    39  
    40  		Context("with a valid enum validation", func() {
    41  			BeforeEach(func() {
    42  				dsl = func() {
    43  					Attribute(attName, String, func() {
    44  						Enum("red", "blue")
    45  					})
    46  				}
    47  			})
    48  
    49  			It("records the validation", func() {
    50  				Ω(dslengine.Errors).ShouldNot(HaveOccurred())
    51  				Ω(att.Validation).ShouldNot(BeNil())
    52  				Ω(att.Validation.Values).Should(Equal([]interface{}{"red", "blue"}))
    53  			})
    54  		})
    55  
    56  		Context("with an incompatible enum validation type", func() {
    57  			BeforeEach(func() {
    58  				dsl = func() {
    59  					Attribute(attName, Integer, func() {
    60  						Enum(1, "blue")
    61  					})
    62  				}
    63  			})
    64  
    65  			It("produces an error", func() {
    66  				Ω(dslengine.Errors).Should(HaveOccurred())
    67  			})
    68  		})
    69  
    70  		Context("with a default value that doesn't exist in enum", func() {
    71  			BeforeEach(func() {
    72  				dsl = func() {
    73  					Attribute(attName, Integer, func() {
    74  						Enum(1, 2, 3)
    75  						Default(4)
    76  					})
    77  				}
    78  			})
    79  			It("produces an error", func() {
    80  				Ω(dslengine.Errors).Should(HaveOccurred())
    81  				Ω(dslengine.Errors.Error()).Should(Equal(
    82  					`type "bar": field attName - default value 4 is not one of the accepted values: []interface {}{1, 2, 3}`))
    83  			})
    84  		})
    85  
    86  		Context("with a valid format validation", func() {
    87  			BeforeEach(func() {
    88  				dsl = func() {
    89  					Attribute(attName, String, func() {
    90  						Format("email")
    91  					})
    92  				}
    93  			})
    94  
    95  			It("records the validation", func() {
    96  				Ω(dslengine.Errors).ShouldNot(HaveOccurred())
    97  				Ω(att.Validation).ShouldNot(BeNil())
    98  				Ω(att.Validation.Format).Should(Equal("email"))
    99  			})
   100  		})
   101  
   102  		Context("with an invalid format validation", func() {
   103  			BeforeEach(func() {
   104  				dsl = func() {
   105  					Attribute(attName, String, func() {
   106  						Format("emailz")
   107  					})
   108  				}
   109  			})
   110  
   111  			It("produces an error", func() {
   112  				Ω(dslengine.Errors).Should(HaveOccurred())
   113  			})
   114  		})
   115  
   116  		Context("with a valid pattern validation", func() {
   117  			BeforeEach(func() {
   118  				dsl = func() {
   119  					Attribute(attName, String, func() {
   120  						Pattern("^foo$")
   121  					})
   122  				}
   123  			})
   124  
   125  			It("records the validation", func() {
   126  				Ω(dslengine.Errors).ShouldNot(HaveOccurred())
   127  				Ω(att.Validation).ShouldNot(BeNil())
   128  				Ω(att.Validation.Pattern).Should(Equal("^foo$"))
   129  			})
   130  		})
   131  
   132  		Context("with an invalid pattern validation", func() {
   133  			BeforeEach(func() {
   134  				dsl = func() {
   135  					Attribute(attName, String, func() {
   136  						Pattern("[invalid")
   137  					})
   138  				}
   139  			})
   140  
   141  			It("produces an error", func() {
   142  				Ω(dslengine.Errors).Should(HaveOccurred())
   143  			})
   144  		})
   145  
   146  		Context("with an invalid format validation type", func() {
   147  			BeforeEach(func() {
   148  				dsl = func() {
   149  					Attribute(attName, Integer, func() {
   150  						Format("email")
   151  					})
   152  				}
   153  			})
   154  
   155  			It("produces an error", func() {
   156  				Ω(dslengine.Errors).Should(HaveOccurred())
   157  			})
   158  		})
   159  
   160  		Context("with a valid min value validation", func() {
   161  			BeforeEach(func() {
   162  				dsl = func() {
   163  					Attribute(attName, Integer, func() {
   164  						Minimum(2)
   165  					})
   166  				}
   167  			})
   168  
   169  			It("records the validation", func() {
   170  				Ω(dslengine.Errors).ShouldNot(HaveOccurred())
   171  				Ω(att.Validation).ShouldNot(BeNil())
   172  				Ω(*att.Validation.Minimum).Should(Equal(2.0))
   173  			})
   174  		})
   175  
   176  		Context("with an invalid min value validation", func() {
   177  			BeforeEach(func() {
   178  				dsl = func() {
   179  					Attribute(attName, String, func() {
   180  						Minimum(2)
   181  					})
   182  				}
   183  			})
   184  
   185  			It("produces an error", func() {
   186  				Ω(dslengine.Errors).Should(HaveOccurred())
   187  			})
   188  		})
   189  
   190  		Context("with a valid max value validation", func() {
   191  			BeforeEach(func() {
   192  				dsl = func() {
   193  					Attribute(attName, Integer, func() {
   194  						Maximum(2)
   195  					})
   196  				}
   197  			})
   198  
   199  			It("records the validation", func() {
   200  				Ω(dslengine.Errors).ShouldNot(HaveOccurred())
   201  				Ω(att.Validation).ShouldNot(BeNil())
   202  				Ω(*att.Validation.Maximum).Should(Equal(2.0))
   203  			})
   204  		})
   205  
   206  		Context("with an invalid max value validation", func() {
   207  			BeforeEach(func() {
   208  				dsl = func() {
   209  					Attribute(attName, String, func() {
   210  						Maximum(2)
   211  					})
   212  				}
   213  			})
   214  
   215  			It("produces an error", func() {
   216  				Ω(dslengine.Errors).Should(HaveOccurred())
   217  			})
   218  		})
   219  
   220  		Context("with a valid min length validation", func() {
   221  			BeforeEach(func() {
   222  				dsl = func() {
   223  					Attribute(attName, ArrayOf(Integer), func() {
   224  						MinLength(2)
   225  					})
   226  				}
   227  			})
   228  
   229  			It("records the validation", func() {
   230  				Ω(dslengine.Errors).ShouldNot(HaveOccurred())
   231  				Ω(att.Validation).ShouldNot(BeNil())
   232  				Ω(*att.Validation.MinLength).Should(Equal(2))
   233  			})
   234  		})
   235  
   236  		Context("with an invalid min length validation", func() {
   237  			BeforeEach(func() {
   238  				dsl = func() {
   239  					Attribute(attName, Integer, func() {
   240  						MinLength(2)
   241  					})
   242  				}
   243  			})
   244  
   245  			It("produces an error", func() {
   246  				Ω(dslengine.Errors).Should(HaveOccurred())
   247  			})
   248  		})
   249  
   250  		Context("with a valid max length validation", func() {
   251  			BeforeEach(func() {
   252  				dsl = func() {
   253  					Attribute(attName, String, func() {
   254  						MaxLength(2)
   255  					})
   256  				}
   257  			})
   258  
   259  			It("records the validation", func() {
   260  				Ω(dslengine.Errors).ShouldNot(HaveOccurred())
   261  				Ω(att.Validation).ShouldNot(BeNil())
   262  				Ω(*att.Validation.MaxLength).Should(Equal(2))
   263  			})
   264  		})
   265  
   266  		Context("with an invalid max length validation", func() {
   267  			BeforeEach(func() {
   268  				dsl = func() {
   269  					Attribute(attName, Integer, func() {
   270  						MaxLength(2)
   271  					})
   272  				}
   273  			})
   274  
   275  			It("produces an error", func() {
   276  				Ω(dslengine.Errors).Should(HaveOccurred())
   277  			})
   278  		})
   279  
   280  		Context("with a required field validation", func() {
   281  			BeforeEach(func() {
   282  				dsl = func() {
   283  					Attribute(attName, String)
   284  					Required(attName)
   285  				}
   286  			})
   287  
   288  			It("records the validation", func() {
   289  				Ω(dslengine.Errors).ShouldNot(HaveOccurred())
   290  				Ω(Design.Types["bar"].Validation).ShouldNot(BeNil())
   291  				Ω(Design.Types["bar"].Validation.Required).Should(Equal([]string{attName}))
   292  			})
   293  		})
   294  	})
   295  
   296  	Describe("EncoderDefinition", func() {
   297  		var (
   298  			enc           *EncodingDefinition
   299  			oldGoPath     string
   300  			oldWorkingDir string
   301  			cellarPath    string
   302  		)
   303  
   304  		BeforeEach(func() {
   305  			enc = &EncodingDefinition{MIMETypes: []string{"application/foo"}, Encoder: true, PackagePath: "github.com/goadesign/goa/encoding/foo"}
   306  			oldGoPath = build.Default.GOPATH
   307  
   308  			var err error
   309  			oldWorkingDir, err = os.Getwd()
   310  			Ω(err).ShouldNot(HaveOccurred())
   311  
   312  			cellarPath = path.Join(oldWorkingDir, "tmp_gopath/src/github.com/goadesign/goa_fake_cellar")
   313  			Ω(os.MkdirAll(cellarPath, 0777)).ShouldNot(HaveOccurred())
   314  		})
   315  
   316  		JustBeforeEach(func() {
   317  			build.Default.GOPATH = path.Join(oldWorkingDir, "tmp_gopath")
   318  			Ω(os.Chdir(cellarPath)).ShouldNot(HaveOccurred())
   319  		})
   320  
   321  		AfterEach(func() {
   322  			build.Default.GOPATH = oldGoPath
   323  			os.Chdir(oldWorkingDir)
   324  			Ω(os.RemoveAll("tmp_gopath")).ShouldNot(HaveOccurred())
   325  		})
   326  
   327  		Context("with package is not found", func() {
   328  			It("returns a validation error", func() {
   329  				Ω(len(enc.Validate().Errors)).Should(Equal(1))
   330  				Ω(enc.Validate().Errors[0].Error()).Should(MatchRegexp("^invalid Go package path"))
   331  			})
   332  		})
   333  
   334  		Context("with package in gopath", func() {
   335  			BeforeEach(func() {
   336  				packagePath := path.Join(cellarPath, "../goa/encoding/foo")
   337  
   338  				Ω(os.MkdirAll(packagePath, 0777)).ShouldNot(HaveOccurred())
   339  				Ω(ioutil.WriteFile(path.Join(packagePath, "encoding.go"), []byte("package foo"), 0777)).ShouldNot(HaveOccurred())
   340  			})
   341  
   342  			It("validates EncoderDefinition", func() {
   343  				Ω(enc.Validate().Errors).Should(BeNil())
   344  			})
   345  		})
   346  
   347  		Context("with package in vendor", func() {
   348  			BeforeEach(func() {
   349  				packagePath := path.Join(cellarPath, "vendor/github.com/goadesign/goa/encoding/foo")
   350  
   351  				Ω(os.MkdirAll(packagePath, 0777)).ShouldNot(HaveOccurred())
   352  				Ω(ioutil.WriteFile(path.Join(packagePath, "encoding.go"), []byte("package foo"), 0777)).ShouldNot(HaveOccurred())
   353  			})
   354  
   355  			It("validates EncoderDefinition", func() {
   356  				Ω(enc.Validate().Errors).Should(BeNil())
   357  			})
   358  		})
   359  	})
   360  })