github.com/furusax0621/goa-v1@v1.4.3/goagen/gen_app/test_generator_test.go (about) 1 package genapp_test 2 3 import ( 4 "io/ioutil" 5 "os" 6 "path/filepath" 7 "strings" 8 9 "github.com/goadesign/goa/design" 10 "github.com/goadesign/goa/dslengine" 11 "github.com/goadesign/goa/goagen/codegen" 12 genapp "github.com/goadesign/goa/goagen/gen_app" 13 "github.com/goadesign/goa/version" 14 . "github.com/onsi/ginkgo" 15 . "github.com/onsi/gomega" 16 ) 17 18 var _ = Describe("Generate", func() { 19 const testgenPackagePath = "github.com/goadesign/goa/goagen/gen_app/test_" 20 21 var outDir string 22 var files []string 23 var genErr error 24 25 BeforeEach(func() { 26 gopath := filepath.SplitList(os.Getenv("GOPATH"))[0] 27 outDir = filepath.Join(gopath, "src", testgenPackagePath) 28 err := os.MkdirAll(outDir, 0777) 29 Ω(err).ShouldNot(HaveOccurred()) 30 os.Args = []string{"goagen", "--out=" + outDir, "--design=foo", "--version=" + version.String()} 31 design.GeneratedMediaTypes = make(design.MediaTypeRoot) 32 design.ProjectedMediaTypes = make(design.MediaTypeRoot) 33 }) 34 35 JustBeforeEach(func() { 36 files, genErr = genapp.Generate() 37 }) 38 39 AfterEach(func() { 40 os.RemoveAll(outDir) 41 delete(codegen.Reserved, "app") 42 }) 43 44 Context("with notest flag", func() { 45 BeforeEach(func() { 46 os.Args = []string{"goagen", "--out=" + outDir, "--design=foo", "--notest", "--version=" + version.String()} 47 }) 48 49 It("does not generate tests", func() { 50 _, err := os.Stat(filepath.Join(outDir, "app", "test")) 51 Expect(err).To(HaveOccurred()) 52 Expect(os.IsNotExist(err)).To(BeTrue()) 53 }) 54 }) 55 56 Context("with an basic action", func() { 57 BeforeEach(func() { 58 codegen.TempCount = 0 59 60 userType := &design.UserTypeDefinition{ 61 AttributeDefinition: &design.AttributeDefinition{Type: &design.Array{ElemType: &design.AttributeDefinition{Type: design.String}}}, 62 TypeName: "CustomName", 63 } 64 65 intAttr := &design.AttributeDefinition{ 66 Type: design.Object{"foo": &design.AttributeDefinition{Type: design.Integer}}, 67 Validation: &dslengine.ValidationDefinition{Required: []string{"foo"}}, 68 } 69 70 intMedia := &design.MediaTypeDefinition{ 71 Identifier: "application/vnd.goa.test.int", 72 UserTypeDefinition: &design.UserTypeDefinition{ 73 AttributeDefinition: intAttr, 74 TypeName: "IntContainer", 75 }, 76 } 77 78 defaultView := &design.ViewDefinition{ 79 AttributeDefinition: intAttr, 80 Name: "default", 81 Parent: intMedia, 82 } 83 84 intMedia.Views = map[string]*design.ViewDefinition{"default": defaultView} 85 86 design.Design = &design.APIDefinition{ 87 Name: "testapi", 88 Title: "dummy API with no resource", 89 Description: "I told you it's dummy", 90 MediaTypes: map[string]*design.MediaTypeDefinition{ 91 design.ErrorMedia.Identifier: design.ErrorMedia, 92 intMedia.Identifier: intMedia, 93 }, 94 Resources: map[string]*design.ResourceDefinition{ 95 "foo": { 96 Name: "foo", 97 Headers: &design.AttributeDefinition{ 98 Type: design.Object{ 99 "optionalResourceHeader": &design.AttributeDefinition{Type: design.Integer}, 100 "requiredResourceHeader": &design.AttributeDefinition{Type: design.String}, 101 }, 102 Validation: &dslengine.ValidationDefinition{Required: []string{"requiredResourceHeader"}}, 103 }, 104 Actions: map[string]*design.ActionDefinition{ 105 "show": { 106 Name: "show", 107 Params: &design.AttributeDefinition{ 108 Type: design.Object{ 109 "param": &design.AttributeDefinition{Type: design.Integer}, 110 "time": &design.AttributeDefinition{Type: design.DateTime}, 111 "uuid": &design.AttributeDefinition{Type: design.UUID}, 112 "optional": &design.AttributeDefinition{Type: design.Integer}, 113 "required": &design.AttributeDefinition{Type: design.DateTime}, 114 "query": &design.AttributeDefinition{Type: design.String}, 115 }, 116 Validation: &dslengine.ValidationDefinition{Required: []string{"required"}}, 117 }, 118 Headers: &design.AttributeDefinition{ 119 Type: design.Object{ 120 "optionalHeader": &design.AttributeDefinition{Type: design.Integer}, 121 "requiredHeader": &design.AttributeDefinition{Type: design.String}, 122 }, 123 Validation: &dslengine.ValidationDefinition{Required: []string{"requiredHeader", "requiredResourceHeader"}}, 124 }, 125 QueryParams: &design.AttributeDefinition{ 126 Type: design.Object{ 127 "optional": &design.AttributeDefinition{Type: design.Integer}, 128 "required": &design.AttributeDefinition{Type: design.DateTime}, 129 "query": &design.AttributeDefinition{Type: design.String}, 130 }, 131 Validation: &dslengine.ValidationDefinition{Required: []string{"required"}}, 132 }, 133 Routes: []*design.RouteDefinition{ 134 { 135 Verb: "GET", 136 Path: "p/:param/u/:uuid/:required", 137 }, 138 { 139 Verb: "POST", 140 Path: "", 141 }, 142 }, 143 Responses: map[string]*design.ResponseDefinition{ 144 "ok": { 145 Name: "ok", 146 Status: 200, 147 MediaType: intMedia.Identifier, 148 }, 149 }, 150 }, 151 "get": { 152 Name: "get", 153 Params: &design.AttributeDefinition{ 154 Type: design.Object{ 155 "param": &design.AttributeDefinition{Type: design.Integer}, 156 "time": &design.AttributeDefinition{Type: design.DateTime}, 157 "uuid": &design.AttributeDefinition{Type: design.UUID}, 158 }, 159 }, 160 Routes: []*design.RouteDefinition{ 161 { 162 Verb: "GET", 163 Path: "", 164 }, 165 }, 166 Payload: userType, 167 Responses: map[string]*design.ResponseDefinition{ 168 "ok": { 169 Name: "ok", 170 Type: design.ErrorMedia, 171 MediaType: "application/vnd.goa.error", 172 }, 173 }, 174 }, 175 }, 176 }, 177 }, 178 } 179 fooRes := design.Design.Resources["foo"] 180 for _, a := range fooRes.Actions { 181 a.Parent = fooRes 182 a.Routes[0].Parent = a 183 } 184 }) 185 186 It("does not call Validate on the resulting media type when it does not exist", func() { 187 Ω(genErr).Should(BeNil()) 188 Ω(files).Should(HaveLen(8)) 189 content, err := ioutil.ReadFile(filepath.Join(outDir, "app", "test", "foo_testing.go")) 190 Ω(err).ShouldNot(HaveOccurred()) 191 192 Ω(content).ShouldNot(ContainSubstring("err = mt.Validate()")) 193 }) 194 195 It("generates the ActionRouteResponse test methods ", func() { 196 Ω(genErr).Should(BeNil()) 197 Ω(files).Should(HaveLen(8)) 198 content, err := ioutil.ReadFile(filepath.Join(outDir, "app", "test", "foo_testing.go")) 199 Ω(err).ShouldNot(HaveOccurred()) 200 201 Ω(content).Should(ContainSubstring("ShowFooOK(")) 202 // Multiple Routes 203 Ω(content).Should(ContainSubstring("ShowFooOK1(")) 204 // Get returns an error media type 205 Ω(content).Should(ContainSubstring("GetFooOK(t goatest.TInterface, ctx context.Context, service *goa.Service, ctrl app.FooController, optionalResourceHeader *int, requiredResourceHeader string, payload app.CustomName) (http.ResponseWriter, error)")) 206 }) 207 208 It("generates the route path parameters", func() { 209 content, err := ioutil.ReadFile(filepath.Join(outDir, "app", "test", "foo_testing.go")) 210 Ω(err).ShouldNot(HaveOccurred()) 211 212 Ω(content).Should(ContainSubstring(`["param"] = []string{`)) 213 Ω(content).Should(ContainSubstring(`["uuid"] = []string{`)) 214 Ω(content).Should(ContainSubstring(`["required"] = []string{`)) 215 Ω(content).ShouldNot(ContainSubstring(`["time"] = []string{`)) 216 }) 217 218 It("properly handles query parameters", func() { 219 content, err := ioutil.ReadFile(filepath.Join(outDir, "app", "test", "foo_testing.go")) 220 Ω(err).ShouldNot(HaveOccurred()) 221 222 Ω(content).Should(ContainSubstring(`if optional != nil`)) 223 Ω(content).ShouldNot(ContainSubstring(`if required != nil`)) 224 Ω(content).Should(ContainSubstring(`if query != nil`)) 225 }) 226 227 It("properly handles headers", func() { 228 content, err := ioutil.ReadFile(filepath.Join(outDir, "app", "test", "foo_testing.go")) 229 Ω(err).ShouldNot(HaveOccurred()) 230 231 Ω(content).Should(ContainSubstring(`if optionalHeader != nil`)) 232 Ω(content).ShouldNot(ContainSubstring(`if requiredHeader != nil`)) 233 Ω(content).Should(ContainSubstring(`req.Header["Requiredheader"] = sliceVal`)) 234 Ω(content).Should(ContainSubstring(`if optionalResourceHeader != nil`)) 235 Ω(content).ShouldNot(ContainSubstring(`if requiredResourceHeader != nil`)) 236 Ω(content).Should(ContainSubstring(`req.Header["Requiredresourceheader"] = sliceVal`)) 237 }) 238 239 It("generates calls to new Context ", func() { 240 content, err := ioutil.ReadFile(filepath.Join(outDir, "app", "test", "foo_testing.go")) 241 Ω(err).ShouldNot(HaveOccurred()) 242 243 Ω(content).Should(ContainSubstring("app.NewShowFooContext(")) 244 }) 245 246 It("generates calls controller action method", func() { 247 content, err := ioutil.ReadFile(filepath.Join(outDir, "app", "test", "foo_testing.go")) 248 Ω(err).ShouldNot(HaveOccurred()) 249 250 Ω(content).Should(ContainSubstring("ctrl.Show(")) 251 }) 252 253 It("generates non pointer references to primitive/array/hash payloads", func() { 254 content, err := ioutil.ReadFile(filepath.Join(outDir, "app", "test", "foo_testing.go")) 255 Ω(err).ShouldNot(HaveOccurred()) 256 257 Ω(content).Should(ContainSubstring(", payload app.CustomName)")) 258 }) 259 260 It("generates header compliant with https://github.com/golang/go/issues/13560", func() { 261 content, err := ioutil.ReadFile(filepath.Join(outDir, "app", "test", "foo_testing.go")) 262 Ω(err).ShouldNot(HaveOccurred()) 263 Ω(strings.Split(string(content), "\n")).Should(ContainElement(MatchRegexp(`^// Code generated .* DO NOT EDIT\.$`))) 264 }) 265 }) 266 })